PKHZ$exceptions/InvalidEmailException.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use InvalidArgumentException; class InvalidEmailException extends InvalidArgumentException implements Exception { } PKHZ_Uj)exceptions/ElementCollectionException.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use InvalidArgumentException; class ElementCollectionException extends InvalidArgumentException implements Exception { } PKHZMV11.exceptions/InvalidApplicationNameException.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use InvalidArgumentException; class InvalidApplicationNameException extends InvalidArgumentException implements Exception { public const InvalidFormat = 2; } PKHZ`'i.exceptions/ManifestDocumentMapperException.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use RuntimeException; class ManifestDocumentMapperException extends RuntimeException implements Exception { } PKHZwkjjexceptions/Exception.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeUnit; use Throwable; interface Exception extends Throwable { } PKHZ o(exceptions/ManifestDocumentException.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use RuntimeException; class ManifestDocumentException extends RuntimeException implements Exception { } PKHZq:&exceptions/NoEmailAddressException.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use InvalidArgumentException; class NoEmailAddressException extends InvalidArgumentException implements Exception { } PKHZY"exceptions/InvalidUrlException.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use InvalidArgumentException; class InvalidUrlException extends InvalidArgumentException implements Exception { } PKHZ4o&exceptions/ManifestLoaderException.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class ManifestLoaderException extends \Exception implements Exception { } PKHZ#m'exceptions/ManifestElementException.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use RuntimeException; class ManifestElementException extends RuntimeException implements Exception { } PKHZգ/exceptions/ManifestDocumentLoadingException.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use LibXMLError; use function sprintf; class ManifestDocumentLoadingException extends \Exception implements Exception { /** @var LibXMLError[] */ private $libxmlErrors; /** * ManifestDocumentLoadingException constructor. * * @param LibXMLError[] $libxmlErrors */ public function __construct(array $libxmlErrors) { $this->libxmlErrors = $libxmlErrors; $first = $this->libxmlErrors[0]; parent::__construct( sprintf( '%s (Line: %d / Column: %d / File: %s)', $first->message, $first->line, $first->column, $first->file ), $first->code ); } /** * @return LibXMLError[] */ public function getLibxmlErrors(): array { return $this->libxmlErrors; } } PKHZg- - values/Manifest.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use PharIo\Version\Version; class Manifest { /** @var ApplicationName */ private $name; /** @var Version */ private $version; /** @var Type */ private $type; /** @var CopyrightInformation */ private $copyrightInformation; /** @var RequirementCollection */ private $requirements; /** @var BundledComponentCollection */ private $bundledComponents; public function __construct(ApplicationName $name, Version $version, Type $type, CopyrightInformation $copyrightInformation, RequirementCollection $requirements, BundledComponentCollection $bundledComponents) { $this->name = $name; $this->version = $version; $this->type = $type; $this->copyrightInformation = $copyrightInformation; $this->requirements = $requirements; $this->bundledComponents = $bundledComponents; } public function getName(): ApplicationName { return $this->name; } public function getVersion(): Version { return $this->version; } public function getType(): Type { return $this->type; } public function getCopyrightInformation(): CopyrightInformation { return $this->copyrightInformation; } public function getRequirements(): RequirementCollection { return $this->requirements; } public function getBundledComponents(): BundledComponentCollection { return $this->bundledComponents; } public function isApplication(): bool { return $this->type->isApplication(); } public function isLibrary(): bool { return $this->type->isLibrary(); } public function isExtension(): bool { return $this->type->isExtension(); } public function isExtensionFor(ApplicationName $application, ?Version $version = null): bool { if (!$this->isExtension()) { return false; } /** @var Extension $type */ $type = $this->type; if ($version !== null) { return $type->isCompatibleWith($application, $version); } return $type->isExtensionFor($application); } } PKHZ (values/RequirementCollectionIterator.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use Iterator; use function count; /** @template-implements Iterator */ class RequirementCollectionIterator implements Iterator { /** @var Requirement[] */ private $requirements; /** @var int */ private $position = 0; public function __construct(RequirementCollection $requirements) { $this->requirements = $requirements->getRequirements(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->requirements); } public function key(): int { return $this->position; } public function current(): Requirement { return $this->requirements[$this->position]; } public function next(): void { $this->position++; } } PKHZvalues/AuthorCollection.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use Countable; use IteratorAggregate; use function count; /** @template-implements IteratorAggregate */ class AuthorCollection implements Countable, IteratorAggregate { /** @var Author[] */ private $authors = []; public function add(Author $author): void { $this->authors[] = $author; } /** * @return Author[] */ public function getAuthors(): array { return $this->authors; } public function count(): int { return count($this->authors); } public function getIterator(): AuthorCollectionIterator { return new AuthorCollectionIterator($this); } } PKHZ\\values/CopyrightInformation.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class CopyrightInformation { /** @var AuthorCollection */ private $authors; /** @var License */ private $license; public function __construct(AuthorCollection $authors, License $license) { $this->authors = $authors; $this->license = $license; } public function getAuthors(): AuthorCollection { return $this->authors; } public function getLicense(): License { return $this->license; } } PKHZ^values/License.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class License { /** @var string */ private $name; /** @var Url */ private $url; public function __construct(string $name, Url $url) { $this->name = $name; $this->url = $url; } public function getName(): string { return $this->name; } public function getUrl(): Url { return $this->url; } } PKHZ]=#values/AuthorCollectionIterator.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use Iterator; use function count; /** @template-implements Iterator */ class AuthorCollectionIterator implements Iterator { /** @var Author[] */ private $authors; /** @var int */ private $position = 0; public function __construct(AuthorCollection $authors) { $this->authors = $authors->getAuthors(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->authors); } public function key(): int { return $this->position; } public function current(): Author { return $this->authors[$this->position]; } public function next(): void { $this->position++; } } PKHZ$%values/BundledComponentCollection.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use Countable; use IteratorAggregate; use function count; /** @template-implements IteratorAggregate */ class BundledComponentCollection implements Countable, IteratorAggregate { /** @var BundledComponent[] */ private $bundledComponents = []; public function add(BundledComponent $bundledComponent): void { $this->bundledComponents[] = $bundledComponent; } /** * @return BundledComponent[] */ public function getBundledComponents(): array { return $this->bundledComponents; } public function count(): int { return count($this->bundledComponents); } public function getIterator(): BundledComponentCollectionIterator { return new BundledComponentCollectionIterator($this); } } PKHZX?\\ values/RequirementCollection.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use Countable; use IteratorAggregate; use function count; /** @template-implements IteratorAggregate */ class RequirementCollection implements Countable, IteratorAggregate { /** @var Requirement[] */ private $requirements = []; public function add(Requirement $requirement): void { $this->requirements[] = $requirement; } /** * @return Requirement[] */ public function getRequirements(): array { return $this->requirements; } public function count(): int { return count($this->requirements); } public function getIterator(): RequirementCollectionIterator { return new RequirementCollectionIterator($this); } } PKHZS|values/Email.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use const FILTER_VALIDATE_EMAIL; use function filter_var; class Email { /** @var string */ private $email; public function __construct(string $email) { $this->ensureEmailIsValid($email); $this->email = $email; } public function asString(): string { return $this->email; } private function ensureEmailIsValid(string $url): void { if (filter_var($url, FILTER_VALIDATE_EMAIL) === false) { throw new InvalidEmailException; } } } PKHZ<2values/Type.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use PharIo\Version\VersionConstraint; abstract class Type { public static function application(): Application { return new Application; } public static function library(): Library { return new Library; } public static function extension(ApplicationName $application, VersionConstraint $versionConstraint): Extension { return new Extension($application, $versionConstraint); } /** @psalm-assert-if-true Application $this */ public function isApplication(): bool { return false; } /** @psalm-assert-if-true Library $this */ public function isLibrary(): bool { return false; } /** @psalm-assert-if-true Extension $this */ public function isExtension(): bool { return false; } } PKHZ1qvalues/Requirement.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; interface Requirement { } PKHZ("values/PhpExtensionRequirement.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class PhpExtensionRequirement implements Requirement { /** @var string */ private $extension; public function __construct(string $extension) { $this->extension = $extension; } public function asString(): string { return $this->extension; } } PKHZf=values/Application.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class Application extends Type { public function isApplication(): bool { return true; } } PKHZZ HHvalues/BundledComponent.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use PharIo\Version\Version; class BundledComponent { /** @var string */ private $name; /** @var Version */ private $version; public function __construct(string $name, Version $version) { $this->name = $name; $this->version = $version; } public function getName(): string { return $this->name; } public function getVersion(): Version { return $this->version; } } PKHZZ7'values/Extension.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use PharIo\Version\Version; use PharIo\Version\VersionConstraint; class Extension extends Type { /** @var ApplicationName */ private $application; /** @var VersionConstraint */ private $versionConstraint; public function __construct(ApplicationName $application, VersionConstraint $versionConstraint) { $this->application = $application; $this->versionConstraint = $versionConstraint; } public function getApplicationName(): ApplicationName { return $this->application; } public function getVersionConstraint(): VersionConstraint { return $this->versionConstraint; } public function isExtension(): bool { return true; } public function isExtensionFor(ApplicationName $name): bool { return $this->application->isEqual($name); } public function isCompatibleWith(ApplicationName $name, Version $version): bool { return $this->isExtensionFor($name) && $this->versionConstraint->complies($version); } } PKHZ:"-values/BundledComponentCollectionIterator.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use Iterator; use function count; /** @template-implements Iterator */ class BundledComponentCollectionIterator implements Iterator { /** @var BundledComponent[] */ private $bundledComponents; /** @var int */ private $position = 0; public function __construct(BundledComponentCollection $bundledComponents) { $this->bundledComponents = $bundledComponents->getBundledComponents(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->bundledComponents); } public function key(): int { return $this->position; } public function current(): BundledComponent { return $this->bundledComponents[$this->position]; } public function next(): void { $this->position++; } } PKHZvalues/Library.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class Library extends Type { public function isLibrary(): bool { return true; } } PKHZvalues/ApplicationName.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use function preg_match; use function sprintf; class ApplicationName { /** @var string */ private $name; public function __construct(string $name) { $this->ensureValidFormat($name); $this->name = $name; } public function asString(): string { return $this->name; } public function isEqual(ApplicationName $name): bool { return $this->name === $name->name; } private function ensureValidFormat(string $name): void { if (!preg_match('#\w/\w#', $name)) { throw new InvalidApplicationNameException( sprintf('Format of name "%s" is not valid - expected: vendor/packagename', $name), InvalidApplicationNameException::InvalidFormat ); } } } PKHZ#lͣvalues/Url.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use const FILTER_VALIDATE_URL; use function filter_var; class Url { /** @var string */ private $url; public function __construct(string $url) { $this->ensureUrlIsValid($url); $this->url = $url; } public function asString(): string { return $this->url; } /** * @throws InvalidUrlException */ private function ensureUrlIsValid(string $url): void { if (filter_var($url, FILTER_VALIDATE_URL) === false) { throw new InvalidUrlException; } } } PKHZ, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use function sprintf; class Author { /** @var string */ private $name; /** @var null|Email */ private $email; public function __construct(string $name, ?Email $email = null) { $this->name = $name; $this->email = $email; } public function asString(): string { if (!$this->hasEmail()) { return $this->name; } return sprintf( '%s <%s>', $this->name, $this->email->asString() ); } public function getName(): string { return $this->name; } /** * @psalm-assert-if-true Email $this->email */ public function hasEmail(): bool { return $this->email !== null; } public function getEmail(): Email { if (!$this->hasEmail()) { throw new NoEmailAddressException(); } return $this->email; } } PKHZ"&$$ values/PhpVersionRequirement.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use PharIo\Version\VersionConstraint; class PhpVersionRequirement implements Requirement { /** @var VersionConstraint */ private $versionConstraint; public function __construct(VersionConstraint $versionConstraint) { $this->versionConstraint = $versionConstraint; } public function getVersionConstraint(): VersionConstraint { return $this->versionConstraint; } } PKHZqManifestDocumentMapper.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use PharIo\Version\Exception as VersionException; use PharIo\Version\Version; use PharIo\Version\VersionConstraintParser; use Throwable; use function sprintf; class ManifestDocumentMapper { public function map(ManifestDocument $document): Manifest { try { $contains = $document->getContainsElement(); $type = $this->mapType($contains); $copyright = $this->mapCopyright($document->getCopyrightElement()); $requirements = $this->mapRequirements($document->getRequiresElement()); $bundledComponents = $this->mapBundledComponents($document); return new Manifest( new ApplicationName($contains->getName()), new Version($contains->getVersion()), $type, $copyright, $requirements, $bundledComponents ); } catch (Throwable $e) { throw new ManifestDocumentMapperException($e->getMessage(), (int)$e->getCode(), $e); } } private function mapType(ContainsElement $contains): Type { switch ($contains->getType()) { case 'application': return Type::application(); case 'library': return Type::library(); case 'extension': return $this->mapExtension($contains->getExtensionElement()); } throw new ManifestDocumentMapperException( sprintf('Unsupported type %s', $contains->getType()) ); } private function mapCopyright(CopyrightElement $copyright): CopyrightInformation { $authors = new AuthorCollection(); foreach ($copyright->getAuthorElements() as $authorElement) { $authors->add( new Author( $authorElement->getName(), $authorElement->hasEMail() ? new Email($authorElement->getEmail()) : null ) ); } $licenseElement = $copyright->getLicenseElement(); $license = new License( $licenseElement->getType(), new Url($licenseElement->getUrl()) ); return new CopyrightInformation( $authors, $license ); } private function mapRequirements(RequiresElement $requires): RequirementCollection { $collection = new RequirementCollection(); $phpElement = $requires->getPHPElement(); $parser = new VersionConstraintParser; try { $versionConstraint = $parser->parse($phpElement->getVersion()); } catch (VersionException $e) { throw new ManifestDocumentMapperException( sprintf('Unsupported version constraint - %s', $e->getMessage()), (int)$e->getCode(), $e ); } $collection->add( new PhpVersionRequirement( $versionConstraint ) ); if (!$phpElement->hasExtElements()) { return $collection; } foreach ($phpElement->getExtElements() as $extElement) { $collection->add( new PhpExtensionRequirement($extElement->getName()) ); } return $collection; } private function mapBundledComponents(ManifestDocument $document): BundledComponentCollection { $collection = new BundledComponentCollection(); if (!$document->hasBundlesElement()) { return $collection; } foreach ($document->getBundlesElement()->getComponentElements() as $componentElement) { $collection->add( new BundledComponent( $componentElement->getName(), new Version( $componentElement->getVersion() ) ) ); } return $collection; } private function mapExtension(ExtensionElement $extension): Extension { try { $versionConstraint = (new VersionConstraintParser)->parse($extension->getCompatible()); return Type::extension( new ApplicationName($extension->getFor()), $versionConstraint ); } catch (VersionException $e) { throw new ManifestDocumentMapperException( sprintf('Unsupported version constraint - %s', $e->getMessage()), (int)$e->getCode(), $e ); } } } PKHZۂManifestSerializer.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use PharIo\Version\AnyVersionConstraint; use PharIo\Version\Version; use PharIo\Version\VersionConstraint; use XMLWriter; use function count; use function file_put_contents; use function str_repeat; /** @psalm-suppress MissingConstructor */ class ManifestSerializer { /** @var XMLWriter */ private $xmlWriter; public function serializeToFile(Manifest $manifest, string $filename): void { file_put_contents( $filename, $this->serializeToString($manifest) ); } public function serializeToString(Manifest $manifest): string { $this->startDocument(); $this->addContains($manifest->getName(), $manifest->getVersion(), $manifest->getType()); $this->addCopyright($manifest->getCopyrightInformation()); $this->addRequirements($manifest->getRequirements()); $this->addBundles($manifest->getBundledComponents()); return $this->finishDocument(); } private function startDocument(): void { $xmlWriter = new XMLWriter(); $xmlWriter->openMemory(); $xmlWriter->setIndent(true); $xmlWriter->setIndentString(str_repeat(' ', 4)); $xmlWriter->startDocument('1.0', 'UTF-8'); $xmlWriter->startElement('phar'); $xmlWriter->writeAttribute('xmlns', 'https://phar.io/xml/manifest/1.0'); $this->xmlWriter = $xmlWriter; } private function finishDocument(): string { $this->xmlWriter->endElement(); $this->xmlWriter->endDocument(); return $this->xmlWriter->outputMemory(); } private function addContains(ApplicationName $name, Version $version, Type $type): void { $this->xmlWriter->startElement('contains'); $this->xmlWriter->writeAttribute('name', $name->asString()); $this->xmlWriter->writeAttribute('version', $version->getVersionString()); switch (true) { case $type->isApplication(): { $this->xmlWriter->writeAttribute('type', 'application'); break; } case $type->isLibrary(): { $this->xmlWriter->writeAttribute('type', 'library'); break; } case $type->isExtension(): { $this->xmlWriter->writeAttribute('type', 'extension'); /* @var $type Extension */ $this->addExtension( $type->getApplicationName(), $type->getVersionConstraint() ); break; } default: { $this->xmlWriter->writeAttribute('type', 'custom'); } } $this->xmlWriter->endElement(); } private function addCopyright(CopyrightInformation $copyrightInformation): void { $this->xmlWriter->startElement('copyright'); foreach ($copyrightInformation->getAuthors() as $author) { $this->xmlWriter->startElement('author'); $this->xmlWriter->writeAttribute('name', $author->getName()); $this->xmlWriter->writeAttribute('email', $author->getEmail()->asString()); $this->xmlWriter->endElement(); } $license = $copyrightInformation->getLicense(); $this->xmlWriter->startElement('license'); $this->xmlWriter->writeAttribute('type', $license->getName()); $this->xmlWriter->writeAttribute('url', $license->getUrl()->asString()); $this->xmlWriter->endElement(); $this->xmlWriter->endElement(); } private function addRequirements(RequirementCollection $requirementCollection): void { $phpRequirement = new AnyVersionConstraint(); $extensions = []; foreach ($requirementCollection as $requirement) { if ($requirement instanceof PhpVersionRequirement) { $phpRequirement = $requirement->getVersionConstraint(); continue; } if ($requirement instanceof PhpExtensionRequirement) { $extensions[] = $requirement->asString(); } } $this->xmlWriter->startElement('requires'); $this->xmlWriter->startElement('php'); $this->xmlWriter->writeAttribute('version', $phpRequirement->asString()); foreach ($extensions as $extension) { $this->xmlWriter->startElement('ext'); $this->xmlWriter->writeAttribute('name', $extension); $this->xmlWriter->endElement(); } $this->xmlWriter->endElement(); $this->xmlWriter->endElement(); } private function addBundles(BundledComponentCollection $bundledComponentCollection): void { if (count($bundledComponentCollection) === 0) { return; } $this->xmlWriter->startElement('bundles'); foreach ($bundledComponentCollection as $bundledComponent) { $this->xmlWriter->startElement('component'); $this->xmlWriter->writeAttribute('name', $bundledComponent->getName()); $this->xmlWriter->writeAttribute('version', $bundledComponent->getVersion()->getVersionString()); $this->xmlWriter->endElement(); } $this->xmlWriter->endElement(); } private function addExtension(ApplicationName $applicationName, VersionConstraint $versionConstraint): void { $this->xmlWriter->startElement('extension'); $this->xmlWriter->writeAttribute('for', $applicationName->asString()); $this->xmlWriter->writeAttribute('compatible', $versionConstraint->asString()); $this->xmlWriter->endElement(); } } PKHZJJxml/ExtElementCollection.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class ExtElementCollection extends ElementCollection { public function current(): ExtElement { return new ExtElement( $this->getCurrentElement() ); } } PKHZ(7SSxml/AuthorElementCollection.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class AuthorElementCollection extends ElementCollection { public function current(): AuthorElement { return new AuthorElement( $this->getCurrentElement() ); } } PKHZtTX||xml/LicenseElement.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class LicenseElement extends ManifestElement { public function getType(): string { return $this->getAttributeValue('type'); } public function getUrl(): string { return $this->getAttributeValue('url'); } } PKHZaΉxml/ContainsElement.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class ContainsElement extends ManifestElement { public function getName(): string { return $this->getAttributeValue('name'); } public function getVersion(): string { return $this->getAttributeValue('version'); } public function getType(): string { return $this->getAttributeValue('type'); } public function getExtensionElement(): ExtensionElement { return new ExtensionElement( $this->getChildByName('extension') ); } } PKHZ砲Lxml/ElementCollection.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use DOMElement; use DOMNodeList; use Iterator; use ReturnTypeWillChange; use function count; use function get_class; use function sprintf; /** @template-implements Iterator */ abstract class ElementCollection implements Iterator { /** @var DOMElement[] */ private $nodes = []; /** @var int */ private $position; public function __construct(DOMNodeList $nodeList) { $this->position = 0; $this->importNodes($nodeList); } #[ReturnTypeWillChange] abstract public function current(); public function next(): void { $this->position++; } public function key(): int { return $this->position; } public function valid(): bool { return $this->position < count($this->nodes); } public function rewind(): void { $this->position = 0; } protected function getCurrentElement(): DOMElement { return $this->nodes[$this->position]; } private function importNodes(DOMNodeList $nodeList): void { foreach ($nodeList as $node) { if (!$node instanceof DOMElement) { throw new ElementCollectionException( sprintf('\DOMElement expected, got \%s', get_class($node)) ); } $this->nodes[] = $node; } } } PKHZ}zzxml/BundlesElement.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class BundlesElement extends ManifestElement { public function getComponentElements(): ComponentElementCollection { return new ComponentElementCollection( $this->getChildrenByName('component') ); } } PKHZxml/ExtElement.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class ExtElement extends ManifestElement { public function getName(): string { return $this->getAttributeValue('name'); } } PKHZܗKKxml/RequiresElement.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class RequiresElement extends ManifestElement { public function getPHPElement(): PhpElement { return new PhpElement( $this->getChildByName('php') ); } } PKHZ$Sgxml/ComponentElement.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class ComponentElement extends ManifestElement { public function getName(): string { return $this->getAttributeValue('name'); } public function getVersion(): string { return $this->getAttributeValue('version'); } } PKHZpnnxml/ManifestElement.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use DOMElement; use DOMNodeList; use function sprintf; class ManifestElement { public const XMLNS = 'https://phar.io/xml/manifest/1.0'; /** @var DOMElement */ private $element; public function __construct(DOMElement $element) { $this->element = $element; } protected function getAttributeValue(string $name): string { if (!$this->element->hasAttribute($name)) { throw new ManifestElementException( sprintf( 'Attribute %s not set on element %s', $name, $this->element->localName ) ); } return $this->element->getAttribute($name); } protected function hasAttribute(string $name): bool { return $this->element->hasAttribute($name); } protected function getChildByName(string $elementName): DOMElement { $element = $this->element->getElementsByTagNameNS(self::XMLNS, $elementName)->item(0); if (!$element instanceof DOMElement) { throw new ManifestElementException( sprintf('Element %s missing', $elementName) ); } return $element; } protected function getChildrenByName(string $elementName): DOMNodeList { $elementList = $this->element->getElementsByTagNameNS(self::XMLNS, $elementName); if ($elementList->length === 0) { throw new ManifestElementException( sprintf('Element(s) %s missing', $elementName) ); } return $elementList; } protected function hasChild(string $elementName): bool { return $this->element->getElementsByTagNameNS(self::XMLNS, $elementName)->length !== 0; } } PKHZ9S xml/ManifestDocument.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use DOMDocument; use DOMElement; use Throwable; use function count; use function file_get_contents; use function is_file; use function libxml_clear_errors; use function libxml_get_errors; use function libxml_use_internal_errors; use function sprintf; class ManifestDocument { public const XMLNS = 'https://phar.io/xml/manifest/1.0'; /** @var DOMDocument */ private $dom; public static function fromFile(string $filename): ManifestDocument { if (!is_file($filename)) { throw new ManifestDocumentException( sprintf('File "%s" not found', $filename) ); } return self::fromString( file_get_contents($filename) ); } public static function fromString(string $xmlString): ManifestDocument { $prev = libxml_use_internal_errors(true); libxml_clear_errors(); try { $dom = new DOMDocument(); $dom->loadXML($xmlString); $errors = libxml_get_errors(); libxml_use_internal_errors($prev); } catch (Throwable $t) { throw new ManifestDocumentException($t->getMessage(), 0, $t); } if (count($errors) !== 0) { throw new ManifestDocumentLoadingException($errors); } return new self($dom); } private function __construct(DOMDocument $dom) { $this->ensureCorrectDocumentType($dom); $this->dom = $dom; } public function getContainsElement(): ContainsElement { return new ContainsElement( $this->fetchElementByName('contains') ); } public function getCopyrightElement(): CopyrightElement { return new CopyrightElement( $this->fetchElementByName('copyright') ); } public function getRequiresElement(): RequiresElement { return new RequiresElement( $this->fetchElementByName('requires') ); } public function hasBundlesElement(): bool { return $this->dom->getElementsByTagNameNS(self::XMLNS, 'bundles')->length === 1; } public function getBundlesElement(): BundlesElement { return new BundlesElement( $this->fetchElementByName('bundles') ); } private function ensureCorrectDocumentType(DOMDocument $dom): void { $root = $dom->documentElement; if ($root->localName !== 'phar' || $root->namespaceURI !== self::XMLNS) { throw new ManifestDocumentException('Not a phar.io manifest document'); } } private function fetchElementByName(string $elementName): DOMElement { $element = $this->dom->getElementsByTagNameNS(self::XMLNS, $elementName)->item(0); if (!$element instanceof DOMElement) { throw new ManifestDocumentException( sprintf('Element %s missing', $elementName) ); } return $element; } } PKHZzjxml/ExtensionElement.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class ExtensionElement extends ManifestElement { public function getFor(): string { return $this->getAttributeValue('for'); } public function getCompatible(): string { return $this->getAttributeValue('compatible'); } } PKHZwOxml/PhpElement.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class PhpElement extends ManifestElement { public function getVersion(): string { return $this->getAttributeValue('version'); } public function hasExtElements(): bool { return $this->hasChild('ext'); } public function getExtElements(): ExtElementCollection { return new ExtElementCollection( $this->getChildrenByName('ext') ); } } PKHZ2xml/AuthorElement.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class AuthorElement extends ManifestElement { public function getName(): string { return $this->getAttributeValue('name'); } public function getEmail(): string { return $this->getAttributeValue('email'); } public function hasEMail(): bool { return $this->hasAttribute('email'); } } PKHZt)T  xml/CopyrightElement.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class CopyrightElement extends ManifestElement { public function getAuthorElements(): AuthorElementCollection { return new AuthorElementCollection( $this->getChildrenByName('author') ); } public function getLicenseElement(): LicenseElement { return new LicenseElement( $this->getChildByName('license') ); } } PKHZ6 \\"xml/ComponentElementCollection.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class ComponentElementCollection extends ElementCollection { public function current(): ComponentElement { return new ComponentElement( $this->getCurrentElement() ); } } PKHZq̠ManifestLoader.phpnuW+A, Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use function sprintf; class ManifestLoader { public static function fromFile(string $filename): Manifest { try { return (new ManifestDocumentMapper())->map( ManifestDocument::fromFile($filename) ); } catch (Exception $e) { throw new ManifestLoaderException( sprintf('Loading %s failed.', $filename), (int)$e->getCode(), $e ); } } public static function fromPhar(string $filename): Manifest { return self::fromFile('phar://' . $filename . '/manifest.xml'); } public static function fromString(string $manifest): Manifest { try { return (new ManifestDocumentMapper())->map( ManifestDocument::fromString($manifest) ); } catch (Exception $e) { throw new ManifestLoaderException( 'Processing string failed', (int)$e->getCode(), $e ); } } } PKZe 'SimplePie\Cache\MySQL', 'memcache' => 'SimplePie\Cache\Memcache', 'memcached' => 'SimplePie\Cache\Memcached', 'redis' => 'SimplePie\Cache\Redis' ]; /** * Don't call the constructor. Please. */ private function __construct() { } /** * Create a new SimplePie\Cache object * * @param string $location URL location (scheme is used to determine handler) * @param string $filename Unique identifier for cache object * @param Base::TYPE_FEED|Base::TYPE_IMAGE $extension 'spi' or 'spc' * @return Base Type of object depends on scheme of `$location` */ public static function get_handler($location, $filename, $extension) { $type = explode(':', $location, 2); $type = $type[0]; if (!empty(self::$handlers[$type])) { $class = self::$handlers[$type]; return new $class($location, $filename, $extension); } return new \SimplePie\Cache\File($location, $filename, $extension); } /** * Create a new SimplePie\Cache object * * @deprecated since SimplePie 1.3.1, use {@see get_handler()} instead */ public function create($location, $filename, $extension) { trigger_error('Cache::create() has been replaced with Cache::get_handler() since SimplePie 1.3.1, use the registry system instead.', \E_USER_DEPRECATED); return self::get_handler($location, $filename, $extension); } /** * Register a handler * * @param string $type DSN type to register for * @param class-string $class Name of handler class. Must implement Base */ public static function register($type, $class) { self::$handlers[$type] = $class; } /** * Parse a URL into an array * * @param string $url * @return array */ public static function parse_URL($url) { $params = parse_url($url); $params['extras'] = []; if (isset($params['query'])) { parse_str($params['query'], $params['extras']); } return $params; } } class_alias('SimplePie\Cache', 'SimplePie_Cache'); PKZMCore.phpnuW+Adata = $data; $this->data_length = strlen($this->data); } /** * Parse the input data * * @access public * @return bool true on success, false on failure */ public function parse() { while ($this->state && $this->state !== self::STATE_EMIT && $this->has_data()) { $state = $this->state; $this->$state(); } $this->data = ''; if ($this->state === self::STATE_EMIT) { return true; } $this->version = ''; $this->encoding = ''; $this->standalone = ''; return false; } /** * Check whether there is data beyond the pointer * * @access private * @return bool true if there is further data, false if not */ public function has_data() { return (bool) ($this->position < $this->data_length); } /** * Advance past any whitespace * * @return int Number of whitespace characters passed */ public function skip_whitespace() { $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position); $this->position += $whitespace; return $whitespace; } /** * Read value */ public function get_value() { $quote = substr($this->data, $this->position, 1); if ($quote === '"' || $quote === "'") { $this->position++; $len = strcspn($this->data, $quote, $this->position); if ($this->has_data()) { $value = substr($this->data, $this->position, $len); $this->position += $len + 1; return $value; } } return false; } public function before_version_name() { if ($this->skip_whitespace()) { $this->state = self::STATE_VERSION_NAME; } else { $this->state = self::STATE_ERROR; } } public function version_name() { if (substr($this->data, $this->position, 7) === 'version') { $this->position += 7; $this->skip_whitespace(); $this->state = self::STATE_VERSION_EQUALS; } else { $this->state = self::STATE_ERROR; } } public function version_equals() { if (substr($this->data, $this->position, 1) === '=') { $this->position++; $this->skip_whitespace(); $this->state = self::STATE_VERSION_VALUE; } else { $this->state = self::STATE_ERROR; } } public function version_value() { if ($this->version = $this->get_value()) { $this->skip_whitespace(); if ($this->has_data()) { $this->state = self::STATE_ENCODING_NAME; } else { $this->state = self::STATE_EMIT; } } else { $this->state = self::STATE_ERROR; } } public function encoding_name() { if (substr($this->data, $this->position, 8) === 'encoding') { $this->position += 8; $this->skip_whitespace(); $this->state = self::STATE_ENCODING_EQUALS; } else { $this->state = self::STATE_STANDALONE_NAME; } } public function encoding_equals() { if (substr($this->data, $this->position, 1) === '=') { $this->position++; $this->skip_whitespace(); $this->state = self::STATE_ENCODING_VALUE; } else { $this->state = self::STATE_ERROR; } } public function encoding_value() { if ($this->encoding = $this->get_value()) { $this->skip_whitespace(); if ($this->has_data()) { $this->state = self::STATE_STANDALONE_NAME; } else { $this->state = self::STATE_EMIT; } } else { $this->state = self::STATE_ERROR; } } public function standalone_name() { if (substr($this->data, $this->position, 10) === 'standalone') { $this->position += 10; $this->skip_whitespace(); $this->state = self::STATE_STANDALONE_EQUALS; } else { $this->state = self::STATE_ERROR; } } public function standalone_equals() { if (substr($this->data, $this->position, 1) === '=') { $this->position++; $this->skip_whitespace(); $this->state = self::STATE_STANDALONE_VALUE; } else { $this->state = self::STATE_ERROR; } } public function standalone_value() { if ($standalone = $this->get_value()) { switch ($standalone) { case 'yes': $this->standalone = true; break; case 'no': $this->standalone = false; break; default: $this->state = self::STATE_ERROR; return; } $this->skip_whitespace(); if ($this->has_data()) { $this->state = self::STATE_ERROR; } else { $this->state = self::STATE_EMIT; } } else { $this->state = self::STATE_ERROR; } } } class_alias('SimplePie\XML\Declaration\Parser', 'SimplePie_XML_Declaration_Parser'); PKZUʎRestriction.phpnuW+A` as defined in Media RSS * * Used by {@see \SimplePie\Enclosure::get_restriction()} and {@see \SimplePie\Enclosure::get_restrictions()} * * This class can be overloaded with {@see \SimplePie\SimplePie::set_restriction_class()} * * @package SimplePie * @subpackage API */ class Restriction { /** * Relationship ('allow'/'deny') * * @var string * @see get_relationship() */ public $relationship; /** * Type of restriction * * @var string * @see get_type() */ public $type; /** * Restricted values * * @var string * @see get_value() */ public $value; /** * Constructor, used to input the data * * For documentation on all the parameters, see the corresponding * properties and their accessors */ public function __construct($relationship = null, $type = null, $value = null) { $this->relationship = $relationship; $this->type = $type; $this->value = $value; } /** * String-ified version * * @return string */ public function __toString() { // There is no $this->data here return md5(serialize($this)); } /** * Get the relationship * * @return string|null Either 'allow' or 'deny' */ public function get_relationship() { if ($this->relationship !== null) { return $this->relationship; } return null; } /** * Get the type * * @return string|null */ public function get_type() { if ($this->type !== null) { return $this->type; } return null; } /** * Get the list of restricted things * * @return string|null */ public function get_value() { if ($this->value !== null) { return $this->value; } return null; } } class_alias('SimplePie\Restriction', 'SimplePie_Restriction'); PKZzzItem.phpnuW+Afeed = $feed; $this->data = $data; } /** * Set the registry handler * * This is usually used by {@see \SimplePie\Registry::create} * * @since 1.3 * @param \SimplePie\Registry $registry */ public function set_registry(\SimplePie\Registry $registry)/* : void */ { $this->registry = $registry; } /** * Get a string representation of the item * * @return string */ public function __toString() { return md5(serialize($this->data)); } /** * Remove items that link back to this before destroying this object */ public function __destruct() { if (!gc_enabled()) { unset($this->feed); } } /** * Get data for an item-level element * * This method allows you to get access to ANY element/attribute that is a * sub-element of the item/entry tag. * * See {@see \SimplePie\SimplePie::get_feed_tags()} for a description of the return value * * @since 1.0 * @see http://simplepie.org/wiki/faq/supported_xml_namespaces * @param string $namespace The URL of the XML namespace of the elements you're trying to access * @param string $tag Tag name * @return array */ public function get_item_tags($namespace, $tag) { if (isset($this->data['child'][$namespace][$tag])) { return $this->data['child'][$namespace][$tag]; } return null; } /** * Get the base URL value. * Uses ``, or item link, or feed base URL. * * @param array $element * @return string */ public function get_base($element = []) { if (!empty($element['xml_base_explicit']) && isset($element['xml_base'])) { return $element['xml_base']; } $link = $this->get_permalink(); if ($link != null) { return $link; } return $this->feed->get_base($element); } /** * Sanitize feed data * * @access private * @see \SimplePie\SimplePie::sanitize() * @param string $data Data to sanitize * @param int $type One of the \SimplePie\SimplePie::CONSTRUCT_* constants * @param string $base Base URL to resolve URLs against * @return string Sanitized data */ public function sanitize($data, $type, $base = '') { return $this->feed->sanitize($data, $type, $base); } /** * Get the parent feed * * Note: this may not work as you think for multifeeds! * * @link http://simplepie.org/faq/typical_multifeed_gotchas#missing_data_from_feed * @since 1.0 * @return \SimplePie\SimplePie */ public function get_feed() { return $this->feed; } /** * Get the unique identifier for the item * * This is usually used when writing code to check for new items in a feed. * * Uses ``, ``, `` or the `about` attribute * for RDF. If none of these are supplied (or `$hash` is true), creates an * MD5 hash based on the permalink, title and content. * * @since Beta 2 * @param boolean $hash Should we force using a hash instead of the supplied ID? * @param string|false $fn User-supplied function to generate an hash * @return string|null */ public function get_id($hash = false, $fn = 'md5') { if (!$hash) { if ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'id')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'id')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'guid')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, 'identifier')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, 'identifier')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } elseif (isset($this->data['attribs'][\SimplePie\SimplePie::NAMESPACE_RDF]['about'])) { return $this->sanitize($this->data['attribs'][\SimplePie\SimplePie::NAMESPACE_RDF]['about'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } } if ($fn === false) { return null; } elseif (!is_callable($fn)) { trigger_error('User-supplied function $fn must be callable', E_USER_WARNING); $fn = 'md5'; } return call_user_func( $fn, $this->get_permalink().$this->get_title().$this->get_content() ); } /** * Get the title of the item * * Uses ``, `` or `<dc:title>` * * @since Beta 2 (previously called `get_item_title` since 0.8) * @return string|null */ public function get_title() { if (!isset($this->data['title'])) { if ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'title')) { $this->data['title'] = $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_10_construct_type', [$return[0]['attribs']]), $this->get_base($return[0])); } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'title')) { $this->data['title'] = $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_03_construct_type', [$return[0]['attribs']]), $this->get_base($return[0])); } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_10, 'title')) { $this->data['title'] = $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_090, 'title')) { $this->data['title'] = $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'title')) { $this->data['title'] = $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, 'title')) { $this->data['title'] = $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, 'title')) { $this->data['title'] = $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $this->data['title'] = null; } } return $this->data['title']; } /** * Get the content for the item * * Prefers summaries over full content , but will return full content if a * summary does not exist. * * To prefer full content instead, use {@see get_content} * * Uses `<atom:summary>`, `<description>`, `<dc:description>` or * `<itunes:subtitle>` * * @since 0.8 * @param boolean $description_only Should we avoid falling back to the content? * @return string|null */ public function get_description($description_only = false) { if (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'summary')) && ($return = $this->sanitize($tags[0]['data'], $this->registry->call(Misc::class, 'atom_10_construct_type', [$tags[0]['attribs']]), $this->get_base($tags[0])))) { return $return; } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'summary')) && ($return = $this->sanitize($tags[0]['data'], $this->registry->call(Misc::class, 'atom_03_construct_type', [$tags[0]['attribs']]), $this->get_base($tags[0])))) { return $return; } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_10, 'description')) && ($return = $this->sanitize($tags[0]['data'], \SimplePie\SimplePie::CONSTRUCT_MAYBE_HTML, $this->get_base($tags[0])))) { return $return; } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'description')) && ($return = $this->sanitize($tags[0]['data'], \SimplePie\SimplePie::CONSTRUCT_HTML, $this->get_base($tags[0])))) { return $return; } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, 'description')) && ($return = $this->sanitize($tags[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT))) { return $return; } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, 'description')) && ($return = $this->sanitize($tags[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT))) { return $return; } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'summary')) && ($return = $this->sanitize($tags[0]['data'], \SimplePie\SimplePie::CONSTRUCT_HTML, $this->get_base($tags[0])))) { return $return; } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'subtitle')) && ($return = $this->sanitize($tags[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT))) { return $return; } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_090, 'description')) && ($return = $this->sanitize($tags[0]['data'], \SimplePie\SimplePie::CONSTRUCT_HTML))) { return $return; } elseif (!$description_only) { return $this->get_content(true); } return null; } /** * Get the content for the item * * Prefers full content over summaries, but will return a summary if full * content does not exist. * * To prefer summaries instead, use {@see get_description} * * Uses `<atom:content>` or `<content:encoded>` (RSS 1.0 Content Module) * * @since 1.0 * @param boolean $content_only Should we avoid falling back to the description? * @return string|null */ public function get_content($content_only = false) { if (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'content')) && ($return = $this->sanitize($tags[0]['data'], $this->registry->call(Misc::class, 'atom_10_content_construct_type', [$tags[0]['attribs']]), $this->get_base($tags[0])))) { return $return; } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'content')) && ($return = $this->sanitize($tags[0]['data'], $this->registry->call(Misc::class, 'atom_03_construct_type', [$tags[0]['attribs']]), $this->get_base($tags[0])))) { return $return; } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded')) && ($return = $this->sanitize($tags[0]['data'], \SimplePie\SimplePie::CONSTRUCT_HTML, $this->get_base($tags[0])))) { return $return; } elseif (!$content_only) { return $this->get_description(true); } return null; } /** * Get the media:thumbnail of the item * * Uses `<media:thumbnail>` * * * @return array|null */ public function get_thumbnail() { if (!isset($this->data['thumbnail'])) { if ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'thumbnail')) { $thumbnail = $return[0]['attribs']['']; if (empty($thumbnail['url'])) { $this->data['thumbnail'] = null; } else { $thumbnail['url'] = $this->sanitize($thumbnail['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($return[0])); $this->data['thumbnail'] = $thumbnail; } } else { $this->data['thumbnail'] = null; } } return $this->data['thumbnail']; } /** * Get a category for the item * * @since Beta 3 (previously called `get_categories()` since Beta 2) * @param int $key The category that you want to return. Remember that arrays begin with 0, not 1 * @return \SimplePie\Category|null */ public function get_category($key = 0) { $categories = $this->get_categories(); if (isset($categories[$key])) { return $categories[$key]; } return null; } /** * Get all categories for the item * * Uses `<atom:category>`, `<category>` or `<dc:subject>` * * @since Beta 3 * @return \SimplePie\Category[]|null List of {@see \SimplePie\Category} objects */ public function get_categories() { $categories = []; $type = 'category'; foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, $type) as $category) { $term = null; $scheme = null; $label = null; if (isset($category['attribs']['']['term'])) { $term = $this->sanitize($category['attribs']['']['term'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($category['attribs']['']['scheme'])) { $scheme = $this->sanitize($category['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($category['attribs']['']['label'])) { $label = $this->sanitize($category['attribs']['']['label'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $categories[] = $this->registry->create(Category::class, [$term, $scheme, $label, $type]); } foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, $type) as $category) { // This is really the label, but keep this as the term also for BC. // Label will also work on retrieving because that falls back to term. $term = $this->sanitize($category['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); if (isset($category['attribs']['']['domain'])) { $scheme = $this->sanitize($category['attribs']['']['domain'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $scheme = null; } $categories[] = $this->registry->create(Category::class, [$term, $scheme, null, $type]); } $type = 'subject'; foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, $type) as $category) { $categories[] = $this->registry->create(Category::class, [$this->sanitize($category['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT), null, null, $type]); } foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, $type) as $category) { $categories[] = $this->registry->create(Category::class, [$this->sanitize($category['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT), null, null, $type]); } if (!empty($categories)) { return array_unique($categories); } return null; } /** * Get an author for the item * * @since Beta 2 * @param int $key The author that you want to return. Remember that arrays begin with 0, not 1 * @return \SimplePie\Author|null */ public function get_author($key = 0) { $authors = $this->get_authors(); if (isset($authors[$key])) { return $authors[$key]; } return null; } /** * Get a contributor for the item * * @since 1.1 * @param int $key The contrbutor that you want to return. Remember that arrays begin with 0, not 1 * @return \SimplePie\Author|null */ public function get_contributor($key = 0) { $contributors = $this->get_contributors(); if (isset($contributors[$key])) { return $contributors[$key]; } return null; } /** * Get all contributors for the item * * Uses `<atom:contributor>` * * @since 1.1 * @return \SimplePie\Author[]|null List of {@see \SimplePie\Author} objects */ public function get_contributors() { $contributors = []; foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'contributor') as $contributor) { $name = null; $uri = null; $email = null; if (isset($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['name'][0]['data'])) { $name = $this->sanitize($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['name'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['uri'][0]['data'])) { $uri = $this->sanitize($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['uri'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['uri'][0])); } if (isset($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['email'][0]['data'])) { $email = $this->sanitize($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['email'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if ($name !== null || $email !== null || $uri !== null) { $contributors[] = $this->registry->create(Author::class, [$name, $uri, $email]); } } foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'contributor') as $contributor) { $name = null; $url = null; $email = null; if (isset($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['name'][0]['data'])) { $name = $this->sanitize($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['name'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['url'][0]['data'])) { $url = $this->sanitize($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['url'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['url'][0])); } if (isset($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['email'][0]['data'])) { $email = $this->sanitize($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['email'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if ($name !== null || $email !== null || $url !== null) { $contributors[] = $this->registry->create(Author::class, [$name, $url, $email]); } } if (!empty($contributors)) { return array_unique($contributors); } return null; } /** * Get all authors for the item * * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>` * * @since Beta 2 * @return \SimplePie\Author[]|null List of {@see \SimplePie\Author} objects */ public function get_authors() { $authors = []; foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'author') as $author) { $name = null; $uri = null; $email = null; if (isset($author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['name'][0]['data'])) { $name = $this->sanitize($author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['name'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['uri'][0]['data'])) { $uri = $this->sanitize($author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['uri'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['uri'][0])); } if (isset($author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['email'][0]['data'])) { $email = $this->sanitize($author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['email'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if ($name !== null || $email !== null || $uri !== null) { $authors[] = $this->registry->create(Author::class, [$name, $uri, $email]); } } if ($author = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'author')) { $name = null; $url = null; $email = null; if (isset($author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['name'][0]['data'])) { $name = $this->sanitize($author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['name'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['url'][0]['data'])) { $url = $this->sanitize($author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['url'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['url'][0])); } if (isset($author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['email'][0]['data'])) { $email = $this->sanitize($author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['email'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if ($name !== null || $email !== null || $url !== null) { $authors[] = $this->registry->create(Author::class, [$name, $url, $email]); } } if ($author = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'author')) { $authors[] = $this->registry->create(Author::class, [null, null, $this->sanitize($author[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT)]); } foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, 'creator') as $author) { $authors[] = $this->registry->create(Author::class, [$this->sanitize($author['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT), null, null]); } foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, 'creator') as $author) { $authors[] = $this->registry->create(Author::class, [$this->sanitize($author['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT), null, null]); } foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'author') as $author) { $authors[] = $this->registry->create(Author::class, [$this->sanitize($author['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT), null, null]); } if (!empty($authors)) { return array_unique($authors); } elseif (($source = $this->get_source()) && ($authors = $source->get_authors())) { return $authors; } elseif ($authors = $this->feed->get_authors()) { return $authors; } return null; } /** * Get the copyright info for the item * * Uses `<atom:rights>` or `<dc:rights>` * * @since 1.1 * @return string */ public function get_copyright() { if ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'rights')) { return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_10_construct_type', [$return[0]['attribs']]), $this->get_base($return[0])); } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, 'rights')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, 'rights')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } return null; } /** * Get the posting date/time for the item * * Uses `<atom:published>`, `<atom:updated>`, `<atom:issued>`, * `<atom:modified>`, `<pubDate>` or `<dc:date>` * * Note: obeys PHP's timezone setting. To get a UTC date/time, use * {@see get_gmdate} * * @since Beta 2 (previously called `get_item_date` since 0.8) * * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data) * @return int|string|null */ public function get_date($date_format = 'j F Y, g:i a') { if (!isset($this->data['date'])) { if ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'published')) { $this->data['date']['raw'] = $return[0]['data']; } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'pubDate')) { $this->data['date']['raw'] = $return[0]['data']; } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, 'date')) { $this->data['date']['raw'] = $return[0]['data']; } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, 'date')) { $this->data['date']['raw'] = $return[0]['data']; } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'updated')) { $this->data['date']['raw'] = $return[0]['data']; } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'issued')) { $this->data['date']['raw'] = $return[0]['data']; } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'created')) { $this->data['date']['raw'] = $return[0]['data']; } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'modified')) { $this->data['date']['raw'] = $return[0]['data']; } if (!empty($this->data['date']['raw'])) { $parser = $this->registry->call(Parse\Date::class, 'get'); $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']) ?: null; } else { $this->data['date'] = null; } } if ($this->data['date']) { $date_format = (string) $date_format; switch ($date_format) { case '': return $this->sanitize($this->data['date']['raw'], \SimplePie\SimplePie::CONSTRUCT_TEXT); case 'U': return $this->data['date']['parsed']; default: return date($date_format, $this->data['date']['parsed']); } } return null; } /** * Get the update date/time for the item * * Uses `<atom:updated>` * * Note: obeys PHP's timezone setting. To get a UTC date/time, use * {@see get_gmdate} * * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data) * @return int|string|null */ public function get_updated_date($date_format = 'j F Y, g:i a') { if (!isset($this->data['updated'])) { if ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'updated')) { $this->data['updated']['raw'] = $return[0]['data']; } if (!empty($this->data['updated']['raw'])) { $parser = $this->registry->call(Parse\Date::class, 'get'); $this->data['updated']['parsed'] = $parser->parse($this->data['updated']['raw']) ?: null; } else { $this->data['updated'] = null; } } if ($this->data['updated']) { $date_format = (string) $date_format; switch ($date_format) { case '': return $this->sanitize($this->data['updated']['raw'], \SimplePie\SimplePie::CONSTRUCT_TEXT); case 'U': return $this->data['updated']['parsed']; default: return date($date_format, $this->data['updated']['parsed']); } } return null; } /** * Get the localized posting date/time for the item * * Returns the date formatted in the localized language. To display in * languages other than the server's default, you need to change the locale * with {@link http://php.net/setlocale setlocale()}. The available * localizations depend on which ones are installed on your web server. * * @since 1.0 * * @param string $date_format Supports any PHP date format from {@see http://php.net/strftime} (empty for the raw data) * @return int|string|null */ public function get_local_date($date_format = '%c') { if (!$date_format) { return $this->sanitize($this->get_date(''), \SimplePie\SimplePie::CONSTRUCT_TEXT); } elseif (($date = $this->get_date('U')) !== null && $date !== false) { return strftime($date_format, $date); } return null; } /** * Get the posting date/time for the item (UTC time) * * @see get_date * @param string $date_format Supports any PHP date format from {@see http://php.net/date} * @return int|string|null */ public function get_gmdate($date_format = 'j F Y, g:i a') { $date = $this->get_date('U'); if ($date === null) { return null; } return gmdate($date_format, $date); } /** * Get the update date/time for the item (UTC time) * * @see get_updated_date * @param string $date_format Supports any PHP date format from {@see http://php.net/date} * @return int|string|null */ public function get_updated_gmdate($date_format = 'j F Y, g:i a') { $date = $this->get_updated_date('U'); if ($date === null) { return null; } return gmdate($date_format, $date); } /** * Get the permalink for the item * * Returns the first link available with a relationship of "alternate". * Identical to {@see get_link()} with key 0 * * @see get_link * @since 0.8 * @return string|null Permalink URL */ public function get_permalink() { $link = $this->get_link(); $enclosure = $this->get_enclosure(0); if ($link !== null) { return $link; } elseif ($enclosure !== null) { return $enclosure->get_link(); } return null; } /** * Get a single link for the item * * @since Beta 3 * @param int $key The link that you want to return. Remember that arrays begin with 0, not 1 * @param string $rel The relationship of the link to return * @return string|null Link URL */ public function get_link($key = 0, $rel = 'alternate') { $links = $this->get_links($rel); if ($links && $links[$key] !== null) { return $links[$key]; } return null; } /** * Get all links for the item * * Uses `<atom:link>`, `<link>` or `<guid>` * * @since Beta 2 * @param string $rel The relationship of links to return * @return array|null Links found for the item (strings) */ public function get_links($rel = 'alternate') { if (!isset($this->data['links'])) { $this->data['links'] = []; foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'link') as $link) { if (isset($link['attribs']['']['href'])) { $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($link)); } } foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'link') as $link) { if (isset($link['attribs']['']['href'])) { $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($link)); } } if ($links = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_10, 'link')) { $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($links[0])); } if ($links = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_090, 'link')) { $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($links[0])); } if ($links = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'link')) { $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($links[0])); } if ($links = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'guid')) { if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true') { $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($links[0])); } } $keys = array_keys($this->data['links']); foreach ($keys as $key) { if ($this->registry->call(Misc::class, 'is_isegment_nz_nc', [$key])) { if (isset($this->data['links'][\SimplePie\SimplePie::IANA_LINK_RELATIONS_REGISTRY . $key])) { $this->data['links'][\SimplePie\SimplePie::IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][\SimplePie\SimplePie::IANA_LINK_RELATIONS_REGISTRY . $key]); $this->data['links'][$key] = &$this->data['links'][\SimplePie\SimplePie::IANA_LINK_RELATIONS_REGISTRY . $key]; } else { $this->data['links'][\SimplePie\SimplePie::IANA_LINK_RELATIONS_REGISTRY . $key] = &$this->data['links'][$key]; } } elseif (substr($key, 0, 41) === \SimplePie\SimplePie::IANA_LINK_RELATIONS_REGISTRY) { $this->data['links'][substr($key, 41)] = &$this->data['links'][$key]; } $this->data['links'][$key] = array_unique($this->data['links'][$key]); } } if (isset($this->data['links'][$rel])) { return $this->data['links'][$rel]; } return null; } /** * Get an enclosure from the item * * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS. * * @since Beta 2 * @todo Add ability to prefer one type of content over another (in a media group). * @param int $key The enclosure that you want to return. Remember that arrays begin with 0, not 1 * @return \SimplePie\Enclosure|null */ public function get_enclosure($key = 0, $prefer = null) { $enclosures = $this->get_enclosures(); if (isset($enclosures[$key])) { return $enclosures[$key]; } return null; } /** * Get all available enclosures (podcasts, etc.) * * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS. * * At this point, we're pretty much assuming that all enclosures for an item * are the same content. Anything else is too complicated to * properly support. * * @since Beta 2 * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4). * @todo If an element exists at a level, but its value is empty, we should fall back to the value from the parent (if it exists). * @return \SimplePie\Enclosure[]|null List of \SimplePie\Enclosure items */ public function get_enclosures() { if (!isset($this->data['enclosures'])) { $this->data['enclosures'] = []; // Elements $captions_parent = null; $categories_parent = null; $copyrights_parent = null; $credits_parent = null; $description_parent = null; $duration_parent = null; $hashes_parent = null; $keywords_parent = null; $player_parent = null; $ratings_parent = null; $restrictions_parent = null; $thumbnails_parent = null; $title_parent = null; // Let's do the channel and item-level ones first, and just re-use them if we need to. $parent = $this->get_feed(); // CAPTIONS if ($captions = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'text')) { foreach ($captions as $caption) { $caption_type = null; $caption_lang = null; $caption_startTime = null; $caption_endTime = null; $caption_text = null; if (isset($caption['attribs']['']['type'])) { $caption_type = $this->sanitize($caption['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['attribs']['']['lang'])) { $caption_lang = $this->sanitize($caption['attribs']['']['lang'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['attribs']['']['start'])) { $caption_startTime = $this->sanitize($caption['attribs']['']['start'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['attribs']['']['end'])) { $caption_endTime = $this->sanitize($caption['attribs']['']['end'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['data'])) { $caption_text = $this->sanitize($caption['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $captions_parent[] = $this->registry->create(Caption::class, [$caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text]); } } elseif ($captions = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'text')) { foreach ($captions as $caption) { $caption_type = null; $caption_lang = null; $caption_startTime = null; $caption_endTime = null; $caption_text = null; if (isset($caption['attribs']['']['type'])) { $caption_type = $this->sanitize($caption['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['attribs']['']['lang'])) { $caption_lang = $this->sanitize($caption['attribs']['']['lang'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['attribs']['']['start'])) { $caption_startTime = $this->sanitize($caption['attribs']['']['start'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['attribs']['']['end'])) { $caption_endTime = $this->sanitize($caption['attribs']['']['end'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['data'])) { $caption_text = $this->sanitize($caption['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $captions_parent[] = $this->registry->create(Caption::class, [$caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text]); } } if (is_array($captions_parent)) { $captions_parent = array_values(array_unique($captions_parent)); } // CATEGORIES foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'category') as $category) { $term = null; $scheme = null; $label = null; if (isset($category['data'])) { $term = $this->sanitize($category['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($category['attribs']['']['scheme'])) { $scheme = $this->sanitize($category['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $scheme = 'http://search.yahoo.com/mrss/category_schema'; } if (isset($category['attribs']['']['label'])) { $label = $this->sanitize($category['attribs']['']['label'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $categories_parent[] = $this->registry->create(Category::class, [$term, $scheme, $label]); } foreach ((array) $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'category') as $category) { $term = null; $scheme = null; $label = null; if (isset($category['data'])) { $term = $this->sanitize($category['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($category['attribs']['']['scheme'])) { $scheme = $this->sanitize($category['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $scheme = 'http://search.yahoo.com/mrss/category_schema'; } if (isset($category['attribs']['']['label'])) { $label = $this->sanitize($category['attribs']['']['label'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $categories_parent[] = $this->registry->create(Category::class, [$term, $scheme, $label]); } foreach ((array) $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'category') as $category) { $term = null; $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd'; $label = null; if (isset($category['attribs']['']['text'])) { $label = $this->sanitize($category['attribs']['']['text'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $categories_parent[] = $this->registry->create(Category::class, [$term, $scheme, $label]); if (isset($category['child'][\SimplePie\SimplePie::NAMESPACE_ITUNES]['category'])) { foreach ((array) $category['child'][\SimplePie\SimplePie::NAMESPACE_ITUNES]['category'] as $subcategory) { if (isset($subcategory['attribs']['']['text'])) { $label = $this->sanitize($subcategory['attribs']['']['text'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $categories_parent[] = $this->registry->create(Category::class, [$term, $scheme, $label]); } } } if (is_array($categories_parent)) { $categories_parent = array_values(array_unique($categories_parent)); } // COPYRIGHT if ($copyright = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'copyright')) { $copyright_url = null; $copyright_label = null; if (isset($copyright[0]['attribs']['']['url'])) { $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($copyright[0]['data'])) { $copyright_label = $this->sanitize($copyright[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $copyrights_parent = $this->registry->create(Copyright::class, [$copyright_url, $copyright_label]); } elseif ($copyright = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'copyright')) { $copyright_url = null; $copyright_label = null; if (isset($copyright[0]['attribs']['']['url'])) { $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($copyright[0]['data'])) { $copyright_label = $this->sanitize($copyright[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $copyrights_parent = $this->registry->create(Copyright::class, [$copyright_url, $copyright_label]); } // CREDITS if ($credits = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'credit')) { foreach ($credits as $credit) { $credit_role = null; $credit_scheme = null; $credit_name = null; if (isset($credit['attribs']['']['role'])) { $credit_role = $this->sanitize($credit['attribs']['']['role'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($credit['attribs']['']['scheme'])) { $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $credit_scheme = 'urn:ebu'; } if (isset($credit['data'])) { $credit_name = $this->sanitize($credit['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $credits_parent[] = $this->registry->create(Credit::class, [$credit_role, $credit_scheme, $credit_name]); } } elseif ($credits = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'credit')) { foreach ($credits as $credit) { $credit_role = null; $credit_scheme = null; $credit_name = null; if (isset($credit['attribs']['']['role'])) { $credit_role = $this->sanitize($credit['attribs']['']['role'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($credit['attribs']['']['scheme'])) { $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $credit_scheme = 'urn:ebu'; } if (isset($credit['data'])) { $credit_name = $this->sanitize($credit['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $credits_parent[] = $this->registry->create(Credit::class, [$credit_role, $credit_scheme, $credit_name]); } } if (is_array($credits_parent)) { $credits_parent = array_values(array_unique($credits_parent)); } // DESCRIPTION if ($description_parent = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'description')) { if (isset($description_parent[0]['data'])) { $description_parent = $this->sanitize($description_parent[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } } elseif ($description_parent = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'description')) { if (isset($description_parent[0]['data'])) { $description_parent = $this->sanitize($description_parent[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } } // DURATION if ($duration_parent = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'duration')) { $seconds = null; $minutes = null; $hours = null; if (isset($duration_parent[0]['data'])) { $temp = explode(':', $this->sanitize($duration_parent[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT)); if (sizeof($temp) > 0) { $seconds = (int) array_pop($temp); } if (sizeof($temp) > 0) { $minutes = (int) array_pop($temp); $seconds += $minutes * 60; } if (sizeof($temp) > 0) { $hours = (int) array_pop($temp); $seconds += $hours * 3600; } unset($temp); $duration_parent = $seconds; } } // HASHES if ($hashes_iterator = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'hash')) { foreach ($hashes_iterator as $hash) { $value = null; $algo = null; if (isset($hash['data'])) { $value = $this->sanitize($hash['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($hash['attribs']['']['algo'])) { $algo = $this->sanitize($hash['attribs']['']['algo'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $algo = 'md5'; } $hashes_parent[] = $algo.':'.$value; } } elseif ($hashes_iterator = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'hash')) { foreach ($hashes_iterator as $hash) { $value = null; $algo = null; if (isset($hash['data'])) { $value = $this->sanitize($hash['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($hash['attribs']['']['algo'])) { $algo = $this->sanitize($hash['attribs']['']['algo'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $algo = 'md5'; } $hashes_parent[] = $algo.':'.$value; } } if (is_array($hashes_parent)) { $hashes_parent = array_values(array_unique($hashes_parent)); } // KEYWORDS if ($keywords = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'keywords')) { if (isset($keywords[0]['data'])) { $temp = explode(',', $this->sanitize($keywords[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT)); foreach ($temp as $word) { $keywords_parent[] = trim($word); } } unset($temp); } elseif ($keywords = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'keywords')) { if (isset($keywords[0]['data'])) { $temp = explode(',', $this->sanitize($keywords[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT)); foreach ($temp as $word) { $keywords_parent[] = trim($word); } } unset($temp); } elseif ($keywords = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'keywords')) { if (isset($keywords[0]['data'])) { $temp = explode(',', $this->sanitize($keywords[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT)); foreach ($temp as $word) { $keywords_parent[] = trim($word); } } unset($temp); } elseif ($keywords = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'keywords')) { if (isset($keywords[0]['data'])) { $temp = explode(',', $this->sanitize($keywords[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT)); foreach ($temp as $word) { $keywords_parent[] = trim($word); } } unset($temp); } if (is_array($keywords_parent)) { $keywords_parent = array_values(array_unique($keywords_parent)); } // PLAYER if ($player_parent = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'player')) { if (isset($player_parent[0]['attribs']['']['url'])) { $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI); } } elseif ($player_parent = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'player')) { if (isset($player_parent[0]['attribs']['']['url'])) { $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI); } } // RATINGS if ($ratings = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'rating')) { foreach ($ratings as $rating) { $rating_scheme = null; $rating_value = null; if (isset($rating['attribs']['']['scheme'])) { $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $rating_scheme = 'urn:simple'; } if (isset($rating['data'])) { $rating_value = $this->sanitize($rating['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $ratings_parent[] = $this->registry->create(Rating::class, [$rating_scheme, $rating_value]); } } elseif ($ratings = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'explicit')) { foreach ($ratings as $rating) { $rating_scheme = 'urn:itunes'; $rating_value = null; if (isset($rating['data'])) { $rating_value = $this->sanitize($rating['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $ratings_parent[] = $this->registry->create(Rating::class, [$rating_scheme, $rating_value]); } } elseif ($ratings = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'rating')) { foreach ($ratings as $rating) { $rating_scheme = null; $rating_value = null; if (isset($rating['attribs']['']['scheme'])) { $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $rating_scheme = 'urn:simple'; } if (isset($rating['data'])) { $rating_value = $this->sanitize($rating['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $ratings_parent[] = $this->registry->create(Rating::class, [$rating_scheme, $rating_value]); } } elseif ($ratings = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'explicit')) { foreach ($ratings as $rating) { $rating_scheme = 'urn:itunes'; $rating_value = null; if (isset($rating['data'])) { $rating_value = $this->sanitize($rating['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $ratings_parent[] = $this->registry->create(Rating::class, [$rating_scheme, $rating_value]); } } if (is_array($ratings_parent)) { $ratings_parent = array_values(array_unique($ratings_parent)); } // RESTRICTIONS if ($restrictions = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'restriction')) { foreach ($restrictions as $restriction) { $restriction_relationship = null; $restriction_type = null; $restriction_value = null; if (isset($restriction['attribs']['']['relationship'])) { $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($restriction['attribs']['']['type'])) { $restriction_type = $this->sanitize($restriction['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($restriction['data'])) { $restriction_value = $this->sanitize($restriction['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $restrictions_parent[] = $this->registry->create(Restriction::class, [$restriction_relationship, $restriction_type, $restriction_value]); } } elseif ($restrictions = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'block')) { foreach ($restrictions as $restriction) { $restriction_relationship = 'allow'; $restriction_type = null; $restriction_value = 'itunes'; if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes') { $restriction_relationship = 'deny'; } $restrictions_parent[] = $this->registry->create(Restriction::class, [$restriction_relationship, $restriction_type, $restriction_value]); } } elseif ($restrictions = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'restriction')) { foreach ($restrictions as $restriction) { $restriction_relationship = null; $restriction_type = null; $restriction_value = null; if (isset($restriction['attribs']['']['relationship'])) { $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($restriction['attribs']['']['type'])) { $restriction_type = $this->sanitize($restriction['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($restriction['data'])) { $restriction_value = $this->sanitize($restriction['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $restrictions_parent[] = $this->registry->create(Restriction::class, [$restriction_relationship, $restriction_type, $restriction_value]); } } elseif ($restrictions = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'block')) { foreach ($restrictions as $restriction) { $restriction_relationship = 'allow'; $restriction_type = null; $restriction_value = 'itunes'; if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes') { $restriction_relationship = 'deny'; } $restrictions_parent[] = $this->registry->create(Restriction::class, [$restriction_relationship, $restriction_type, $restriction_value]); } } if (is_array($restrictions_parent)) { $restrictions_parent = array_values(array_unique($restrictions_parent)); } else { $restrictions_parent = [new \SimplePie\Restriction('allow', null, 'default')]; } // THUMBNAILS if ($thumbnails = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'thumbnail')) { foreach ($thumbnails as $thumbnail) { if (isset($thumbnail['attribs']['']['url'])) { $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI); } } } elseif ($thumbnails = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'thumbnail')) { foreach ($thumbnails as $thumbnail) { if (isset($thumbnail['attribs']['']['url'])) { $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI); } } } // TITLES if ($title_parent = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'title')) { if (isset($title_parent[0]['data'])) { $title_parent = $this->sanitize($title_parent[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } } elseif ($title_parent = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'title')) { if (isset($title_parent[0]['data'])) { $title_parent = $this->sanitize($title_parent[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } } // Clear the memory unset($parent); // Attributes $bitrate = null; $channels = null; $duration = null; $expression = null; $framerate = null; $height = null; $javascript = null; $lang = null; $length = null; $medium = null; $samplingrate = null; $type = null; $url = null; $width = null; // Elements $captions = null; $categories = null; $copyrights = null; $credits = null; $description = null; $hashes = null; $keywords = null; $player = null; $ratings = null; $restrictions = null; $thumbnails = null; $title = null; // If we have media:group tags, loop through them. foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'group') as $group) { if (isset($group['child']) && isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['content'])) { // If we have media:content tags, loop through them. foreach ((array) $group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['content'] as $content) { if (isset($content['attribs']['']['url'])) { // Attributes $bitrate = null; $channels = null; $duration = null; $expression = null; $framerate = null; $height = null; $javascript = null; $lang = null; $length = null; $medium = null; $samplingrate = null; $type = null; $url = null; $width = null; // Elements $captions = null; $categories = null; $copyrights = null; $credits = null; $description = null; $hashes = null; $keywords = null; $player = null; $ratings = null; $restrictions = null; $thumbnails = null; $title = null; // Start checking the attributes of media:content if (isset($content['attribs']['']['bitrate'])) { $bitrate = $this->sanitize($content['attribs']['']['bitrate'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['attribs']['']['channels'])) { $channels = $this->sanitize($content['attribs']['']['channels'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['attribs']['']['duration'])) { $duration = $this->sanitize($content['attribs']['']['duration'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $duration = $duration_parent; } if (isset($content['attribs']['']['expression'])) { $expression = $this->sanitize($content['attribs']['']['expression'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['attribs']['']['framerate'])) { $framerate = $this->sanitize($content['attribs']['']['framerate'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['attribs']['']['height'])) { $height = $this->sanitize($content['attribs']['']['height'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['attribs']['']['lang'])) { $lang = $this->sanitize($content['attribs']['']['lang'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['attribs']['']['fileSize'])) { $length = intval($content['attribs']['']['fileSize']); } if (isset($content['attribs']['']['medium'])) { $medium = $this->sanitize($content['attribs']['']['medium'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['attribs']['']['samplingrate'])) { $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['attribs']['']['type'])) { $type = $this->sanitize($content['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['attribs']['']['width'])) { $width = $this->sanitize($content['attribs']['']['width'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $url = $this->sanitize($content['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI); // Checking the other optional media: elements. Priority: media:content, media:group, item, channel // CAPTIONS if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['text'])) { foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['text'] as $caption) { $caption_type = null; $caption_lang = null; $caption_startTime = null; $caption_endTime = null; $caption_text = null; if (isset($caption['attribs']['']['type'])) { $caption_type = $this->sanitize($caption['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['attribs']['']['lang'])) { $caption_lang = $this->sanitize($caption['attribs']['']['lang'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['attribs']['']['start'])) { $caption_startTime = $this->sanitize($caption['attribs']['']['start'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['attribs']['']['end'])) { $caption_endTime = $this->sanitize($caption['attribs']['']['end'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['data'])) { $caption_text = $this->sanitize($caption['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $captions[] = $this->registry->create(Caption::class, [$caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text]); } if (is_array($captions)) { $captions = array_values(array_unique($captions)); } } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['text'])) { foreach ($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['text'] as $caption) { $caption_type = null; $caption_lang = null; $caption_startTime = null; $caption_endTime = null; $caption_text = null; if (isset($caption['attribs']['']['type'])) { $caption_type = $this->sanitize($caption['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['attribs']['']['lang'])) { $caption_lang = $this->sanitize($caption['attribs']['']['lang'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['attribs']['']['start'])) { $caption_startTime = $this->sanitize($caption['attribs']['']['start'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['attribs']['']['end'])) { $caption_endTime = $this->sanitize($caption['attribs']['']['end'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['data'])) { $caption_text = $this->sanitize($caption['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $captions[] = $this->registry->create(Caption::class, [$caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text]); } if (is_array($captions)) { $captions = array_values(array_unique($captions)); } } else { $captions = $captions_parent; } // CATEGORIES if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['category'])) { foreach ((array) $content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['category'] as $category) { $term = null; $scheme = null; $label = null; if (isset($category['data'])) { $term = $this->sanitize($category['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($category['attribs']['']['scheme'])) { $scheme = $this->sanitize($category['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $scheme = 'http://search.yahoo.com/mrss/category_schema'; } if (isset($category['attribs']['']['label'])) { $label = $this->sanitize($category['attribs']['']['label'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $categories[] = $this->registry->create(Category::class, [$term, $scheme, $label]); } } if (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['category'])) { foreach ((array) $group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['category'] as $category) { $term = null; $scheme = null; $label = null; if (isset($category['data'])) { $term = $this->sanitize($category['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($category['attribs']['']['scheme'])) { $scheme = $this->sanitize($category['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $scheme = 'http://search.yahoo.com/mrss/category_schema'; } if (isset($category['attribs']['']['label'])) { $label = $this->sanitize($category['attribs']['']['label'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $categories[] = $this->registry->create(Category::class, [$term, $scheme, $label]); } } if (is_array($categories) && is_array($categories_parent)) { $categories = array_values(array_unique(array_merge($categories, $categories_parent))); } elseif (is_array($categories)) { $categories = array_values(array_unique($categories)); } elseif (is_array($categories_parent)) { $categories = array_values(array_unique($categories_parent)); } // COPYRIGHTS if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'])) { $copyright_url = null; $copyright_label = null; if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'])) { $copyright_url = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['data'])) { $copyright_label = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $copyrights = $this->registry->create(Copyright::class, [$copyright_url, $copyright_label]); } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'])) { $copyright_url = null; $copyright_label = null; if (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'])) { $copyright_url = $this->sanitize($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['data'])) { $copyright_label = $this->sanitize($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $copyrights = $this->registry->create(Copyright::class, [$copyright_url, $copyright_label]); } else { $copyrights = $copyrights_parent; } // CREDITS if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['credit'])) { foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['credit'] as $credit) { $credit_role = null; $credit_scheme = null; $credit_name = null; if (isset($credit['attribs']['']['role'])) { $credit_role = $this->sanitize($credit['attribs']['']['role'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($credit['attribs']['']['scheme'])) { $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $credit_scheme = 'urn:ebu'; } if (isset($credit['data'])) { $credit_name = $this->sanitize($credit['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $credits[] = $this->registry->create(Credit::class, [$credit_role, $credit_scheme, $credit_name]); } if (is_array($credits)) { $credits = array_values(array_unique($credits)); } } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['credit'])) { foreach ($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['credit'] as $credit) { $credit_role = null; $credit_scheme = null; $credit_name = null; if (isset($credit['attribs']['']['role'])) { $credit_role = $this->sanitize($credit['attribs']['']['role'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($credit['attribs']['']['scheme'])) { $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $credit_scheme = 'urn:ebu'; } if (isset($credit['data'])) { $credit_name = $this->sanitize($credit['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $credits[] = $this->registry->create(Credit::class, [$credit_role, $credit_scheme, $credit_name]); } if (is_array($credits)) { $credits = array_values(array_unique($credits)); } } else { $credits = $credits_parent; } // DESCRIPTION if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['description'])) { $description = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['description'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['description'])) { $description = $this->sanitize($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['description'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $description = $description_parent; } // HASHES if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['hash'])) { foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['hash'] as $hash) { $value = null; $algo = null; if (isset($hash['data'])) { $value = $this->sanitize($hash['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($hash['attribs']['']['algo'])) { $algo = $this->sanitize($hash['attribs']['']['algo'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $algo = 'md5'; } $hashes[] = $algo.':'.$value; } if (is_array($hashes)) { $hashes = array_values(array_unique($hashes)); } } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['hash'])) { foreach ($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['hash'] as $hash) { $value = null; $algo = null; if (isset($hash['data'])) { $value = $this->sanitize($hash['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($hash['attribs']['']['algo'])) { $algo = $this->sanitize($hash['attribs']['']['algo'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $algo = 'md5'; } $hashes[] = $algo.':'.$value; } if (is_array($hashes)) { $hashes = array_values(array_unique($hashes)); } } else { $hashes = $hashes_parent; } // KEYWORDS if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['keywords'])) { if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['keywords'][0]['data'])) { $temp = explode(',', $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['keywords'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT)); foreach ($temp as $word) { $keywords[] = trim($word); } unset($temp); } if (is_array($keywords)) { $keywords = array_values(array_unique($keywords)); } } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['keywords'])) { if (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['keywords'][0]['data'])) { $temp = explode(',', $this->sanitize($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['keywords'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT)); foreach ($temp as $word) { $keywords[] = trim($word); } unset($temp); } if (is_array($keywords)) { $keywords = array_values(array_unique($keywords)); } } else { $keywords = $keywords_parent; } // PLAYER if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'])) { $player = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI); } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'])) { $player = $this->sanitize($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI); } else { $player = $player_parent; } // RATINGS if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['rating'])) { foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['rating'] as $rating) { $rating_scheme = null; $rating_value = null; if (isset($rating['attribs']['']['scheme'])) { $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $rating_scheme = 'urn:simple'; } if (isset($rating['data'])) { $rating_value = $this->sanitize($rating['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $ratings[] = $this->registry->create(Rating::class, [$rating_scheme, $rating_value]); } if (is_array($ratings)) { $ratings = array_values(array_unique($ratings)); } } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['rating'])) { foreach ($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['rating'] as $rating) { $rating_scheme = null; $rating_value = null; if (isset($rating['attribs']['']['scheme'])) { $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $rating_scheme = 'urn:simple'; } if (isset($rating['data'])) { $rating_value = $this->sanitize($rating['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $ratings[] = $this->registry->create(Rating::class, [$rating_scheme, $rating_value]); } if (is_array($ratings)) { $ratings = array_values(array_unique($ratings)); } } else { $ratings = $ratings_parent; } // RESTRICTIONS if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['restriction'])) { foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['restriction'] as $restriction) { $restriction_relationship = null; $restriction_type = null; $restriction_value = null; if (isset($restriction['attribs']['']['relationship'])) { $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($restriction['attribs']['']['type'])) { $restriction_type = $this->sanitize($restriction['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($restriction['data'])) { $restriction_value = $this->sanitize($restriction['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $restrictions[] = $this->registry->create(Restriction::class, [$restriction_relationship, $restriction_type, $restriction_value]); } if (is_array($restrictions)) { $restrictions = array_values(array_unique($restrictions)); } } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['restriction'])) { foreach ($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['restriction'] as $restriction) { $restriction_relationship = null; $restriction_type = null; $restriction_value = null; if (isset($restriction['attribs']['']['relationship'])) { $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($restriction['attribs']['']['type'])) { $restriction_type = $this->sanitize($restriction['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($restriction['data'])) { $restriction_value = $this->sanitize($restriction['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $restrictions[] = $this->registry->create(Restriction::class, [$restriction_relationship, $restriction_type, $restriction_value]); } if (is_array($restrictions)) { $restrictions = array_values(array_unique($restrictions)); } } else { $restrictions = $restrictions_parent; } // THUMBNAILS if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['thumbnail'])) { foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) { $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI); } if (is_array($thumbnails)) { $thumbnails = array_values(array_unique($thumbnails)); } } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['thumbnail'])) { foreach ($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) { $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI); } if (is_array($thumbnails)) { $thumbnails = array_values(array_unique($thumbnails)); } } else { $thumbnails = $thumbnails_parent; } // TITLES if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['title'])) { $title = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['title'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['title'])) { $title = $this->sanitize($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['title'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $title = $title_parent; } $this->data['enclosures'][] = $this->registry->create(Enclosure::class, [$url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width]); } } } } // If we have standalone media:content tags, loop through them. if (isset($this->data['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['content'])) { foreach ((array) $this->data['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['content'] as $content) { if (isset($content['attribs']['']['url']) || isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'])) { // Attributes $bitrate = null; $channels = null; $duration = null; $expression = null; $framerate = null; $height = null; $javascript = null; $lang = null; $length = null; $medium = null; $samplingrate = null; $type = null; $url = null; $width = null; // Elements $captions = null; $categories = null; $copyrights = null; $credits = null; $description = null; $hashes = null; $keywords = null; $player = null; $ratings = null; $restrictions = null; $thumbnails = null; $title = null; // Start checking the attributes of media:content if (isset($content['attribs']['']['bitrate'])) { $bitrate = $this->sanitize($content['attribs']['']['bitrate'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['attribs']['']['channels'])) { $channels = $this->sanitize($content['attribs']['']['channels'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['attribs']['']['duration'])) { $duration = $this->sanitize($content['attribs']['']['duration'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $duration = $duration_parent; } if (isset($content['attribs']['']['expression'])) { $expression = $this->sanitize($content['attribs']['']['expression'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['attribs']['']['framerate'])) { $framerate = $this->sanitize($content['attribs']['']['framerate'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['attribs']['']['height'])) { $height = $this->sanitize($content['attribs']['']['height'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['attribs']['']['lang'])) { $lang = $this->sanitize($content['attribs']['']['lang'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['attribs']['']['fileSize'])) { $length = intval($content['attribs']['']['fileSize']); } if (isset($content['attribs']['']['medium'])) { $medium = $this->sanitize($content['attribs']['']['medium'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['attribs']['']['samplingrate'])) { $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['attribs']['']['type'])) { $type = $this->sanitize($content['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['attribs']['']['width'])) { $width = $this->sanitize($content['attribs']['']['width'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['attribs']['']['url'])) { $url = $this->sanitize($content['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI); } // Checking the other optional media: elements. Priority: media:content, media:group, item, channel // CAPTIONS if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['text'])) { foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['text'] as $caption) { $caption_type = null; $caption_lang = null; $caption_startTime = null; $caption_endTime = null; $caption_text = null; if (isset($caption['attribs']['']['type'])) { $caption_type = $this->sanitize($caption['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['attribs']['']['lang'])) { $caption_lang = $this->sanitize($caption['attribs']['']['lang'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['attribs']['']['start'])) { $caption_startTime = $this->sanitize($caption['attribs']['']['start'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['attribs']['']['end'])) { $caption_endTime = $this->sanitize($caption['attribs']['']['end'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($caption['data'])) { $caption_text = $this->sanitize($caption['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $captions[] = $this->registry->create(Caption::class, [$caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text]); } if (is_array($captions)) { $captions = array_values(array_unique($captions)); } } else { $captions = $captions_parent; } // CATEGORIES if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['category'])) { foreach ((array) $content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['category'] as $category) { $term = null; $scheme = null; $label = null; if (isset($category['data'])) { $term = $this->sanitize($category['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($category['attribs']['']['scheme'])) { $scheme = $this->sanitize($category['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $scheme = 'http://search.yahoo.com/mrss/category_schema'; } if (isset($category['attribs']['']['label'])) { $label = $this->sanitize($category['attribs']['']['label'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $categories[] = $this->registry->create(Category::class, [$term, $scheme, $label]); } } if (is_array($categories) && is_array($categories_parent)) { $categories = array_values(array_unique(array_merge($categories, $categories_parent))); } elseif (is_array($categories)) { $categories = array_values(array_unique($categories)); } elseif (is_array($categories_parent)) { $categories = array_values(array_unique($categories_parent)); } else { $categories = null; } // COPYRIGHTS if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'])) { $copyright_url = null; $copyright_label = null; if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'])) { $copyright_url = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['data'])) { $copyright_label = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $copyrights = $this->registry->create(Copyright::class, [$copyright_url, $copyright_label]); } else { $copyrights = $copyrights_parent; } // CREDITS if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['credit'])) { foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['credit'] as $credit) { $credit_role = null; $credit_scheme = null; $credit_name = null; if (isset($credit['attribs']['']['role'])) { $credit_role = $this->sanitize($credit['attribs']['']['role'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($credit['attribs']['']['scheme'])) { $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $credit_scheme = 'urn:ebu'; } if (isset($credit['data'])) { $credit_name = $this->sanitize($credit['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $credits[] = $this->registry->create(Credit::class, [$credit_role, $credit_scheme, $credit_name]); } if (is_array($credits)) { $credits = array_values(array_unique($credits)); } } else { $credits = $credits_parent; } // DESCRIPTION if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['description'])) { $description = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['description'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $description = $description_parent; } // HASHES if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['hash'])) { foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['hash'] as $hash) { $value = null; $algo = null; if (isset($hash['data'])) { $value = $this->sanitize($hash['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($hash['attribs']['']['algo'])) { $algo = $this->sanitize($hash['attribs']['']['algo'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $algo = 'md5'; } $hashes[] = $algo.':'.$value; } if (is_array($hashes)) { $hashes = array_values(array_unique($hashes)); } } else { $hashes = $hashes_parent; } // KEYWORDS if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['keywords'])) { if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['keywords'][0]['data'])) { $temp = explode(',', $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['keywords'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT)); foreach ($temp as $word) { $keywords[] = trim($word); } unset($temp); } if (is_array($keywords)) { $keywords = array_values(array_unique($keywords)); } } else { $keywords = $keywords_parent; } // PLAYER if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'])) { if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'])) { $player = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI); } } else { $player = $player_parent; } // RATINGS if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['rating'])) { foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['rating'] as $rating) { $rating_scheme = null; $rating_value = null; if (isset($rating['attribs']['']['scheme'])) { $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $rating_scheme = 'urn:simple'; } if (isset($rating['data'])) { $rating_value = $this->sanitize($rating['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $ratings[] = $this->registry->create(Rating::class, [$rating_scheme, $rating_value]); } if (is_array($ratings)) { $ratings = array_values(array_unique($ratings)); } } else { $ratings = $ratings_parent; } // RESTRICTIONS if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['restriction'])) { foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['restriction'] as $restriction) { $restriction_relationship = null; $restriction_type = null; $restriction_value = null; if (isset($restriction['attribs']['']['relationship'])) { $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($restriction['attribs']['']['type'])) { $restriction_type = $this->sanitize($restriction['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($restriction['data'])) { $restriction_value = $this->sanitize($restriction['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $restrictions[] = $this->registry->create(Restriction::class, [$restriction_relationship, $restriction_type, $restriction_value]); } if (is_array($restrictions)) { $restrictions = array_values(array_unique($restrictions)); } } else { $restrictions = $restrictions_parent; } // THUMBNAILS if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['thumbnail'])) { foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) { if (isset($thumbnail['attribs']['']['url'])) { $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI); } } if (is_array($thumbnails)) { $thumbnails = array_values(array_unique($thumbnails)); } } else { $thumbnails = $thumbnails_parent; } // TITLES if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['title'])) { $title = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['title'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $title = $title_parent; } $this->data['enclosures'][] = $this->registry->create(Enclosure::class, [$url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width]); } } } foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'link') as $link) { if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure') { // Attributes $bitrate = null; $channels = null; $duration = null; $expression = null; $framerate = null; $height = null; $javascript = null; $lang = null; $length = null; $medium = null; $samplingrate = null; $type = null; $url = null; $width = null; $url = $this->sanitize($link['attribs']['']['href'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($link)); if (isset($link['attribs']['']['type'])) { $type = $this->sanitize($link['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($link['attribs']['']['length'])) { $length = intval($link['attribs']['']['length']); } if (isset($link['attribs']['']['title'])) { $title = $this->sanitize($link['attribs']['']['title'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $title = $title_parent; } // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor $this->data['enclosures'][] = $this->registry->create(Enclosure::class, [$url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title, $width]); } } foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'link') as $link) { if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure') { // Attributes $bitrate = null; $channels = null; $duration = null; $expression = null; $framerate = null; $height = null; $javascript = null; $lang = null; $length = null; $medium = null; $samplingrate = null; $type = null; $url = null; $width = null; $url = $this->sanitize($link['attribs']['']['href'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($link)); if (isset($link['attribs']['']['type'])) { $type = $this->sanitize($link['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($link['attribs']['']['length'])) { $length = intval($link['attribs']['']['length']); } // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor $this->data['enclosures'][] = $this->registry->create(Enclosure::class, [$url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width]); } } foreach ($this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'enclosure') ?? [] as $enclosure) { if (isset($enclosure['attribs']['']['url'])) { // Attributes $bitrate = null; $channels = null; $duration = null; $expression = null; $framerate = null; $height = null; $javascript = null; $lang = null; $length = null; $medium = null; $samplingrate = null; $type = null; $url = null; $width = null; $url = $this->sanitize($enclosure['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($enclosure)); $url = $this->feed->sanitize->https_url($url); if (isset($enclosure['attribs']['']['type'])) { $type = $this->sanitize($enclosure['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($enclosure['attribs']['']['length'])) { $length = intval($enclosure['attribs']['']['length']); } // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor $this->data['enclosures'][] = $this->registry->create(Enclosure::class, [$url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width]); } } if (sizeof($this->data['enclosures']) === 0 && ($url || $type || $length || $bitrate || $captions_parent || $categories_parent || $channels || $copyrights_parent || $credits_parent || $description_parent || $duration_parent || $expression || $framerate || $hashes_parent || $height || $keywords_parent || $lang || $medium || $player_parent || $ratings_parent || $restrictions_parent || $samplingrate || $thumbnails_parent || $title_parent || $width)) { // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor $this->data['enclosures'][] = $this->registry->create(Enclosure::class, [$url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width]); } $this->data['enclosures'] = array_values(array_unique($this->data['enclosures'])); } if (!empty($this->data['enclosures'])) { return $this->data['enclosures']; } return null; } /** * Get the latitude coordinates for the item * * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications * * Uses `<geo:lat>` or `<georss:point>` * * @since 1.0 * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo * @link http://www.georss.org/ GeoRSS * @return string|null */ public function get_latitude() { if ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_W3C_BASIC_GEO, 'lat')) { return (float) $return[0]['data']; } elseif (($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) { return (float) $match[1]; } return null; } /** * Get the longitude coordinates for the item * * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications * * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>` * * @since 1.0 * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo * @link http://www.georss.org/ GeoRSS * @return string|null */ public function get_longitude() { if ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_W3C_BASIC_GEO, 'long')) { return (float) $return[0]['data']; } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_W3C_BASIC_GEO, 'lon')) { return (float) $return[0]['data']; } elseif (($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) { return (float) $match[2]; } return null; } /** * Get the `<atom:source>` for the item * * @since 1.1 * @return \SimplePie\Source|null */ public function get_source() { if ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'source')) { return $this->registry->create(Source::class, [$this, $return[0]]); } return null; } } class_alias('SimplePie\Item', 'SimplePie_Item'); PK������Z۶���� ��Credit.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie; /** * Handles `<media:credit>` as defined in Media RSS * * Used by {@see \SimplePie\Enclosure::get_credit()} and {@see \SimplePie\Enclosure::get_credits()} * * This class can be overloaded with {@see \SimplePie\SimplePie::set_credit_class()} * * @package SimplePie * @subpackage API */ class Credit { /** * Credited role * * @var string * @see get_role() */ public $role; /** * Organizational scheme * * @var string * @see get_scheme() */ public $scheme; /** * Credited name * * @var string * @see get_name() */ public $name; /** * Constructor, used to input the data * * For documentation on all the parameters, see the corresponding * properties and their accessors */ public function __construct($role = null, $scheme = null, $name = null) { $this->role = $role; $this->scheme = $scheme; $this->name = $name; } /** * String-ified version * * @return string */ public function __toString() { // There is no $this->data here return md5(serialize($this)); } /** * Get the role of the person receiving credit * * @return string|null */ public function get_role() { if ($this->role !== null) { return $this->role; } return null; } /** * Get the organizational scheme * * @return string|null */ public function get_scheme() { if ($this->scheme !== null) { return $this->scheme; } return null; } /** * Get the credited person/entity's name * * @return string|null */ public function get_name() { if ($this->name !== null) { return $this->name; } return null; } } class_alias('SimplePie\Credit', 'SimplePie_Credit'); PK������Z^��^�� ��Source.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie; /** * Handles `<atom:source>` * * Used by {@see \SimplePie\Item::get_source()} * * This class can be overloaded with {@see \SimplePie::set_source_class()} * * @package SimplePie * @subpackage API */ class Source implements RegistryAware { public $item; public $data = []; protected $registry; public function __construct($item, $data) { $this->item = $item; $this->data = $data; } public function set_registry(\SimplePie\Registry $registry)/* : void */ { $this->registry = $registry; } public function __toString() { return md5(serialize($this->data)); } public function get_source_tags($namespace, $tag) { if (isset($this->data['child'][$namespace][$tag])) { return $this->data['child'][$namespace][$tag]; } return null; } public function get_base($element = []) { return $this->item->get_base($element); } public function sanitize($data, $type, $base = '') { return $this->item->sanitize($data, $type, $base); } public function get_item() { return $this->item; } public function get_title() { if ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'title')) { return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_10_construct_type', [$return[0]['attribs']]), $this->get_base($return[0])); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'title')) { return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_03_construct_type', [$return[0]['attribs']]), $this->get_base($return[0])); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_RSS_10, 'title')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_RSS_090, 'title')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'title')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, 'title')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, 'title')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } return null; } public function get_category($key = 0) { $categories = $this->get_categories(); if (isset($categories[$key])) { return $categories[$key]; } return null; } public function get_categories() { $categories = []; foreach ((array) $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'category') as $category) { $term = null; $scheme = null; $label = null; if (isset($category['attribs']['']['term'])) { $term = $this->sanitize($category['attribs']['']['term'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($category['attribs']['']['scheme'])) { $scheme = $this->sanitize($category['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($category['attribs']['']['label'])) { $label = $this->sanitize($category['attribs']['']['label'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } $categories[] = $this->registry->create(Category::class, [$term, $scheme, $label]); } foreach ((array) $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'category') as $category) { // This is really the label, but keep this as the term also for BC. // Label will also work on retrieving because that falls back to term. $term = $this->sanitize($category['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); if (isset($category['attribs']['']['domain'])) { $scheme = $this->sanitize($category['attribs']['']['domain'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } else { $scheme = null; } $categories[] = $this->registry->create(Category::class, [$term, $scheme, null]); } foreach ((array) $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, 'subject') as $category) { $categories[] = $this->registry->create(Category::class, [$this->sanitize($category['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT), null, null]); } foreach ((array) $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, 'subject') as $category) { $categories[] = $this->registry->create(Category::class, [$this->sanitize($category['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT), null, null]); } if (!empty($categories)) { return array_unique($categories); } return null; } public function get_author($key = 0) { $authors = $this->get_authors(); if (isset($authors[$key])) { return $authors[$key]; } return null; } public function get_authors() { $authors = []; foreach ((array) $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'author') as $author) { $name = null; $uri = null; $email = null; if (isset($author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['name'][0]['data'])) { $name = $this->sanitize($author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['name'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['uri'][0]['data'])) { $uri = $this->sanitize($author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['uri'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['uri'][0])); } if (isset($author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['email'][0]['data'])) { $email = $this->sanitize($author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['email'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if ($name !== null || $email !== null || $uri !== null) { $authors[] = $this->registry->create(Author::class, [$name, $uri, $email]); } } if ($author = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'author')) { $name = null; $url = null; $email = null; if (isset($author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['name'][0]['data'])) { $name = $this->sanitize($author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['name'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['url'][0]['data'])) { $url = $this->sanitize($author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['url'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['url'][0])); } if (isset($author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['email'][0]['data'])) { $email = $this->sanitize($author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['email'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if ($name !== null || $email !== null || $url !== null) { $authors[] = $this->registry->create(Author::class, [$name, $url, $email]); } } foreach ((array) $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, 'creator') as $author) { $authors[] = $this->registry->create(Author::class, [$this->sanitize($author['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT), null, null]); } foreach ((array) $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, 'creator') as $author) { $authors[] = $this->registry->create(Author::class, [$this->sanitize($author['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT), null, null]); } foreach ((array) $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'author') as $author) { $authors[] = $this->registry->create(Author::class, [$this->sanitize($author['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT), null, null]); } if (!empty($authors)) { return array_unique($authors); } return null; } public function get_contributor($key = 0) { $contributors = $this->get_contributors(); if (isset($contributors[$key])) { return $contributors[$key]; } return null; } public function get_contributors() { $contributors = []; foreach ((array) $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'contributor') as $contributor) { $name = null; $uri = null; $email = null; if (isset($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['name'][0]['data'])) { $name = $this->sanitize($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['name'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['uri'][0]['data'])) { $uri = $this->sanitize($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['uri'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['uri'][0])); } if (isset($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['email'][0]['data'])) { $email = $this->sanitize($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['email'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if ($name !== null || $email !== null || $uri !== null) { $contributors[] = $this->registry->create(Author::class, [$name, $uri, $email]); } } foreach ((array) $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'contributor') as $contributor) { $name = null; $url = null; $email = null; if (isset($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['name'][0]['data'])) { $name = $this->sanitize($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['name'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if (isset($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['url'][0]['data'])) { $url = $this->sanitize($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['url'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['url'][0])); } if (isset($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['email'][0]['data'])) { $email = $this->sanitize($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['email'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } if ($name !== null || $email !== null || $url !== null) { $contributors[] = $this->registry->create(Author::class, [$name, $url, $email]); } } if (!empty($contributors)) { return array_unique($contributors); } return null; } public function get_link($key = 0, $rel = 'alternate') { $links = $this->get_links($rel); if (isset($links[$key])) { return $links[$key]; } return null; } /** * Added for parity between the parent-level and the item/entry-level. */ public function get_permalink() { return $this->get_link(0); } public function get_links($rel = 'alternate') { if (!isset($this->data['links'])) { $this->data['links'] = []; if ($links = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'link')) { foreach ($links as $link) { if (isset($link['attribs']['']['href'])) { $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($link)); } } } if ($links = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'link')) { foreach ($links as $link) { if (isset($link['attribs']['']['href'])) { $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($link)); } } } if ($links = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_RSS_10, 'link')) { $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($links[0])); } if ($links = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_RSS_090, 'link')) { $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($links[0])); } if ($links = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'link')) { $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($links[0])); } $keys = array_keys($this->data['links']); foreach ($keys as $key) { if ($this->registry->call(Misc::class, 'is_isegment_nz_nc', [$key])) { if (isset($this->data['links'][\SimplePie\SimplePie::IANA_LINK_RELATIONS_REGISTRY . $key])) { $this->data['links'][\SimplePie\SimplePie::IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][\SimplePie\SimplePie::IANA_LINK_RELATIONS_REGISTRY . $key]); $this->data['links'][$key] = &$this->data['links'][\SimplePie\SimplePie::IANA_LINK_RELATIONS_REGISTRY . $key]; } else { $this->data['links'][\SimplePie\SimplePie::IANA_LINK_RELATIONS_REGISTRY . $key] = &$this->data['links'][$key]; } } elseif (substr($key, 0, 41) === \SimplePie\SimplePie::IANA_LINK_RELATIONS_REGISTRY) { $this->data['links'][substr($key, 41)] = &$this->data['links'][$key]; } $this->data['links'][$key] = array_unique($this->data['links'][$key]); } } if (isset($this->data['links'][$rel])) { return $this->data['links'][$rel]; } return null; } public function get_description() { if ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'subtitle')) { return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_10_construct_type', [$return[0]['attribs']]), $this->get_base($return[0])); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'tagline')) { return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_03_construct_type', [$return[0]['attribs']]), $this->get_base($return[0])); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_RSS_10, 'description')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_RSS_090, 'description')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'description')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, 'description')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, 'description')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'summary')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_HTML, $this->get_base($return[0])); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'subtitle')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_HTML, $this->get_base($return[0])); } return null; } public function get_copyright() { if ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'rights')) { return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_10_construct_type', [$return[0]['attribs']]), $this->get_base($return[0])); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'copyright')) { return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_03_construct_type', [$return[0]['attribs']]), $this->get_base($return[0])); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'copyright')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, 'rights')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, 'rights')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } return null; } public function get_language() { if ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'language')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, 'language')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, 'language')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } elseif (isset($this->data['xml_lang'])) { return $this->sanitize($this->data['xml_lang'], \SimplePie\SimplePie::CONSTRUCT_TEXT); } return null; } public function get_latitude() { if ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_W3C_BASIC_GEO, 'lat')) { return (float) $return[0]['data']; } elseif (($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) { return (float) $match[1]; } return null; } public function get_longitude() { if ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_W3C_BASIC_GEO, 'long')) { return (float) $return[0]['data']; } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_W3C_BASIC_GEO, 'lon')) { return (float) $return[0]['data']; } elseif (($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) { return (float) $match[2]; } return null; } public function get_image_url() { if ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'image')) { return $this->sanitize($return[0]['attribs']['']['href'], \SimplePie\SimplePie::CONSTRUCT_IRI); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'logo')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($return[0])); } elseif ($return = $this->get_source_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'icon')) { return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($return[0])); } return null; } } class_alias('SimplePie\Source', 'SimplePie_Source'); PK������Z���� ��Parser.phpnu�W+A��������<?php namespace Egulias\EmailValidator; use Egulias\EmailValidator\Result\Result; use Egulias\EmailValidator\Result\ValidEmail; use Egulias\EmailValidator\Result\InvalidEmail; use Egulias\EmailValidator\Result\Reason\ExpectingATEXT; abstract class Parser { /** * @var Warning\Warning[] */ protected $warnings = []; /** * @var EmailLexer */ protected $lexer; /** * id-left "@" id-right */ abstract protected function parseRightFromAt(): Result; abstract protected function parseLeftFromAt(): Result; abstract protected function preLeftParsing(): Result; public function __construct(EmailLexer $lexer) { $this->lexer = $lexer; } public function parse(string $str): Result { $this->lexer->setInput($str); if ($this->lexer->hasInvalidTokens()) { return new InvalidEmail(new ExpectingATEXT("Invalid tokens found"), $this->lexer->current->value); } $preParsingResult = $this->preLeftParsing(); if ($preParsingResult->isInvalid()) { return $preParsingResult; } $localPartResult = $this->parseLeftFromAt(); if ($localPartResult->isInvalid()) { return $localPartResult; } $domainPartResult = $this->parseRightFromAt(); if ($domainPartResult->isInvalid()) { return $domainPartResult; } return new ValidEmail(); } /** * @return Warning\Warning[] */ public function getWarnings(): array { return $this->warnings; } protected function hasAtToken(): bool { $this->lexer->moveNext(); $this->lexer->moveNext(); return !$this->lexer->current->isA(EmailLexer::S_AT); } } PK������ZL������ ��Enclosure.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie; /** * Handles everything related to enclosures (including Media RSS and iTunes RSS) * * Used by {@see \SimplePie\Item::get_enclosure()} and {@see \SimplePie\Item::get_enclosures()} * * This class can be overloaded with {@see \SimplePie\SimplePie::set_enclosure_class()} * * @package SimplePie * @subpackage API */ class Enclosure { /** * @var string * @see get_bitrate() */ public $bitrate; /** * @var array * @see get_captions() */ public $captions; /** * @var array * @see get_categories() */ public $categories; /** * @var int * @see get_channels() */ public $channels; /** * @var \SimplePie\Copyright * @see get_copyright() */ public $copyright; /** * @var array * @see get_credits() */ public $credits; /** * @var string * @see get_description() */ public $description; /** * @var int * @see get_duration() */ public $duration; /** * @var string * @see get_expression() */ public $expression; /** * @var string * @see get_framerate() */ public $framerate; /** * @var string * @see get_handler() */ public $handler; /** * @var array * @see get_hashes() */ public $hashes; /** * @var string * @see get_height() */ public $height; /** * @deprecated * @var null */ public $javascript; /** * @var array * @see get_keywords() */ public $keywords; /** * @var string * @see get_language() */ public $lang; /** * @var string * @see get_length() */ public $length; /** * @var string * @see get_link() */ public $link; /** * @var string * @see get_medium() */ public $medium; /** * @var string * @see get_player() */ public $player; /** * @var array * @see get_ratings() */ public $ratings; /** * @var array * @see get_restrictions() */ public $restrictions; /** * @var string * @see get_sampling_rate() */ public $samplingrate; /** * @var array * @see get_thumbnails() */ public $thumbnails; /** * @var string * @see get_title() */ public $title; /** * @var string * @see get_type() */ public $type; /** * @var string * @see get_width() */ public $width; /** * Constructor, used to input the data * * For documentation on all the parameters, see the corresponding * properties and their accessors * * @uses idna_convert If available, this will convert an IDN */ public function __construct($link = null, $type = null, $length = null, $javascript = null, $bitrate = null, $captions = null, $categories = null, $channels = null, $copyright = null, $credits = null, $description = null, $duration = null, $expression = null, $framerate = null, $hashes = null, $height = null, $keywords = null, $lang = null, $medium = null, $player = null, $ratings = null, $restrictions = null, $samplingrate = null, $thumbnails = null, $title = null, $width = null) { $this->bitrate = $bitrate; $this->captions = $captions; $this->categories = $categories; $this->channels = $channels; $this->copyright = $copyright; $this->credits = $credits; $this->description = $description; $this->duration = $duration; $this->expression = $expression; $this->framerate = $framerate; $this->hashes = $hashes; $this->height = $height; $this->keywords = $keywords; $this->lang = $lang; $this->length = $length; $this->link = $link; $this->medium = $medium; $this->player = $player; $this->ratings = $ratings; $this->restrictions = $restrictions; $this->samplingrate = $samplingrate; $this->thumbnails = $thumbnails; $this->title = $title; $this->type = $type; $this->width = $width; if (class_exists('idna_convert')) { $idn = new \idna_convert(); $parsed = \SimplePie\Misc::parse_url($link); $this->link = \SimplePie\Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']); } $this->handler = $this->get_handler(); // Needs to load last } /** * String-ified version * * @return string */ public function __toString() { // There is no $this->data here return md5(serialize($this)); } /** * Get the bitrate * * @return string|null */ public function get_bitrate() { if ($this->bitrate !== null) { return $this->bitrate; } return null; } /** * Get a single caption * * @param int $key * @return \SimplePie\Caption|null */ public function get_caption($key = 0) { $captions = $this->get_captions(); if (isset($captions[$key])) { return $captions[$key]; } return null; } /** * Get all captions * * @return array|null Array of {@see \SimplePie\Caption} objects */ public function get_captions() { if ($this->captions !== null) { return $this->captions; } return null; } /** * Get a single category * * @param int $key * @return \SimplePie\Category|null */ public function get_category($key = 0) { $categories = $this->get_categories(); if (isset($categories[$key])) { return $categories[$key]; } return null; } /** * Get all categories * * @return array|null Array of {@see \SimplePie\Category} objects */ public function get_categories() { if ($this->categories !== null) { return $this->categories; } return null; } /** * Get the number of audio channels * * @return int|null */ public function get_channels() { if ($this->channels !== null) { return $this->channels; } return null; } /** * Get the copyright information * * @return \SimplePie\Copyright|null */ public function get_copyright() { if ($this->copyright !== null) { return $this->copyright; } return null; } /** * Get a single credit * * @param int $key * @return \SimplePie\Credit|null */ public function get_credit($key = 0) { $credits = $this->get_credits(); if (isset($credits[$key])) { return $credits[$key]; } return null; } /** * Get all credits * * @return array|null Array of {@see \SimplePie\Credit} objects */ public function get_credits() { if ($this->credits !== null) { return $this->credits; } return null; } /** * Get the description of the enclosure * * @return string|null */ public function get_description() { if ($this->description !== null) { return $this->description; } return null; } /** * Get the duration of the enclosure * * @param bool $convert Convert seconds into hh:mm:ss * @return string|int|null 'hh:mm:ss' string if `$convert` was specified, otherwise integer (or null if none found) */ public function get_duration($convert = false) { if ($this->duration !== null) { if ($convert) { $time = \SimplePie\Misc::time_hms($this->duration); return $time; } return $this->duration; } return null; } /** * Get the expression * * @return string Probably one of 'sample', 'full', 'nonstop', 'clip'. Defaults to 'full' */ public function get_expression() { if ($this->expression !== null) { return $this->expression; } return 'full'; } /** * Get the file extension * * @return string|null */ public function get_extension() { if ($this->link !== null) { $url = \SimplePie\Misc::parse_url($this->link); if ($url['path'] !== '') { return pathinfo($url['path'], PATHINFO_EXTENSION); } } return null; } /** * Get the framerate (in frames-per-second) * * @return string|null */ public function get_framerate() { if ($this->framerate !== null) { return $this->framerate; } return null; } /** * Get the preferred handler * * @return string|null One of 'flash', 'fmedia', 'quicktime', 'wmedia', 'mp3' */ public function get_handler() { return $this->get_real_type(true); } /** * Get a single hash * * @link http://www.rssboard.org/media-rss#media-hash * @param int $key * @return string|null Hash as per `media:hash`, prefixed with "$algo:" */ public function get_hash($key = 0) { $hashes = $this->get_hashes(); if (isset($hashes[$key])) { return $hashes[$key]; } return null; } /** * Get all credits * * @return array|null Array of strings, see {@see get_hash()} */ public function get_hashes() { if ($this->hashes !== null) { return $this->hashes; } return null; } /** * Get the height * * @return string|null */ public function get_height() { if ($this->height !== null) { return $this->height; } return null; } /** * Get the language * * @link http://tools.ietf.org/html/rfc3066 * @return string|null Language code as per RFC 3066 */ public function get_language() { if ($this->lang !== null) { return $this->lang; } return null; } /** * Get a single keyword * * @param int $key * @return string|null */ public function get_keyword($key = 0) { $keywords = $this->get_keywords(); if (isset($keywords[$key])) { return $keywords[$key]; } return null; } /** * Get all keywords * * @return array|null Array of strings */ public function get_keywords() { if ($this->keywords !== null) { return $this->keywords; } return null; } /** * Get length * * @return float Length in bytes */ public function get_length() { if ($this->length !== null) { return $this->length; } return null; } /** * Get the URL * * @return string|null */ public function get_link() { if ($this->link !== null) { return $this->link; } return null; } /** * Get the medium * * @link http://www.rssboard.org/media-rss#media-content * @return string|null Should be one of 'image', 'audio', 'video', 'document', 'executable' */ public function get_medium() { if ($this->medium !== null) { return $this->medium; } return null; } /** * Get the player URL * * Typically the same as {@see get_permalink()} * @return string|null Player URL */ public function get_player() { if ($this->player !== null) { return $this->player; } return null; } /** * Get a single rating * * @param int $key * @return \SimplePie\Rating|null */ public function get_rating($key = 0) { $ratings = $this->get_ratings(); if (isset($ratings[$key])) { return $ratings[$key]; } return null; } /** * Get all ratings * * @return array|null Array of {@see \SimplePie\Rating} objects */ public function get_ratings() { if ($this->ratings !== null) { return $this->ratings; } return null; } /** * Get a single restriction * * @param int $key * @return \SimplePie\Restriction|null */ public function get_restriction($key = 0) { $restrictions = $this->get_restrictions(); if (isset($restrictions[$key])) { return $restrictions[$key]; } return null; } /** * Get all restrictions * * @return array|null Array of {@see \SimplePie\Restriction} objects */ public function get_restrictions() { if ($this->restrictions !== null) { return $this->restrictions; } return null; } /** * Get the sampling rate (in kHz) * * @return string|null */ public function get_sampling_rate() { if ($this->samplingrate !== null) { return $this->samplingrate; } return null; } /** * Get the file size (in MiB) * * @return float|null File size in mebibytes (1048 bytes) */ public function get_size() { $length = $this->get_length(); if ($length !== null) { return round($length / 1048576, 2); } return null; } /** * Get a single thumbnail * * @param int $key * @return string|null Thumbnail URL */ public function get_thumbnail($key = 0) { $thumbnails = $this->get_thumbnails(); if (isset($thumbnails[$key])) { return $thumbnails[$key]; } return null; } /** * Get all thumbnails * * @return array|null Array of thumbnail URLs */ public function get_thumbnails() { if ($this->thumbnails !== null) { return $this->thumbnails; } return null; } /** * Get the title * * @return string|null */ public function get_title() { if ($this->title !== null) { return $this->title; } return null; } /** * Get mimetype of the enclosure * * @see get_real_type() * @return string|null MIME type */ public function get_type() { if ($this->type !== null) { return $this->type; } return null; } /** * Get the width * * @return string|null */ public function get_width() { if ($this->width !== null) { return $this->width; } return null; } /** * Embed the enclosure using `<embed>` * * @deprecated Use the second parameter to {@see embed} instead * * @param array|string $options See first parameter to {@see embed} * @return string HTML string to output */ public function native_embed($options = '') { return $this->embed($options, true); } /** * Embed the enclosure using Javascript * * `$options` is an array or comma-separated key:value string, with the * following properties: * * - `alt` (string): Alternate content for when an end-user does not have * the appropriate handler installed or when a file type is * unsupported. Can be any text or HTML. Defaults to blank. * - `altclass` (string): If a file type is unsupported, the end-user will * see the alt text (above) linked directly to the content. That link * will have this value as its class name. Defaults to blank. * - `audio` (string): This is an image that should be used as a * placeholder for audio files before they're loaded (QuickTime-only). * Can be any relative or absolute URL. Defaults to blank. * - `bgcolor` (string): The background color for the media, if not * already transparent. Defaults to `#ffffff`. * - `height` (integer): The height of the embedded media. Accepts any * numeric pixel value (such as `360`) or `auto`. Defaults to `auto`, * and it is recommended that you use this default. * - `loop` (boolean): Do you want the media to loop when it's done? * Defaults to `false`. * - `mediaplayer` (string): The location of the included * `mediaplayer.swf` file. This allows for the playback of Flash Video * (`.flv`) files, and is the default handler for non-Odeo MP3's. * Defaults to blank. * - `video` (string): This is an image that should be used as a * placeholder for video files before they're loaded (QuickTime-only). * Can be any relative or absolute URL. Defaults to blank. * - `width` (integer): The width of the embedded media. Accepts any * numeric pixel value (such as `480`) or `auto`. Defaults to `auto`, * and it is recommended that you use this default. * - `widescreen` (boolean): Is the enclosure widescreen or standard? * This applies only to video enclosures, and will automatically resize * the content appropriately. Defaults to `false`, implying 4:3 mode. * * Note: Non-widescreen (4:3) mode with `width` and `height` set to `auto` * will default to 480x360 video resolution. Widescreen (16:9) mode with * `width` and `height` set to `auto` will default to 480x270 video resolution. * * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'. * @param array|string $options Comma-separated key:value list, or array * @param bool $native Use `<embed>` * @return string HTML string to output */ public function embed($options = '', $native = false) { // Set up defaults $audio = ''; $video = ''; $alt = ''; $altclass = ''; $loop = 'false'; $width = 'auto'; $height = 'auto'; $bgcolor = '#ffffff'; $mediaplayer = ''; $widescreen = false; $handler = $this->get_handler(); $type = $this->get_real_type(); $placeholder = ''; // Process options and reassign values as necessary if (is_array($options)) { extract($options); } else { $options = explode(',', $options); foreach ($options as $option) { $opt = explode(':', $option, 2); if (isset($opt[0], $opt[1])) { $opt[0] = trim($opt[0]); $opt[1] = trim($opt[1]); switch ($opt[0]) { case 'audio': $audio = $opt[1]; break; case 'video': $video = $opt[1]; break; case 'alt': $alt = $opt[1]; break; case 'altclass': $altclass = $opt[1]; break; case 'loop': $loop = $opt[1]; break; case 'width': $width = $opt[1]; break; case 'height': $height = $opt[1]; break; case 'bgcolor': $bgcolor = $opt[1]; break; case 'mediaplayer': $mediaplayer = $opt[1]; break; case 'widescreen': $widescreen = $opt[1]; break; } } } } $mime = explode('/', $type, 2); $mime = $mime[0]; // Process values for 'auto' if ($width === 'auto') { if ($mime === 'video') { if ($height === 'auto') { $width = 480; } elseif ($widescreen) { $width = round((intval($height) / 9) * 16); } else { $width = round((intval($height) / 3) * 4); } } else { $width = '100%'; } } if ($height === 'auto') { if ($mime === 'audio') { $height = 0; } elseif ($mime === 'video') { if ($width === 'auto') { if ($widescreen) { $height = 270; } else { $height = 360; } } elseif ($widescreen) { $height = round((intval($width) / 16) * 9); } else { $height = round((intval($width) / 4) * 3); } } else { $height = 376; } } elseif ($mime === 'audio') { $height = 0; } // Set proper placeholder value if ($mime === 'audio') { $placeholder = $audio; } elseif ($mime === 'video') { $placeholder = $video; } $embed = ''; // Flash if ($handler === 'flash') { if ($native) { $embed .= "<embed src=\"" . $this->get_link() . "\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"$type\" quality=\"high\" width=\"$width\" height=\"$height\" bgcolor=\"$bgcolor\" loop=\"$loop\"></embed>"; } else { $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>"; } } // Flash Media Player file types. // Preferred handler for MP3 file types. elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== '')) { $height += 20; if ($native) { $embed .= "<embed src=\"$mediaplayer\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" quality=\"high\" width=\"$width\" height=\"$height\" wmode=\"transparent\" flashvars=\"file=" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "&autostart=false&repeat=$loop&showdigits=true&showfsbutton=false\"></embed>"; } else { $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>"; } } // QuickTime 7 file types. Need to test with QuickTime 6. // Only handle MP3's if the Flash Media Player is not present. elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === '')) { $height += 16; if ($native) { if ($placeholder !== '') { $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" href=\"" . $this->get_link() . "\" src=\"$placeholder\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"false\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>"; } else { $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" src=\"" . $this->get_link() . "\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"true\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>"; } } else { $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>"; } } // Windows Media elseif ($handler === 'wmedia') { $height += 45; if ($native) { $embed .= "<embed type=\"application/x-mplayer2\" src=\"" . $this->get_link() . "\" autosize=\"1\" width=\"$width\" height=\"$height\" showcontrols=\"1\" showstatusbar=\"0\" showdisplay=\"0\" autostart=\"0\"></embed>"; } else { $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>"; } } // Everything else else { $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>'; } return $embed; } /** * Get the real media type * * Often, feeds lie to us, necessitating a bit of deeper inspection. This * converts types to their canonical representations based on the file * extension * * @see get_type() * @param bool $find_handler Internal use only, use {@see get_handler()} instead * @return string MIME type */ public function get_real_type($find_handler = false) { // Mime-types by handler. $types_flash = ['application/x-shockwave-flash', 'application/futuresplash']; // Flash $types_fmedia = ['video/flv', 'video/x-flv','flv-application/octet-stream']; // Flash Media Player $types_quicktime = ['audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video']; // QuickTime $types_wmedia = ['application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx']; // Windows Media $types_mp3 = ['audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg']; // MP3 if ($this->get_type() !== null) { $type = strtolower($this->type); } else { $type = null; } // If we encounter an unsupported mime-type, check the file extension and guess intelligently. if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3))) { $extension = $this->get_extension(); if ($extension === null) { return null; } switch (strtolower($extension)) { // Audio mime-types case 'aac': case 'adts': $type = 'audio/acc'; break; case 'aif': case 'aifc': case 'aiff': case 'cdda': $type = 'audio/aiff'; break; case 'bwf': $type = 'audio/wav'; break; case 'kar': case 'mid': case 'midi': case 'smf': $type = 'audio/midi'; break; case 'm4a': $type = 'audio/x-m4a'; break; case 'mp3': case 'swa': $type = 'audio/mp3'; break; case 'wav': $type = 'audio/wav'; break; case 'wax': $type = 'audio/x-ms-wax'; break; case 'wma': $type = 'audio/x-ms-wma'; break; // Video mime-types case '3gp': case '3gpp': $type = 'video/3gpp'; break; case '3g2': case '3gp2': $type = 'video/3gpp2'; break; case 'asf': $type = 'video/x-ms-asf'; break; case 'flv': $type = 'video/x-flv'; break; case 'm1a': case 'm1s': case 'm1v': case 'm15': case 'm75': case 'mp2': case 'mpa': case 'mpeg': case 'mpg': case 'mpm': case 'mpv': $type = 'video/mpeg'; break; case 'm4v': $type = 'video/x-m4v'; break; case 'mov': case 'qt': $type = 'video/quicktime'; break; case 'mp4': case 'mpg4': $type = 'video/mp4'; break; case 'sdv': $type = 'video/sd-video'; break; case 'wm': $type = 'video/x-ms-wm'; break; case 'wmv': $type = 'video/x-ms-wmv'; break; case 'wvx': $type = 'video/x-ms-wvx'; break; // Flash mime-types case 'spl': $type = 'application/futuresplash'; break; case 'swf': $type = 'application/x-shockwave-flash'; break; } } if ($find_handler) { if (in_array($type, $types_flash)) { return 'flash'; } elseif (in_array($type, $types_fmedia)) { return 'fmedia'; } elseif (in_array($type, $types_quicktime)) { return 'quicktime'; } elseif (in_array($type, $types_wmedia)) { return 'wmedia'; } elseif (in_array($type, $types_mp3)) { return 'mp3'; } return null; } return $type; } } class_alias('SimplePie\Enclosure', 'SimplePie_Enclosure'); PK������Zp5J$��J$����Content/Type/Sniffer.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie\Content\Type; /** * Content-type sniffing * * Based on the rules in http://tools.ietf.org/html/draft-abarth-mime-sniff-06 * * This is used since we can't always trust Content-Type headers, and is based * upon the HTML5 parsing rules. * * * This class can be overloaded with {@see \SimplePie\SimplePie::set_content_type_sniffer_class()} * * @package SimplePie * @subpackage HTTP */ class Sniffer { /** * File object * * @var \SimplePie\File */ public $file; /** * Create an instance of the class with the input file * * @param Sniffer $file Input file */ public function __construct($file) { $this->file = $file; } /** * Get the Content-Type of the specified file * * @return string Actual Content-Type */ public function get_type() { if (isset($this->file->headers['content-type'])) { if (!isset($this->file->headers['content-encoding']) && ($this->file->headers['content-type'] === 'text/plain' || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1' || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1' || $this->file->headers['content-type'] === 'text/plain; charset=UTF-8')) { return $this->text_or_binary(); } if (($pos = strpos($this->file->headers['content-type'], ';')) !== false) { $official = substr($this->file->headers['content-type'], 0, $pos); } else { $official = $this->file->headers['content-type']; } $official = trim(strtolower($official)); if ($official === 'unknown/unknown' || $official === 'application/unknown') { return $this->unknown(); } elseif (substr($official, -4) === '+xml' || $official === 'text/xml' || $official === 'application/xml') { return $official; } elseif (substr($official, 0, 6) === 'image/') { if ($return = $this->image()) { return $return; } return $official; } elseif ($official === 'text/html') { return $this->feed_or_html(); } return $official; } return $this->unknown(); } /** * Sniff text or binary * * @return string Actual Content-Type */ public function text_or_binary() { if (substr($this->file->body, 0, 2) === "\xFE\xFF" || substr($this->file->body, 0, 2) === "\xFF\xFE" || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF" || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF") { return 'text/plain'; } elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body)) { return 'application/octet-stream'; } return 'text/plain'; } /** * Sniff unknown * * @return string Actual Content-Type */ public function unknown() { $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20"); if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html' || strtolower(substr($this->file->body, $ws, 5)) === '<html' || strtolower(substr($this->file->body, $ws, 7)) === '<script') { return 'text/html'; } elseif (substr($this->file->body, 0, 5) === '%PDF-') { return 'application/pdf'; } elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-') { return 'application/postscript'; } elseif (substr($this->file->body, 0, 6) === 'GIF87a' || substr($this->file->body, 0, 6) === 'GIF89a') { return 'image/gif'; } elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A") { return 'image/png'; } elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF") { return 'image/jpeg'; } elseif (substr($this->file->body, 0, 2) === "\x42\x4D") { return 'image/bmp'; } elseif (substr($this->file->body, 0, 4) === "\x00\x00\x01\x00") { return 'image/vnd.microsoft.icon'; } return $this->text_or_binary(); } /** * Sniff images * * @return string Actual Content-Type */ public function image() { if (substr($this->file->body, 0, 6) === 'GIF87a' || substr($this->file->body, 0, 6) === 'GIF89a') { return 'image/gif'; } elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A") { return 'image/png'; } elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF") { return 'image/jpeg'; } elseif (substr($this->file->body, 0, 2) === "\x42\x4D") { return 'image/bmp'; } elseif (substr($this->file->body, 0, 4) === "\x00\x00\x01\x00") { return 'image/vnd.microsoft.icon'; } return false; } /** * Sniff HTML * * @return string Actual Content-Type */ public function feed_or_html() { $len = strlen($this->file->body); $pos = strspn($this->file->body, "\x09\x0A\x0D\x20\xEF\xBB\xBF"); while ($pos < $len) { switch ($this->file->body[$pos]) { case "\x09": case "\x0A": case "\x0D": case "\x20": $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos); continue 2; case '<': $pos++; break; default: return 'text/html'; } if (substr($this->file->body, $pos, 3) === '!--') { $pos += 3; if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false) { $pos += 3; } else { return 'text/html'; } } elseif (substr($this->file->body, $pos, 1) === '!') { if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false) { $pos++; } else { return 'text/html'; } } elseif (substr($this->file->body, $pos, 1) === '?') { if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false) { $pos += 2; } else { return 'text/html'; } } elseif (substr($this->file->body, $pos, 3) === 'rss' || substr($this->file->body, $pos, 7) === 'rdf:RDF') { return 'application/rss+xml'; } elseif (substr($this->file->body, $pos, 4) === 'feed') { return 'application/atom+xml'; } else { return 'text/html'; } } return 'text/html'; } } class_alias('SimplePie\Content\Type\Sniffer', 'SimplePie_Content_Type_Sniffer'); PK������Z #h��h����Parse/Date.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie\Parse; /** * Date Parser * * @package SimplePie * @subpackage Parsing */ class Date { /** * Input data * * @access protected * @var string */ public $date; /** * List of days, calendar day name => ordinal day number in the week * * @access protected * @var array */ public $day = [ // English 'mon' => 1, 'monday' => 1, 'tue' => 2, 'tuesday' => 2, 'wed' => 3, 'wednesday' => 3, 'thu' => 4, 'thursday' => 4, 'fri' => 5, 'friday' => 5, 'sat' => 6, 'saturday' => 6, 'sun' => 7, 'sunday' => 7, // Dutch 'maandag' => 1, 'dinsdag' => 2, 'woensdag' => 3, 'donderdag' => 4, 'vrijdag' => 5, 'zaterdag' => 6, 'zondag' => 7, // French 'lundi' => 1, 'mardi' => 2, 'mercredi' => 3, 'jeudi' => 4, 'vendredi' => 5, 'samedi' => 6, 'dimanche' => 7, // German 'montag' => 1, 'mo' => 1, 'dienstag' => 2, 'di' => 2, 'mittwoch' => 3, 'mi' => 3, 'donnerstag' => 4, 'do' => 4, 'freitag' => 5, 'fr' => 5, 'samstag' => 6, 'sa' => 6, 'sonnabend' => 6, // AFAIK no short form for sonnabend 'so' => 7, 'sonntag' => 7, // Italian 'lunedì' => 1, 'martedì' => 2, 'mercoledì' => 3, 'giovedì' => 4, 'venerdì' => 5, 'sabato' => 6, 'domenica' => 7, // Spanish 'lunes' => 1, 'martes' => 2, 'miércoles' => 3, 'jueves' => 4, 'viernes' => 5, 'sábado' => 6, 'domingo' => 7, // Finnish 'maanantai' => 1, 'tiistai' => 2, 'keskiviikko' => 3, 'torstai' => 4, 'perjantai' => 5, 'lauantai' => 6, 'sunnuntai' => 7, // Hungarian 'hétfő' => 1, 'kedd' => 2, 'szerda' => 3, 'csütörtok' => 4, 'péntek' => 5, 'szombat' => 6, 'vasárnap' => 7, // Greek 'Δευ' => 1, 'Τρι' => 2, 'Τετ' => 3, 'Πεμ' => 4, 'Παρ' => 5, 'Σαβ' => 6, 'Κυρ' => 7, // Russian 'Пн.' => 1, 'Вт.' => 2, 'Ср.' => 3, 'Чт.' => 4, 'Пт.' => 5, 'Сб.' => 6, 'Вс.' => 7, ]; /** * List of months, calendar month name => calendar month number * * @access protected * @var array */ public $month = [ // English 'jan' => 1, 'january' => 1, 'feb' => 2, 'february' => 2, 'mar' => 3, 'march' => 3, 'apr' => 4, 'april' => 4, 'may' => 5, // No long form of May 'jun' => 6, 'june' => 6, 'jul' => 7, 'july' => 7, 'aug' => 8, 'august' => 8, 'sep' => 9, 'september' => 9, 'oct' => 10, 'october' => 10, 'nov' => 11, 'november' => 11, 'dec' => 12, 'december' => 12, // Dutch 'januari' => 1, 'februari' => 2, 'maart' => 3, 'april' => 4, 'mei' => 5, 'juni' => 6, 'juli' => 7, 'augustus' => 8, 'september' => 9, 'oktober' => 10, 'november' => 11, 'december' => 12, // French 'janvier' => 1, 'février' => 2, 'mars' => 3, 'avril' => 4, 'mai' => 5, 'juin' => 6, 'juillet' => 7, 'août' => 8, 'septembre' => 9, 'octobre' => 10, 'novembre' => 11, 'décembre' => 12, // German 'januar' => 1, 'jan' => 1, 'februar' => 2, 'feb' => 2, 'märz' => 3, 'mär' => 3, 'april' => 4, 'apr' => 4, 'mai' => 5, // no short form for may 'juni' => 6, 'jun' => 6, 'juli' => 7, 'jul' => 7, 'august' => 8, 'aug' => 8, 'september' => 9, 'sep' => 9, 'oktober' => 10, 'okt' => 10, 'november' => 11, 'nov' => 11, 'dezember' => 12, 'dez' => 12, // Italian 'gennaio' => 1, 'febbraio' => 2, 'marzo' => 3, 'aprile' => 4, 'maggio' => 5, 'giugno' => 6, 'luglio' => 7, 'agosto' => 8, 'settembre' => 9, 'ottobre' => 10, 'novembre' => 11, 'dicembre' => 12, // Spanish 'enero' => 1, 'febrero' => 2, 'marzo' => 3, 'abril' => 4, 'mayo' => 5, 'junio' => 6, 'julio' => 7, 'agosto' => 8, 'septiembre' => 9, 'setiembre' => 9, 'octubre' => 10, 'noviembre' => 11, 'diciembre' => 12, // Finnish 'tammikuu' => 1, 'helmikuu' => 2, 'maaliskuu' => 3, 'huhtikuu' => 4, 'toukokuu' => 5, 'kesäkuu' => 6, 'heinäkuu' => 7, 'elokuu' => 8, 'suuskuu' => 9, 'lokakuu' => 10, 'marras' => 11, 'joulukuu' => 12, // Hungarian 'január' => 1, 'február' => 2, 'március' => 3, 'április' => 4, 'május' => 5, 'június' => 6, 'július' => 7, 'augusztus' => 8, 'szeptember' => 9, 'október' => 10, 'november' => 11, 'december' => 12, // Greek 'Ιαν' => 1, 'Φεβ' => 2, 'Μάώ' => 3, 'Μαώ' => 3, 'Απρ' => 4, 'Μάι' => 5, 'Μαϊ' => 5, 'Μαι' => 5, 'Ιούν' => 6, 'Ιον' => 6, 'Ιούλ' => 7, 'Ιολ' => 7, 'Αύγ' => 8, 'Αυγ' => 8, 'Σεπ' => 9, 'Οκτ' => 10, 'Νοέ' => 11, 'Δεκ' => 12, // Russian 'Янв' => 1, 'января' => 1, 'Фев' => 2, 'февраля' => 2, 'Мар' => 3, 'марта' => 3, 'Апр' => 4, 'апреля' => 4, 'Май' => 5, 'мая' => 5, 'Июн' => 6, 'июня' => 6, 'Июл' => 7, 'июля' => 7, 'Авг' => 8, 'августа' => 8, 'Сен' => 9, 'сентября' => 9, 'Окт' => 10, 'октября' => 10, 'Ноя' => 11, 'ноября' => 11, 'Дек' => 12, 'декабря' => 12, ]; /** * List of timezones, abbreviation => offset from UTC * * @access protected * @var array */ public $timezone = [ 'ACDT' => 37800, 'ACIT' => 28800, 'ACST' => 34200, 'ACT' => -18000, 'ACWDT' => 35100, 'ACWST' => 31500, 'AEDT' => 39600, 'AEST' => 36000, 'AFT' => 16200, 'AKDT' => -28800, 'AKST' => -32400, 'AMDT' => 18000, 'AMT' => -14400, 'ANAST' => 46800, 'ANAT' => 43200, 'ART' => -10800, 'AZOST' => -3600, 'AZST' => 18000, 'AZT' => 14400, 'BIOT' => 21600, 'BIT' => -43200, 'BOT' => -14400, 'BRST' => -7200, 'BRT' => -10800, 'BST' => 3600, 'BTT' => 21600, 'CAST' => 18000, 'CAT' => 7200, 'CCT' => 23400, 'CDT' => -18000, 'CEDT' => 7200, 'CEST' => 7200, 'CET' => 3600, 'CGST' => -7200, 'CGT' => -10800, 'CHADT' => 49500, 'CHAST' => 45900, 'CIST' => -28800, 'CKT' => -36000, 'CLDT' => -10800, 'CLST' => -14400, 'COT' => -18000, 'CST' => -21600, 'CVT' => -3600, 'CXT' => 25200, 'DAVT' => 25200, 'DTAT' => 36000, 'EADT' => -18000, 'EAST' => -21600, 'EAT' => 10800, 'ECT' => -18000, 'EDT' => -14400, 'EEST' => 10800, 'EET' => 7200, 'EGT' => -3600, 'EKST' => 21600, 'EST' => -18000, 'FJT' => 43200, 'FKDT' => -10800, 'FKST' => -14400, 'FNT' => -7200, 'GALT' => -21600, 'GEDT' => 14400, 'GEST' => 10800, 'GFT' => -10800, 'GILT' => 43200, 'GIT' => -32400, 'GST' => 14400, 'GST' => -7200, 'GYT' => -14400, 'HAA' => -10800, 'HAC' => -18000, 'HADT' => -32400, 'HAE' => -14400, 'HAP' => -25200, 'HAR' => -21600, 'HAST' => -36000, 'HAT' => -9000, 'HAY' => -28800, 'HKST' => 28800, 'HMT' => 18000, 'HNA' => -14400, 'HNC' => -21600, 'HNE' => -18000, 'HNP' => -28800, 'HNR' => -25200, 'HNT' => -12600, 'HNY' => -32400, 'IRDT' => 16200, 'IRKST' => 32400, 'IRKT' => 28800, 'IRST' => 12600, 'JFDT' => -10800, 'JFST' => -14400, 'JST' => 32400, 'KGST' => 21600, 'KGT' => 18000, 'KOST' => 39600, 'KOVST' => 28800, 'KOVT' => 25200, 'KRAST' => 28800, 'KRAT' => 25200, 'KST' => 32400, 'LHDT' => 39600, 'LHST' => 37800, 'LINT' => 50400, 'LKT' => 21600, 'MAGST' => 43200, 'MAGT' => 39600, 'MAWT' => 21600, 'MDT' => -21600, 'MESZ' => 7200, 'MEZ' => 3600, 'MHT' => 43200, 'MIT' => -34200, 'MNST' => 32400, 'MSDT' => 14400, 'MSST' => 10800, 'MST' => -25200, 'MUT' => 14400, 'MVT' => 18000, 'MYT' => 28800, 'NCT' => 39600, 'NDT' => -9000, 'NFT' => 41400, 'NMIT' => 36000, 'NOVST' => 25200, 'NOVT' => 21600, 'NPT' => 20700, 'NRT' => 43200, 'NST' => -12600, 'NUT' => -39600, 'NZDT' => 46800, 'NZST' => 43200, 'OMSST' => 25200, 'OMST' => 21600, 'PDT' => -25200, 'PET' => -18000, 'PETST' => 46800, 'PETT' => 43200, 'PGT' => 36000, 'PHOT' => 46800, 'PHT' => 28800, 'PKT' => 18000, 'PMDT' => -7200, 'PMST' => -10800, 'PONT' => 39600, 'PST' => -28800, 'PWT' => 32400, 'PYST' => -10800, 'PYT' => -14400, 'RET' => 14400, 'ROTT' => -10800, 'SAMST' => 18000, 'SAMT' => 14400, 'SAST' => 7200, 'SBT' => 39600, 'SCDT' => 46800, 'SCST' => 43200, 'SCT' => 14400, 'SEST' => 3600, 'SGT' => 28800, 'SIT' => 28800, 'SRT' => -10800, 'SST' => -39600, 'SYST' => 10800, 'SYT' => 7200, 'TFT' => 18000, 'THAT' => -36000, 'TJT' => 18000, 'TKT' => -36000, 'TMT' => 18000, 'TOT' => 46800, 'TPT' => 32400, 'TRUT' => 36000, 'TVT' => 43200, 'TWT' => 28800, 'UYST' => -7200, 'UYT' => -10800, 'UZT' => 18000, 'VET' => -14400, 'VLAST' => 39600, 'VLAT' => 36000, 'VOST' => 21600, 'VUT' => 39600, 'WAST' => 7200, 'WAT' => 3600, 'WDT' => 32400, 'WEST' => 3600, 'WFT' => 43200, 'WIB' => 25200, 'WIT' => 32400, 'WITA' => 28800, 'WKST' => 18000, 'WST' => 28800, 'YAKST' => 36000, 'YAKT' => 32400, 'YAPT' => 36000, 'YEKST' => 21600, 'YEKT' => 18000, ]; /** * Cached PCRE for Date::$day * * @access protected * @var string */ public $day_pcre; /** * Cached PCRE for Date::$month * * @access protected * @var string */ public $month_pcre; /** * Array of user-added callback methods * * @access private * @var array */ public $built_in = []; /** * Array of user-added callback methods * * @access private * @var array */ public $user = []; /** * Create new Date object, and set self::day_pcre, * self::month_pcre, and self::built_in * * @access private */ public function __construct() { $this->day_pcre = '(' . implode('|', array_keys($this->day)) . ')'; $this->month_pcre = '(' . implode('|', array_keys($this->month)) . ')'; static $cache; if (!isset($cache[get_class($this)])) { $all_methods = get_class_methods($this); foreach ($all_methods as $method) { if (strtolower(substr($method, 0, 5)) === 'date_') { $cache[get_class($this)][] = $method; } } } foreach ($cache[get_class($this)] as $method) { $this->built_in[] = $method; } } /** * Get the object * * @access public */ public static function get() { static $object; if (!$object) { $object = new Date(); } return $object; } /** * Parse a date * * @final * @access public * @param string $date Date to parse * @return int Timestamp corresponding to date string, or false on failure */ public function parse($date) { foreach ($this->user as $method) { if (($returned = call_user_func($method, $date)) !== false) { return $returned; } } foreach ($this->built_in as $method) { if (($returned = call_user_func([$this, $method], $date)) !== false) { return $returned; } } return false; } /** * Add a callback method to parse a date * * @final * @access public * @param callable $callback */ public function add_callback($callback) { if (is_callable($callback)) { $this->user[] = $callback; } else { trigger_error('User-supplied function must be a valid callback', E_USER_WARNING); } } /** * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as * well as allowing any of upper or lower case "T", horizontal tabs, or * spaces to be used as the time separator (including more than one)) * * @access protected * @return int Timestamp */ public function date_w3cdtf($date) { $pcre = <<<'PCRE' / ^ (?P<year>[0-9]{4}) (?: -? (?P<month>[0-9]{2}) (?: -? (?P<day>[0-9]{2}) (?: [Tt\x09\x20]+ (?P<hour>[0-9]{2}) (?: :? (?P<minute>[0-9]{2}) (?: :? (?P<second>[0-9]{2}) (?: . (?P<second_fraction>[0-9]*) )? )? )? (?: (?P<zulu>Z) | (?P<tz_sign>[+\-]) (?P<tz_hour>[0-9]{1,2}) :? (?P<tz_minute>[0-9]{1,2}) ) )? )? )? $ /x PCRE; if (preg_match($pcre, $date, $match)) { // Fill in empty matches and convert to proper types. $year = (int) $match['year']; $month = isset($match['month']) ? (int) $match['month'] : 1; $day = isset($match['day']) ? (int) $match['day'] : 1; $hour = isset($match['hour']) ? (int) $match['hour'] : 0; $minute = isset($match['minute']) ? (int) $match['minute'] : 0; $second = isset($match['second']) ? (int) $match['second'] : 0; $second_fraction = isset($match['second_fraction']) ? ((int) $match['second_fraction']) / (10 ** strlen($match['second_fraction'])) : 0; $tz_sign = ($match['tz_sign'] ?? '') === '-' ? -1 : 1; $tz_hour = isset($match['tz_hour']) ? (int) $match['tz_hour'] : 0; $tz_minute = isset($match['tz_minute']) ? (int) $match['tz_minute'] : 0; // Numeric timezone $timezone = $tz_hour * 3600; $timezone += $tz_minute * 60; $timezone *= $tz_sign; // Convert the number of seconds to an integer, taking decimals into account $second = (int) round($second + $second_fraction); return gmmktime($hour, $minute, $second, $month, $day, $year) - $timezone; } return false; } /** * Remove RFC822 comments * * @access protected * @param string $data Data to strip comments from * @return string Comment stripped string */ public function remove_rfc2822_comments($string) { $string = (string) $string; $position = 0; $length = strlen($string); $depth = 0; $output = ''; while ($position < $length && ($pos = strpos($string, '(', $position)) !== false) { $output .= substr($string, $position, $pos - $position); $position = $pos + 1; if ($pos === 0 || $string[$pos - 1] !== '\\') { $depth++; while ($depth && $position < $length) { $position += strcspn($string, '()', $position); if ($string[$position - 1] === '\\') { $position++; continue; } elseif (isset($string[$position])) { switch ($string[$position]) { case '(': $depth++; break; case ')': $depth--; break; } $position++; } else { break; } } } else { $output .= '('; } } $output .= substr($string, $position); return $output; } /** * Parse RFC2822's date format * * @access protected * @return int Timestamp */ public function date_rfc2822($date) { static $pcre; if (!$pcre) { $wsp = '[\x09\x20]'; $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)'; $optional_fws = $fws . '?'; $day_name = $this->day_pcre; $month = $this->month_pcre; $day = '([0-9]{1,2})'; $hour = $minute = $second = '([0-9]{2})'; $year = '([0-9]{2,4})'; $num_zone = '([+\-])([0-9]{2})([0-9]{2})'; $character_zone = '([A-Z]{1,5})'; $zone = '(?:' . $num_zone . '|' . $character_zone . ')'; $pcre = '/(?:' . $optional_fws . $day_name . $optional_fws . ',)?' . $optional_fws . $day . $fws . $month . $fws . $year . $fws . $hour . $optional_fws . ':' . $optional_fws . $minute . '(?:' . $optional_fws . ':' . $optional_fws . $second . ')?' . $fws . $zone . '/i'; } if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match)) { /* Capturing subpatterns: 1: Day name 2: Day 3: Month 4: Year 5: Hour 6: Minute 7: Second 8: Timezone ± 9: Timezone hours 10: Timezone minutes 11: Alphabetic timezone */ // Find the month number $month = $this->month[strtolower($match[3])]; // Numeric timezone if ($match[8] !== '') { $timezone = $match[9] * 3600; $timezone += $match[10] * 60; if ($match[8] === '-') { $timezone = 0 - $timezone; } } // Character timezone elseif (isset($this->timezone[strtoupper($match[11])])) { $timezone = $this->timezone[strtoupper($match[11])]; } // Assume everything else to be -0000 else { $timezone = 0; } // Deal with 2/3 digit years if ($match[4] < 50) { $match[4] += 2000; } elseif ($match[4] < 1000) { $match[4] += 1900; } // Second is optional, if it is empty set it to zero if ($match[7] !== '') { $second = $match[7]; } else { $second = 0; } return gmmktime(intval($match[5]), intval($match[6]), intval($second), intval($month), intval($match[2]), intval($match[4])) - $timezone; } return false; } /** * Parse RFC850's date format * * @access protected * @return int Timestamp */ public function date_rfc850($date) { static $pcre; if (!$pcre) { $space = '[\x09\x20]+'; $day_name = $this->day_pcre; $month = $this->month_pcre; $day = '([0-9]{1,2})'; $year = $hour = $minute = $second = '([0-9]{2})'; $zone = '([A-Z]{1,5})'; $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i'; } if (preg_match($pcre, $date, $match)) { /* Capturing subpatterns: 1: Day name 2: Day 3: Month 4: Year 5: Hour 6: Minute 7: Second 8: Timezone */ // Month $month = $this->month[strtolower($match[3])]; // Character timezone if (isset($this->timezone[strtoupper($match[8])])) { $timezone = $this->timezone[strtoupper($match[8])]; } // Assume everything else to be -0000 else { $timezone = 0; } // Deal with 2 digit year if ($match[4] < 50) { $match[4] += 2000; } else { $match[4] += 1900; } return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone; } return false; } /** * Parse C99's asctime()'s date format * * @access protected * @return int Timestamp */ public function date_asctime($date) { static $pcre; if (!$pcre) { $space = '[\x09\x20]+'; $wday_name = $this->day_pcre; $mon_name = $this->month_pcre; $day = '([0-9]{1,2})'; $hour = $sec = $min = '([0-9]{2})'; $year = '([0-9]{4})'; $terminator = '\x0A?\x00?'; $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i'; } if (preg_match($pcre, $date, $match)) { /* Capturing subpatterns: 1: Day name 2: Month 3: Day 4: Hour 5: Minute 6: Second 7: Year */ $month = $this->month[strtolower($match[2])]; return gmmktime((int) $match[4], (int) $match[5], (int) $match[6], $month, (int) $match[3], (int) $match[7]); } return false; } /** * Parse dates using strtotime() * * @access protected * @return int Timestamp */ public function date_strtotime($date) { $strtotime = strtotime($date); if ($strtotime === -1 || $strtotime === false) { return false; } return $strtotime; } } class_alias('SimplePie\Parse\Date', 'SimplePie_Parse_Date'); PK������ZS���� ��Exception.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie; use Exception as NativeException; /** * General SimplePie exception class * * @package SimplePie */ class Exception extends NativeException { } class_alias('SimplePie\Exception', 'SimplePie_Exception'); PK������ZO��O�� ��Caption.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie; /** * Handles `<media:text>` captions as defined in Media RSS. * * Used by {@see \SimplePie\Enclosure::get_caption()} and {@see \SimplePie\Enclosure::get_captions()} * * This class can be overloaded with {@see \SimplePie\SimplePie::set_caption_class()} * * @package SimplePie * @subpackage API */ class Caption { /** * Content type * * @var string * @see get_type() */ public $type; /** * Language * * @var string * @see get_language() */ public $lang; /** * Start time * * @var string * @see get_starttime() */ public $startTime; /** * End time * * @var string * @see get_endtime() */ public $endTime; /** * Caption text * * @var string * @see get_text() */ public $text; /** * Constructor, used to input the data * * For documentation on all the parameters, see the corresponding * properties and their accessors */ public function __construct($type = null, $lang = null, $startTime = null, $endTime = null, $text = null) { $this->type = $type; $this->lang = $lang; $this->startTime = $startTime; $this->endTime = $endTime; $this->text = $text; } /** * String-ified version * * @return string */ public function __toString() { // There is no $this->data here return md5(serialize($this)); } /** * Get the end time * * @return string|null Time in the format 'hh:mm:ss.SSS' */ public function get_endtime() { if ($this->endTime !== null) { return $this->endTime; } return null; } /** * Get the language * * @link http://tools.ietf.org/html/rfc3066 * @return string|null Language code as per RFC 3066 */ public function get_language() { if ($this->lang !== null) { return $this->lang; } return null; } /** * Get the start time * * @return string|null Time in the format 'hh:mm:ss.SSS' */ public function get_starttime() { if ($this->startTime !== null) { return $this->startTime; } return null; } /** * Get the text of the caption * * @return string|null */ public function get_text() { if ($this->text !== null) { return $this->text; } return null; } /** * Get the content type (not MIME type) * * @return string|null Either 'text' or 'html' */ public function get_type() { if ($this->type !== null) { return $this->type; } return null; } } class_alias('SimplePie\Caption', 'SimplePie_Caption'); PK������Zk!��!�� ��Registry.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie; use SimplePie\Content\Type\Sniffer; use SimplePie\Parse\Date; use SimplePie\XML\Declaration\Parser as DeclarationParser; /** * Handles creating objects and calling methods * * Access this via {@see \SimplePie\SimplePie::get_registry()} * * @package SimplePie */ class Registry { /** * Default class mapping * * Overriding classes *must* subclass these. * * @var array<class-string, class-string> */ protected $default = [ Cache::class => Cache::class, Locator::class => Locator::class, Parser::class => Parser::class, File::class => File::class, Sanitize::class => Sanitize::class, Item::class => Item::class, Author::class => Author::class, Category::class => Category::class, Enclosure::class => Enclosure::class, Caption::class => Caption::class, Copyright::class => Copyright::class, Credit::class => Credit::class, Rating::class => Rating::class, Restriction::class => Restriction::class, Sniffer::class => Sniffer::class, Source::class => Source::class, Misc::class => Misc::class, DeclarationParser::class => DeclarationParser::class, Date::class => Date::class, ]; /** * Class mapping * * @see register() * @var array */ protected $classes = []; /** * Legacy classes * * @see register() * @var array<class-string> */ protected $legacy = []; /** * Legacy types * * @see register() * @var array<string, class-string> */ private $legacyTypes = [ 'Cache' => Cache::class, 'Locator' => Locator::class, 'Parser' => Parser::class, 'File' => File::class, 'Sanitize' => Sanitize::class, 'Item' => Item::class, 'Author' => Author::class, 'Category' => Category::class, 'Enclosure' => Enclosure::class, 'Caption' => Caption::class, 'Copyright' => Copyright::class, 'Credit' => Credit::class, 'Rating' => Rating::class, 'Restriction' => Restriction::class, 'Content_Type_Sniffer' => Sniffer::class, 'Source' => Source::class, 'Misc' => Misc::class, 'XML_Declaration_Parser' => DeclarationParser::class, 'Parse_Date' => Date::class, ]; /** * Constructor * * No-op */ public function __construct() { } /** * Register a class * * @param string $type See {@see $default} for names * @param class-string $class Class name, must subclass the corresponding default * @param bool $legacy Whether to enable legacy support for this class * @return bool Successfulness */ public function register($type, $class, $legacy = false) { if (array_key_exists($type, $this->legacyTypes)) { // trigger_error(sprintf('"%s"(): Using argument #1 ($type) with value "%s" is deprecated since SimplePie 1.8.0, use class-string "%s" instead.', __METHOD__, $type, $this->legacyTypes[$type]), \E_USER_DEPRECATED); $type = $this->legacyTypes[$type]; } if (!array_key_exists($type, $this->default)) { return false; } if (!class_exists($class)) { return false; } /** @var string */ $base_class = $this->default[$type]; if (!is_subclass_of($class, $base_class)) { return false; } $this->classes[$type] = $class; if ($legacy) { $this->legacy[] = $class; } return true; } /** * Get the class registered for a type * * Where possible, use {@see create()} or {@see call()} instead * * @template T * @param class-string<T> $type * @return class-string<T>|null */ public function get_class($type) { if (array_key_exists($type, $this->legacyTypes)) { // trigger_error(sprintf('"%s"(): Using argument #1 ($type) with value "%s" is deprecated since SimplePie 1.8.0, use class-string "%s" instead.', __METHOD__, $type, $this->legacyTypes[$type]), \E_USER_DEPRECATED); $type = $this->legacyTypes[$type]; } if (!array_key_exists($type, $this->default)) { return null; } $class = $this->default[$type]; if (array_key_exists($type, $this->classes)) { $class = $this->classes[$type]; } return $class; } /** * Create a new instance of a given type * * @template T class-string $type * @param class-string<T> $type * @param array $parameters Parameters to pass to the constructor * @return T Instance of class */ public function &create($type, $parameters = []) { $class = $this->get_class($type); if (!method_exists($class, '__construct')) { $instance = new $class(); } else { $reflector = new \ReflectionClass($class); $instance = $reflector->newInstanceArgs($parameters); } if ($instance instanceof RegistryAware) { $instance->set_registry($this); } elseif (method_exists($instance, 'set_registry')) { trigger_error(sprintf('Using the method "set_registry()" without implementing "%s" is deprecated since SimplePie 1.8.0, implement "%s" in "%s".', RegistryAware::class, RegistryAware::class, $class), \E_USER_DEPRECATED); $instance->set_registry($this); } return $instance; } /** * Call a static method for a type * * @param class-string $type * @param string $method * @param array $parameters * @return mixed */ public function &call($type, $method, $parameters = []) { $class = $this->get_class($type); if (in_array($class, $this->legacy)) { switch ($type) { case Cache::class: // For backwards compatibility with old non-static // Cache::create() methods in PHP < 8.0. // No longer supported as of PHP 8.0. if ($method === 'get_handler') { $result = @call_user_func_array([$class, 'create'], $parameters); return $result; } break; } } $result = call_user_func_array([$class, $method], $parameters); return $result; } } class_alias('SimplePie\Registry', 'SimplePie_Registry'); PK������ZR`*;��;����IRI.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie; /** * IRI parser/serialiser/normaliser * * @package SimplePie * @subpackage HTTP * @author Sam Sneddon * @author Steve Minutillo * @author Ryan McCue * @copyright 2007-2012 Sam Sneddon, Steve Minutillo, Ryan McCue * @license http://www.opensource.org/licenses/bsd-license.php */ class IRI { /** * Scheme * * @var string */ protected $scheme = null; /** * User Information * * @var string */ protected $iuserinfo = null; /** * ihost * * @var string */ protected $ihost = null; /** * Port * * @var string */ protected $port = null; /** * ipath * * @var string */ protected $ipath = ''; /** * iquery * * @var string */ protected $iquery = null; /** * ifragment * * @var string */ protected $ifragment = null; /** * Normalization database * * Each key is the scheme, each value is an array with each key as the IRI * part and value as the default value for that part. */ protected $normalization = [ 'acap' => [ 'port' => 674 ], 'dict' => [ 'port' => 2628 ], 'file' => [ 'ihost' => 'localhost' ], 'http' => [ 'port' => 80, 'ipath' => '/' ], 'https' => [ 'port' => 443, 'ipath' => '/' ], ]; /** * Return the entire IRI when you try and read the object as a string * * @return string */ public function __toString() { return $this->get_iri(); } /** * Overload __set() to provide access via properties * * @param string $name Property name * @param mixed $value Property value */ public function __set($name, $value) { if (method_exists($this, 'set_' . $name)) { call_user_func([$this, 'set_' . $name], $value); } elseif ( $name === 'iauthority' || $name === 'iuserinfo' || $name === 'ihost' || $name === 'ipath' || $name === 'iquery' || $name === 'ifragment' ) { call_user_func([$this, 'set_' . substr($name, 1)], $value); } } /** * Overload __get() to provide access via properties * * @param string $name Property name * @return mixed */ public function __get($name) { // isset() returns false for null, we don't want to do that // Also why we use array_key_exists below instead of isset() $props = get_object_vars($this); if ( $name === 'iri' || $name === 'uri' || $name === 'iauthority' || $name === 'authority' ) { $return = $this->{"get_$name"}(); } elseif (array_key_exists($name, $props)) { $return = $this->$name; } // host -> ihost elseif (($prop = 'i' . $name) && array_key_exists($prop, $props)) { $name = $prop; $return = $this->$prop; } // ischeme -> scheme elseif (($prop = substr($name, 1)) && array_key_exists($prop, $props)) { $name = $prop; $return = $this->$prop; } else { trigger_error('Undefined property: ' . get_class($this) . '::' . $name, E_USER_NOTICE); $return = null; } if ($return === null && isset($this->normalization[$this->scheme][$name])) { return $this->normalization[$this->scheme][$name]; } return $return; } /** * Overload __isset() to provide access via properties * * @param string $name Property name * @return bool */ public function __isset($name) { return method_exists($this, 'get_' . $name) || isset($this->$name); } /** * Overload __unset() to provide access via properties * * @param string $name Property name */ public function __unset($name) { if (method_exists($this, 'set_' . $name)) { call_user_func([$this, 'set_' . $name], ''); } } /** * Create a new IRI object, from a specified string * * @param string $iri */ public function __construct($iri = null) { $this->set_iri($iri); } /** * Clean up */ public function __destruct() { $this->set_iri(null, true); $this->set_path(null, true); $this->set_authority(null, true); } /** * Create a new IRI object by resolving a relative IRI * * Returns false if $base is not absolute, otherwise an IRI. * * @param IRI|string $base (Absolute) Base IRI * @param IRI|string $relative Relative IRI * @return IRI|false */ public static function absolutize($base, $relative) { if (!($relative instanceof IRI)) { $relative = new IRI($relative); } if (!$relative->is_valid()) { return false; } elseif ($relative->scheme !== null) { return clone $relative; } else { if (!($base instanceof IRI)) { $base = new IRI($base); } if ($base->scheme !== null && $base->is_valid()) { if ($relative->get_iri() !== '') { if ($relative->iuserinfo !== null || $relative->ihost !== null || $relative->port !== null) { $target = clone $relative; $target->scheme = $base->scheme; } else { $target = new IRI(); $target->scheme = $base->scheme; $target->iuserinfo = $base->iuserinfo; $target->ihost = $base->ihost; $target->port = $base->port; if ($relative->ipath !== '') { if ($relative->ipath[0] === '/') { $target->ipath = $relative->ipath; } elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '') { $target->ipath = '/' . $relative->ipath; } elseif (($last_segment = strrpos($base->ipath, '/')) !== false) { $target->ipath = substr($base->ipath, 0, $last_segment + 1) . $relative->ipath; } else { $target->ipath = $relative->ipath; } $target->ipath = $target->remove_dot_segments($target->ipath); $target->iquery = $relative->iquery; } else { $target->ipath = $base->ipath; if ($relative->iquery !== null) { $target->iquery = $relative->iquery; } elseif ($base->iquery !== null) { $target->iquery = $base->iquery; } } $target->ifragment = $relative->ifragment; } } else { $target = clone $base; $target->ifragment = null; } $target->scheme_normalization(); return $target; } return false; } } /** * Parse an IRI into scheme/authority/path/query/fragment segments * * @param string $iri * @return array */ protected function parse_iri($iri) { $iri = trim($iri, "\x20\x09\x0A\x0C\x0D"); if (preg_match('/^((?P<scheme>[^:\/?#]+):)?(\/\/(?P<authority>[^\/?#]*))?(?P<path>[^?#]*)(\?(?P<query>[^#]*))?(#(?P<fragment>.*))?$/', $iri, $match)) { if ($match[1] === '') { $match['scheme'] = null; } if (!isset($match[3]) || $match[3] === '') { $match['authority'] = null; } if (!isset($match[5])) { $match['path'] = ''; } if (!isset($match[6]) || $match[6] === '') { $match['query'] = null; } if (!isset($match[8]) || $match[8] === '') { $match['fragment'] = null; } return $match; } // This can occur when a paragraph is accidentally parsed as a URI return false; } /** * Remove dot segments from a path * * @param string $input * @return string */ protected function remove_dot_segments($input) { $output = ''; while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..') { // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise, if (strpos($input, '../') === 0) { $input = substr($input, 3); } elseif (strpos($input, './') === 0) { $input = substr($input, 2); } // B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise, elseif (strpos($input, '/./') === 0) { $input = substr($input, 2); } elseif ($input === '/.') { $input = '/'; } // C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise, elseif (strpos($input, '/../') === 0) { $input = substr($input, 3); $output = substr_replace($output, '', intval(strrpos($output, '/'))); } elseif ($input === '/..') { $input = '/'; $output = substr_replace($output, '', intval(strrpos($output, '/'))); } // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise, elseif ($input === '.' || $input === '..') { $input = ''; } // E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer elseif (($pos = strpos($input, '/', 1)) !== false) { $output .= substr($input, 0, $pos); $input = substr_replace($input, '', 0, $pos); } else { $output .= $input; $input = ''; } } return $output . $input; } /** * Replace invalid character with percent encoding * * @param string $string Input string * @param string $extra_chars Valid characters not in iunreserved or * iprivate (this is ASCII-only) * @param bool $iprivate Allow iprivate * @return string */ protected function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false) { // Normalize as many pct-encoded sections as possible $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', [$this, 'remove_iunreserved_percent_encoded'], $string); // Replace invalid percent characters $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string); // Add unreserved and % to $extra_chars (the latter is safe because all // pct-encoded sections are now valid). $extra_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%'; // Now replace any bytes that aren't allowed with their pct-encoded versions $position = 0; $strlen = strlen($string); while (($position += strspn($string, $extra_chars, $position)) < $strlen) { $value = ord($string[$position]); $character = 0; // Start position $start = $position; // By default we are valid $valid = true; // No one byte sequences are valid due to the while. // Two byte sequence: if (($value & 0xE0) === 0xC0) { $character = ($value & 0x1F) << 6; $length = 2; $remaining = 1; } // Three byte sequence: elseif (($value & 0xF0) === 0xE0) { $character = ($value & 0x0F) << 12; $length = 3; $remaining = 2; } // Four byte sequence: elseif (($value & 0xF8) === 0xF0) { $character = ($value & 0x07) << 18; $length = 4; $remaining = 3; } // Invalid byte: else { $valid = false; $length = 1; $remaining = 0; } if ($remaining) { if ($position + $length <= $strlen) { for ($position++; $remaining; $position++) { $value = ord($string[$position]); // Check that the byte is valid, then add it to the character: if (($value & 0xC0) === 0x80) { $character |= ($value & 0x3F) << (--$remaining * 6); } // If it is invalid, count the sequence as invalid and reprocess the current byte: else { $valid = false; $position--; break; } } } else { $position = $strlen - 1; $valid = false; } } // Percent encode anything invalid or not in ucschar if ( // Invalid sequences !$valid // Non-shortest form sequences are invalid || $length > 1 && $character <= 0x7F || $length > 2 && $character <= 0x7FF || $length > 3 && $character <= 0xFFFF // Outside of range of ucschar codepoints // Noncharacters || ($character & 0xFFFE) === 0xFFFE || $character >= 0xFDD0 && $character <= 0xFDEF || ( // Everything else not in ucschar $character > 0xD7FF && $character < 0xF900 || $character < 0xA0 || $character > 0xEFFFD ) && ( // Everything not in iprivate, if it applies !$iprivate || $character < 0xE000 || $character > 0x10FFFD ) ) { // If we were a character, pretend we weren't, but rather an error. if ($valid) { $position--; } for ($j = $start; $j <= $position; $j++) { $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1); $j += 2; $position += 2; $strlen += 2; } } } return $string; } /** * Callback function for preg_replace_callback. * * Removes sequences of percent encoded bytes that represent UTF-8 * encoded characters in iunreserved * * @param array $match PCRE match * @return string Replacement */ protected function remove_iunreserved_percent_encoded($match) { // As we just have valid percent encoded sequences we can just explode // and ignore the first member of the returned array (an empty string). $bytes = explode('%', $match[0]); // Initialize the new string (this is what will be returned) and that // there are no bytes remaining in the current sequence (unsurprising // at the first byte!). $string = ''; $remaining = 0; // these variables will be initialized in the loop but PHPStan is not able to detect it currently $start = 0; $character = 0; $length = 0; $valid = true; // Loop over each and every byte, and set $value to its value for ($i = 1, $len = count($bytes); $i < $len; $i++) { $value = hexdec($bytes[$i]); // If we're the first byte of sequence: if (!$remaining) { // Start position $start = $i; // By default we are valid $valid = true; // One byte sequence: if ($value <= 0x7F) { $character = $value; $length = 1; } // Two byte sequence: elseif (($value & 0xE0) === 0xC0) { $character = ($value & 0x1F) << 6; $length = 2; $remaining = 1; } // Three byte sequence: elseif (($value & 0xF0) === 0xE0) { $character = ($value & 0x0F) << 12; $length = 3; $remaining = 2; } // Four byte sequence: elseif (($value & 0xF8) === 0xF0) { $character = ($value & 0x07) << 18; $length = 4; $remaining = 3; } // Invalid byte: else { $valid = false; $remaining = 0; } } // Continuation byte: else { // Check that the byte is valid, then add it to the character: if (($value & 0xC0) === 0x80) { $remaining--; $character |= ($value & 0x3F) << ($remaining * 6); } // If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence: else { $valid = false; $remaining = 0; $i--; } } // If we've reached the end of the current byte sequence, append it to Unicode::$data if (!$remaining) { // Percent encode anything invalid or not in iunreserved if ( // Invalid sequences !$valid // Non-shortest form sequences are invalid || $length > 1 && $character <= 0x7F || $length > 2 && $character <= 0x7FF || $length > 3 && $character <= 0xFFFF // Outside of range of iunreserved codepoints || $character < 0x2D || $character > 0xEFFFD // Noncharacters || ($character & 0xFFFE) === 0xFFFE || $character >= 0xFDD0 && $character <= 0xFDEF // Everything else not in iunreserved (this is all BMP) || $character === 0x2F || $character > 0x39 && $character < 0x41 || $character > 0x5A && $character < 0x61 || $character > 0x7A && $character < 0x7E || $character > 0x7E && $character < 0xA0 || $character > 0xD7FF && $character < 0xF900 ) { for ($j = $start; $j <= $i; $j++) { $string .= '%' . strtoupper($bytes[$j]); } } else { for ($j = $start; $j <= $i; $j++) { $string .= chr(hexdec($bytes[$j])); } } } } // If we have any bytes left over they are invalid (i.e., we are // mid-way through a multi-byte sequence) if ($remaining) { for ($j = $start; $j < $len; $j++) { $string .= '%' . strtoupper($bytes[$j]); } } return $string; } protected function scheme_normalization() { if (isset($this->normalization[$this->scheme]['iuserinfo']) && $this->iuserinfo === $this->normalization[$this->scheme]['iuserinfo']) { $this->iuserinfo = null; } if (isset($this->normalization[$this->scheme]['ihost']) && $this->ihost === $this->normalization[$this->scheme]['ihost']) { $this->ihost = null; } if (isset($this->normalization[$this->scheme]['port']) && $this->port === $this->normalization[$this->scheme]['port']) { $this->port = null; } if (isset($this->normalization[$this->scheme]['ipath']) && $this->ipath === $this->normalization[$this->scheme]['ipath']) { $this->ipath = ''; } if (isset($this->normalization[$this->scheme]['iquery']) && $this->iquery === $this->normalization[$this->scheme]['iquery']) { $this->iquery = null; } if (isset($this->normalization[$this->scheme]['ifragment']) && $this->ifragment === $this->normalization[$this->scheme]['ifragment']) { $this->ifragment = null; } } /** * Check if the object represents a valid IRI. This needs to be done on each * call as some things change depending on another part of the IRI. * * @return bool */ public function is_valid() { if ($this->ipath === '') { return true; } $isauthority = $this->iuserinfo !== null || $this->ihost !== null || $this->port !== null; if ($isauthority && $this->ipath[0] === '/') { return true; } if (!$isauthority && (substr($this->ipath, 0, 2) === '//')) { return false; } // Relative urls cannot have a colon in the first path segment (and the // slashes themselves are not included so skip the first character). if (!$this->scheme && !$isauthority && strpos($this->ipath, ':') !== false && strpos($this->ipath, '/', 1) !== false && strpos($this->ipath, ':') < strpos($this->ipath, '/', 1)) { return false; } return true; } /** * Set the entire IRI. Returns true on success, false on failure (if there * are any invalid characters). * * @param string $iri * @return bool */ public function set_iri($iri, $clear_cache = false) { static $cache; if ($clear_cache) { $cache = null; return; } if (!$cache) { $cache = []; } if ($iri === null) { return true; } elseif (isset($cache[$iri])) { [ $this->scheme, $this->iuserinfo, $this->ihost, $this->port, $this->ipath, $this->iquery, $this->ifragment, $return ] = $cache[$iri]; return $return; } $parsed = $this->parse_iri((string) $iri); if (!$parsed) { return false; } $return = $this->set_scheme($parsed['scheme']) && $this->set_authority($parsed['authority']) && $this->set_path($parsed['path']) && $this->set_query($parsed['query']) && $this->set_fragment($parsed['fragment']); $cache[$iri] = [ $this->scheme, $this->iuserinfo, $this->ihost, $this->port, $this->ipath, $this->iquery, $this->ifragment, $return ]; return $return; } /** * Set the scheme. Returns true on success, false on failure (if there are * any invalid characters). * * @param string $scheme * @return bool */ public function set_scheme($scheme) { if ($scheme === null) { $this->scheme = null; } elseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\-.]*$/', $scheme)) { $this->scheme = null; return false; } else { $this->scheme = strtolower($scheme); } return true; } /** * Set the authority. Returns true on success, false on failure (if there are * any invalid characters). * * @param string $authority * @return bool */ public function set_authority($authority, $clear_cache = false) { static $cache; if ($clear_cache) { $cache = null; return; } if (!$cache) { $cache = []; } if ($authority === null) { $this->iuserinfo = null; $this->ihost = null; $this->port = null; return true; } elseif (isset($cache[$authority])) { [ $this->iuserinfo, $this->ihost, $this->port, $return ] = $cache[$authority]; return $return; } $remaining = $authority; if (($iuserinfo_end = strrpos($remaining, '@')) !== false) { $iuserinfo = substr($remaining, 0, $iuserinfo_end); $remaining = substr($remaining, $iuserinfo_end + 1); } else { $iuserinfo = null; } if (($port_start = strpos($remaining, ':', intval(strpos($remaining, ']')))) !== false) { if (($port = substr($remaining, $port_start + 1)) === false) { $port = null; } $remaining = substr($remaining, 0, $port_start); } else { $port = null; } $return = $this->set_userinfo($iuserinfo) && $this->set_host($remaining) && $this->set_port($port); $cache[$authority] = [ $this->iuserinfo, $this->ihost, $this->port, $return ]; return $return; } /** * Set the iuserinfo. * * @param string $iuserinfo * @return bool */ public function set_userinfo($iuserinfo) { if ($iuserinfo === null) { $this->iuserinfo = null; } else { $this->iuserinfo = $this->replace_invalid_with_pct_encoding($iuserinfo, '!$&\'()*+,;=:'); $this->scheme_normalization(); } return true; } /** * Set the ihost. Returns true on success, false on failure (if there are * any invalid characters). * * @param string $ihost * @return bool */ public function set_host($ihost) { if ($ihost === null) { $this->ihost = null; return true; } elseif (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']') { if (\SimplePie\Net\IPv6::check_ipv6(substr($ihost, 1, -1))) { $this->ihost = '[' . \SimplePie\Net\IPv6::compress(substr($ihost, 1, -1)) . ']'; } else { $this->ihost = null; return false; } } else { $ihost = $this->replace_invalid_with_pct_encoding($ihost, '!$&\'()*+,;='); // Lowercase, but ignore pct-encoded sections (as they should // remain uppercase). This must be done after the previous step // as that can add unescaped characters. $position = 0; $strlen = strlen($ihost); while (($position += strcspn($ihost, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ%', $position)) < $strlen) { if ($ihost[$position] === '%') { $position += 3; } else { $ihost[$position] = strtolower($ihost[$position]); $position++; } } $this->ihost = $ihost; } $this->scheme_normalization(); return true; } /** * Set the port. Returns true on success, false on failure (if there are * any invalid characters). * * @param string $port * @return bool */ public function set_port($port) { if ($port === null) { $this->port = null; return true; } elseif (strspn($port, '0123456789') === strlen($port)) { $this->port = (int) $port; $this->scheme_normalization(); return true; } $this->port = null; return false; } /** * Set the ipath. * * @param string $ipath * @return bool */ public function set_path($ipath, $clear_cache = false) { static $cache; if ($clear_cache) { $cache = null; return; } if (!$cache) { $cache = []; } $ipath = (string) $ipath; if (isset($cache[$ipath])) { $this->ipath = $cache[$ipath][(int) ($this->scheme !== null)]; } else { $valid = $this->replace_invalid_with_pct_encoding($ipath, '!$&\'()*+,;=@:/'); $removed = $this->remove_dot_segments($valid); $cache[$ipath] = [$valid, $removed]; $this->ipath = ($this->scheme !== null) ? $removed : $valid; } $this->scheme_normalization(); return true; } /** * Set the iquery. * * @param string $iquery * @return bool */ public function set_query($iquery) { if ($iquery === null) { $this->iquery = null; } else { $this->iquery = $this->replace_invalid_with_pct_encoding($iquery, '!$&\'()*+,;=:@/?', true); $this->scheme_normalization(); } return true; } /** * Set the ifragment. * * @param string $ifragment * @return bool */ public function set_fragment($ifragment) { if ($ifragment === null) { $this->ifragment = null; } else { $this->ifragment = $this->replace_invalid_with_pct_encoding($ifragment, '!$&\'()*+,;=:@/?'); $this->scheme_normalization(); } return true; } /** * Convert an IRI to a URI (or parts thereof) * * @return string */ public function to_uri($string) { static $non_ascii; if (!$non_ascii) { $non_ascii = implode('', range("\x80", "\xFF")); } $position = 0; $strlen = strlen($string); while (($position += strcspn($string, $non_ascii, $position)) < $strlen) { $string = substr_replace($string, sprintf('%%%02X', ord($string[$position])), $position, 1); $position += 3; $strlen += 2; } return $string; } /** * Get the complete IRI * * @return string */ public function get_iri() { if (!$this->is_valid()) { return false; } $iri = ''; if ($this->scheme !== null) { $iri .= $this->scheme . ':'; } if (($iauthority = $this->get_iauthority()) !== null) { $iri .= '//' . $iauthority; } if ($this->ipath !== '') { $iri .= $this->ipath; } elseif (!empty($this->normalization[$this->scheme]['ipath']) && $iauthority !== null && $iauthority !== '') { $iri .= $this->normalization[$this->scheme]['ipath']; } if ($this->iquery !== null) { $iri .= '?' . $this->iquery; } if ($this->ifragment !== null) { $iri .= '#' . $this->ifragment; } return $iri; } /** * Get the complete URI * * @return string */ public function get_uri() { return $this->to_uri($this->get_iri()); } /** * Get the complete iauthority * * @return string */ protected function get_iauthority() { if ($this->iuserinfo !== null || $this->ihost !== null || $this->port !== null) { $iauthority = ''; if ($this->iuserinfo !== null) { $iauthority .= $this->iuserinfo . '@'; } if ($this->ihost !== null) { $iauthority .= $this->ihost; } if ($this->port !== null && $this->port !== 0) { $iauthority .= ':' . $this->port; } return $iauthority; } return null; } /** * Get the complete authority * * @return string */ protected function get_authority() { $iauthority = $this->get_iauthority(); if (is_string($iauthority)) { return $this->to_uri($iauthority); } return $iauthority; } } class_alias('SimplePie\IRI', 'SimplePie_IRI'); PK������Z<82'��'�� ��Gzdecode.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie; /** * Decode 'gzip' encoded HTTP data * * @package SimplePie * @subpackage HTTP * @link http://www.gzip.org/format.txt */ class Gzdecode { /** * Compressed data * * @access private * @var string * @see gzdecode::$data */ public $compressed_data; /** * Size of compressed data * * @access private * @var int */ public $compressed_size; /** * Minimum size of a valid gzip string * * @access private * @var int */ public $min_compressed_size = 18; /** * Current position of pointer * * @access private * @var int */ public $position = 0; /** * Flags (FLG) * * @access private * @var int */ public $flags; /** * Uncompressed data * * @access public * @see gzdecode::$compressed_data * @var string */ public $data; /** * Modified time * * @access public * @var int */ public $MTIME; /** * Extra Flags * * @access public * @var int */ public $XFL; /** * Operating System * * @access public * @var int */ public $OS; /** * Subfield ID 1 * * @access public * @see gzdecode::$extra_field * @see gzdecode::$SI2 * @var string */ public $SI1; /** * Subfield ID 2 * * @access public * @see gzdecode::$extra_field * @see gzdecode::$SI1 * @var string */ public $SI2; /** * Extra field content * * @access public * @see gzdecode::$SI1 * @see gzdecode::$SI2 * @var string */ public $extra_field; /** * Original filename * * @access public * @var string */ public $filename; /** * Human readable comment * * @access public * @var string */ public $comment; /** * Don't allow anything to be set * * @param string $name * @param mixed $value */ public function __set($name, $value) { throw new Exception("Cannot write property $name"); } /** * Set the compressed string and related properties * * @param string $data */ public function __construct($data) { $this->compressed_data = $data; $this->compressed_size = strlen($data); } /** * Decode the GZIP stream * * @return bool Successfulness */ public function parse() { if ($this->compressed_size >= $this->min_compressed_size) { $len = 0; // Check ID1, ID2, and CM if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08") { return false; } // Get the FLG (FLaGs) $this->flags = ord($this->compressed_data[3]); // FLG bits above (1 << 4) are reserved if ($this->flags > 0x1F) { return false; } // Advance the pointer after the above $this->position += 4; // MTIME $mtime = substr($this->compressed_data, $this->position, 4); // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness if (current(unpack('S', "\x00\x01")) === 1) { $mtime = strrev($mtime); } $this->MTIME = current(unpack('l', $mtime)); $this->position += 4; // Get the XFL (eXtra FLags) $this->XFL = ord($this->compressed_data[$this->position++]); // Get the OS (Operating System) $this->OS = ord($this->compressed_data[$this->position++]); // Parse the FEXTRA if ($this->flags & 4) { // Read subfield IDs $this->SI1 = $this->compressed_data[$this->position++]; $this->SI2 = $this->compressed_data[$this->position++]; // SI2 set to zero is reserved for future use if ($this->SI2 === "\x00") { return false; } // Get the length of the extra field $len = current(unpack('v', substr($this->compressed_data, $this->position, 2))); $this->position += 2; // Check the length of the string is still valid $this->min_compressed_size += $len + 4; if ($this->compressed_size >= $this->min_compressed_size) { // Set the extra field to the given data $this->extra_field = substr($this->compressed_data, $this->position, $len); $this->position += $len; } else { return false; } } // Parse the FNAME if ($this->flags & 8) { // Get the length of the filename $len = strcspn($this->compressed_data, "\x00", $this->position); // Check the length of the string is still valid $this->min_compressed_size += $len + 1; if ($this->compressed_size >= $this->min_compressed_size) { // Set the original filename to the given string $this->filename = substr($this->compressed_data, $this->position, $len); $this->position += $len + 1; } else { return false; } } // Parse the FCOMMENT if ($this->flags & 16) { // Get the length of the comment $len = strcspn($this->compressed_data, "\x00", $this->position); // Check the length of the string is still valid $this->min_compressed_size += $len + 1; if ($this->compressed_size >= $this->min_compressed_size) { // Set the original comment to the given string $this->comment = substr($this->compressed_data, $this->position, $len); $this->position += $len + 1; } else { return false; } } // Parse the FHCRC if ($this->flags & 2) { // Check the length of the string is still valid $this->min_compressed_size += $len + 2; if ($this->compressed_size >= $this->min_compressed_size) { // Read the CRC $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2))); // Check the CRC matches if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc) { $this->position += 2; } else { return false; } } else { return false; } } // Decompress the actual data if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false) { return false; } $this->position = $this->compressed_size - 8; // Check CRC of data $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4))); $this->position += 4; /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc)) { return false; }*/ // Check ISIZE of data $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4))); $this->position += 4; if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize)) { return false; } // Wow, against all odds, we've actually got a valid gzip string return true; } return false; } } class_alias('SimplePie\Gzdecode', 'SimplePie_gzdecode'); PK������Zp � ���Misc.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie; use SimplePie\XML\Declaration\Parser; /** * Miscellaneous utilities * * @package SimplePie */ class Misc { private static $SIMPLEPIE_BUILD = null; public static function time_hms($seconds) { $time = ''; $hours = floor($seconds / 3600); $remainder = $seconds % 3600; if ($hours > 0) { $time .= $hours.':'; } $minutes = floor($remainder / 60); $seconds = $remainder % 60; if ($minutes < 10 && $hours > 0) { $minutes = '0' . $minutes; } if ($seconds < 10) { $seconds = '0' . $seconds; } $time .= $minutes.':'; $time .= $seconds; return $time; } public static function absolutize_url($relative, $base) { $iri = \SimplePie\IRI::absolutize(new \SimplePie\IRI($base), $relative); if ($iri === false) { return false; } return $iri->get_uri(); } /** * Get a HTML/XML element from a HTML string * * @deprecated since SimplePie 1.3, use DOMDocument instead (parsing HTML with regex is bad!) * @param string $realname Element name (including namespace prefix if applicable) * @param string $string HTML document * @return array */ public static function get_element($realname, $string) { // trigger_error(sprintf('Using method "' . __METHOD__ . '" is deprecated since SimplePie 1.3, use "DOMDocument" instead.'), \E_USER_DEPRECATED); $return = []; $name = preg_quote($realname, '/'); if (preg_match_all("/<($name)" . \SimplePie\SimplePie::PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++) { $return[$i]['tag'] = $realname; $return[$i]['full'] = $matches[$i][0][0]; $return[$i]['offset'] = $matches[$i][0][1]; if (strlen($matches[$i][3][0]) <= 2) { $return[$i]['self_closing'] = true; } else { $return[$i]['self_closing'] = false; $return[$i]['content'] = $matches[$i][4][0]; } $return[$i]['attribs'] = []; if (isset($matches[$i][2][0]) && preg_match_all('/[\x09\x0A\x0B\x0C\x0D\x20]+([^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*)(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"([^"]*)"|\'([^\']*)\'|([^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?/', ' ' . $matches[$i][2][0] . ' ', $attribs, PREG_SET_ORDER)) { for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++) { if (count($attribs[$j]) === 2) { $attribs[$j][2] = $attribs[$j][1]; } $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = Misc::entities_decode(end($attribs[$j])); } } } } return $return; } public static function element_implode($element) { $full = "<$element[tag]"; foreach ($element['attribs'] as $key => $value) { $key = strtolower($key); $full .= " $key=\"" . htmlspecialchars($value['data'], ENT_COMPAT, 'UTF-8') . '"'; } if ($element['self_closing']) { $full .= ' />'; } else { $full .= ">$element[content]</$element[tag]>"; } return $full; } public static function error($message, $level, $file, $line) { if ((error_reporting() & $level) > 0) { switch ($level) { case E_USER_ERROR: $note = 'PHP Error'; break; case E_USER_WARNING: $note = 'PHP Warning'; break; case E_USER_NOTICE: $note = 'PHP Notice'; break; default: $note = 'Unknown Error'; break; } $log_error = true; if (!function_exists('error_log')) { $log_error = false; } $log_file = @ini_get('error_log'); if (!empty($log_file) && ('syslog' !== $log_file) && !@is_writable($log_file)) { $log_error = false; } if ($log_error) { @error_log("$note: $message in $file on line $line", 0); } } return $message; } public static function fix_protocol($url, $http = 1) { $url = Misc::normalize_url($url); $parsed = Misc::parse_url($url); if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https') { return Misc::fix_protocol(Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http); } if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url)) { return Misc::fix_protocol(Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http); } if ($http === 2 && $parsed['scheme'] !== '') { return "feed:$url"; } elseif ($http === 3 && strtolower($parsed['scheme']) === 'http') { return substr_replace($url, 'podcast', 0, 4); } elseif ($http === 4 && strtolower($parsed['scheme']) === 'http') { return substr_replace($url, 'itpc', 0, 4); } return $url; } /** * @deprecated since SimplePie 1.8.0, use PHP native array_replace_recursive() instead. */ public static function array_merge_recursive($array1, $array2) { foreach ($array2 as $key => $value) { if (is_array($value)) { $array1[$key] = Misc::array_merge_recursive($array1[$key], $value); } else { $array1[$key] = $value; } } return $array1; } public static function parse_url($url) { $iri = new \SimplePie\IRI($url); return [ 'scheme' => (string) $iri->scheme, 'authority' => (string) $iri->authority, 'path' => (string) $iri->path, 'query' => (string) $iri->query, 'fragment' => (string) $iri->fragment ]; } public static function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '') { $iri = new \SimplePie\IRI(''); $iri->scheme = $scheme; $iri->authority = $authority; $iri->path = $path; $iri->query = $query; $iri->fragment = $fragment; return $iri->get_uri(); } public static function normalize_url($url) { $iri = new \SimplePie\IRI($url); return $iri->get_uri(); } public static function percent_encoding_normalization($match) { $integer = hexdec($match[1]); if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E) { return chr($integer); } return strtoupper($match[0]); } /** * Converts a Windows-1252 encoded string to a UTF-8 encoded string * * @static * @param string $string Windows-1252 encoded string * @return string UTF-8 encoded string */ public static function windows_1252_to_utf8($string) { static $convert_table = ["\x80" => "\xE2\x82\xAC", "\x81" => "\xEF\xBF\xBD", "\x82" => "\xE2\x80\x9A", "\x83" => "\xC6\x92", "\x84" => "\xE2\x80\x9E", "\x85" => "\xE2\x80\xA6", "\x86" => "\xE2\x80\xA0", "\x87" => "\xE2\x80\xA1", "\x88" => "\xCB\x86", "\x89" => "\xE2\x80\xB0", "\x8A" => "\xC5\xA0", "\x8B" => "\xE2\x80\xB9", "\x8C" => "\xC5\x92", "\x8D" => "\xEF\xBF\xBD", "\x8E" => "\xC5\xBD", "\x8F" => "\xEF\xBF\xBD", "\x90" => "\xEF\xBF\xBD", "\x91" => "\xE2\x80\x98", "\x92" => "\xE2\x80\x99", "\x93" => "\xE2\x80\x9C", "\x94" => "\xE2\x80\x9D", "\x95" => "\xE2\x80\xA2", "\x96" => "\xE2\x80\x93", "\x97" => "\xE2\x80\x94", "\x98" => "\xCB\x9C", "\x99" => "\xE2\x84\xA2", "\x9A" => "\xC5\xA1", "\x9B" => "\xE2\x80\xBA", "\x9C" => "\xC5\x93", "\x9D" => "\xEF\xBF\xBD", "\x9E" => "\xC5\xBE", "\x9F" => "\xC5\xB8", "\xA0" => "\xC2\xA0", "\xA1" => "\xC2\xA1", "\xA2" => "\xC2\xA2", "\xA3" => "\xC2\xA3", "\xA4" => "\xC2\xA4", "\xA5" => "\xC2\xA5", "\xA6" => "\xC2\xA6", "\xA7" => "\xC2\xA7", "\xA8" => "\xC2\xA8", "\xA9" => "\xC2\xA9", "\xAA" => "\xC2\xAA", "\xAB" => "\xC2\xAB", "\xAC" => "\xC2\xAC", "\xAD" => "\xC2\xAD", "\xAE" => "\xC2\xAE", "\xAF" => "\xC2\xAF", "\xB0" => "\xC2\xB0", "\xB1" => "\xC2\xB1", "\xB2" => "\xC2\xB2", "\xB3" => "\xC2\xB3", "\xB4" => "\xC2\xB4", "\xB5" => "\xC2\xB5", "\xB6" => "\xC2\xB6", "\xB7" => "\xC2\xB7", "\xB8" => "\xC2\xB8", "\xB9" => "\xC2\xB9", "\xBA" => "\xC2\xBA", "\xBB" => "\xC2\xBB", "\xBC" => "\xC2\xBC", "\xBD" => "\xC2\xBD", "\xBE" => "\xC2\xBE", "\xBF" => "\xC2\xBF", "\xC0" => "\xC3\x80", "\xC1" => "\xC3\x81", "\xC2" => "\xC3\x82", "\xC3" => "\xC3\x83", "\xC4" => "\xC3\x84", "\xC5" => "\xC3\x85", "\xC6" => "\xC3\x86", "\xC7" => "\xC3\x87", "\xC8" => "\xC3\x88", "\xC9" => "\xC3\x89", "\xCA" => "\xC3\x8A", "\xCB" => "\xC3\x8B", "\xCC" => "\xC3\x8C", "\xCD" => "\xC3\x8D", "\xCE" => "\xC3\x8E", "\xCF" => "\xC3\x8F", "\xD0" => "\xC3\x90", "\xD1" => "\xC3\x91", "\xD2" => "\xC3\x92", "\xD3" => "\xC3\x93", "\xD4" => "\xC3\x94", "\xD5" => "\xC3\x95", "\xD6" => "\xC3\x96", "\xD7" => "\xC3\x97", "\xD8" => "\xC3\x98", "\xD9" => "\xC3\x99", "\xDA" => "\xC3\x9A", "\xDB" => "\xC3\x9B", "\xDC" => "\xC3\x9C", "\xDD" => "\xC3\x9D", "\xDE" => "\xC3\x9E", "\xDF" => "\xC3\x9F", "\xE0" => "\xC3\xA0", "\xE1" => "\xC3\xA1", "\xE2" => "\xC3\xA2", "\xE3" => "\xC3\xA3", "\xE4" => "\xC3\xA4", "\xE5" => "\xC3\xA5", "\xE6" => "\xC3\xA6", "\xE7" => "\xC3\xA7", "\xE8" => "\xC3\xA8", "\xE9" => "\xC3\xA9", "\xEA" => "\xC3\xAA", "\xEB" => "\xC3\xAB", "\xEC" => "\xC3\xAC", "\xED" => "\xC3\xAD", "\xEE" => "\xC3\xAE", "\xEF" => "\xC3\xAF", "\xF0" => "\xC3\xB0", "\xF1" => "\xC3\xB1", "\xF2" => "\xC3\xB2", "\xF3" => "\xC3\xB3", "\xF4" => "\xC3\xB4", "\xF5" => "\xC3\xB5", "\xF6" => "\xC3\xB6", "\xF7" => "\xC3\xB7", "\xF8" => "\xC3\xB8", "\xF9" => "\xC3\xB9", "\xFA" => "\xC3\xBA", "\xFB" => "\xC3\xBB", "\xFC" => "\xC3\xBC", "\xFD" => "\xC3\xBD", "\xFE" => "\xC3\xBE", "\xFF" => "\xC3\xBF"]; return strtr($string, $convert_table); } /** * Change a string from one encoding to another * * @param string $data Raw data in $input encoding * @param string $input Encoding of $data * @param string $output Encoding you want * @return string|boolean False if we can't convert it */ public static function change_encoding($data, $input, $output) { $input = Misc::encoding($input); $output = Misc::encoding($output); // We fail to fail on non US-ASCII bytes if ($input === 'US-ASCII') { static $non_ascii_octects = ''; if (!$non_ascii_octects) { for ($i = 0x80; $i <= 0xFF; $i++) { $non_ascii_octects .= chr($i); } } $data = substr($data, 0, strcspn($data, $non_ascii_octects)); } // This is first, as behaviour of this is completely predictable if ($input === 'windows-1252' && $output === 'UTF-8') { return Misc::windows_1252_to_utf8($data); } // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported). elseif (function_exists('mb_convert_encoding') && ($return = Misc::change_encoding_mbstring($data, $input, $output))) { return $return; } // This is third, as behaviour of this varies with OS userland and PHP version elseif (function_exists('iconv') && ($return = Misc::change_encoding_iconv($data, $input, $output))) { return $return; } // This is last, as behaviour of this varies with OS userland and PHP version elseif (class_exists('\UConverter') && ($return = Misc::change_encoding_uconverter($data, $input, $output))) { return $return; } // If we can't do anything, just fail return false; } protected static function change_encoding_mbstring($data, $input, $output) { if ($input === 'windows-949') { $input = 'EUC-KR'; } if ($output === 'windows-949') { $output = 'EUC-KR'; } if ($input === 'Windows-31J') { $input = 'SJIS'; } if ($output === 'Windows-31J') { $output = 'SJIS'; } // Check that the encoding is supported if (!in_array($input, mb_list_encodings())) { return false; } if (@mb_convert_encoding("\x80", 'UTF-16BE', $input) === "\x00\x80") { return false; } // Let's do some conversion if ($return = @mb_convert_encoding($data, $output, $input)) { return $return; } return false; } protected static function change_encoding_iconv($data, $input, $output) { return @iconv($input, $output, $data); } /** * @param string $data * @param string $input * @param string $output * @return string|false */ protected static function change_encoding_uconverter($data, $input, $output) { return @\UConverter::transcode($data, $output, $input); } /** * Normalize an encoding name * * This is automatically generated by create.php * * To generate it, run `php create.php` on the command line, and copy the * output to replace this function. * * @param string $charset Character set to standardise * @return string Standardised name */ public static function encoding($charset) { // Normalization from UTS #22 switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset))) { case 'adobestandardencoding': case 'csadobestandardencoding': return 'Adobe-Standard-Encoding'; case 'adobesymbolencoding': case 'cshppsmath': return 'Adobe-Symbol-Encoding'; case 'ami1251': case 'amiga1251': return 'Amiga-1251'; case 'ansix31101983': case 'csat5001983': case 'csiso99naplps': case 'isoir99': case 'naplps': return 'ANSI_X3.110-1983'; case 'arabic7': case 'asmo449': case 'csiso89asmo449': case 'iso9036': case 'isoir89': return 'ASMO_449'; case 'big5': case 'csbig5': return 'Big5'; case 'big5hkscs': return 'Big5-HKSCS'; case 'bocu1': case 'csbocu1': return 'BOCU-1'; case 'brf': case 'csbrf': return 'BRF'; case 'bs4730': case 'csiso4unitedkingdom': case 'gb': case 'iso646gb': case 'isoir4': case 'uk': return 'BS_4730'; case 'bsviewdata': case 'csiso47bsviewdata': case 'isoir47': return 'BS_viewdata'; case 'cesu8': case 'cscesu8': return 'CESU-8'; case 'ca': case 'csa71': case 'csaz243419851': case 'csiso121canadian1': case 'iso646ca': case 'isoir121': return 'CSA_Z243.4-1985-1'; case 'csa72': case 'csaz243419852': case 'csiso122canadian2': case 'iso646ca2': case 'isoir122': return 'CSA_Z243.4-1985-2'; case 'csaz24341985gr': case 'csiso123csaz24341985gr': case 'isoir123': return 'CSA_Z243.4-1985-gr'; case 'csiso139csn369103': case 'csn369103': case 'isoir139': return 'CSN_369103'; case 'csdecmcs': case 'dec': case 'decmcs': return 'DEC-MCS'; case 'csiso21german': case 'de': case 'din66003': case 'iso646de': case 'isoir21': return 'DIN_66003'; case 'csdkus': case 'dkus': return 'dk-us'; case 'csiso646danish': case 'dk': case 'ds2089': case 'iso646dk': return 'DS_2089'; case 'csibmebcdicatde': case 'ebcdicatde': return 'EBCDIC-AT-DE'; case 'csebcdicatdea': case 'ebcdicatdea': return 'EBCDIC-AT-DE-A'; case 'csebcdiccafr': case 'ebcdiccafr': return 'EBCDIC-CA-FR'; case 'csebcdicdkno': case 'ebcdicdkno': return 'EBCDIC-DK-NO'; case 'csebcdicdknoa': case 'ebcdicdknoa': return 'EBCDIC-DK-NO-A'; case 'csebcdices': case 'ebcdices': return 'EBCDIC-ES'; case 'csebcdicesa': case 'ebcdicesa': return 'EBCDIC-ES-A'; case 'csebcdicess': case 'ebcdicess': return 'EBCDIC-ES-S'; case 'csebcdicfise': case 'ebcdicfise': return 'EBCDIC-FI-SE'; case 'csebcdicfisea': case 'ebcdicfisea': return 'EBCDIC-FI-SE-A'; case 'csebcdicfr': case 'ebcdicfr': return 'EBCDIC-FR'; case 'csebcdicit': case 'ebcdicit': return 'EBCDIC-IT'; case 'csebcdicpt': case 'ebcdicpt': return 'EBCDIC-PT'; case 'csebcdicuk': case 'ebcdicuk': return 'EBCDIC-UK'; case 'csebcdicus': case 'ebcdicus': return 'EBCDIC-US'; case 'csiso111ecmacyrillic': case 'ecmacyrillic': case 'isoir111': case 'koi8e': return 'ECMA-cyrillic'; case 'csiso17spanish': case 'es': case 'iso646es': case 'isoir17': return 'ES'; case 'csiso85spanish2': case 'es2': case 'iso646es2': case 'isoir85': return 'ES2'; case 'cseucpkdfmtjapanese': case 'eucjp': case 'extendedunixcodepackedformatforjapanese': return 'EUC-JP'; case 'cseucfixwidjapanese': case 'extendedunixcodefixedwidthforjapanese': return 'Extended_UNIX_Code_Fixed_Width_for_Japanese'; case 'gb18030': return 'GB18030'; case 'chinese': case 'cp936': case 'csgb2312': case 'csiso58gb231280': case 'gb2312': case 'gb231280': case 'gbk': case 'isoir58': case 'ms936': case 'windows936': return 'GBK'; case 'cn': case 'csiso57gb1988': case 'gb198880': case 'iso646cn': case 'isoir57': return 'GB_1988-80'; case 'csiso153gost1976874': case 'gost1976874': case 'isoir153': case 'stsev35888': return 'GOST_19768-74'; case 'csiso150': case 'csiso150greekccitt': case 'greekccitt': case 'isoir150': return 'greek-ccitt'; case 'csiso88greek7': case 'greek7': case 'isoir88': return 'greek7'; case 'csiso18greek7old': case 'greek7old': case 'isoir18': return 'greek7-old'; case 'cshpdesktop': case 'hpdesktop': return 'HP-DeskTop'; case 'cshplegal': case 'hplegal': return 'HP-Legal'; case 'cshpmath8': case 'hpmath8': return 'HP-Math8'; case 'cshppifont': case 'hppifont': return 'HP-Pi-font'; case 'cshproman8': case 'hproman8': case 'r8': case 'roman8': return 'hp-roman8'; case 'hzgb2312': return 'HZ-GB-2312'; case 'csibmsymbols': case 'ibmsymbols': return 'IBM-Symbols'; case 'csibmthai': case 'ibmthai': return 'IBM-Thai'; case 'cp37': case 'csibm37': case 'ebcdiccpca': case 'ebcdiccpnl': case 'ebcdiccpus': case 'ebcdiccpwt': case 'ibm37': return 'IBM037'; case 'cp38': case 'csibm38': case 'ebcdicint': case 'ibm38': return 'IBM038'; case 'cp273': case 'csibm273': case 'ibm273': return 'IBM273'; case 'cp274': case 'csibm274': case 'ebcdicbe': case 'ibm274': return 'IBM274'; case 'cp275': case 'csibm275': case 'ebcdicbr': case 'ibm275': return 'IBM275'; case 'csibm277': case 'ebcdiccpdk': case 'ebcdiccpno': case 'ibm277': return 'IBM277'; case 'cp278': case 'csibm278': case 'ebcdiccpfi': case 'ebcdiccpse': case 'ibm278': return 'IBM278'; case 'cp280': case 'csibm280': case 'ebcdiccpit': case 'ibm280': return 'IBM280'; case 'cp281': case 'csibm281': case 'ebcdicjpe': case 'ibm281': return 'IBM281'; case 'cp284': case 'csibm284': case 'ebcdiccpes': case 'ibm284': return 'IBM284'; case 'cp285': case 'csibm285': case 'ebcdiccpgb': case 'ibm285': return 'IBM285'; case 'cp290': case 'csibm290': case 'ebcdicjpkana': case 'ibm290': return 'IBM290'; case 'cp297': case 'csibm297': case 'ebcdiccpfr': case 'ibm297': return 'IBM297'; case 'cp420': case 'csibm420': case 'ebcdiccpar1': case 'ibm420': return 'IBM420'; case 'cp423': case 'csibm423': case 'ebcdiccpgr': case 'ibm423': return 'IBM423'; case 'cp424': case 'csibm424': case 'ebcdiccphe': case 'ibm424': return 'IBM424'; case '437': case 'cp437': case 'cspc8codepage437': case 'ibm437': return 'IBM437'; case 'cp500': case 'csibm500': case 'ebcdiccpbe': case 'ebcdiccpch': case 'ibm500': return 'IBM500'; case 'cp775': case 'cspc775baltic': case 'ibm775': return 'IBM775'; case '850': case 'cp850': case 'cspc850multilingual': case 'ibm850': return 'IBM850'; case '851': case 'cp851': case 'csibm851': case 'ibm851': return 'IBM851'; case '852': case 'cp852': case 'cspcp852': case 'ibm852': return 'IBM852'; case '855': case 'cp855': case 'csibm855': case 'ibm855': return 'IBM855'; case '857': case 'cp857': case 'csibm857': case 'ibm857': return 'IBM857'; case 'ccsid858': case 'cp858': case 'ibm858': case 'pcmultilingual850euro': return 'IBM00858'; case '860': case 'cp860': case 'csibm860': case 'ibm860': return 'IBM860'; case '861': case 'cp861': case 'cpis': case 'csibm861': case 'ibm861': return 'IBM861'; case '862': case 'cp862': case 'cspc862latinhebrew': case 'ibm862': return 'IBM862'; case '863': case 'cp863': case 'csibm863': case 'ibm863': return 'IBM863'; case 'cp864': case 'csibm864': case 'ibm864': return 'IBM864'; case '865': case 'cp865': case 'csibm865': case 'ibm865': return 'IBM865'; case '866': case 'cp866': case 'csibm866': case 'ibm866': return 'IBM866'; case 'cp868': case 'cpar': case 'csibm868': case 'ibm868': return 'IBM868'; case '869': case 'cp869': case 'cpgr': case 'csibm869': case 'ibm869': return 'IBM869'; case 'cp870': case 'csibm870': case 'ebcdiccproece': case 'ebcdiccpyu': case 'ibm870': return 'IBM870'; case 'cp871': case 'csibm871': case 'ebcdiccpis': case 'ibm871': return 'IBM871'; case 'cp880': case 'csibm880': case 'ebcdiccyrillic': case 'ibm880': return 'IBM880'; case 'cp891': case 'csibm891': case 'ibm891': return 'IBM891'; case 'cp903': case 'csibm903': case 'ibm903': return 'IBM903'; case '904': case 'cp904': case 'csibbm904': case 'ibm904': return 'IBM904'; case 'cp905': case 'csibm905': case 'ebcdiccptr': case 'ibm905': return 'IBM905'; case 'cp918': case 'csibm918': case 'ebcdiccpar2': case 'ibm918': return 'IBM918'; case 'ccsid924': case 'cp924': case 'ebcdiclatin9euro': case 'ibm924': return 'IBM00924'; case 'cp1026': case 'csibm1026': case 'ibm1026': return 'IBM1026'; case 'ibm1047': return 'IBM1047'; case 'ccsid1140': case 'cp1140': case 'ebcdicus37euro': case 'ibm1140': return 'IBM01140'; case 'ccsid1141': case 'cp1141': case 'ebcdicde273euro': case 'ibm1141': return 'IBM01141'; case 'ccsid1142': case 'cp1142': case 'ebcdicdk277euro': case 'ebcdicno277euro': case 'ibm1142': return 'IBM01142'; case 'ccsid1143': case 'cp1143': case 'ebcdicfi278euro': case 'ebcdicse278euro': case 'ibm1143': return 'IBM01143'; case 'ccsid1144': case 'cp1144': case 'ebcdicit280euro': case 'ibm1144': return 'IBM01144'; case 'ccsid1145': case 'cp1145': case 'ebcdices284euro': case 'ibm1145': return 'IBM01145'; case 'ccsid1146': case 'cp1146': case 'ebcdicgb285euro': case 'ibm1146': return 'IBM01146'; case 'ccsid1147': case 'cp1147': case 'ebcdicfr297euro': case 'ibm1147': return 'IBM01147'; case 'ccsid1148': case 'cp1148': case 'ebcdicinternational500euro': case 'ibm1148': return 'IBM01148'; case 'ccsid1149': case 'cp1149': case 'ebcdicis871euro': case 'ibm1149': return 'IBM01149'; case 'csiso143iecp271': case 'iecp271': case 'isoir143': return 'IEC_P27-1'; case 'csiso49inis': case 'inis': case 'isoir49': return 'INIS'; case 'csiso50inis8': case 'inis8': case 'isoir50': return 'INIS-8'; case 'csiso51iniscyrillic': case 'iniscyrillic': case 'isoir51': return 'INIS-cyrillic'; case 'csinvariant': case 'invariant': return 'INVARIANT'; case 'iso2022cn': return 'ISO-2022-CN'; case 'iso2022cnext': return 'ISO-2022-CN-EXT'; case 'csiso2022jp': case 'iso2022jp': return 'ISO-2022-JP'; case 'csiso2022jp2': case 'iso2022jp2': return 'ISO-2022-JP-2'; case 'csiso2022kr': case 'iso2022kr': return 'ISO-2022-KR'; case 'cswindows30latin1': case 'iso88591windows30latin1': return 'ISO-8859-1-Windows-3.0-Latin-1'; case 'cswindows31latin1': case 'iso88591windows31latin1': return 'ISO-8859-1-Windows-3.1-Latin-1'; case 'csisolatin2': case 'iso88592': case 'iso885921987': case 'isoir101': case 'l2': case 'latin2': return 'ISO-8859-2'; case 'cswindows31latin2': case 'iso88592windowslatin2': return 'ISO-8859-2-Windows-Latin-2'; case 'csisolatin3': case 'iso88593': case 'iso885931988': case 'isoir109': case 'l3': case 'latin3': return 'ISO-8859-3'; case 'csisolatin4': case 'iso88594': case 'iso885941988': case 'isoir110': case 'l4': case 'latin4': return 'ISO-8859-4'; case 'csisolatincyrillic': case 'cyrillic': case 'iso88595': case 'iso885951988': case 'isoir144': return 'ISO-8859-5'; case 'arabic': case 'asmo708': case 'csisolatinarabic': case 'ecma114': case 'iso88596': case 'iso885961987': case 'isoir127': return 'ISO-8859-6'; case 'csiso88596e': case 'iso88596e': return 'ISO-8859-6-E'; case 'csiso88596i': case 'iso88596i': return 'ISO-8859-6-I'; case 'csisolatingreek': case 'ecma118': case 'elot928': case 'greek': case 'greek8': case 'iso88597': case 'iso885971987': case 'isoir126': return 'ISO-8859-7'; case 'csisolatinhebrew': case 'hebrew': case 'iso88598': case 'iso885981988': case 'isoir138': return 'ISO-8859-8'; case 'csiso88598e': case 'iso88598e': return 'ISO-8859-8-E'; case 'csiso88598i': case 'iso88598i': return 'ISO-8859-8-I'; case 'cswindows31latin5': case 'iso88599windowslatin5': return 'ISO-8859-9-Windows-Latin-5'; case 'csisolatin6': case 'iso885910': case 'iso8859101992': case 'isoir157': case 'l6': case 'latin6': return 'ISO-8859-10'; case 'iso885913': return 'ISO-8859-13'; case 'iso885914': case 'iso8859141998': case 'isoceltic': case 'isoir199': case 'l8': case 'latin8': return 'ISO-8859-14'; case 'iso885915': case 'latin9': return 'ISO-8859-15'; case 'iso885916': case 'iso8859162001': case 'isoir226': case 'l10': case 'latin10': return 'ISO-8859-16'; case 'iso10646j1': return 'ISO-10646-J-1'; case 'csunicode': case 'iso10646ucs2': return 'ISO-10646-UCS-2'; case 'csucs4': case 'iso10646ucs4': return 'ISO-10646-UCS-4'; case 'csunicodeascii': case 'iso10646ucsbasic': return 'ISO-10646-UCS-Basic'; case 'csunicodelatin1': case 'iso10646': case 'iso10646unicodelatin1': return 'ISO-10646-Unicode-Latin1'; case 'csiso10646utf1': case 'iso10646utf1': return 'ISO-10646-UTF-1'; case 'csiso115481': case 'iso115481': case 'isotr115481': return 'ISO-11548-1'; case 'csiso90': case 'isoir90': return 'iso-ir-90'; case 'csunicodeibm1261': case 'isounicodeibm1261': return 'ISO-Unicode-IBM-1261'; case 'csunicodeibm1264': case 'isounicodeibm1264': return 'ISO-Unicode-IBM-1264'; case 'csunicodeibm1265': case 'isounicodeibm1265': return 'ISO-Unicode-IBM-1265'; case 'csunicodeibm1268': case 'isounicodeibm1268': return 'ISO-Unicode-IBM-1268'; case 'csunicodeibm1276': case 'isounicodeibm1276': return 'ISO-Unicode-IBM-1276'; case 'csiso646basic1983': case 'iso646basic1983': case 'ref': return 'ISO_646.basic:1983'; case 'csiso2intlrefversion': case 'irv': case 'iso646irv1983': case 'isoir2': return 'ISO_646.irv:1983'; case 'csiso2033': case 'e13b': case 'iso20331983': case 'isoir98': return 'ISO_2033-1983'; case 'csiso5427cyrillic': case 'iso5427': case 'isoir37': return 'ISO_5427'; case 'iso5427cyrillic1981': case 'iso54271981': case 'isoir54': return 'ISO_5427:1981'; case 'csiso5428greek': case 'iso54281980': case 'isoir55': return 'ISO_5428:1980'; case 'csiso6937add': case 'iso6937225': case 'isoir152': return 'ISO_6937-2-25'; case 'csisotextcomm': case 'iso69372add': case 'isoir142': return 'ISO_6937-2-add'; case 'csiso8859supp': case 'iso8859supp': case 'isoir154': case 'latin125': return 'ISO_8859-supp'; case 'csiso10367box': case 'iso10367box': case 'isoir155': return 'ISO_10367-box'; case 'csiso15italian': case 'iso646it': case 'isoir15': case 'it': return 'IT'; case 'csiso13jisc6220jp': case 'isoir13': case 'jisc62201969': case 'jisc62201969jp': case 'katakana': case 'x2017': return 'JIS_C6220-1969-jp'; case 'csiso14jisc6220ro': case 'iso646jp': case 'isoir14': case 'jisc62201969ro': case 'jp': return 'JIS_C6220-1969-ro'; case 'csiso42jisc62261978': case 'isoir42': case 'jisc62261978': return 'JIS_C6226-1978'; case 'csiso87jisx208': case 'isoir87': case 'jisc62261983': case 'jisx2081983': case 'x208': return 'JIS_C6226-1983'; case 'csiso91jisc62291984a': case 'isoir91': case 'jisc62291984a': case 'jpocra': return 'JIS_C6229-1984-a'; case 'csiso92jisc62991984b': case 'iso646jpocrb': case 'isoir92': case 'jisc62291984b': case 'jpocrb': return 'JIS_C6229-1984-b'; case 'csiso93jis62291984badd': case 'isoir93': case 'jisc62291984badd': case 'jpocrbadd': return 'JIS_C6229-1984-b-add'; case 'csiso94jis62291984hand': case 'isoir94': case 'jisc62291984hand': case 'jpocrhand': return 'JIS_C6229-1984-hand'; case 'csiso95jis62291984handadd': case 'isoir95': case 'jisc62291984handadd': case 'jpocrhandadd': return 'JIS_C6229-1984-hand-add'; case 'csiso96jisc62291984kana': case 'isoir96': case 'jisc62291984kana': return 'JIS_C6229-1984-kana'; case 'csjisencoding': case 'jisencoding': return 'JIS_Encoding'; case 'cshalfwidthkatakana': case 'jisx201': case 'x201': return 'JIS_X0201'; case 'csiso159jisx2121990': case 'isoir159': case 'jisx2121990': case 'x212': return 'JIS_X0212-1990'; case 'csiso141jusib1002': case 'iso646yu': case 'isoir141': case 'js': case 'jusib1002': case 'yu': return 'JUS_I.B1.002'; case 'csiso147macedonian': case 'isoir147': case 'jusib1003mac': case 'macedonian': return 'JUS_I.B1.003-mac'; case 'csiso146serbian': case 'isoir146': case 'jusib1003serb': case 'serbian': return 'JUS_I.B1.003-serb'; case 'koi7switched': return 'KOI7-switched'; case 'cskoi8r': case 'koi8r': return 'KOI8-R'; case 'koi8u': return 'KOI8-U'; case 'csksc5636': case 'iso646kr': case 'ksc5636': return 'KSC5636'; case 'cskz1048': case 'kz1048': case 'rk1048': case 'strk10482002': return 'KZ-1048'; case 'csiso19latingreek': case 'isoir19': case 'latingreek': return 'latin-greek'; case 'csiso27latingreek1': case 'isoir27': case 'latingreek1': return 'Latin-greek-1'; case 'csiso158lap': case 'isoir158': case 'lap': case 'latinlap': return 'latin-lap'; case 'csmacintosh': case 'mac': case 'macintosh': return 'macintosh'; case 'csmicrosoftpublishing': case 'microsoftpublishing': return 'Microsoft-Publishing'; case 'csmnem': case 'mnem': return 'MNEM'; case 'csmnemonic': case 'mnemonic': return 'MNEMONIC'; case 'csiso86hungarian': case 'hu': case 'iso646hu': case 'isoir86': case 'msz77953': return 'MSZ_7795.3'; case 'csnatsdano': case 'isoir91': case 'natsdano': return 'NATS-DANO'; case 'csnatsdanoadd': case 'isoir92': case 'natsdanoadd': return 'NATS-DANO-ADD'; case 'csnatssefi': case 'isoir81': case 'natssefi': return 'NATS-SEFI'; case 'csnatssefiadd': case 'isoir82': case 'natssefiadd': return 'NATS-SEFI-ADD'; case 'csiso151cuba': case 'cuba': case 'iso646cu': case 'isoir151': case 'ncnc1081': return 'NC_NC00-10:81'; case 'csiso69french': case 'fr': case 'iso646fr': case 'isoir69': case 'nfz62010': return 'NF_Z_62-010'; case 'csiso25french': case 'iso646fr1': case 'isoir25': case 'nfz620101973': return 'NF_Z_62-010_(1973)'; case 'csiso60danishnorwegian': case 'csiso60norwegian1': case 'iso646no': case 'isoir60': case 'no': case 'ns45511': return 'NS_4551-1'; case 'csiso61norwegian2': case 'iso646no2': case 'isoir61': case 'no2': case 'ns45512': return 'NS_4551-2'; case 'osdebcdicdf3irv': return 'OSD_EBCDIC_DF03_IRV'; case 'osdebcdicdf41': return 'OSD_EBCDIC_DF04_1'; case 'osdebcdicdf415': return 'OSD_EBCDIC_DF04_15'; case 'cspc8danishnorwegian': case 'pc8danishnorwegian': return 'PC8-Danish-Norwegian'; case 'cspc8turkish': case 'pc8turkish': return 'PC8-Turkish'; case 'csiso16portuguese': case 'iso646pt': case 'isoir16': case 'pt': return 'PT'; case 'csiso84portuguese2': case 'iso646pt2': case 'isoir84': case 'pt2': return 'PT2'; case 'cp154': case 'csptcp154': case 'cyrillicasian': case 'pt154': case 'ptcp154': return 'PTCP154'; case 'scsu': return 'SCSU'; case 'csiso10swedish': case 'fi': case 'iso646fi': case 'iso646se': case 'isoir10': case 'se': case 'sen850200b': return 'SEN_850200_B'; case 'csiso11swedishfornames': case 'iso646se2': case 'isoir11': case 'se2': case 'sen850200c': return 'SEN_850200_C'; case 'csiso102t617bit': case 'isoir102': case 't617bit': return 'T.61-7bit'; case 'csiso103t618bit': case 'isoir103': case 't61': case 't618bit': return 'T.61-8bit'; case 'csiso128t101g2': case 'isoir128': case 't101g2': return 'T.101-G2'; case 'cstscii': case 'tscii': return 'TSCII'; case 'csunicode11': case 'unicode11': return 'UNICODE-1-1'; case 'csunicode11utf7': case 'unicode11utf7': return 'UNICODE-1-1-UTF-7'; case 'csunknown8bit': case 'unknown8bit': return 'UNKNOWN-8BIT'; case 'ansix341968': case 'ansix341986': case 'ascii': case 'cp367': case 'csascii': case 'ibm367': case 'iso646irv1991': case 'iso646us': case 'isoir6': case 'us': case 'usascii': return 'US-ASCII'; case 'csusdk': case 'usdk': return 'us-dk'; case 'utf7': return 'UTF-7'; case 'utf8': return 'UTF-8'; case 'utf16': return 'UTF-16'; case 'utf16be': return 'UTF-16BE'; case 'utf16le': return 'UTF-16LE'; case 'utf32': return 'UTF-32'; case 'utf32be': return 'UTF-32BE'; case 'utf32le': return 'UTF-32LE'; case 'csventurainternational': case 'venturainternational': return 'Ventura-International'; case 'csventuramath': case 'venturamath': return 'Ventura-Math'; case 'csventuraus': case 'venturaus': return 'Ventura-US'; case 'csiso70videotexsupp1': case 'isoir70': case 'videotexsuppl': return 'videotex-suppl'; case 'csviqr': case 'viqr': return 'VIQR'; case 'csviscii': case 'viscii': return 'VISCII'; case 'csshiftjis': case 'cswindows31j': case 'mskanji': case 'shiftjis': case 'windows31j': return 'Windows-31J'; case 'iso885911': case 'tis620': return 'windows-874'; case 'cseuckr': case 'csksc56011987': case 'euckr': case 'isoir149': case 'korean': case 'ksc5601': case 'ksc56011987': case 'ksc56011989': case 'windows949': return 'windows-949'; case 'windows1250': return 'windows-1250'; case 'windows1251': return 'windows-1251'; case 'cp819': case 'csisolatin1': case 'ibm819': case 'iso88591': case 'iso885911987': case 'isoir100': case 'l1': case 'latin1': case 'windows1252': return 'windows-1252'; case 'windows1253': return 'windows-1253'; case 'csisolatin5': case 'iso88599': case 'iso885991989': case 'isoir148': case 'l5': case 'latin5': case 'windows1254': return 'windows-1254'; case 'windows1255': return 'windows-1255'; case 'windows1256': return 'windows-1256'; case 'windows1257': return 'windows-1257'; case 'windows1258': return 'windows-1258'; default: return $charset; } } public static function get_curl_version() { if (is_array($curl = curl_version())) { $curl = $curl['version']; } elseif (substr($curl, 0, 5) === 'curl/') { $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5)); } elseif (substr($curl, 0, 8) === 'libcurl/') { $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8)); } else { $curl = 0; } return $curl; } /** * Strip HTML comments * * @param string $data Data to strip comments from * @return string Comment stripped string */ public static function strip_comments($data) { $output = ''; while (($start = strpos($data, '<!--')) !== false) { $output .= substr($data, 0, $start); if (($end = strpos($data, '-->', $start)) !== false) { $data = substr_replace($data, '', 0, $end + 3); } else { $data = ''; } } return $output . $data; } public static function parse_date($dt) { $parser = \SimplePie\Parse\Date::get(); return $parser->parse($dt); } /** * Decode HTML entities * * @deprecated since SimplePie 1.3, use DOMDocument instead * @param string $data Input data * @return string Output data */ public static function entities_decode($data) { // trigger_error(sprintf('Using method "' . __METHOD__ . '" is deprecated since SimplePie 1.3, use "DOMDocument" instead.'), \E_USER_DEPRECATED); $decoder = new \SimplePie_Decode_HTML_Entities($data); return $decoder->parse(); } /** * Remove RFC822 comments * * @param string $data Data to strip comments from * @return string Comment stripped string */ public static function uncomment_rfc822($string) { $string = (string) $string; $position = 0; $length = strlen($string); $depth = 0; $output = ''; while ($position < $length && ($pos = strpos($string, '(', $position)) !== false) { $output .= substr($string, $position, $pos - $position); $position = $pos + 1; if ($string[$pos - 1] !== '\\') { $depth++; while ($depth && $position < $length) { $position += strcspn($string, '()', $position); if ($string[$position - 1] === '\\') { $position++; continue; } elseif (isset($string[$position])) { switch ($string[$position]) { case '(': $depth++; break; case ')': $depth--; break; } $position++; } else { break; } } } else { $output .= '('; } } $output .= substr($string, $position); return $output; } public static function parse_mime($mime) { if (($pos = strpos($mime, ';')) === false) { return trim($mime); } return trim(substr($mime, 0, $pos)); } public static function atom_03_construct_type($attribs) { if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode'])) === 'base64') { $mode = \SimplePie\SimplePie::CONSTRUCT_BASE64; } else { $mode = \SimplePie\SimplePie::CONSTRUCT_NONE; } if (isset($attribs['']['type'])) { switch (strtolower(trim($attribs['']['type']))) { case 'text': case 'text/plain': return \SimplePie\SimplePie::CONSTRUCT_TEXT | $mode; case 'html': case 'text/html': return \SimplePie\SimplePie::CONSTRUCT_HTML | $mode; case 'xhtml': case 'application/xhtml+xml': return \SimplePie\SimplePie::CONSTRUCT_XHTML | $mode; default: return \SimplePie\SimplePie::CONSTRUCT_NONE | $mode; } } return \SimplePie\SimplePie::CONSTRUCT_TEXT | $mode; } public static function atom_10_construct_type($attribs) { if (isset($attribs['']['type'])) { switch (strtolower(trim($attribs['']['type']))) { case 'text': return \SimplePie\SimplePie::CONSTRUCT_TEXT; case 'html': return \SimplePie\SimplePie::CONSTRUCT_HTML; case 'xhtml': return \SimplePie\SimplePie::CONSTRUCT_XHTML; default: return \SimplePie\SimplePie::CONSTRUCT_NONE; } } return \SimplePie\SimplePie::CONSTRUCT_TEXT; } public static function atom_10_content_construct_type($attribs) { if (isset($attribs['']['type'])) { $type = strtolower(trim($attribs['']['type'])); switch ($type) { case 'text': return \SimplePie\SimplePie::CONSTRUCT_TEXT; case 'html': return \SimplePie\SimplePie::CONSTRUCT_HTML; case 'xhtml': return \SimplePie\SimplePie::CONSTRUCT_XHTML; } if (in_array(substr($type, -4), ['+xml', '/xml']) || substr($type, 0, 5) === 'text/') { return \SimplePie\SimplePie::CONSTRUCT_NONE; } else { return \SimplePie\SimplePie::CONSTRUCT_BASE64; } } return \SimplePie\SimplePie::CONSTRUCT_TEXT; } public static function is_isegment_nz_nc($string) { return (bool) preg_match('/^([A-Za-z0-9\-._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!$&\'()*+,;=@]|(%[0-9ABCDEF]{2}))+$/u', $string); } public static function space_separated_tokens($string) { $space_characters = "\x20\x09\x0A\x0B\x0C\x0D"; $string_length = strlen($string); $position = strspn($string, $space_characters); $tokens = []; while ($position < $string_length) { $len = strcspn($string, $space_characters, $position); $tokens[] = substr($string, $position, $len); $position += $len; $position += strspn($string, $space_characters, $position); } return $tokens; } /** * Converts a unicode codepoint to a UTF-8 character * * @static * @param int $codepoint Unicode codepoint * @return string UTF-8 character */ public static function codepoint_to_utf8($codepoint) { $codepoint = (int) $codepoint; if ($codepoint < 0) { return false; } elseif ($codepoint <= 0x7f) { return chr($codepoint); } elseif ($codepoint <= 0x7ff) { return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f)); } elseif ($codepoint <= 0xffff) { return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f)); } elseif ($codepoint <= 0x10ffff) { return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f)); } // U+FFFD REPLACEMENT CHARACTER return "\xEF\xBF\xBD"; } /** * Similar to parse_str() * * Returns an associative array of name/value pairs, where the value is an * array of values that have used the same name * * @static * @param string $str The input string. * @return array */ public static function parse_str($str) { $return = []; $str = explode('&', $str); foreach ($str as $section) { if (strpos($section, '=') !== false) { [$name, $value] = explode('=', $section, 2); $return[urldecode($name)][] = urldecode($value); } else { $return[urldecode($section)][] = null; } } return $return; } /** * Detect XML encoding, as per XML 1.0 Appendix F.1 * * @todo Add support for EBCDIC * @param string $data XML data * @param \SimplePie\Registry $registry Class registry * @return array Possible encodings */ public static function xml_encoding($data, $registry) { // UTF-32 Big Endian BOM if (substr($data, 0, 4) === "\x00\x00\xFE\xFF") { $encoding[] = 'UTF-32BE'; } // UTF-32 Little Endian BOM elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00") { $encoding[] = 'UTF-32LE'; } // UTF-16 Big Endian BOM elseif (substr($data, 0, 2) === "\xFE\xFF") { $encoding[] = 'UTF-16BE'; } // UTF-16 Little Endian BOM elseif (substr($data, 0, 2) === "\xFF\xFE") { $encoding[] = 'UTF-16LE'; } // UTF-8 BOM elseif (substr($data, 0, 3) === "\xEF\xBB\xBF") { $encoding[] = 'UTF-8'; } // UTF-32 Big Endian Without BOM elseif (substr($data, 0, 20) === "\x00\x00\x00\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C") { if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E")) { $parser = $registry->create(Parser::class, [Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8')]); if ($parser->parse()) { $encoding[] = $parser->encoding; } } $encoding[] = 'UTF-32BE'; } // UTF-32 Little Endian Without BOM elseif (substr($data, 0, 20) === "\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C\x00\x00\x00") { if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00")) { $parser = $registry->create(Parser::class, [Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8')]); if ($parser->parse()) { $encoding[] = $parser->encoding; } } $encoding[] = 'UTF-32LE'; } // UTF-16 Big Endian Without BOM elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C") { if ($pos = strpos($data, "\x00\x3F\x00\x3E")) { $parser = $registry->create(Parser::class, [Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8')]); if ($parser->parse()) { $encoding[] = $parser->encoding; } } $encoding[] = 'UTF-16BE'; } // UTF-16 Little Endian Without BOM elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00") { if ($pos = strpos($data, "\x3F\x00\x3E\x00")) { $parser = $registry->create(Parser::class, [Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8')]); if ($parser->parse()) { $encoding[] = $parser->encoding; } } $encoding[] = 'UTF-16LE'; } // US-ASCII (or superset) elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C") { if ($pos = strpos($data, "\x3F\x3E")) { $parser = $registry->create(Parser::class, [substr($data, 5, $pos - 5)]); if ($parser->parse()) { $encoding[] = $parser->encoding; } } $encoding[] = 'UTF-8'; } // Fallback to UTF-8 else { $encoding[] = 'UTF-8'; } return $encoding; } public static function output_javascript() { if (function_exists('ob_gzhandler')) { ob_start('ob_gzhandler'); } header('Content-type: text/javascript; charset: UTF-8'); header('Cache-Control: must-revalidate'); header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days $body = <<<END function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) { if (placeholder != '') { document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" href="'+link+'" src="'+placeholder+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="false" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>'); } else { document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" src="'+link+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="true" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>'); } } function embed_flash(bgcolor, width, height, link, loop, type) { document.writeln('<embed src="'+link+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="'+type+'" quality="high" width="'+width+'" height="'+height+'" bgcolor="'+bgcolor+'" loop="'+loop+'"></embed>'); } function embed_flv(width, height, link, placeholder, loop, player) { document.writeln('<embed src="'+player+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="'+width+'" height="'+height+'" wmode="transparent" flashvars="file='+link+'&autostart=false&repeat='+loop+'&showdigits=true&showfsbutton=false"></embed>'); } function embed_wmedia(width, height, link) { document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>'); } END; echo $body; } /** * Get the SimplePie build timestamp * * Uses the git index if it exists, otherwise uses the modification time * of the newest file. */ public static function get_build() { if (static::$SIMPLEPIE_BUILD !== null) { return static::$SIMPLEPIE_BUILD; } $root = dirname(__FILE__, 2); if (file_exists($root . '/.git/index')) { static::$SIMPLEPIE_BUILD = filemtime($root . '/.git/index'); return static::$SIMPLEPIE_BUILD; } elseif (file_exists($root . '/SimplePie')) { $time = 0; foreach (glob($root . '/SimplePie/*.php') as $file) { if (($mtime = filemtime($file)) > $time) { $time = $mtime; } } static::$SIMPLEPIE_BUILD = $time; return static::$SIMPLEPIE_BUILD; } elseif (file_exists(dirname(__FILE__) . '/Core.php')) { static::$SIMPLEPIE_BUILD = filemtime(dirname(__FILE__) . '/Core.php'); return static::$SIMPLEPIE_BUILD; } static::$SIMPLEPIE_BUILD = filemtime(__FILE__); return static::$SIMPLEPIE_BUILD; } /** * Get the default user agent string * * @return string */ public static function get_default_useragent() { return \SimplePie\SimplePie::NAME . '/' . \SimplePie\SimplePie::VERSION . ' (Feed Parser; ' . \SimplePie\SimplePie::URL . '; Allow like Gecko) Build/' . static::get_build(); } /** * Format debugging information */ public static function debug(&$sp) { $info = 'SimplePie ' . \SimplePie\SimplePie::VERSION . ' Build ' . static::get_build() . "\n"; $info .= 'PHP ' . PHP_VERSION . "\n"; if ($sp->error() !== null) { $info .= 'Error occurred: ' . $sp->error() . "\n"; } else { $info .= "No error found.\n"; } $info .= "Extensions:\n"; $extensions = ['pcre', 'curl', 'zlib', 'mbstring', 'iconv', 'xmlreader', 'xml']; foreach ($extensions as $ext) { if (extension_loaded($ext)) { $info .= " $ext loaded\n"; switch ($ext) { case 'pcre': $info .= ' Version ' . PCRE_VERSION . "\n"; break; case 'curl': $version = curl_version(); $info .= ' Version ' . $version['version'] . "\n"; break; case 'mbstring': $info .= ' Overloading: ' . mb_get_info('func_overload') . "\n"; break; case 'iconv': $info .= ' Version ' . ICONV_VERSION . "\n"; break; case 'xml': $info .= ' Version ' . LIBXML_DOTTED_VERSION . "\n"; break; } } else { $info .= " $ext not loaded\n"; } } return $info; } public static function silence_errors($num, $str) { // No-op } /** * Sanitize a URL by removing HTTP credentials. * @param string $url the URL to sanitize. * @return string the same URL without HTTP credentials. */ public static function url_remove_credentials($url) { return preg_replace('#^(https?://)[^/:@]+:[^/:@]+@#i', '$1', $url); } } class_alias('SimplePie\Misc', 'SimplePie_Misc', false); PK������ZT���� ��Category.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie; /** * Manages all category-related data * * Used by {@see \SimplePie\Item::get_category()} and {@see \SimplePie\Item::get_categories()} * * This class can be overloaded with {@see \SimplePie\SimplePie::set_category_class()} * * @package SimplePie * @subpackage API */ class Category { /** * Category identifier * * @var string|null * @see get_term */ public $term; /** * Categorization scheme identifier * * @var string|null * @see get_scheme() */ public $scheme; /** * Human readable label * * @var string|null * @see get_label() */ public $label; /** * Category type * * category for <category> * subject for <dc:subject> * * @var string|null * @see get_type() */ public $type; /** * Constructor, used to input the data * * @param string|null $term * @param string|null $scheme * @param string|null $label * @param string|null $type */ public function __construct($term = null, $scheme = null, $label = null, $type = null) { $this->term = $term; $this->scheme = $scheme; $this->label = $label; $this->type = $type; } /** * String-ified version * * @return string */ public function __toString() { // There is no $this->data here return md5(serialize($this)); } /** * Get the category identifier * * @return string|null */ public function get_term() { return $this->term; } /** * Get the categorization scheme identifier * * @return string|null */ public function get_scheme() { return $this->scheme; } /** * Get the human readable label * * @param bool $strict * @return string|null */ public function get_label($strict = false) { if ($this->label === null && $strict !== true) { return $this->get_term(); } return $this->label; } /** * Get the category type * * @return string|null */ public function get_type() { return $this->type; } } class_alias('SimplePie\Category', 'SimplePie_Category'); PK������Zqk ��k ����RegistryAware.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2022 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie; /** * Handles the injection of Registry into other class * * {@see \SimplePie\SimplePie::get_registry()} * * @package SimplePie */ interface RegistryAware { /** * Set the Registry into the class * * @param Registry $registry * * @return void */ public function set_registry(Registry $registry)/* : void */; } PK������ZۊYC��YC����Decode/HTML/Entities.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ /** * Decode HTML Entities * * This implements HTML5 as of revision 967 (2007-06-28) * * @deprecated Use DOMDocument instead! * @package SimplePie */ class SimplePie_Decode_HTML_Entities { /** * Data to be parsed * * @access private * @var string */ var $data = ''; /** * Currently consumed bytes * * @access private * @var string */ var $consumed = ''; /** * Position of the current byte being parsed * * @access private * @var int */ var $position = 0; /** * Create an instance of the class with the input data * * @access public * @param string $data Input data */ public function __construct($data) { $this->data = $data; } /** * Parse the input data * * @access public * @return string Output data */ public function parse() { while (($this->position = strpos($this->data, '&', $this->position)) !== false) { $this->consume(); $this->entity(); $this->consumed = ''; } return $this->data; } /** * Consume the next byte * * @access private * @return mixed The next byte, or false, if there is no more data */ public function consume() { if (isset($this->data[$this->position])) { $this->consumed .= $this->data[$this->position]; return $this->data[$this->position++]; } return false; } /** * Consume a range of characters * * @access private * @param string $chars Characters to consume * @return mixed A series of characters that match the range, or false */ public function consume_range($chars) { if ($len = strspn($this->data, $chars, $this->position)) { $data = substr($this->data, $this->position, $len); $this->consumed .= $data; $this->position += $len; return $data; } return false; } /** * Unconsume one byte * * @access private */ public function unconsume() { $this->consumed = substr($this->consumed, 0, -1); $this->position--; } /** * Decode an entity * * @access private */ public function entity() { switch ($this->consume()) { case "\x09": case "\x0A": case "\x0B": case "\x0C": case "\x20": case "\x3C": case "\x26": case false: break; case "\x23": switch ($this->consume()) { case "\x78": case "\x58": $range = '0123456789ABCDEFabcdef'; $hex = true; break; default: $range = '0123456789'; $hex = false; $this->unconsume(); break; } if ($codepoint = $this->consume_range($range)) { static $windows_1252_specials = array(0x0D => "\x0A", 0x80 => "\xE2\x82\xAC", 0x81 => "\xEF\xBF\xBD", 0x82 => "\xE2\x80\x9A", 0x83 => "\xC6\x92", 0x84 => "\xE2\x80\x9E", 0x85 => "\xE2\x80\xA6", 0x86 => "\xE2\x80\xA0", 0x87 => "\xE2\x80\xA1", 0x88 => "\xCB\x86", 0x89 => "\xE2\x80\xB0", 0x8A => "\xC5\xA0", 0x8B => "\xE2\x80\xB9", 0x8C => "\xC5\x92", 0x8D => "\xEF\xBF\xBD", 0x8E => "\xC5\xBD", 0x8F => "\xEF\xBF\xBD", 0x90 => "\xEF\xBF\xBD", 0x91 => "\xE2\x80\x98", 0x92 => "\xE2\x80\x99", 0x93 => "\xE2\x80\x9C", 0x94 => "\xE2\x80\x9D", 0x95 => "\xE2\x80\xA2", 0x96 => "\xE2\x80\x93", 0x97 => "\xE2\x80\x94", 0x98 => "\xCB\x9C", 0x99 => "\xE2\x84\xA2", 0x9A => "\xC5\xA1", 0x9B => "\xE2\x80\xBA", 0x9C => "\xC5\x93", 0x9D => "\xEF\xBF\xBD", 0x9E => "\xC5\xBE", 0x9F => "\xC5\xB8"); if ($hex) { $codepoint = hexdec($codepoint); } else { $codepoint = intval($codepoint); } if (isset($windows_1252_specials[$codepoint])) { $replacement = $windows_1252_specials[$codepoint]; } else { $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint); } if (!in_array($this->consume(), array(';', false), true)) { $this->unconsume(); } $consumed_length = strlen($this->consumed); $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length); $this->position += strlen($replacement) - $consumed_length; } break; default: static $entities = array( 'Aacute' => "\xC3\x81", 'aacute' => "\xC3\xA1", 'Aacute;' => "\xC3\x81", 'aacute;' => "\xC3\xA1", 'Acirc' => "\xC3\x82", 'acirc' => "\xC3\xA2", 'Acirc;' => "\xC3\x82", 'acirc;' => "\xC3\xA2", 'acute' => "\xC2\xB4", 'acute;' => "\xC2\xB4", 'AElig' => "\xC3\x86", 'aelig' => "\xC3\xA6", 'AElig;' => "\xC3\x86", 'aelig;' => "\xC3\xA6", 'Agrave' => "\xC3\x80", 'agrave' => "\xC3\xA0", 'Agrave;' => "\xC3\x80", 'agrave;' => "\xC3\xA0", 'alefsym;' => "\xE2\x84\xB5", 'Alpha;' => "\xCE\x91", 'alpha;' => "\xCE\xB1", 'AMP' => "\x26", 'amp' => "\x26", 'AMP;' => "\x26", 'amp;' => "\x26", 'and;' => "\xE2\x88\xA7", 'ang;' => "\xE2\x88\xA0", 'apos;' => "\x27", 'Aring' => "\xC3\x85", 'aring' => "\xC3\xA5", 'Aring;' => "\xC3\x85", 'aring;' => "\xC3\xA5", 'asymp;' => "\xE2\x89\x88", 'Atilde' => "\xC3\x83", 'atilde' => "\xC3\xA3", 'Atilde;' => "\xC3\x83", 'atilde;' => "\xC3\xA3", 'Auml' => "\xC3\x84", 'auml' => "\xC3\xA4", 'Auml;' => "\xC3\x84", 'auml;' => "\xC3\xA4", 'bdquo;' => "\xE2\x80\x9E", 'Beta;' => "\xCE\x92", 'beta;' => "\xCE\xB2", 'brvbar' => "\xC2\xA6", 'brvbar;' => "\xC2\xA6", 'bull;' => "\xE2\x80\xA2", 'cap;' => "\xE2\x88\xA9", 'Ccedil' => "\xC3\x87", 'ccedil' => "\xC3\xA7", 'Ccedil;' => "\xC3\x87", 'ccedil;' => "\xC3\xA7", 'cedil' => "\xC2\xB8", 'cedil;' => "\xC2\xB8", 'cent' => "\xC2\xA2", 'cent;' => "\xC2\xA2", 'Chi;' => "\xCE\xA7", 'chi;' => "\xCF\x87", 'circ;' => "\xCB\x86", 'clubs;' => "\xE2\x99\xA3", 'cong;' => "\xE2\x89\x85", 'COPY' => "\xC2\xA9", 'copy' => "\xC2\xA9", 'COPY;' => "\xC2\xA9", 'copy;' => "\xC2\xA9", 'crarr;' => "\xE2\x86\xB5", 'cup;' => "\xE2\x88\xAA", 'curren' => "\xC2\xA4", 'curren;' => "\xC2\xA4", 'Dagger;' => "\xE2\x80\xA1", 'dagger;' => "\xE2\x80\xA0", 'dArr;' => "\xE2\x87\x93", 'darr;' => "\xE2\x86\x93", 'deg' => "\xC2\xB0", 'deg;' => "\xC2\xB0", 'Delta;' => "\xCE\x94", 'delta;' => "\xCE\xB4", 'diams;' => "\xE2\x99\xA6", 'divide' => "\xC3\xB7", 'divide;' => "\xC3\xB7", 'Eacute' => "\xC3\x89", 'eacute' => "\xC3\xA9", 'Eacute;' => "\xC3\x89", 'eacute;' => "\xC3\xA9", 'Ecirc' => "\xC3\x8A", 'ecirc' => "\xC3\xAA", 'Ecirc;' => "\xC3\x8A", 'ecirc;' => "\xC3\xAA", 'Egrave' => "\xC3\x88", 'egrave' => "\xC3\xA8", 'Egrave;' => "\xC3\x88", 'egrave;' => "\xC3\xA8", 'empty;' => "\xE2\x88\x85", 'emsp;' => "\xE2\x80\x83", 'ensp;' => "\xE2\x80\x82", 'Epsilon;' => "\xCE\x95", 'epsilon;' => "\xCE\xB5", 'equiv;' => "\xE2\x89\xA1", 'Eta;' => "\xCE\x97", 'eta;' => "\xCE\xB7", 'ETH' => "\xC3\x90", 'eth' => "\xC3\xB0", 'ETH;' => "\xC3\x90", 'eth;' => "\xC3\xB0", 'Euml' => "\xC3\x8B", 'euml' => "\xC3\xAB", 'Euml;' => "\xC3\x8B", 'euml;' => "\xC3\xAB", 'euro;' => "\xE2\x82\xAC", 'exist;' => "\xE2\x88\x83", 'fnof;' => "\xC6\x92", 'forall;' => "\xE2\x88\x80", 'frac12' => "\xC2\xBD", 'frac12;' => "\xC2\xBD", 'frac14' => "\xC2\xBC", 'frac14;' => "\xC2\xBC", 'frac34' => "\xC2\xBE", 'frac34;' => "\xC2\xBE", 'frasl;' => "\xE2\x81\x84", 'Gamma;' => "\xCE\x93", 'gamma;' => "\xCE\xB3", 'ge;' => "\xE2\x89\xA5", 'GT' => "\x3E", 'gt' => "\x3E", 'GT;' => "\x3E", 'gt;' => "\x3E", 'hArr;' => "\xE2\x87\x94", 'harr;' => "\xE2\x86\x94", 'hearts;' => "\xE2\x99\xA5", 'hellip;' => "\xE2\x80\xA6", 'Iacute' => "\xC3\x8D", 'iacute' => "\xC3\xAD", 'Iacute;' => "\xC3\x8D", 'iacute;' => "\xC3\xAD", 'Icirc' => "\xC3\x8E", 'icirc' => "\xC3\xAE", 'Icirc;' => "\xC3\x8E", 'icirc;' => "\xC3\xAE", 'iexcl' => "\xC2\xA1", 'iexcl;' => "\xC2\xA1", 'Igrave' => "\xC3\x8C", 'igrave' => "\xC3\xAC", 'Igrave;' => "\xC3\x8C", 'igrave;' => "\xC3\xAC", 'image;' => "\xE2\x84\x91", 'infin;' => "\xE2\x88\x9E", 'int;' => "\xE2\x88\xAB", 'Iota;' => "\xCE\x99", 'iota;' => "\xCE\xB9", 'iquest' => "\xC2\xBF", 'iquest;' => "\xC2\xBF", 'isin;' => "\xE2\x88\x88", 'Iuml' => "\xC3\x8F", 'iuml' => "\xC3\xAF", 'Iuml;' => "\xC3\x8F", 'iuml;' => "\xC3\xAF", 'Kappa;' => "\xCE\x9A", 'kappa;' => "\xCE\xBA", 'Lambda;' => "\xCE\x9B", 'lambda;' => "\xCE\xBB", 'lang;' => "\xE3\x80\x88", 'laquo' => "\xC2\xAB", 'laquo;' => "\xC2\xAB", 'lArr;' => "\xE2\x87\x90", 'larr;' => "\xE2\x86\x90", 'lceil;' => "\xE2\x8C\x88", 'ldquo;' => "\xE2\x80\x9C", 'le;' => "\xE2\x89\xA4", 'lfloor;' => "\xE2\x8C\x8A", 'lowast;' => "\xE2\x88\x97", 'loz;' => "\xE2\x97\x8A", 'lrm;' => "\xE2\x80\x8E", 'lsaquo;' => "\xE2\x80\xB9", 'lsquo;' => "\xE2\x80\x98", 'LT' => "\x3C", 'lt' => "\x3C", 'LT;' => "\x3C", 'lt;' => "\x3C", 'macr' => "\xC2\xAF", 'macr;' => "\xC2\xAF", 'mdash;' => "\xE2\x80\x94", 'micro' => "\xC2\xB5", 'micro;' => "\xC2\xB5", 'middot' => "\xC2\xB7", 'middot;' => "\xC2\xB7", 'minus;' => "\xE2\x88\x92", 'Mu;' => "\xCE\x9C", 'mu;' => "\xCE\xBC", 'nabla;' => "\xE2\x88\x87", 'nbsp' => "\xC2\xA0", 'nbsp;' => "\xC2\xA0", 'ndash;' => "\xE2\x80\x93", 'ne;' => "\xE2\x89\xA0", 'ni;' => "\xE2\x88\x8B", 'not' => "\xC2\xAC", 'not;' => "\xC2\xAC", 'notin;' => "\xE2\x88\x89", 'nsub;' => "\xE2\x8A\x84", 'Ntilde' => "\xC3\x91", 'ntilde' => "\xC3\xB1", 'Ntilde;' => "\xC3\x91", 'ntilde;' => "\xC3\xB1", 'Nu;' => "\xCE\x9D", 'nu;' => "\xCE\xBD", 'Oacute' => "\xC3\x93", 'oacute' => "\xC3\xB3", 'Oacute;' => "\xC3\x93", 'oacute;' => "\xC3\xB3", 'Ocirc' => "\xC3\x94", 'ocirc' => "\xC3\xB4", 'Ocirc;' => "\xC3\x94", 'ocirc;' => "\xC3\xB4", 'OElig;' => "\xC5\x92", 'oelig;' => "\xC5\x93", 'Ograve' => "\xC3\x92", 'ograve' => "\xC3\xB2", 'Ograve;' => "\xC3\x92", 'ograve;' => "\xC3\xB2", 'oline;' => "\xE2\x80\xBE", 'Omega;' => "\xCE\xA9", 'omega;' => "\xCF\x89", 'Omicron;' => "\xCE\x9F", 'omicron;' => "\xCE\xBF", 'oplus;' => "\xE2\x8A\x95", 'or;' => "\xE2\x88\xA8", 'ordf' => "\xC2\xAA", 'ordf;' => "\xC2\xAA", 'ordm' => "\xC2\xBA", 'ordm;' => "\xC2\xBA", 'Oslash' => "\xC3\x98", 'oslash' => "\xC3\xB8", 'Oslash;' => "\xC3\x98", 'oslash;' => "\xC3\xB8", 'Otilde' => "\xC3\x95", 'otilde' => "\xC3\xB5", 'Otilde;' => "\xC3\x95", 'otilde;' => "\xC3\xB5", 'otimes;' => "\xE2\x8A\x97", 'Ouml' => "\xC3\x96", 'ouml' => "\xC3\xB6", 'Ouml;' => "\xC3\x96", 'ouml;' => "\xC3\xB6", 'para' => "\xC2\xB6", 'para;' => "\xC2\xB6", 'part;' => "\xE2\x88\x82", 'permil;' => "\xE2\x80\xB0", 'perp;' => "\xE2\x8A\xA5", 'Phi;' => "\xCE\xA6", 'phi;' => "\xCF\x86", 'Pi;' => "\xCE\xA0", 'pi;' => "\xCF\x80", 'piv;' => "\xCF\x96", 'plusmn' => "\xC2\xB1", 'plusmn;' => "\xC2\xB1", 'pound' => "\xC2\xA3", 'pound;' => "\xC2\xA3", 'Prime;' => "\xE2\x80\xB3", 'prime;' => "\xE2\x80\xB2", 'prod;' => "\xE2\x88\x8F", 'prop;' => "\xE2\x88\x9D", 'Psi;' => "\xCE\xA8", 'psi;' => "\xCF\x88", 'QUOT' => "\x22", 'quot' => "\x22", 'QUOT;' => "\x22", 'quot;' => "\x22", 'radic;' => "\xE2\x88\x9A", 'rang;' => "\xE3\x80\x89", 'raquo' => "\xC2\xBB", 'raquo;' => "\xC2\xBB", 'rArr;' => "\xE2\x87\x92", 'rarr;' => "\xE2\x86\x92", 'rceil;' => "\xE2\x8C\x89", 'rdquo;' => "\xE2\x80\x9D", 'real;' => "\xE2\x84\x9C", 'REG' => "\xC2\xAE", 'reg' => "\xC2\xAE", 'REG;' => "\xC2\xAE", 'reg;' => "\xC2\xAE", 'rfloor;' => "\xE2\x8C\x8B", 'Rho;' => "\xCE\xA1", 'rho;' => "\xCF\x81", 'rlm;' => "\xE2\x80\x8F", 'rsaquo;' => "\xE2\x80\xBA", 'rsquo;' => "\xE2\x80\x99", 'sbquo;' => "\xE2\x80\x9A", 'Scaron;' => "\xC5\xA0", 'scaron;' => "\xC5\xA1", 'sdot;' => "\xE2\x8B\x85", 'sect' => "\xC2\xA7", 'sect;' => "\xC2\xA7", 'shy' => "\xC2\xAD", 'shy;' => "\xC2\xAD", 'Sigma;' => "\xCE\xA3", 'sigma;' => "\xCF\x83", 'sigmaf;' => "\xCF\x82", 'sim;' => "\xE2\x88\xBC", 'spades;' => "\xE2\x99\xA0", 'sub;' => "\xE2\x8A\x82", 'sube;' => "\xE2\x8A\x86", 'sum;' => "\xE2\x88\x91", 'sup;' => "\xE2\x8A\x83", 'sup1' => "\xC2\xB9", 'sup1;' => "\xC2\xB9", 'sup2' => "\xC2\xB2", 'sup2;' => "\xC2\xB2", 'sup3' => "\xC2\xB3", 'sup3;' => "\xC2\xB3", 'supe;' => "\xE2\x8A\x87", 'szlig' => "\xC3\x9F", 'szlig;' => "\xC3\x9F", 'Tau;' => "\xCE\xA4", 'tau;' => "\xCF\x84", 'there4;' => "\xE2\x88\xB4", 'Theta;' => "\xCE\x98", 'theta;' => "\xCE\xB8", 'thetasym;' => "\xCF\x91", 'thinsp;' => "\xE2\x80\x89", 'THORN' => "\xC3\x9E", 'thorn' => "\xC3\xBE", 'THORN;' => "\xC3\x9E", 'thorn;' => "\xC3\xBE", 'tilde;' => "\xCB\x9C", 'times' => "\xC3\x97", 'times;' => "\xC3\x97", 'TRADE;' => "\xE2\x84\xA2", 'trade;' => "\xE2\x84\xA2", 'Uacute' => "\xC3\x9A", 'uacute' => "\xC3\xBA", 'Uacute;' => "\xC3\x9A", 'uacute;' => "\xC3\xBA", 'uArr;' => "\xE2\x87\x91", 'uarr;' => "\xE2\x86\x91", 'Ucirc' => "\xC3\x9B", 'ucirc' => "\xC3\xBB", 'Ucirc;' => "\xC3\x9B", 'ucirc;' => "\xC3\xBB", 'Ugrave' => "\xC3\x99", 'ugrave' => "\xC3\xB9", 'Ugrave;' => "\xC3\x99", 'ugrave;' => "\xC3\xB9", 'uml' => "\xC2\xA8", 'uml;' => "\xC2\xA8", 'upsih;' => "\xCF\x92", 'Upsilon;' => "\xCE\xA5", 'upsilon;' => "\xCF\x85", 'Uuml' => "\xC3\x9C", 'uuml' => "\xC3\xBC", 'Uuml;' => "\xC3\x9C", 'uuml;' => "\xC3\xBC", 'weierp;' => "\xE2\x84\x98", 'Xi;' => "\xCE\x9E", 'xi;' => "\xCE\xBE", 'Yacute' => "\xC3\x9D", 'yacute' => "\xC3\xBD", 'Yacute;' => "\xC3\x9D", 'yacute;' => "\xC3\xBD", 'yen' => "\xC2\xA5", 'yen;' => "\xC2\xA5", 'yuml' => "\xC3\xBF", 'Yuml;' => "\xC5\xB8", 'yuml;' => "\xC3\xBF", 'Zeta;' => "\xCE\x96", 'zeta;' => "\xCE\xB6", 'zwj;' => "\xE2\x80\x8D", 'zwnj;' => "\xE2\x80\x8C" ); for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++) { $consumed = substr($this->consumed, 1); if (isset($entities[$consumed])) { $match = $consumed; } } if ($match !== null) { $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1); $this->position += strlen($entities[$match]) - strlen($consumed) - 1; } break; } } } PK������Z�� ��SimplePie.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie; use InvalidArgumentException; use Psr\SimpleCache\CacheInterface; use SimplePie\Cache\Base; use SimplePie\Cache\BaseDataCache; use SimplePie\Cache\CallableNameFilter; use SimplePie\Cache\DataCache; use SimplePie\Cache\NameFilter; use SimplePie\Cache\Psr16; use SimplePie\Content\Type\Sniffer; /** * SimplePie * * @package SimplePie * @subpackage API */ class SimplePie { /** * SimplePie Name */ public const NAME = 'SimplePie'; /** * SimplePie Version */ public const VERSION = '1.8.0'; /** * SimplePie Website URL */ public const URL = 'http://simplepie.org'; /** * SimplePie Linkback */ public const LINKBACK = '<a href="' . self::URL . '" title="' . self::NAME . ' ' . self::VERSION . '">' . self::NAME . '</a>'; /** * No Autodiscovery * @see SimplePie::set_autodiscovery_level() */ public const LOCATOR_NONE = 0; /** * Feed Link Element Autodiscovery * @see SimplePie::set_autodiscovery_level() */ public const LOCATOR_AUTODISCOVERY = 1; /** * Local Feed Extension Autodiscovery * @see SimplePie::set_autodiscovery_level() */ public const LOCATOR_LOCAL_EXTENSION = 2; /** * Local Feed Body Autodiscovery * @see SimplePie::set_autodiscovery_level() */ public const LOCATOR_LOCAL_BODY = 4; /** * Remote Feed Extension Autodiscovery * @see SimplePie::set_autodiscovery_level() */ public const LOCATOR_REMOTE_EXTENSION = 8; /** * Remote Feed Body Autodiscovery * @see SimplePie::set_autodiscovery_level() */ public const LOCATOR_REMOTE_BODY = 16; /** * All Feed Autodiscovery * @see SimplePie::set_autodiscovery_level() */ public const LOCATOR_ALL = 31; /** * No known feed type */ public const TYPE_NONE = 0; /** * RSS 0.90 */ public const TYPE_RSS_090 = 1; /** * RSS 0.91 (Netscape) */ public const TYPE_RSS_091_NETSCAPE = 2; /** * RSS 0.91 (Userland) */ public const TYPE_RSS_091_USERLAND = 4; /** * RSS 0.91 (both Netscape and Userland) */ public const TYPE_RSS_091 = 6; /** * RSS 0.92 */ public const TYPE_RSS_092 = 8; /** * RSS 0.93 */ public const TYPE_RSS_093 = 16; /** * RSS 0.94 */ public const TYPE_RSS_094 = 32; /** * RSS 1.0 */ public const TYPE_RSS_10 = 64; /** * RSS 2.0 */ public const TYPE_RSS_20 = 128; /** * RDF-based RSS */ public const TYPE_RSS_RDF = 65; /** * Non-RDF-based RSS (truly intended as syndication format) */ public const TYPE_RSS_SYNDICATION = 190; /** * All RSS */ public const TYPE_RSS_ALL = 255; /** * Atom 0.3 */ public const TYPE_ATOM_03 = 256; /** * Atom 1.0 */ public const TYPE_ATOM_10 = 512; /** * All Atom */ public const TYPE_ATOM_ALL = 768; /** * All feed types */ public const TYPE_ALL = 1023; /** * No construct */ public const CONSTRUCT_NONE = 0; /** * Text construct */ public const CONSTRUCT_TEXT = 1; /** * HTML construct */ public const CONSTRUCT_HTML = 2; /** * XHTML construct */ public const CONSTRUCT_XHTML = 4; /** * base64-encoded construct */ public const CONSTRUCT_BASE64 = 8; /** * IRI construct */ public const CONSTRUCT_IRI = 16; /** * A construct that might be HTML */ public const CONSTRUCT_MAYBE_HTML = 32; /** * All constructs */ public const CONSTRUCT_ALL = 63; /** * Don't change case */ public const SAME_CASE = 1; /** * Change to lowercase */ public const LOWERCASE = 2; /** * Change to uppercase */ public const UPPERCASE = 4; /** * PCRE for HTML attributes */ public const PCRE_HTML_ATTRIBUTE = '((?:[\x09\x0A\x0B\x0C\x0D\x20]+[^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?)*)[\x09\x0A\x0B\x0C\x0D\x20]*'; /** * PCRE for XML attributes */ public const PCRE_XML_ATTRIBUTE = '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*'; /** * XML Namespace */ public const NAMESPACE_XML = 'http://www.w3.org/XML/1998/namespace'; /** * Atom 1.0 Namespace */ public const NAMESPACE_ATOM_10 = 'http://www.w3.org/2005/Atom'; /** * Atom 0.3 Namespace */ public const NAMESPACE_ATOM_03 = 'http://purl.org/atom/ns#'; /** * RDF Namespace */ public const NAMESPACE_RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'; /** * RSS 0.90 Namespace */ public const NAMESPACE_RSS_090 = 'http://my.netscape.com/rdf/simple/0.9/'; /** * RSS 1.0 Namespace */ public const NAMESPACE_RSS_10 = 'http://purl.org/rss/1.0/'; /** * RSS 1.0 Content Module Namespace */ public const NAMESPACE_RSS_10_MODULES_CONTENT = 'http://purl.org/rss/1.0/modules/content/'; /** * RSS 2.0 Namespace * (Stupid, I know, but I'm certain it will confuse people less with support.) */ public const NAMESPACE_RSS_20 = ''; /** * DC 1.0 Namespace */ public const NAMESPACE_DC_10 = 'http://purl.org/dc/elements/1.0/'; /** * DC 1.1 Namespace */ public const NAMESPACE_DC_11 = 'http://purl.org/dc/elements/1.1/'; /** * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace */ public const NAMESPACE_W3C_BASIC_GEO = 'http://www.w3.org/2003/01/geo/wgs84_pos#'; /** * GeoRSS Namespace */ public const NAMESPACE_GEORSS = 'http://www.georss.org/georss'; /** * Media RSS Namespace */ public const NAMESPACE_MEDIARSS = 'http://search.yahoo.com/mrss/'; /** * Wrong Media RSS Namespace. Caused by a long-standing typo in the spec. */ public const NAMESPACE_MEDIARSS_WRONG = 'http://search.yahoo.com/mrss'; /** * Wrong Media RSS Namespace #2. New namespace introduced in Media RSS 1.5. */ public const NAMESPACE_MEDIARSS_WRONG2 = 'http://video.search.yahoo.com/mrss'; /** * Wrong Media RSS Namespace #3. A possible typo of the Media RSS 1.5 namespace. */ public const NAMESPACE_MEDIARSS_WRONG3 = 'http://video.search.yahoo.com/mrss/'; /** * Wrong Media RSS Namespace #4. New spec location after the RSS Advisory Board takes it over, but not a valid namespace. */ public const NAMESPACE_MEDIARSS_WRONG4 = 'http://www.rssboard.org/media-rss'; /** * Wrong Media RSS Namespace #5. A possible typo of the RSS Advisory Board URL. */ public const NAMESPACE_MEDIARSS_WRONG5 = 'http://www.rssboard.org/media-rss/'; /** * iTunes RSS Namespace */ public const NAMESPACE_ITUNES = 'http://www.itunes.com/dtds/podcast-1.0.dtd'; /** * XHTML Namespace */ public const NAMESPACE_XHTML = 'http://www.w3.org/1999/xhtml'; /** * IANA Link Relations Registry */ public const IANA_LINK_RELATIONS_REGISTRY = 'http://www.iana.org/assignments/relation/'; /** * No file source */ public const FILE_SOURCE_NONE = 0; /** * Remote file source */ public const FILE_SOURCE_REMOTE = 1; /** * Local file source */ public const FILE_SOURCE_LOCAL = 2; /** * fsockopen() file source */ public const FILE_SOURCE_FSOCKOPEN = 4; /** * cURL file source */ public const FILE_SOURCE_CURL = 8; /** * file_get_contents() file source */ public const FILE_SOURCE_FILE_GET_CONTENTS = 16; /** * @var array Raw data * @access private */ public $data = []; /** * @var mixed Error string * @access private */ public $error; /** * @var int HTTP status code * @see SimplePie::status_code() * @access private */ public $status_code = 0; /** * @var object Instance of \SimplePie\Sanitize (or other class) * @see SimplePie::set_sanitize_class() * @access private */ public $sanitize; /** * @var string SimplePie Useragent * @see SimplePie::set_useragent() * @access private */ public $useragent = ''; /** * @var string Feed URL * @see SimplePie::set_feed_url() * @access private */ public $feed_url; /** * @var string Original feed URL, or new feed URL iff HTTP 301 Moved Permanently * @see SimplePie::subscribe_url() * @access private */ public $permanent_url = null; /** * @var object Instance of \SimplePie\File to use as a feed * @see SimplePie::set_file() * @access private */ public $file; /** * @var string Raw feed data * @see SimplePie::set_raw_data() * @access private */ public $raw_data; /** * @var int Timeout for fetching remote files * @see SimplePie::set_timeout() * @access private */ public $timeout = 10; /** * @var array Custom curl options * @see SimplePie::set_curl_options() * @access private */ public $curl_options = []; /** * @var bool Forces fsockopen() to be used for remote files instead * of cURL, even if a new enough version is installed * @see SimplePie::force_fsockopen() * @access private */ public $force_fsockopen = false; /** * @var bool Force the given data/URL to be treated as a feed no matter what * it appears like * @see SimplePie::force_feed() * @access private */ public $force_feed = false; /** * @var bool Enable/Disable Caching * @see SimplePie::enable_cache() * @access private */ private $enable_cache = true; /** * @var DataCache|null * @see SimplePie::set_cache() */ private $cache = null; /** * @var NameFilter * @see SimplePie::set_cache_namefilter() */ private $cache_namefilter; /** * @var bool Force SimplePie to fallback to expired cache, if enabled, * when feed is unavailable. * @see SimplePie::force_cache_fallback() * @access private */ public $force_cache_fallback = false; /** * @var int Cache duration (in seconds) * @see SimplePie::set_cache_duration() * @access private */ public $cache_duration = 3600; /** * @var int Auto-discovery cache duration (in seconds) * @see SimplePie::set_autodiscovery_cache_duration() * @access private */ public $autodiscovery_cache_duration = 604800; // 7 Days. /** * @var string Cache location (relative to executing script) * @see SimplePie::set_cache_location() * @access private */ public $cache_location = './cache'; /** * @var string Function that creates the cache filename * @see SimplePie::set_cache_name_function() * @access private */ public $cache_name_function = 'md5'; /** * @var bool Reorder feed by date descending * @see SimplePie::enable_order_by_date() * @access private */ public $order_by_date = true; /** * @var mixed Force input encoding to be set to the follow value * (false, or anything type-cast to false, disables this feature) * @see SimplePie::set_input_encoding() * @access private */ public $input_encoding = false; /** * @var int Feed Autodiscovery Level * @see SimplePie::set_autodiscovery_level() * @access private */ public $autodiscovery = self::LOCATOR_ALL; /** * Class registry object * * @var \SimplePie\Registry */ public $registry; /** * @var int Maximum number of feeds to check with autodiscovery * @see SimplePie::set_max_checked_feeds() * @access private */ public $max_checked_feeds = 10; /** * @var array All the feeds found during the autodiscovery process * @see SimplePie::get_all_discovered_feeds() * @access private */ public $all_discovered_feeds = []; /** * @var string Web-accessible path to the handler_image.php file. * @see SimplePie::set_image_handler() * @access private */ public $image_handler = ''; /** * @var array Stores the URLs when multiple feeds are being initialized. * @see SimplePie::set_feed_url() * @access private */ public $multifeed_url = []; /** * @var array Stores SimplePie objects when multiple feeds initialized. * @access private */ public $multifeed_objects = []; /** * @var array Stores the get_object_vars() array for use with multifeeds. * @see SimplePie::set_feed_url() * @access private */ public $config_settings = null; /** * @var integer Stores the number of items to return per-feed with multifeeds. * @see SimplePie::set_item_limit() * @access private */ public $item_limit = 0; /** * @var bool Stores if last-modified and/or etag headers were sent with the * request when checking a feed. */ public $check_modified = false; /** * @var array Stores the default attributes to be stripped by strip_attributes(). * @see SimplePie::strip_attributes() * @access private */ public $strip_attributes = ['bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc']; /** * @var array Stores the default attributes to add to different tags by add_attributes(). * @see SimplePie::add_attributes() * @access private */ public $add_attributes = ['audio' => ['preload' => 'none'], 'iframe' => ['sandbox' => 'allow-scripts allow-same-origin'], 'video' => ['preload' => 'none']]; /** * @var array Stores the default tags to be stripped by strip_htmltags(). * @see SimplePie::strip_htmltags() * @access private */ public $strip_htmltags = ['base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style']; /** * @var array Stores the default attributes to be renamed by rename_attributes(). * @see SimplePie::rename_attributes() * @access private */ public $rename_attributes = []; /** * @var bool Should we throw exceptions, or use the old-style error property? * @access private */ public $enable_exceptions = false; /** * The SimplePie class contains feed level data and options * * To use SimplePie, create the SimplePie object with no parameters. You can * then set configuration options using the provided methods. After setting * them, you must initialise the feed using $feed->init(). At that point the * object's methods and properties will be available to you. * * Previously, it was possible to pass in the feed URL along with cache * options directly into the constructor. This has been removed as of 1.3 as * it caused a lot of confusion. * * @since 1.0 Preview Release */ public function __construct() { if (version_compare(PHP_VERSION, '7.2', '<')) { exit('Please upgrade to PHP 7.2 or newer.'); } $this->set_useragent(); $this->set_cache_namefilter(new CallableNameFilter($this->cache_name_function)); // Other objects, instances created here so we can set options on them $this->sanitize = new \SimplePie\Sanitize(); $this->registry = new \SimplePie\Registry(); if (func_num_args() > 0) { trigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_duration() directly.', \E_USER_DEPRECATED); $args = func_get_args(); switch (count($args)) { case 3: $this->set_cache_duration($args[2]); // no break case 2: $this->set_cache_location($args[1]); // no break case 1: $this->set_feed_url($args[0]); $this->init(); } } } /** * Used for converting object to a string */ public function __toString() { return md5(serialize($this->data)); } /** * Remove items that link back to this before destroying this object */ public function __destruct() { if (!gc_enabled()) { if (!empty($this->data['items'])) { foreach ($this->data['items'] as $item) { $item->__destruct(); } unset($item, $this->data['items']); } if (!empty($this->data['ordered_items'])) { foreach ($this->data['ordered_items'] as $item) { $item->__destruct(); } unset($item, $this->data['ordered_items']); } } } /** * Force the given data/URL to be treated as a feed * * This tells SimplePie to ignore the content-type provided by the server. * Be careful when using this option, as it will also disable autodiscovery. * * @since 1.1 * @param bool $enable Force the given data/URL to be treated as a feed */ public function force_feed($enable = false) { $this->force_feed = (bool) $enable; } /** * Set the URL of the feed you want to parse * * This allows you to enter the URL of the feed you want to parse, or the * website you want to try to use auto-discovery on. This takes priority * over any set raw data. * * You can set multiple feeds to mash together by passing an array instead * of a string for the $url. Remember that with each additional feed comes * additional processing and resources. * * @since 1.0 Preview Release * @see set_raw_data() * @param string|array $url This is the URL (or array of URLs) that you want to parse. */ public function set_feed_url($url) { $this->multifeed_url = []; if (is_array($url)) { foreach ($url as $value) { $this->multifeed_url[] = $this->registry->call(Misc::class, 'fix_protocol', [$value, 1]); } } else { $this->feed_url = $this->registry->call(Misc::class, 'fix_protocol', [$url, 1]); $this->permanent_url = $this->feed_url; } } /** * Set an instance of {@see \SimplePie\File} to use as a feed * * @param \SimplePie\File &$file * @return bool True on success, false on failure */ public function set_file(&$file) { if ($file instanceof \SimplePie\File) { $this->feed_url = $file->url; $this->permanent_url = $this->feed_url; $this->file = &$file; return true; } return false; } /** * Set the raw XML data to parse * * Allows you to use a string of RSS/Atom data instead of a remote feed. * * If you have a feed available as a string in PHP, you can tell SimplePie * to parse that data string instead of a remote feed. Any set feed URL * takes precedence. * * @since 1.0 Beta 3 * @param string $data RSS or Atom data as a string. * @see set_feed_url() */ public function set_raw_data($data) { $this->raw_data = $data; } /** * Set the default timeout for fetching remote feeds * * This allows you to change the maximum time the feed's server to respond * and send the feed back. * * @since 1.0 Beta 3 * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed. */ public function set_timeout($timeout = 10) { $this->timeout = (int) $timeout; } /** * Set custom curl options * * This allows you to change default curl options * * @since 1.0 Beta 3 * @param array $curl_options Curl options to add to default settings */ public function set_curl_options(array $curl_options = []) { $this->curl_options = $curl_options; } /** * Force SimplePie to use fsockopen() instead of cURL * * @since 1.0 Beta 3 * @param bool $enable Force fsockopen() to be used */ public function force_fsockopen($enable = false) { $this->force_fsockopen = (bool) $enable; } /** * Enable/disable caching in SimplePie. * * This option allows you to disable caching all-together in SimplePie. * However, disabling the cache can lead to longer load times. * * @since 1.0 Preview Release * @param bool $enable Enable caching */ public function enable_cache($enable = true) { $this->enable_cache = (bool) $enable; } /** * Set a PSR-16 implementation as cache * * @param CacheInterface $psr16cache The PSR-16 cache implementation * * @return void */ public function set_cache(CacheInterface $cache) { $this->cache = new Psr16($cache); } /** * SimplePie to continue to fall back to expired cache, if enabled, when * feed is unavailable. * * This tells SimplePie to ignore any file errors and fall back to cache * instead. This only works if caching is enabled and cached content * still exists. * * @deprecated since SimplePie 1.8.0, expired cache will not be used anymore. * * @param bool $enable Force use of cache on fail. */ public function force_cache_fallback($enable = false) { // @trigger_error(sprintf('SimplePie\SimplePie::force_cache_fallback() is deprecated since SimplePie 1.8.0, expired cache will not be used anymore.'), \E_USER_DEPRECATED); $this->force_cache_fallback = (bool) $enable; } /** * Set the length of time (in seconds) that the contents of a feed will be * cached * * @param int $seconds The feed content cache duration */ public function set_cache_duration($seconds = 3600) { $this->cache_duration = (int) $seconds; } /** * Set the length of time (in seconds) that the autodiscovered feed URL will * be cached * * @param int $seconds The autodiscovered feed URL cache duration. */ public function set_autodiscovery_cache_duration($seconds = 604800) { $this->autodiscovery_cache_duration = (int) $seconds; } /** * Set the file system location where the cached files should be stored * * @deprecated since SimplePie 1.8.0, use \SimplePie\SimplePie::set_cache() instead. * * @param string $location The file system location. */ public function set_cache_location($location = './cache') { // @trigger_error(sprintf('SimplePie\SimplePie::set_cache_location() is deprecated since SimplePie 1.8.0, please use "SimplePie\SimplePie::set_cache()" instead.'), \E_USER_DEPRECATED); $this->cache_location = (string) $location; } /** * Return the filename (i.e. hash, without path and without extension) of the file to cache a given URL. * * @param string $url The URL of the feed to be cached. * @return string A filename (i.e. hash, without path and without extension). */ public function get_cache_filename($url) { // Append custom parameters to the URL to avoid cache pollution in case of multiple calls with different parameters. $url .= $this->force_feed ? '#force_feed' : ''; $options = []; if ($this->timeout != 10) { $options[CURLOPT_TIMEOUT] = $this->timeout; } if ($this->useragent !== \SimplePie\Misc::get_default_useragent()) { $options[CURLOPT_USERAGENT] = $this->useragent; } if (!empty($this->curl_options)) { foreach ($this->curl_options as $k => $v) { $options[$k] = $v; } } if (!empty($options)) { ksort($options); $url .= '#' . urlencode(var_export($options, true)); } return $this->cache_namefilter->filter($url); } /** * Set whether feed items should be sorted into reverse chronological order * * @param bool $enable Sort as reverse chronological order. */ public function enable_order_by_date($enable = true) { $this->order_by_date = (bool) $enable; } /** * Set the character encoding used to parse the feed * * This overrides the encoding reported by the feed, however it will fall * back to the normal encoding detection if the override fails * * @param string $encoding Character encoding */ public function set_input_encoding($encoding = false) { if ($encoding) { $this->input_encoding = (string) $encoding; } else { $this->input_encoding = false; } } /** * Set how much feed autodiscovery to do * * @see \SimplePie\SimplePie::LOCATOR_NONE * @see \SimplePie\SimplePie::LOCATOR_AUTODISCOVERY * @see \SimplePie\SimplePie::LOCATOR_LOCAL_EXTENSION * @see \SimplePie\SimplePie::LOCATOR_LOCAL_BODY * @see \SimplePie\SimplePie::LOCATOR_REMOTE_EXTENSION * @see \SimplePie\SimplePie::LOCATOR_REMOTE_BODY * @see \SimplePie\SimplePie::LOCATOR_ALL * @param int $level Feed Autodiscovery Level (level can be a combination of the above constants, see bitwise OR operator) */ public function set_autodiscovery_level($level = self::LOCATOR_ALL) { $this->autodiscovery = (int) $level; } /** * Get the class registry * * Use this to override SimplePie's default classes * @see \SimplePie\Registry * * @return Registry */ public function &get_registry() { return $this->registry; } /** * Set which class SimplePie uses for caching * * @deprecated since SimplePie 1.3, use {@see set_cache()} instead * * @param string $class Name of custom class * * @return boolean True on success, false otherwise */ public function set_cache_class($class = Cache::class) { // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::set_cache()" instead.', __METHOD__), \E_USER_DEPRECATED); return $this->registry->register(Cache::class, $class, true); } /** * Set which class SimplePie uses for auto-discovery * * @deprecated since SimplePie 1.3, use {@see get_registry()} instead * * @param string $class Name of custom class * * @return boolean True on success, false otherwise */ public function set_locator_class($class = Locator::class) { // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED); return $this->registry->register(Locator::class, $class, true); } /** * Set which class SimplePie uses for XML parsing * * @deprecated since SimplePie 1.3, use {@see get_registry()} instead * * @param string $class Name of custom class * * @return boolean True on success, false otherwise */ public function set_parser_class($class = Parser::class) { // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED); return $this->registry->register(Parser::class, $class, true); } /** * Set which class SimplePie uses for remote file fetching * * @deprecated since SimplePie 1.3, use {@see get_registry()} instead * * @param string $class Name of custom class * * @return boolean True on success, false otherwise */ public function set_file_class($class = File::class) { // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED); return $this->registry->register(File::class, $class, true); } /** * Set which class SimplePie uses for data sanitization * * @deprecated since SimplePie 1.3, use {@see get_registry()} instead * * @param string $class Name of custom class * * @return boolean True on success, false otherwise */ public function set_sanitize_class($class = Sanitize::class) { // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED); return $this->registry->register(Sanitize::class, $class, true); } /** * Set which class SimplePie uses for handling feed items * * @deprecated since SimplePie 1.3, use {@see get_registry()} instead * * @param string $class Name of custom class * * @return boolean True on success, false otherwise */ public function set_item_class($class = Item::class) { // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED); return $this->registry->register(Item::class, $class, true); } /** * Set which class SimplePie uses for handling author data * * @deprecated since SimplePie 1.3, use {@see get_registry()} instead * * @param string $class Name of custom class * * @return boolean True on success, false otherwise */ public function set_author_class($class = Author::class) { // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED); return $this->registry->register(Author::class, $class, true); } /** * Set which class SimplePie uses for handling category data * * @deprecated since SimplePie 1.3, use {@see get_registry()} instead * * @param string $class Name of custom class * * @return boolean True on success, false otherwise */ public function set_category_class($class = Category::class) { // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED); return $this->registry->register(Category::class, $class, true); } /** * Set which class SimplePie uses for feed enclosures * * @deprecated since SimplePie 1.3, use {@see get_registry()} instead * * @param string $class Name of custom class * * @return boolean True on success, false otherwise */ public function set_enclosure_class($class = Enclosure::class) { // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED); return $this->registry->register(Enclosure::class, $class, true); } /** * Set which class SimplePie uses for `<media:text>` captions * * @deprecated since SimplePie 1.3, use {@see get_registry()} instead * * @param string $class Name of custom class * * @return boolean True on success, false otherwise */ public function set_caption_class($class = Caption::class) { // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED); return $this->registry->register(Caption::class, $class, true); } /** * Set which class SimplePie uses for `<media:copyright>` * * @deprecated since SimplePie 1.3, use {@see get_registry()} instead * * @param string $class Name of custom class * * @return boolean True on success, false otherwise */ public function set_copyright_class($class = Copyright::class) { // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED); return $this->registry->register(Copyright::class, $class, true); } /** * Set which class SimplePie uses for `<media:credit>` * * @deprecated since SimplePie 1.3, use {@see get_registry()} instead * * @param string $class Name of custom class * * @return boolean True on success, false otherwise */ public function set_credit_class($class = Credit::class) { // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED); return $this->registry->register(Credit::class, $class, true); } /** * Set which class SimplePie uses for `<media:rating>` * * @deprecated since SimplePie 1.3, use {@see get_registry()} instead * * @param string $class Name of custom class * * @return boolean True on success, false otherwise */ public function set_rating_class($class = Rating::class) { // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED); return $this->registry->register(Rating::class, $class, true); } /** * Set which class SimplePie uses for `<media:restriction>` * * @deprecated since SimplePie 1.3, use {@see get_registry()} instead * * @param string $class Name of custom class * * @return boolean True on success, false otherwise */ public function set_restriction_class($class = Restriction::class) { // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED); return $this->registry->register(Restriction::class, $class, true); } /** * Set which class SimplePie uses for content-type sniffing * * @deprecated since SimplePie 1.3, use {@see get_registry()} instead * * @param string $class Name of custom class * * @return boolean True on success, false otherwise */ public function set_content_type_sniffer_class($class = Sniffer::class) { // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED); return $this->registry->register(Sniffer::class, $class, true); } /** * Set which class SimplePie uses item sources * * @deprecated since SimplePie 1.3, use {@see get_registry()} instead * * @param string $class Name of custom class * * @return boolean True on success, false otherwise */ public function set_source_class($class = Source::class) { // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED); return $this->registry->register(Source::class, $class, true); } /** * Set the user agent string * * @param string $ua New user agent string. */ public function set_useragent($ua = null) { if ($ua === null) { $ua = \SimplePie\Misc::get_default_useragent(); } $this->useragent = (string) $ua; } /** * Set a namefilter to modify the cache filename with * * @param NameFilter $filter * * @return void */ public function set_cache_namefilter(NameFilter $filter): void { $this->cache_namefilter = $filter; } /** * Set callback function to create cache filename with * * @deprecated since SimplePie 1.8.0, use {@see set_cache_namefilter()} instead * * @param mixed $function Callback function */ public function set_cache_name_function($function = 'md5') { // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.8.0, please use "SimplePie\SimplePie::set_cache_namefilter()" instead.', __METHOD__), \E_USER_DEPRECATED); if (is_callable($function)) { $this->cache_name_function = $function; $this->set_cache_namefilter(new CallableNameFilter($this->cache_name_function)); } } /** * Set options to make SP as fast as possible * * Forgoes a substantial amount of data sanitization in favor of speed. This * turns SimplePie into a dumb parser of feeds. * * @param bool $set Whether to set them or not */ public function set_stupidly_fast($set = false) { if ($set) { $this->enable_order_by_date(false); $this->remove_div(false); $this->strip_comments(false); $this->strip_htmltags(false); $this->strip_attributes(false); $this->add_attributes(false); $this->set_image_handler(false); $this->set_https_domains([]); } } /** * Set maximum number of feeds to check with autodiscovery * * @param int $max Maximum number of feeds to check */ public function set_max_checked_feeds($max = 10) { $this->max_checked_feeds = (int) $max; } public function remove_div($enable = true) { $this->sanitize->remove_div($enable); } public function strip_htmltags($tags = '', $encode = null) { if ($tags === '') { $tags = $this->strip_htmltags; } $this->sanitize->strip_htmltags($tags); if ($encode !== null) { $this->sanitize->encode_instead_of_strip($tags); } } public function encode_instead_of_strip($enable = true) { $this->sanitize->encode_instead_of_strip($enable); } public function rename_attributes($attribs = '') { if ($attribs === '') { $attribs = $this->rename_attributes; } $this->sanitize->rename_attributes($attribs); } public function strip_attributes($attribs = '') { if ($attribs === '') { $attribs = $this->strip_attributes; } $this->sanitize->strip_attributes($attribs); } public function add_attributes($attribs = '') { if ($attribs === '') { $attribs = $this->add_attributes; } $this->sanitize->add_attributes($attribs); } /** * Set the output encoding * * Allows you to override SimplePie's output to match that of your webpage. * This is useful for times when your webpages are not being served as * UTF-8. This setting will be obeyed by {@see handle_content_type()}, and * is similar to {@see set_input_encoding()}. * * It should be noted, however, that not all character encodings can support * all characters. If your page is being served as ISO-8859-1 and you try * to display a Japanese feed, you'll likely see garbled characters. * Because of this, it is highly recommended to ensure that your webpages * are served as UTF-8. * * The number of supported character encodings depends on whether your web * host supports {@link http://php.net/mbstring mbstring}, * {@link http://php.net/iconv iconv}, or both. See * {@link http://simplepie.org/wiki/faq/Supported_Character_Encodings} for * more information. * * @param string $encoding */ public function set_output_encoding($encoding = 'UTF-8') { $this->sanitize->set_output_encoding($encoding); } public function strip_comments($strip = false) { $this->sanitize->strip_comments($strip); } /** * Set element/attribute key/value pairs of HTML attributes * containing URLs that need to be resolved relative to the feed * * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite, * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite, * |q|@cite * * @since 1.0 * @param array|null $element_attribute Element/attribute key/value pairs, null for default */ public function set_url_replacements($element_attribute = null) { $this->sanitize->set_url_replacements($element_attribute); } /** * Set the list of domains for which to force HTTPS. * @see \SimplePie\Sanitize::set_https_domains() * @param array List of HTTPS domains. Example array('biz', 'example.com', 'example.org', 'www.example.net'). */ public function set_https_domains($domains = []) { if (is_array($domains)) { $this->sanitize->set_https_domains($domains); } } /** * Set the handler to enable the display of cached images. * * @param string $page Web-accessible path to the handler_image.php file. * @param string $qs The query string that the value should be passed to. */ public function set_image_handler($page = false, $qs = 'i') { if ($page !== false) { $this->sanitize->set_image_handler($page . '?' . $qs . '='); } else { $this->image_handler = ''; } } /** * Set the limit for items returned per-feed with multifeeds * * @param integer $limit The maximum number of items to return. */ public function set_item_limit($limit = 0) { $this->item_limit = (int) $limit; } /** * Enable throwing exceptions * * @param boolean $enable Should we throw exceptions, or use the old-style error property? */ public function enable_exceptions($enable = true) { $this->enable_exceptions = $enable; } /** * Initialize the feed object * * This is what makes everything happen. Period. This is where all of the * configuration options get processed, feeds are fetched, cached, and * parsed, and all of that other good stuff. * * @return boolean True if successful, false otherwise */ public function init() { // Check absolute bare minimum requirements. if (!extension_loaded('xml') || !extension_loaded('pcre')) { $this->error = 'XML or PCRE extensions not loaded!'; return false; } // Then check the xml extension is sane (i.e., libxml 2.7.x issue on PHP < 5.2.9 and libxml 2.7.0 to 2.7.2 on any version) if we don't have xmlreader. elseif (!extension_loaded('xmlreader')) { static $xml_is_sane = null; if ($xml_is_sane === null) { $parser_check = xml_parser_create(); xml_parse_into_struct($parser_check, '<foo>&</foo>', $values); xml_parser_free($parser_check); $xml_is_sane = isset($values[0]['value']); } if (!$xml_is_sane) { return false; } } // The default sanitize class gets set in the constructor, check if it has // changed. if ($this->registry->get_class(Sanitize::class) !== 'SimplePie\Sanitize') { $this->sanitize = $this->registry->create(Sanitize::class); } if (method_exists($this->sanitize, 'set_registry')) { $this->sanitize->set_registry($this->registry); } // Pass whatever was set with config options over to the sanitizer. // Pass the classes in for legacy support; new classes should use the registry instead $this->sanitize->pass_cache_data( $this->enable_cache, $this->cache_location, $this->cache_namefilter, $this->registry->get_class(Cache::class), $this->cache ); $this->sanitize->pass_file_data($this->registry->get_class(File::class), $this->timeout, $this->useragent, $this->force_fsockopen, $this->curl_options); if (!empty($this->multifeed_url)) { $i = 0; $success = 0; $this->multifeed_objects = []; $this->error = []; foreach ($this->multifeed_url as $url) { $this->multifeed_objects[$i] = clone $this; $this->multifeed_objects[$i]->set_feed_url($url); $single_success = $this->multifeed_objects[$i]->init(); $success |= $single_success; if (!$single_success) { $this->error[$i] = $this->multifeed_objects[$i]->error(); } $i++; } return (bool) $success; } elseif ($this->feed_url === null && $this->raw_data === null) { return false; } $this->error = null; $this->data = []; $this->check_modified = false; $this->multifeed_objects = []; $cache = false; if ($this->feed_url !== null) { $parsed_feed_url = $this->registry->call(Misc::class, 'parse_url', [$this->feed_url]); // Decide whether to enable caching if ($this->enable_cache && $parsed_feed_url['scheme'] !== '') { $cache = $this->get_cache($this->feed_url); } // Fetch the data via \SimplePie\File into $this->raw_data if (($fetched = $this->fetch_data($cache)) === true) { return true; } elseif ($fetched === false) { return false; } [$headers, $sniffed] = $fetched; } // Empty response check if (empty($this->raw_data)) { $this->error = "A feed could not be found at `$this->feed_url`. Empty body."; $this->registry->call(Misc::class, 'error', [$this->error, E_USER_NOTICE, __FILE__, __LINE__]); return false; } // Set up array of possible encodings $encodings = []; // First check to see if input has been overridden. if ($this->input_encoding !== false) { $encodings[] = strtoupper($this->input_encoding); } $application_types = ['application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity']; $text_types = ['text/xml', 'text/xml-external-parsed-entity']; // RFC 3023 (only applies to sniffed content) if (isset($sniffed)) { if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml') { if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset)) { $encodings[] = strtoupper($charset[1]); } $encodings = array_merge($encodings, $this->registry->call(Misc::class, 'xml_encoding', [$this->raw_data, &$this->registry])); $encodings[] = 'UTF-8'; } elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml') { if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset)) { $encodings[] = strtoupper($charset[1]); } $encodings[] = 'US-ASCII'; } // Text MIME-type default elseif (substr($sniffed, 0, 5) === 'text/') { $encodings[] = 'UTF-8'; } } // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1 $encodings = array_merge($encodings, $this->registry->call(Misc::class, 'xml_encoding', [$this->raw_data, &$this->registry])); $encodings[] = 'UTF-8'; $encodings[] = 'ISO-8859-1'; // There's no point in trying an encoding twice $encodings = array_unique($encodings); // Loop through each possible encoding, till we return something, or run out of possibilities foreach ($encodings as $encoding) { // Change the encoding to UTF-8 (as we always use UTF-8 internally) if ($utf8_data = $this->registry->call(Misc::class, 'change_encoding', [$this->raw_data, $encoding, 'UTF-8'])) { // Create new parser $parser = $this->registry->create(Parser::class); // If it's parsed fine if ($parser->parse($utf8_data, 'UTF-8', $this->permanent_url)) { $this->data = $parser->get_data(); if (!($this->get_type() & ~self::TYPE_NONE)) { $this->error = "A feed could not be found at `$this->feed_url`. This does not appear to be a valid RSS or Atom feed."; $this->registry->call(Misc::class, 'error', [$this->error, E_USER_NOTICE, __FILE__, __LINE__]); return false; } if (isset($headers)) { $this->data['headers'] = $headers; } $this->data['build'] = \SimplePie\Misc::get_build(); // Cache the file if caching is enabled $this->data['cache_expiration_time'] = $this->cache_duration + time(); if ($cache && !$cache->set_data($this->get_cache_filename($this->feed_url), $this->data, $this->cache_duration)) { trigger_error("$this->cache_location is not writable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING); } return true; } } } if (isset($parser)) { // We have an error, just set \SimplePie\Misc::error to it and quit $this->error = $this->feed_url; $this->error .= sprintf(' is invalid XML, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column()); } else { $this->error = 'The data could not be converted to UTF-8.'; if (!extension_loaded('mbstring') && !extension_loaded('iconv') && !class_exists('\UConverter')) { $this->error .= ' You MUST have either the iconv, mbstring or intl (PHP 5.5+) extension installed and enabled.'; } else { $missingExtensions = []; if (!extension_loaded('iconv')) { $missingExtensions[] = 'iconv'; } if (!extension_loaded('mbstring')) { $missingExtensions[] = 'mbstring'; } if (!class_exists('\UConverter')) { $missingExtensions[] = 'intl (PHP 5.5+)'; } $this->error .= ' Try installing/enabling the ' . implode(' or ', $missingExtensions) . ' extension.'; } } $this->registry->call(Misc::class, 'error', [$this->error, E_USER_NOTICE, __FILE__, __LINE__]); return false; } /** * Fetch the data via \SimplePie\File * * If the data is already cached, attempt to fetch it from there instead * @param Base|DataCache|false $cache Cache handler, or false to not load from the cache * @return array|true Returns true if the data was loaded from the cache, or an array of HTTP headers and sniffed type */ protected function fetch_data(&$cache) { if (is_object($cache) && $cache instanceof Base) { // @trigger_error(sprintf('Providing $cache as "\SimplePie\Cache\Base" in %s() is deprecated since SimplePie 1.8.0, please provide "\SimplePie\Cache\DataCache" implementation instead.', __METHOD__), \E_USER_DEPRECATED); $cache = new BaseDataCache($cache); } if ($cache !== false && !$cache instanceof DataCache) { throw new InvalidArgumentException(sprintf( '%s(): Argument #1 ($cache) must be of type %s|false', __METHOD__, DataCache::class ), 1); } $cacheKey = $this->get_cache_filename($this->feed_url); // If it's enabled, use the cache if ($cache) { // Load the Cache $this->data = $cache->get_data($cacheKey, []); if (!empty($this->data)) { // If the cache is for an outdated build of SimplePie if (!isset($this->data['build']) || $this->data['build'] !== \SimplePie\Misc::get_build()) { $cache->delete_data($cacheKey); $this->data = []; } // If we've hit a collision just rerun it with caching disabled elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url) { $cache = false; $this->data = []; } // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL. elseif (isset($this->data['feed_url'])) { // Do not need to do feed autodiscovery yet. if ($this->data['feed_url'] !== $this->data['url']) { $this->set_feed_url($this->data['feed_url']); $this->data['url'] = $this->data['feed_url']; $cache->set_data($this->get_cache_filename($this->feed_url), $this->data, $this->autodiscovery_cache_duration); return $this->init(); } $cache->delete_data($this->get_cache_filename($this->feed_url)); $this->data = []; } // Check if the cache has been updated elseif (isset($this->data['cache_expiration_time']) && $this->data['cache_expiration_time'] > time()) { // Want to know if we tried to send last-modified and/or etag headers // when requesting this file. (Note that it's up to the file to // support this, but we don't always send the headers either.) $this->check_modified = true; if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag'])) { $headers = [ 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1', ]; if (isset($this->data['headers']['last-modified'])) { $headers['if-modified-since'] = $this->data['headers']['last-modified']; } if (isset($this->data['headers']['etag'])) { $headers['if-none-match'] = $this->data['headers']['etag']; } $file = $this->registry->create(File::class, [$this->feed_url, $this->timeout / 10, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options]); $this->status_code = $file->status_code; if ($file->success) { if ($file->status_code === 304) { // Set raw_data to false here too, to signify that the cache // is still valid. $this->raw_data = false; $cache->set_data($cacheKey, $this->data, $this->cache_duration); return true; } } else { $this->check_modified = false; if ($this->force_cache_fallback) { $cache->set_data($cacheKey, $this->data, $this->cache_duration); return true; } unset($file); } } } // If the cache is still valid, just return true else { $this->raw_data = false; return true; } } // If the cache is empty else { $this->data = []; } } // If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it. if (!isset($file)) { if ($this->file instanceof \SimplePie\File && $this->file->url === $this->feed_url) { $file = &$this->file; } else { $headers = [ 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1', ]; $file = $this->registry->create(File::class, [$this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options]); } } $this->status_code = $file->status_code; // If the file connection has an error, set SimplePie::error to that and quit if (!$file->success && !($file->method & self::FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300))) { $this->error = $file->error; return !empty($this->data); } if (!$this->force_feed) { // Check if the supplied URL is a feed, if it isn't, look for it. $locate = $this->registry->create(Locator::class, [&$file, $this->timeout, $this->useragent, $this->max_checked_feeds, $this->force_fsockopen, $this->curl_options]); if (!$locate->is_feed($file)) { $copyStatusCode = $file->status_code; $copyContentType = $file->headers['content-type']; try { $microformats = false; if (class_exists('DOMXpath') && function_exists('Mf2\parse')) { $doc = new \DOMDocument(); @$doc->loadHTML($file->body); $xpath = new \DOMXpath($doc); // Check for both h-feed and h-entry, as both a feed with no entries // and a list of entries without an h-feed wrapper are both valid. $query = '//*[contains(concat(" ", @class, " "), " h-feed ") or '. 'contains(concat(" ", @class, " "), " h-entry ")]'; $result = $xpath->query($query); $microformats = $result->length !== 0; } // Now also do feed discovery, but if microformats were found don't // overwrite the current value of file. $discovered = $locate->find( $this->autodiscovery, $this->all_discovered_feeds ); if ($microformats) { if ($hub = $locate->get_rel_link('hub')) { $self = $locate->get_rel_link('self'); $this->store_links($file, $hub, $self); } // Push the current file onto all_discovered feeds so the user can // be shown this as one of the options. if (isset($this->all_discovered_feeds)) { $this->all_discovered_feeds[] = $file; } } else { if ($discovered) { $file = $discovered; } else { // We need to unset this so that if SimplePie::set_file() has // been called that object is untouched unset($file); $this->error = "A feed could not be found at `$this->feed_url`; the status code is `$copyStatusCode` and content-type is `$copyContentType`"; $this->registry->call(Misc::class, 'error', [$this->error, E_USER_NOTICE, __FILE__, __LINE__]); return false; } } } catch (\SimplePie\Exception $e) { // We need to unset this so that if SimplePie::set_file() has been called that object is untouched unset($file); // This is usually because DOMDocument doesn't exist $this->error = $e->getMessage(); $this->registry->call(Misc::class, 'error', [$this->error, E_USER_NOTICE, $e->getFile(), $e->getLine()]); return false; } if ($cache) { $this->data = [ 'url' => $this->feed_url, 'feed_url' => $file->url, 'build' => \SimplePie\Misc::get_build(), 'cache_expiration_time' => $this->cache_duration + time(), ]; if (!$cache->set_data($cacheKey, $this->data, $this->cache_duration)) { trigger_error("$this->cache_location is not writable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING); } } } $this->feed_url = $file->url; $locate = null; } $this->raw_data = $file->body; $this->permanent_url = $file->permanent_url; $headers = $file->headers; $sniffer = $this->registry->create(Sniffer::class, [&$file]); $sniffed = $sniffer->get_type(); return [$headers, $sniffed]; } /** * Get the error message for the occurred error * * @return string|array Error message, or array of messages for multifeeds */ public function error() { return $this->error; } /** * Get the last HTTP status code * * @return int Status code */ public function status_code() { return $this->status_code; } /** * Get the raw XML * * This is the same as the old `$feed->enable_xml_dump(true)`, but returns * the data instead of printing it. * * @return string|boolean Raw XML data, false if the cache is used */ public function get_raw_data() { return $this->raw_data; } /** * Get the character encoding used for output * * @since Preview Release * @return string */ public function get_encoding() { return $this->sanitize->output_encoding; } /** * Send the content-type header with correct encoding * * This method ensures that the SimplePie-enabled page is being served with * the correct {@link http://www.iana.org/assignments/media-types/ mime-type} * and character encoding HTTP headers (character encoding determined by the * {@see set_output_encoding} config option). * * This won't work properly if any content or whitespace has already been * sent to the browser, because it relies on PHP's * {@link http://php.net/header header()} function, and these are the * circumstances under which the function works. * * Because it's setting these settings for the entire page (as is the nature * of HTTP headers), this should only be used once per page (again, at the * top). * * @param string $mime MIME type to serve the page as */ public function handle_content_type($mime = 'text/html') { if (!headers_sent()) { $header = "Content-type: $mime;"; if ($this->get_encoding()) { $header .= ' charset=' . $this->get_encoding(); } else { $header .= ' charset=UTF-8'; } header($header); } } /** * Get the type of the feed * * This returns a \SimplePie\SimplePie::TYPE_* constant, which can be tested against * using {@link http://php.net/language.operators.bitwise bitwise operators} * * @since 0.8 (usage changed to using constants in 1.0) * @see \SimplePie\SimplePie::TYPE_NONE Unknown. * @see \SimplePie\SimplePie::TYPE_RSS_090 RSS 0.90. * @see \SimplePie\SimplePie::TYPE_RSS_091_NETSCAPE RSS 0.91 (Netscape). * @see \SimplePie\SimplePie::TYPE_RSS_091_USERLAND RSS 0.91 (Userland). * @see \SimplePie\SimplePie::TYPE_RSS_091 RSS 0.91. * @see \SimplePie\SimplePie::TYPE_RSS_092 RSS 0.92. * @see \SimplePie\SimplePie::TYPE_RSS_093 RSS 0.93. * @see \SimplePie\SimplePie::TYPE_RSS_094 RSS 0.94. * @see \SimplePie\SimplePie::TYPE_RSS_10 RSS 1.0. * @see \SimplePie\SimplePie::TYPE_RSS_20 RSS 2.0.x. * @see \SimplePie\SimplePie::TYPE_RSS_RDF RDF-based RSS. * @see \SimplePie\SimplePie::TYPE_RSS_SYNDICATION Non-RDF-based RSS (truly intended as syndication format). * @see \SimplePie\SimplePie::TYPE_RSS_ALL Any version of RSS. * @see \SimplePie\SimplePie::TYPE_ATOM_03 Atom 0.3. * @see \SimplePie\SimplePie::TYPE_ATOM_10 Atom 1.0. * @see \SimplePie\SimplePie::TYPE_ATOM_ALL Any version of Atom. * @see \SimplePie\SimplePie::TYPE_ALL Any known/supported feed type. * @return int \SimplePie\SimplePie::TYPE_* constant */ public function get_type() { if (!isset($this->data['type'])) { $this->data['type'] = self::TYPE_ALL; if (isset($this->data['child'][self::NAMESPACE_ATOM_10]['feed'])) { $this->data['type'] &= self::TYPE_ATOM_10; } elseif (isset($this->data['child'][self::NAMESPACE_ATOM_03]['feed'])) { $this->data['type'] &= self::TYPE_ATOM_03; } elseif (isset($this->data['child'][self::NAMESPACE_RDF]['RDF'])) { if (isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][self::NAMESPACE_RSS_10]['channel']) || isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][self::NAMESPACE_RSS_10]['image']) || isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][self::NAMESPACE_RSS_10]['item']) || isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][self::NAMESPACE_RSS_10]['textinput'])) { $this->data['type'] &= self::TYPE_RSS_10; } if (isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][self::NAMESPACE_RSS_090]['channel']) || isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][self::NAMESPACE_RSS_090]['image']) || isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][self::NAMESPACE_RSS_090]['item']) || isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][self::NAMESPACE_RSS_090]['textinput'])) { $this->data['type'] &= self::TYPE_RSS_090; } } elseif (isset($this->data['child'][self::NAMESPACE_RSS_20]['rss'])) { $this->data['type'] &= self::TYPE_RSS_ALL; if (isset($this->data['child'][self::NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version'])) { switch (trim($this->data['child'][self::NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version'])) { case '0.91': $this->data['type'] &= self::TYPE_RSS_091; if (isset($this->data['child'][self::NAMESPACE_RSS_20]['rss'][0]['child'][self::NAMESPACE_RSS_20]['skiphours']['hour'][0]['data'])) { switch (trim($this->data['child'][self::NAMESPACE_RSS_20]['rss'][0]['child'][self::NAMESPACE_RSS_20]['skiphours']['hour'][0]['data'])) { case '0': $this->data['type'] &= self::TYPE_RSS_091_NETSCAPE; break; case '24': $this->data['type'] &= self::TYPE_RSS_091_USERLAND; break; } } break; case '0.92': $this->data['type'] &= self::TYPE_RSS_092; break; case '0.93': $this->data['type'] &= self::TYPE_RSS_093; break; case '0.94': $this->data['type'] &= self::TYPE_RSS_094; break; case '2.0': $this->data['type'] &= self::TYPE_RSS_20; break; } } } else { $this->data['type'] = self::TYPE_NONE; } } return $this->data['type']; } /** * Get the URL for the feed * * When the 'permanent' mode is enabled, returns the original feed URL, * except in the case of an `HTTP 301 Moved Permanently` status response, * in which case the location of the first redirection is returned. * * When the 'permanent' mode is disabled (default), * may or may not be different from the URL passed to {@see set_feed_url()}, * depending on whether auto-discovery was used, and whether there were * any redirects along the way. * * @since Preview Release (previously called `get_feed_url()` since SimplePie 0.8.) * @todo Support <itunes:new-feed-url> * @todo Also, |atom:link|@rel=self * @param bool $permanent Permanent mode to return only the original URL or the first redirection * iff it is a 301 redirection * @return string|null */ public function subscribe_url($permanent = false) { if ($permanent) { if ($this->permanent_url !== null) { // sanitize encodes ampersands which are required when used in a url. return str_replace( '&', '&', $this->sanitize( $this->permanent_url, self::CONSTRUCT_IRI ) ); } } else { if ($this->feed_url !== null) { return str_replace( '&', '&', $this->sanitize( $this->feed_url, self::CONSTRUCT_IRI ) ); } } return null; } /** * Get data for an feed-level element * * This method allows you to get access to ANY element/attribute that is a * sub-element of the opening feed tag. * * The return value is an indexed array of elements matching the given * namespace and tag name. Each element has `attribs`, `data` and `child` * subkeys. For `attribs` and `child`, these contain namespace subkeys. * `attribs` then has one level of associative name => value data (where * `value` is a string) after the namespace. `child` has tag-indexed keys * after the namespace, each member of which is an indexed array matching * this same format. * * For example: * <pre> * // This is probably a bad example because we already support * // <media:content> natively, but it shows you how to parse through * // the nodes. * $group = $item->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'group'); * $content = $group[0]['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['content']; * $file = $content[0]['attribs']['']['url']; * echo $file; * </pre> * * @since 1.0 * @see http://simplepie.org/wiki/faq/supported_xml_namespaces * @param string $namespace The URL of the XML namespace of the elements you're trying to access * @param string $tag Tag name * @return array */ public function get_feed_tags($namespace, $tag) { $type = $this->get_type(); if ($type & self::TYPE_ATOM_10) { if (isset($this->data['child'][self::NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag])) { return $this->data['child'][self::NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]; } } if ($type & self::TYPE_ATOM_03) { if (isset($this->data['child'][self::NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag])) { return $this->data['child'][self::NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]; } } if ($type & self::TYPE_RSS_RDF) { if (isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag])) { return $this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]; } } if ($type & self::TYPE_RSS_SYNDICATION) { if (isset($this->data['child'][self::NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag])) { return $this->data['child'][self::NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]; } } return null; } /** * Get data for an channel-level element * * This method allows you to get access to ANY element/attribute in the * channel/header section of the feed. * * See {@see SimplePie::get_feed_tags()} for a description of the return value * * @since 1.0 * @see http://simplepie.org/wiki/faq/supported_xml_namespaces * @param string $namespace The URL of the XML namespace of the elements you're trying to access * @param string $tag Tag name * @return array */ public function get_channel_tags($namespace, $tag) { $type = $this->get_type(); if ($type & self::TYPE_ATOM_ALL) { if ($return = $this->get_feed_tags($namespace, $tag)) { return $return; } } if ($type & self::TYPE_RSS_10) { if ($channel = $this->get_feed_tags(self::NAMESPACE_RSS_10, 'channel')) { if (isset($channel[0]['child'][$namespace][$tag])) { return $channel[0]['child'][$namespace][$tag]; } } } if ($type & self::TYPE_RSS_090) { if ($channel = $this->get_feed_tags(self::NAMESPACE_RSS_090, 'channel')) { if (isset($channel[0]['child'][$namespace][$tag])) { return $channel[0]['child'][$namespace][$tag]; } } } if ($type & self::TYPE_RSS_SYNDICATION) { if ($channel = $this->get_feed_tags(self::NAMESPACE_RSS_20, 'channel')) { if (isset($channel[0]['child'][$namespace][$tag])) { return $channel[0]['child'][$namespace][$tag]; } } } return null; } /** * Get data for an channel-level element * * This method allows you to get access to ANY element/attribute in the * image/logo section of the feed. * * See {@see SimplePie::get_feed_tags()} for a description of the return value * * @since 1.0 * @see http://simplepie.org/wiki/faq/supported_xml_namespaces * @param string $namespace The URL of the XML namespace of the elements you're trying to access * @param string $tag Tag name * @return array */ public function get_image_tags($namespace, $tag) { $type = $this->get_type(); if ($type & self::TYPE_RSS_10) { if ($image = $this->get_feed_tags(self::NAMESPACE_RSS_10, 'image')) { if (isset($image[0]['child'][$namespace][$tag])) { return $image[0]['child'][$namespace][$tag]; } } } if ($type & self::TYPE_RSS_090) { if ($image = $this->get_feed_tags(self::NAMESPACE_RSS_090, 'image')) { if (isset($image[0]['child'][$namespace][$tag])) { return $image[0]['child'][$namespace][$tag]; } } } if ($type & self::TYPE_RSS_SYNDICATION) { if ($image = $this->get_channel_tags(self::NAMESPACE_RSS_20, 'image')) { if (isset($image[0]['child'][$namespace][$tag])) { return $image[0]['child'][$namespace][$tag]; } } } return null; } /** * Get the base URL value from the feed * * Uses `<xml:base>` if available, otherwise uses the first link in the * feed, or failing that, the URL of the feed itself. * * @see get_link * @see subscribe_url * * @param array $element * @return string */ public function get_base($element = []) { if (!empty($element['xml_base_explicit']) && isset($element['xml_base'])) { return $element['xml_base']; } elseif ($this->get_link() !== null) { return $this->get_link(); } return $this->subscribe_url(); } /** * Sanitize feed data * * @access private * @see \SimplePie\Sanitize::sanitize() * @param string $data Data to sanitize * @param int $type One of the \SimplePie\SimplePie::CONSTRUCT_* constants * @param string $base Base URL to resolve URLs against * @return string Sanitized data */ public function sanitize($data, $type, $base = '') { try { return $this->sanitize->sanitize($data, $type, $base); } catch (\SimplePie\Exception $e) { if (!$this->enable_exceptions) { $this->error = $e->getMessage(); $this->registry->call(Misc::class, 'error', [$this->error, E_USER_WARNING, $e->getFile(), $e->getLine()]); return ''; } throw $e; } } /** * Get the title of the feed * * Uses `<atom:title>`, `<title>` or `<dc:title>` * * @since 1.0 (previously called `get_feed_title` since 0.8) * @return string|null */ public function get_title() { if ($return = $this->get_channel_tags(self::NAMESPACE_ATOM_10, 'title')) { return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_10_construct_type', [$return[0]['attribs']]), $this->get_base($return[0])); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_ATOM_03, 'title')) { return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_03_construct_type', [$return[0]['attribs']]), $this->get_base($return[0])); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_RSS_10, 'title')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_RSS_090, 'title')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_RSS_20, 'title')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_DC_11, 'title')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_DC_10, 'title')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT); } return null; } /** * Get a category for the feed * * @since Unknown * @param int $key The category that you want to return. Remember that arrays begin with 0, not 1 * @return \SimplePie\Category|null */ public function get_category($key = 0) { $categories = $this->get_categories(); if (isset($categories[$key])) { return $categories[$key]; } return null; } /** * Get all categories for the feed * * Uses `<atom:category>`, `<category>` or `<dc:subject>` * * @since Unknown * @return array|null List of {@see \SimplePie\Category} objects */ public function get_categories() { $categories = []; foreach ((array) $this->get_channel_tags(self::NAMESPACE_ATOM_10, 'category') as $category) { $term = null; $scheme = null; $label = null; if (isset($category['attribs']['']['term'])) { $term = $this->sanitize($category['attribs']['']['term'], self::CONSTRUCT_TEXT); } if (isset($category['attribs']['']['scheme'])) { $scheme = $this->sanitize($category['attribs']['']['scheme'], self::CONSTRUCT_TEXT); } if (isset($category['attribs']['']['label'])) { $label = $this->sanitize($category['attribs']['']['label'], self::CONSTRUCT_TEXT); } $categories[] = $this->registry->create(Category::class, [$term, $scheme, $label]); } foreach ((array) $this->get_channel_tags(self::NAMESPACE_RSS_20, 'category') as $category) { // This is really the label, but keep this as the term also for BC. // Label will also work on retrieving because that falls back to term. $term = $this->sanitize($category['data'], self::CONSTRUCT_TEXT); if (isset($category['attribs']['']['domain'])) { $scheme = $this->sanitize($category['attribs']['']['domain'], self::CONSTRUCT_TEXT); } else { $scheme = null; } $categories[] = $this->registry->create(Category::class, [$term, $scheme, null]); } foreach ((array) $this->get_channel_tags(self::NAMESPACE_DC_11, 'subject') as $category) { $categories[] = $this->registry->create(Category::class, [$this->sanitize($category['data'], self::CONSTRUCT_TEXT), null, null]); } foreach ((array) $this->get_channel_tags(self::NAMESPACE_DC_10, 'subject') as $category) { $categories[] = $this->registry->create(Category::class, [$this->sanitize($category['data'], self::CONSTRUCT_TEXT), null, null]); } if (!empty($categories)) { return array_unique($categories); } return null; } /** * Get an author for the feed * * @since 1.1 * @param int $key The author that you want to return. Remember that arrays begin with 0, not 1 * @return \SimplePie\Author|null */ public function get_author($key = 0) { $authors = $this->get_authors(); if (isset($authors[$key])) { return $authors[$key]; } return null; } /** * Get all authors for the feed * * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>` * * @since 1.1 * @return array|null List of {@see \SimplePie\Author} objects */ public function get_authors() { $authors = []; foreach ((array) $this->get_channel_tags(self::NAMESPACE_ATOM_10, 'author') as $author) { $name = null; $uri = null; $email = null; if (isset($author['child'][self::NAMESPACE_ATOM_10]['name'][0]['data'])) { $name = $this->sanitize($author['child'][self::NAMESPACE_ATOM_10]['name'][0]['data'], self::CONSTRUCT_TEXT); } if (isset($author['child'][self::NAMESPACE_ATOM_10]['uri'][0]['data'])) { $uri = $this->sanitize($author['child'][self::NAMESPACE_ATOM_10]['uri'][0]['data'], self::CONSTRUCT_IRI, $this->get_base($author['child'][self::NAMESPACE_ATOM_10]['uri'][0])); } if (isset($author['child'][self::NAMESPACE_ATOM_10]['email'][0]['data'])) { $email = $this->sanitize($author['child'][self::NAMESPACE_ATOM_10]['email'][0]['data'], self::CONSTRUCT_TEXT); } if ($name !== null || $email !== null || $uri !== null) { $authors[] = $this->registry->create(Author::class, [$name, $uri, $email]); } } if ($author = $this->get_channel_tags(self::NAMESPACE_ATOM_03, 'author')) { $name = null; $url = null; $email = null; if (isset($author[0]['child'][self::NAMESPACE_ATOM_03]['name'][0]['data'])) { $name = $this->sanitize($author[0]['child'][self::NAMESPACE_ATOM_03]['name'][0]['data'], self::CONSTRUCT_TEXT); } if (isset($author[0]['child'][self::NAMESPACE_ATOM_03]['url'][0]['data'])) { $url = $this->sanitize($author[0]['child'][self::NAMESPACE_ATOM_03]['url'][0]['data'], self::CONSTRUCT_IRI, $this->get_base($author[0]['child'][self::NAMESPACE_ATOM_03]['url'][0])); } if (isset($author[0]['child'][self::NAMESPACE_ATOM_03]['email'][0]['data'])) { $email = $this->sanitize($author[0]['child'][self::NAMESPACE_ATOM_03]['email'][0]['data'], self::CONSTRUCT_TEXT); } if ($name !== null || $email !== null || $url !== null) { $authors[] = $this->registry->create(Author::class, [$name, $url, $email]); } } foreach ((array) $this->get_channel_tags(self::NAMESPACE_DC_11, 'creator') as $author) { $authors[] = $this->registry->create(Author::class, [$this->sanitize($author['data'], self::CONSTRUCT_TEXT), null, null]); } foreach ((array) $this->get_channel_tags(self::NAMESPACE_DC_10, 'creator') as $author) { $authors[] = $this->registry->create(Author::class, [$this->sanitize($author['data'], self::CONSTRUCT_TEXT), null, null]); } foreach ((array) $this->get_channel_tags(self::NAMESPACE_ITUNES, 'author') as $author) { $authors[] = $this->registry->create(Author::class, [$this->sanitize($author['data'], self::CONSTRUCT_TEXT), null, null]); } if (!empty($authors)) { return array_unique($authors); } return null; } /** * Get a contributor for the feed * * @since 1.1 * @param int $key The contrbutor that you want to return. Remember that arrays begin with 0, not 1 * @return \SimplePie\Author|null */ public function get_contributor($key = 0) { $contributors = $this->get_contributors(); if (isset($contributors[$key])) { return $contributors[$key]; } return null; } /** * Get all contributors for the feed * * Uses `<atom:contributor>` * * @since 1.1 * @return array|null List of {@see \SimplePie\Author} objects */ public function get_contributors() { $contributors = []; foreach ((array) $this->get_channel_tags(self::NAMESPACE_ATOM_10, 'contributor') as $contributor) { $name = null; $uri = null; $email = null; if (isset($contributor['child'][self::NAMESPACE_ATOM_10]['name'][0]['data'])) { $name = $this->sanitize($contributor['child'][self::NAMESPACE_ATOM_10]['name'][0]['data'], self::CONSTRUCT_TEXT); } if (isset($contributor['child'][self::NAMESPACE_ATOM_10]['uri'][0]['data'])) { $uri = $this->sanitize($contributor['child'][self::NAMESPACE_ATOM_10]['uri'][0]['data'], self::CONSTRUCT_IRI, $this->get_base($contributor['child'][self::NAMESPACE_ATOM_10]['uri'][0])); } if (isset($contributor['child'][self::NAMESPACE_ATOM_10]['email'][0]['data'])) { $email = $this->sanitize($contributor['child'][self::NAMESPACE_ATOM_10]['email'][0]['data'], self::CONSTRUCT_TEXT); } if ($name !== null || $email !== null || $uri !== null) { $contributors[] = $this->registry->create(Author::class, [$name, $uri, $email]); } } foreach ((array) $this->get_channel_tags(self::NAMESPACE_ATOM_03, 'contributor') as $contributor) { $name = null; $url = null; $email = null; if (isset($contributor['child'][self::NAMESPACE_ATOM_03]['name'][0]['data'])) { $name = $this->sanitize($contributor['child'][self::NAMESPACE_ATOM_03]['name'][0]['data'], self::CONSTRUCT_TEXT); } if (isset($contributor['child'][self::NAMESPACE_ATOM_03]['url'][0]['data'])) { $url = $this->sanitize($contributor['child'][self::NAMESPACE_ATOM_03]['url'][0]['data'], self::CONSTRUCT_IRI, $this->get_base($contributor['child'][self::NAMESPACE_ATOM_03]['url'][0])); } if (isset($contributor['child'][self::NAMESPACE_ATOM_03]['email'][0]['data'])) { $email = $this->sanitize($contributor['child'][self::NAMESPACE_ATOM_03]['email'][0]['data'], self::CONSTRUCT_TEXT); } if ($name !== null || $email !== null || $url !== null) { $contributors[] = $this->registry->create(Author::class, [$name, $url, $email]); } } if (!empty($contributors)) { return array_unique($contributors); } return null; } /** * Get a single link for the feed * * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8) * @param int $key The link that you want to return. Remember that arrays begin with 0, not 1 * @param string $rel The relationship of the link to return * @return string|null Link URL */ public function get_link($key = 0, $rel = 'alternate') { $links = $this->get_links($rel); if (isset($links[$key])) { return $links[$key]; } return null; } /** * Get the permalink for the item * * Returns the first link available with a relationship of "alternate". * Identical to {@see get_link()} with key 0 * * @see get_link * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8) * @internal Added for parity between the parent-level and the item/entry-level. * @return string|null Link URL */ public function get_permalink() { return $this->get_link(0); } /** * Get all links for the feed * * Uses `<atom:link>` or `<link>` * * @since Beta 2 * @param string $rel The relationship of links to return * @return array|null Links found for the feed (strings) */ public function get_links($rel = 'alternate') { if (!isset($this->data['links'])) { $this->data['links'] = []; if ($links = $this->get_channel_tags(self::NAMESPACE_ATOM_10, 'link')) { foreach ($links as $link) { if (isset($link['attribs']['']['href'])) { $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], self::CONSTRUCT_IRI, $this->get_base($link)); } } } if ($links = $this->get_channel_tags(self::NAMESPACE_ATOM_03, 'link')) { foreach ($links as $link) { if (isset($link['attribs']['']['href'])) { $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], self::CONSTRUCT_IRI, $this->get_base($link)); } } } if ($links = $this->get_channel_tags(self::NAMESPACE_RSS_10, 'link')) { $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], self::CONSTRUCT_IRI, $this->get_base($links[0])); } if ($links = $this->get_channel_tags(self::NAMESPACE_RSS_090, 'link')) { $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], self::CONSTRUCT_IRI, $this->get_base($links[0])); } if ($links = $this->get_channel_tags(self::NAMESPACE_RSS_20, 'link')) { $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], self::CONSTRUCT_IRI, $this->get_base($links[0])); } $keys = array_keys($this->data['links']); foreach ($keys as $key) { if ($this->registry->call(Misc::class, 'is_isegment_nz_nc', [$key])) { if (isset($this->data['links'][self::IANA_LINK_RELATIONS_REGISTRY . $key])) { $this->data['links'][self::IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][self::IANA_LINK_RELATIONS_REGISTRY . $key]); $this->data['links'][$key] = &$this->data['links'][self::IANA_LINK_RELATIONS_REGISTRY . $key]; } else { $this->data['links'][self::IANA_LINK_RELATIONS_REGISTRY . $key] = &$this->data['links'][$key]; } } elseif (substr($key, 0, 41) === self::IANA_LINK_RELATIONS_REGISTRY) { $this->data['links'][substr($key, 41)] = &$this->data['links'][$key]; } $this->data['links'][$key] = array_unique($this->data['links'][$key]); } } if (isset($this->data['headers']['link'])) { $link_headers = $this->data['headers']['link']; if (is_array($link_headers)) { $link_headers = implode(',', $link_headers); } // https://datatracker.ietf.org/doc/html/rfc8288 if (is_string($link_headers) && preg_match_all('/<(?P<uri>[^>]+)>\s*;\s*rel\s*=\s*(?P<quote>"?)' . preg_quote($rel) . '(?P=quote)\s*(?=,|$)/i', $link_headers, $matches)) { return $matches['uri']; } } if (isset($this->data['links'][$rel])) { return $this->data['links'][$rel]; } return null; } public function get_all_discovered_feeds() { return $this->all_discovered_feeds; } /** * Get the content for the item * * Uses `<atom:subtitle>`, `<atom:tagline>`, `<description>`, * `<dc:description>`, `<itunes:summary>` or `<itunes:subtitle>` * * @since 1.0 (previously called `get_feed_description()` since 0.8) * @return string|null */ public function get_description() { if ($return = $this->get_channel_tags(self::NAMESPACE_ATOM_10, 'subtitle')) { return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_10_construct_type', [$return[0]['attribs']]), $this->get_base($return[0])); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_ATOM_03, 'tagline')) { return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_03_construct_type', [$return[0]['attribs']]), $this->get_base($return[0])); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_RSS_10, 'description')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_RSS_090, 'description')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_RSS_20, 'description')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_HTML, $this->get_base($return[0])); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_DC_11, 'description')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_DC_10, 'description')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_ITUNES, 'summary')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_HTML, $this->get_base($return[0])); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_ITUNES, 'subtitle')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_HTML, $this->get_base($return[0])); } return null; } /** * Get the copyright info for the feed * * Uses `<atom:rights>`, `<atom:copyright>` or `<dc:rights>` * * @since 1.0 (previously called `get_feed_copyright()` since 0.8) * @return string|null */ public function get_copyright() { if ($return = $this->get_channel_tags(self::NAMESPACE_ATOM_10, 'rights')) { return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_10_construct_type', [$return[0]['attribs']]), $this->get_base($return[0])); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_ATOM_03, 'copyright')) { return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_03_construct_type', [$return[0]['attribs']]), $this->get_base($return[0])); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_RSS_20, 'copyright')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_DC_11, 'rights')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_DC_10, 'rights')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT); } return null; } /** * Get the language for the feed * * Uses `<language>`, `<dc:language>`, or @xml_lang * * @since 1.0 (previously called `get_feed_language()` since 0.8) * @return string|null */ public function get_language() { if ($return = $this->get_channel_tags(self::NAMESPACE_RSS_20, 'language')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_DC_11, 'language')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_DC_10, 'language')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT); } elseif (isset($this->data['child'][self::NAMESPACE_ATOM_10]['feed'][0]['xml_lang'])) { return $this->sanitize($this->data['child'][self::NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], self::CONSTRUCT_TEXT); } elseif (isset($this->data['child'][self::NAMESPACE_ATOM_03]['feed'][0]['xml_lang'])) { return $this->sanitize($this->data['child'][self::NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], self::CONSTRUCT_TEXT); } elseif (isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['xml_lang'])) { return $this->sanitize($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['xml_lang'], self::CONSTRUCT_TEXT); } elseif (isset($this->data['headers']['content-language'])) { return $this->sanitize($this->data['headers']['content-language'], self::CONSTRUCT_TEXT); } return null; } /** * Get the latitude coordinates for the item * * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications * * Uses `<geo:lat>` or `<georss:point>` * * @since 1.0 * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo * @link http://www.georss.org/ GeoRSS * @return string|null */ public function get_latitude() { if ($return = $this->get_channel_tags(self::NAMESPACE_W3C_BASIC_GEO, 'lat')) { return (float) $return[0]['data']; } elseif (($return = $this->get_channel_tags(self::NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) { return (float) $match[1]; } return null; } /** * Get the longitude coordinates for the feed * * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications * * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>` * * @since 1.0 * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo * @link http://www.georss.org/ GeoRSS * @return string|null */ public function get_longitude() { if ($return = $this->get_channel_tags(self::NAMESPACE_W3C_BASIC_GEO, 'long')) { return (float) $return[0]['data']; } elseif ($return = $this->get_channel_tags(self::NAMESPACE_W3C_BASIC_GEO, 'lon')) { return (float) $return[0]['data']; } elseif (($return = $this->get_channel_tags(self::NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) { return (float) $match[2]; } return null; } /** * Get the feed logo's title * * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" title. * * Uses `<image><title>` or `<image><dc:title>` * * @return string|null */ public function get_image_title() { if ($return = $this->get_image_tags(self::NAMESPACE_RSS_10, 'title')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT); } elseif ($return = $this->get_image_tags(self::NAMESPACE_RSS_090, 'title')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT); } elseif ($return = $this->get_image_tags(self::NAMESPACE_RSS_20, 'title')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT); } elseif ($return = $this->get_image_tags(self::NAMESPACE_DC_11, 'title')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT); } elseif ($return = $this->get_image_tags(self::NAMESPACE_DC_10, 'title')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT); } return null; } /** * Get the feed logo's URL * * RSS 0.9.0, 2.0, Atom 1.0, and feeds with iTunes RSS tags are allowed to * have a "feed logo" URL. This points directly to the image itself. * * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`, * `<image><title>` or `<image><dc:title>` * * @return string|null */ public function get_image_url() { if ($return = $this->get_channel_tags(self::NAMESPACE_ITUNES, 'image')) { return $this->sanitize($return[0]['attribs']['']['href'], self::CONSTRUCT_IRI); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_ATOM_10, 'logo')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_IRI, $this->get_base($return[0])); } elseif ($return = $this->get_channel_tags(self::NAMESPACE_ATOM_10, 'icon')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_IRI, $this->get_base($return[0])); } elseif ($return = $this->get_image_tags(self::NAMESPACE_RSS_10, 'url')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_IRI, $this->get_base($return[0])); } elseif ($return = $this->get_image_tags(self::NAMESPACE_RSS_090, 'url')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_IRI, $this->get_base($return[0])); } elseif ($return = $this->get_image_tags(self::NAMESPACE_RSS_20, 'url')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_IRI, $this->get_base($return[0])); } return null; } /** * Get the feed logo's link * * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" link. This * points to a human-readable page that the image should link to. * * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`, * `<image><title>` or `<image><dc:title>` * * @return string|null */ public function get_image_link() { if ($return = $this->get_image_tags(self::NAMESPACE_RSS_10, 'link')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_IRI, $this->get_base($return[0])); } elseif ($return = $this->get_image_tags(self::NAMESPACE_RSS_090, 'link')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_IRI, $this->get_base($return[0])); } elseif ($return = $this->get_image_tags(self::NAMESPACE_RSS_20, 'link')) { return $this->sanitize($return[0]['data'], self::CONSTRUCT_IRI, $this->get_base($return[0])); } return null; } /** * Get the feed logo's link * * RSS 2.0 feeds are allowed to have a "feed logo" width. * * Uses `<image><width>` or defaults to 88 if no width is specified and * the feed is an RSS 2.0 feed. * * @return int|null */ public function get_image_width() { if ($return = $this->get_image_tags(self::NAMESPACE_RSS_20, 'width')) { return intval($return[0]['data']); } elseif ($this->get_type() & self::TYPE_RSS_SYNDICATION && $this->get_image_tags(self::NAMESPACE_RSS_20, 'url')) { return 88; } return null; } /** * Get the feed logo's height * * RSS 2.0 feeds are allowed to have a "feed logo" height. * * Uses `<image><height>` or defaults to 31 if no height is specified and * the feed is an RSS 2.0 feed. * * @return int|null */ public function get_image_height() { if ($return = $this->get_image_tags(self::NAMESPACE_RSS_20, 'height')) { return intval($return[0]['data']); } elseif ($this->get_type() & self::TYPE_RSS_SYNDICATION && $this->get_image_tags(self::NAMESPACE_RSS_20, 'url')) { return 31; } return null; } /** * Get the number of items in the feed * * This is well-suited for {@link http://php.net/for for()} loops with * {@see get_item()} * * @param int $max Maximum value to return. 0 for no limit * @return int Number of items in the feed */ public function get_item_quantity($max = 0) { $max = (int) $max; $qty = count($this->get_items()); if ($max === 0) { return $qty; } return ($qty > $max) ? $max : $qty; } /** * Get a single item from the feed * * This is better suited for {@link http://php.net/for for()} loops, whereas * {@see get_items()} is better suited for * {@link http://php.net/foreach foreach()} loops. * * @see get_item_quantity() * @since Beta 2 * @param int $key The item that you want to return. Remember that arrays begin with 0, not 1 * @return \SimplePie\Item|null */ public function get_item($key = 0) { $items = $this->get_items(); if (isset($items[$key])) { return $items[$key]; } return null; } /** * Get all items from the feed * * This is better suited for {@link http://php.net/for for()} loops, whereas * {@see get_items()} is better suited for * {@link http://php.net/foreach foreach()} loops. * * @see get_item_quantity * @since Beta 2 * @param int $start Index to start at * @param int $end Number of items to return. 0 for all items after `$start` * @return \SimplePie\Item[]|null List of {@see \SimplePie\Item} objects */ public function get_items($start = 0, $end = 0) { if (!isset($this->data['items'])) { if (!empty($this->multifeed_objects)) { $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit); if (empty($this->data['items'])) { return []; } return $this->data['items']; } $this->data['items'] = []; if ($items = $this->get_feed_tags(self::NAMESPACE_ATOM_10, 'entry')) { $keys = array_keys($items); foreach ($keys as $key) { $this->data['items'][] = $this->registry->create(Item::class, [$this, $items[$key]]); } } if ($items = $this->get_feed_tags(self::NAMESPACE_ATOM_03, 'entry')) { $keys = array_keys($items); foreach ($keys as $key) { $this->data['items'][] = $this->registry->create(Item::class, [$this, $items[$key]]); } } if ($items = $this->get_feed_tags(self::NAMESPACE_RSS_10, 'item')) { $keys = array_keys($items); foreach ($keys as $key) { $this->data['items'][] = $this->registry->create(Item::class, [$this, $items[$key]]); } } if ($items = $this->get_feed_tags(self::NAMESPACE_RSS_090, 'item')) { $keys = array_keys($items); foreach ($keys as $key) { $this->data['items'][] = $this->registry->create(Item::class, [$this, $items[$key]]); } } if ($items = $this->get_channel_tags(self::NAMESPACE_RSS_20, 'item')) { $keys = array_keys($items); foreach ($keys as $key) { $this->data['items'][] = $this->registry->create(Item::class, [$this, $items[$key]]); } } } if (empty($this->data['items'])) { return []; } if ($this->order_by_date) { if (!isset($this->data['ordered_items'])) { $this->data['ordered_items'] = $this->data['items']; usort($this->data['ordered_items'], [get_class($this), 'sort_items']); } $items = $this->data['ordered_items']; } else { $items = $this->data['items']; } // Slice the data as desired if ($end === 0) { return array_slice($items, $start); } return array_slice($items, $start, $end); } /** * Set the favicon handler * * @deprecated Use your own favicon handling instead */ public function set_favicon_handler($page = false, $qs = 'i') { trigger_error('Favicon handling has been removed, please use your own handling', \E_USER_DEPRECATED); return false; } /** * Get the favicon for the current feed * * @deprecated Use your own favicon handling instead */ public function get_favicon() { trigger_error('Favicon handling has been removed, please use your own handling', \E_USER_DEPRECATED); if (($url = $this->get_link()) !== null) { return 'https://www.google.com/s2/favicons?domain=' . urlencode($url); } return false; } /** * Magic method handler * * @param string $method Method name * @param array $args Arguments to the method * @return mixed */ public function __call($method, $args) { if (strpos($method, 'subscribe_') === 0) { trigger_error('subscribe_*() has been deprecated, implement the callback yourself', \E_USER_DEPRECATED); return ''; } if ($method === 'enable_xml_dump') { trigger_error('enable_xml_dump() has been deprecated, use get_raw_data() instead', \E_USER_DEPRECATED); return false; } $class = get_class($this); $trace = debug_backtrace(); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection $file = $trace[0]['file']; $line = $trace[0]['line']; throw new SimplePieException("Call to undefined method $class::$method() in $file on line $line"); } /** * Sorting callback for items * * @access private * @param SimplePie $a * @param SimplePie $b * @return boolean */ public static function sort_items($a, $b) { $a_date = $a->get_date('U'); $b_date = $b->get_date('U'); if ($a_date && $b_date) { return $a_date > $b_date ? -1 : 1; } // Sort items without dates to the top. if ($a_date) { return 1; } if ($b_date) { return -1; } return 0; } /** * Merge items from several feeds into one * * If you're merging multiple feeds together, they need to all have dates * for the items or else SimplePie will refuse to sort them. * * @link http://simplepie.org/wiki/tutorial/sort_multiple_feeds_by_time_and_date#if_feeds_require_separate_per-feed_settings * @param array $urls List of SimplePie feed objects to merge * @param int $start Starting item * @param int $end Number of items to return * @param int $limit Maximum number of items per feed * @return array */ public static function merge_items($urls, $start = 0, $end = 0, $limit = 0) { if (is_array($urls) && sizeof($urls) > 0) { $items = []; foreach ($urls as $arg) { if ($arg instanceof SimplePie) { $items = array_merge($items, $arg->get_items(0, $limit)); } else { trigger_error('Arguments must be SimplePie objects', E_USER_WARNING); } } usort($items, [get_class($urls[0]), 'sort_items']); if ($end === 0) { return array_slice($items, $start); } return array_slice($items, $start, $end); } trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING); return []; } /** * Store PubSubHubbub links as headers * * There is no way to find PuSH links in the body of a microformats feed, * so they are added to the headers when found, to be used later by get_links. * @param \SimplePie\File $file * @param string $hub * @param string $self */ private function store_links(&$file, $hub, $self) { if (isset($file->headers['link']['hub']) || (isset($file->headers['link']) && preg_match('/rel=hub/', $file->headers['link']))) { return; } if ($hub) { if (isset($file->headers['link'])) { if ($file->headers['link'] !== '') { $file->headers['link'] = ', '; } } else { $file->headers['link'] = ''; } $file->headers['link'] .= '<'.$hub.'>; rel=hub'; if ($self) { $file->headers['link'] .= ', <'.$self.'>; rel=self'; } } } /** * Get a DataCache * * @param string $feed_url Only needed for BC, can be removed in SimplePie 2.0.0 * * @return DataCache */ private function get_cache($feed_url = '') { if ($this->cache === null) { // @trigger_error(sprintf('Not providing as PSR-16 cache implementation is deprecated since SimplePie 1.8.0, please use "SimplePie\SimplePie::set_cache()".'), \E_USER_DEPRECATED); $cache = $this->registry->call(Cache::class, 'get_handler', [ $this->cache_location, $this->get_cache_filename($feed_url), Base::TYPE_FEED ]); return new BaseDataCache($cache); } return $this->cache; } } class_alias('SimplePie\SimplePie', 'SimplePie'); PK������ZSd2��2����File.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie; /** * Used for fetching remote files and reading local files * * Supports HTTP 1.0 via cURL or fsockopen, with spotty HTTP 1.1 support * * This class can be overloaded with {@see \SimplePie\SimplePie::set_file_class()} * * @package SimplePie * @subpackage HTTP * @todo Move to properly supporting RFC2616 (HTTP/1.1) */ class File { public $url; public $useragent; public $success = true; public $headers = []; public $body; public $status_code = 0; public $redirects = 0; public $error; public $method = \SimplePie\SimplePie::FILE_SOURCE_NONE; public $permanent_url; public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false, $curl_options = []) { if (class_exists('idna_convert')) { $idn = new \idna_convert(); $parsed = \SimplePie\Misc::parse_url($url); $url = \SimplePie\Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], null); } $this->url = $url; $this->permanent_url = $url; $this->useragent = $useragent; if (preg_match('/^http(s)?:\/\//i', $url)) { if ($useragent === null) { $useragent = ini_get('user_agent'); $this->useragent = $useragent; } if (!is_array($headers)) { $headers = []; } if (!$force_fsockopen && function_exists('curl_exec')) { $this->method = \SimplePie\SimplePie::FILE_SOURCE_REMOTE | \SimplePie\SimplePie::FILE_SOURCE_CURL; $fp = curl_init(); $headers2 = []; foreach ($headers as $key => $value) { $headers2[] = "$key: $value"; } if (version_compare(\SimplePie\Misc::get_curl_version(), '7.10.5', '>=')) { curl_setopt($fp, CURLOPT_ENCODING, ''); } curl_setopt($fp, CURLOPT_URL, $url); curl_setopt($fp, CURLOPT_HEADER, 1); curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1); curl_setopt($fp, CURLOPT_FAILONERROR, 1); curl_setopt($fp, CURLOPT_TIMEOUT, $timeout); curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout); curl_setopt($fp, CURLOPT_REFERER, \SimplePie\Misc::url_remove_credentials($url)); curl_setopt($fp, CURLOPT_USERAGENT, $useragent); curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2); foreach ($curl_options as $curl_param => $curl_value) { curl_setopt($fp, $curl_param, $curl_value); } $this->headers = curl_exec($fp); if (curl_errno($fp) === 23 || curl_errno($fp) === 61) { curl_setopt($fp, CURLOPT_ENCODING, 'none'); $this->headers = curl_exec($fp); } $this->status_code = curl_getinfo($fp, CURLINFO_HTTP_CODE); if (curl_errno($fp)) { $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp); $this->success = false; } else { // Use the updated url provided by curl_getinfo after any redirects. if ($info = curl_getinfo($fp)) { $this->url = $info['url']; } curl_close($fp); $this->headers = \SimplePie\HTTP\Parser::prepareHeaders($this->headers, $info['redirect_count'] + 1); $parser = new \SimplePie\HTTP\Parser($this->headers); if ($parser->parse()) { $this->headers = $parser->headers; $this->body = trim($parser->body); $this->status_code = $parser->status_code; if ((in_array($this->status_code, [300, 301, 302, 303, 307]) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects) { $this->redirects++; $location = \SimplePie\Misc::absolutize_url($this->headers['location'], $url); $previousStatusCode = $this->status_code; $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen, $curl_options); $this->permanent_url = ($previousStatusCode == 301) ? $location : $url; return; } } } } else { $this->method = \SimplePie\SimplePie::FILE_SOURCE_REMOTE | \SimplePie\SimplePie::FILE_SOURCE_FSOCKOPEN; $url_parts = parse_url($url); $socket_host = $url_parts['host']; if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https') { $socket_host = "ssl://$url_parts[host]"; $url_parts['port'] = 443; } if (!isset($url_parts['port'])) { $url_parts['port'] = 80; } $fp = @fsockopen($socket_host, $url_parts['port'], $errno, $errstr, $timeout); if (!$fp) { $this->error = 'fsockopen error: ' . $errstr; $this->success = false; } else { stream_set_timeout($fp, $timeout); if (isset($url_parts['path'])) { if (isset($url_parts['query'])) { $get = "$url_parts[path]?$url_parts[query]"; } else { $get = $url_parts['path']; } } else { $get = '/'; } $out = "GET $get HTTP/1.1\r\n"; $out .= "Host: $url_parts[host]\r\n"; $out .= "User-Agent: $useragent\r\n"; if (extension_loaded('zlib')) { $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n"; } if (isset($url_parts['user']) && isset($url_parts['pass'])) { $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n"; } foreach ($headers as $key => $value) { $out .= "$key: $value\r\n"; } $out .= "Connection: Close\r\n\r\n"; fwrite($fp, $out); $info = stream_get_meta_data($fp); $this->headers = ''; while (!$info['eof'] && !$info['timed_out']) { $this->headers .= fread($fp, 1160); $info = stream_get_meta_data($fp); } if (!$info['timed_out']) { $parser = new \SimplePie\HTTP\Parser($this->headers); if ($parser->parse()) { $this->headers = $parser->headers; $this->body = $parser->body; $this->status_code = $parser->status_code; if ((in_array($this->status_code, [300, 301, 302, 303, 307]) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects) { $this->redirects++; $location = \SimplePie\Misc::absolutize_url($this->headers['location'], $url); $previousStatusCode = $this->status_code; $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen, $curl_options); $this->permanent_url = ($previousStatusCode == 301) ? $location : $url; return; } if (isset($this->headers['content-encoding'])) { // Hey, we act dumb elsewhere, so let's do that here too switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20"))) { case 'gzip': case 'x-gzip': $decoder = new \SimplePie\Gzdecode($this->body); if (!$decoder->parse()) { $this->error = 'Unable to decode HTTP "gzip" stream'; $this->success = false; } else { $this->body = trim($decoder->data); } break; case 'deflate': if (($decompressed = gzinflate($this->body)) !== false) { $this->body = $decompressed; } elseif (($decompressed = gzuncompress($this->body)) !== false) { $this->body = $decompressed; } elseif (function_exists('gzdecode') && ($decompressed = gzdecode($this->body)) !== false) { $this->body = $decompressed; } else { $this->error = 'Unable to decode HTTP "deflate" stream'; $this->success = false; } break; default: $this->error = 'Unknown content coding'; $this->success = false; } } } } else { $this->error = 'fsocket timed out'; $this->success = false; } fclose($fp); } } } else { $this->method = \SimplePie\SimplePie::FILE_SOURCE_LOCAL | \SimplePie\SimplePie::FILE_SOURCE_FILE_GET_CONTENTS; if (empty($url) || !($this->body = trim(file_get_contents($url)))) { $this->error = 'file_get_contents could not read the file'; $this->success = false; } } } } class_alias('SimplePie\File', 'SimplePie_File'); PK������Z7-=��-=�� ��Locator.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie; /** * Used for feed auto-discovery * * * This class can be overloaded with {@see \SimplePie\SimplePie::set_locator_class()} * * @package SimplePie */ class Locator implements RegistryAware { public $useragent; public $timeout; public $file; public $local = []; public $elsewhere = []; public $cached_entities = []; public $http_base; public $base; public $base_location = 0; public $checked_feeds = 0; public $max_checked_feeds = 10; public $force_fsockopen = false; public $curl_options = []; public $dom; protected $registry; public function __construct(\SimplePie\File $file, $timeout = 10, $useragent = null, $max_checked_feeds = 10, $force_fsockopen = false, $curl_options = []) { $this->file = $file; $this->useragent = $useragent; $this->timeout = $timeout; $this->max_checked_feeds = $max_checked_feeds; $this->force_fsockopen = $force_fsockopen; $this->curl_options = $curl_options; if (class_exists('DOMDocument') && $this->file->body != '') { $this->dom = new \DOMDocument(); set_error_handler(['SimplePie\Misc', 'silence_errors']); try { $this->dom->loadHTML($this->file->body); } catch (\Throwable $ex) { $this->dom = null; } restore_error_handler(); } else { $this->dom = null; } } public function set_registry(\SimplePie\Registry $registry)/* : void */ { $this->registry = $registry; } public function find($type = \SimplePie\SimplePie::LOCATOR_ALL, &$working = null) { if ($this->is_feed($this->file)) { return $this->file; } if ($this->file->method & \SimplePie\SimplePie::FILE_SOURCE_REMOTE) { $sniffer = $this->registry->create(Content\Type\Sniffer::class, [$this->file]); if ($sniffer->get_type() !== 'text/html') { return null; } } if ($type & ~\SimplePie\SimplePie::LOCATOR_NONE) { $this->get_base(); } if ($type & \SimplePie\SimplePie::LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery()) { return $working[0]; } if ($type & (\SimplePie\SimplePie::LOCATOR_LOCAL_EXTENSION | \SimplePie\SimplePie::LOCATOR_LOCAL_BODY | \SimplePie\SimplePie::LOCATOR_REMOTE_EXTENSION | \SimplePie\SimplePie::LOCATOR_REMOTE_BODY) && $this->get_links()) { if ($type & \SimplePie\SimplePie::LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local)) { return $working[0]; } if ($type & \SimplePie\SimplePie::LOCATOR_LOCAL_BODY && $working = $this->body($this->local)) { return $working[0]; } if ($type & \SimplePie\SimplePie::LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere)) { return $working[0]; } if ($type & \SimplePie\SimplePie::LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere)) { return $working[0]; } } return null; } public function is_feed($file, $check_html = false) { if ($file->method & \SimplePie\SimplePie::FILE_SOURCE_REMOTE) { $sniffer = $this->registry->create(Content\Type\Sniffer::class, [$file]); $sniffed = $sniffer->get_type(); $mime_types = ['application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml', 'application/x-rss+xml']; if ($check_html) { $mime_types[] = 'text/html'; } return in_array($sniffed, $mime_types); } elseif ($file->method & \SimplePie\SimplePie::FILE_SOURCE_LOCAL) { return true; } else { return false; } } public function get_base() { if ($this->dom === null) { throw new \SimplePie\Exception('DOMDocument not found, unable to use locator'); } $this->http_base = $this->file->url; $this->base = $this->http_base; $elements = $this->dom->getElementsByTagName('base'); foreach ($elements as $element) { if ($element->hasAttribute('href')) { $base = $this->registry->call(Misc::class, 'absolutize_url', [trim($element->getAttribute('href')), $this->http_base]); if ($base === false) { continue; } $this->base = $base; $this->base_location = method_exists($element, 'getLineNo') ? $element->getLineNo() : 0; break; } } } public function autodiscovery() { $done = []; $feeds = []; $feeds = array_merge($feeds, $this->search_elements_by_tag('link', $done, $feeds)); $feeds = array_merge($feeds, $this->search_elements_by_tag('a', $done, $feeds)); $feeds = array_merge($feeds, $this->search_elements_by_tag('area', $done, $feeds)); if (!empty($feeds)) { return array_values($feeds); } return null; } protected function search_elements_by_tag($name, &$done, $feeds) { if ($this->dom === null) { throw new \SimplePie\Exception('DOMDocument not found, unable to use locator'); } $links = $this->dom->getElementsByTagName($name); foreach ($links as $link) { if ($this->checked_feeds === $this->max_checked_feeds) { break; } if ($link->hasAttribute('href') && $link->hasAttribute('rel')) { $rel = array_unique($this->registry->call(Misc::class, 'space_separated_tokens', [strtolower($link->getAttribute('rel'))])); $line = method_exists($link, 'getLineNo') ? $link->getLineNo() : 1; if ($this->base_location < $line) { $href = $this->registry->call(Misc::class, 'absolutize_url', [trim($link->getAttribute('href')), $this->base]); } else { $href = $this->registry->call(Misc::class, 'absolutize_url', [trim($link->getAttribute('href')), $this->http_base]); } if ($href === false) { continue; } if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !in_array('stylesheet', $rel) && $link->hasAttribute('type') && in_array(strtolower($this->registry->call(Misc::class, 'parse_mime', [$link->getAttribute('type')])), ['text/html', 'application/rss+xml', 'application/atom+xml'])) && !isset($feeds[$href])) { $this->checked_feeds++; $headers = [ 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1', ]; $feed = $this->registry->create(File::class, [$href, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options]); if ($feed->success && ($feed->method & \SimplePie\SimplePie::FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed, true)) { $feeds[$href] = $feed; } } $done[] = $href; } } return $feeds; } public function get_links() { if ($this->dom === null) { throw new \SimplePie\Exception('DOMDocument not found, unable to use locator'); } $links = $this->dom->getElementsByTagName('a'); foreach ($links as $link) { if ($link->hasAttribute('href')) { $href = trim($link->getAttribute('href')); $parsed = $this->registry->call(Misc::class, 'parse_url', [$href]); if ($parsed['scheme'] === '' || preg_match('/^(https?|feed)?$/i', $parsed['scheme'])) { if (method_exists($link, 'getLineNo') && $this->base_location < $link->getLineNo()) { $href = $this->registry->call(Misc::class, 'absolutize_url', [trim($link->getAttribute('href')), $this->base]); } else { $href = $this->registry->call(Misc::class, 'absolutize_url', [trim($link->getAttribute('href')), $this->http_base]); } if ($href === false) { continue; } $current = $this->registry->call(Misc::class, 'parse_url', [$this->file->url]); if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority']) { $this->local[] = $href; } else { $this->elsewhere[] = $href; } } } } $this->local = array_unique($this->local); $this->elsewhere = array_unique($this->elsewhere); if (!empty($this->local) || !empty($this->elsewhere)) { return true; } return null; } public function get_rel_link($rel) { if ($this->dom === null) { throw new \SimplePie\Exception('DOMDocument not found, unable to use '. 'locator'); } if (!class_exists('DOMXpath')) { throw new \SimplePie\Exception('DOMXpath not found, unable to use '. 'get_rel_link'); } $xpath = new \DOMXpath($this->dom); $query = '//a[@rel and @href] | //link[@rel and @href]'; foreach ($xpath->query($query) as $link) { $href = trim($link->getAttribute('href')); $parsed = $this->registry->call(Misc::class, 'parse_url', [$href]); if ($parsed['scheme'] === '' || preg_match('/^https?$/i', $parsed['scheme'])) { if (method_exists($link, 'getLineNo') && $this->base_location < $link->getLineNo()) { $href = $this->registry->call( Misc::class, 'absolutize_url', [trim($link->getAttribute('href')), $this->base] ); } else { $href = $this->registry->call( Misc::class, 'absolutize_url', [trim($link->getAttribute('href')), $this->http_base] ); } if ($href === false) { return null; } $rel_values = explode(' ', strtolower($link->getAttribute('rel'))); if (in_array($rel, $rel_values)) { return $href; } } } return null; } public function extension(&$array) { foreach ($array as $key => $value) { if ($this->checked_feeds === $this->max_checked_feeds) { break; } if (in_array(strtolower(strrchr($value, '.')), ['.rss', '.rdf', '.atom', '.xml'])) { $this->checked_feeds++; $headers = [ 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1', ]; $feed = $this->registry->create(File::class, [$value, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options]); if ($feed->success && ($feed->method & \SimplePie\SimplePie::FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed)) { return [$feed]; } else { unset($array[$key]); } } } return null; } public function body(&$array) { foreach ($array as $key => $value) { if ($this->checked_feeds === $this->max_checked_feeds) { break; } if (preg_match('/(feed|rss|rdf|atom|xml)/i', $value)) { $this->checked_feeds++; $headers = [ 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1', ]; $feed = $this->registry->create(File::class, [$value, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen, $this->curl_options]); if ($feed->success && ($feed->method & \SimplePie\SimplePie::FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed)) { return [$feed]; } else { unset($array[$key]); } } } return null; } } class_alias('SimplePie\Locator', 'SimplePie_Locator', false); PK������Zd���� ��Cache/DB.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie\Cache; /** * Base class for database-based caches * * @package SimplePie * @subpackage Caching * @deprecated since SimplePie 1.8.0, use implementation of "Psr\SimpleCache\CacheInterface" instead */ abstract class DB implements Base { /** * Helper for database conversion * * Converts a given {@see SimplePie} object into data to be stored * * @param \SimplePie\SimplePie $data * @return array First item is the serialized data for storage, second item is the unique ID for this item */ protected static function prepare_simplepie_object_for_cache($data) { $items = $data->get_items(); $items_by_id = []; if (!empty($items)) { foreach ($items as $item) { $items_by_id[$item->get_id()] = $item; } if (count($items_by_id) !== count($items)) { $items_by_id = []; foreach ($items as $item) { $items_by_id[$item->get_id(true)] = $item; } } if (isset($data->data['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['feed'][0])) { $channel = &$data->data['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['feed'][0]; } elseif (isset($data->data['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['feed'][0])) { $channel = &$data->data['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['feed'][0]; } elseif (isset($data->data['child'][\SimplePie\SimplePie::NAMESPACE_RDF]['RDF'][0])) { $channel = &$data->data['child'][\SimplePie\SimplePie::NAMESPACE_RDF]['RDF'][0]; } elseif (isset($data->data['child'][\SimplePie\SimplePie::NAMESPACE_RSS_20]['rss'][0]['child'][\SimplePie\SimplePie::NAMESPACE_RSS_20]['channel'][0])) { $channel = &$data->data['child'][\SimplePie\SimplePie::NAMESPACE_RSS_20]['rss'][0]['child'][\SimplePie\SimplePie::NAMESPACE_RSS_20]['channel'][0]; } else { $channel = null; } if ($channel !== null) { if (isset($channel['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['entry'])) { unset($channel['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['entry']); } if (isset($channel['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['entry'])) { unset($channel['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['entry']); } if (isset($channel['child'][\SimplePie\SimplePie::NAMESPACE_RSS_10]['item'])) { unset($channel['child'][\SimplePie\SimplePie::NAMESPACE_RSS_10]['item']); } if (isset($channel['child'][\SimplePie\SimplePie::NAMESPACE_RSS_090]['item'])) { unset($channel['child'][\SimplePie\SimplePie::NAMESPACE_RSS_090]['item']); } if (isset($channel['child'][\SimplePie\SimplePie::NAMESPACE_RSS_20]['item'])) { unset($channel['child'][\SimplePie\SimplePie::NAMESPACE_RSS_20]['item']); } } if (isset($data->data['items'])) { unset($data->data['items']); } if (isset($data->data['ordered_items'])) { unset($data->data['ordered_items']); } } return [serialize($data->data), $items_by_id]; } } class_alias('SimplePie\Cache\DB', 'SimplePie_Cache_DB'); PK������ZS{������Cache/Psr16.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2022 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie\Cache; use Psr\SimpleCache\CacheInterface; use Psr\SimpleCache\InvalidArgumentException; /** * Caches data into a PSR-16 cache implementation * * @package SimplePie * @subpackage Caching * @internal */ final class Psr16 implements DataCache { /** * PSR-16 cache implementation * * @var CacheInterface */ private $cache; /** * PSR-16 cache implementation * * @param CacheInterface $cache */ public function __construct(CacheInterface $cache) { $this->cache = $cache; } /** * Fetches a value from the cache. * * Equivalent to \Psr\SimpleCache\CacheInterface::get() * <code> * public function get(string $key, mixed $default = null): mixed; * </code> * * @param string $key The unique key of this item in the cache. * @param mixed $default Default value to return if the key does not exist. * * @return array|mixed The value of the item from the cache, or $default in case of cache miss. * * @throws InvalidArgumentException * MUST be thrown if the $key string is not a legal value. */ public function get_data(string $key, $default = null) { $data = $this->cache->get($key, $default); if (!is_array($data) || $data === $default) { return $default; } return $data; } /** * Persists data in the cache, uniquely referenced by a key with an optional expiration TTL time. * * Equivalent to \Psr\SimpleCache\CacheInterface::set() * <code> * public function set(string $key, mixed $value, null|int|\DateInterval $ttl = null): bool; * </code> * * @param string $key The key of the item to store. * @param array $value The value of the item to store, must be serializable. * @param null|int $ttl Optional. The TTL value of this item. If no value is sent and * the driver supports TTL then the library may set a default value * for it or let the driver take care of that. * * @return bool True on success and false on failure. * * @throws InvalidArgumentException * MUST be thrown if the $key string is not a legal value. */ public function set_data(string $key, array $value, ?int $ttl = null): bool { return $this->cache->set($key, $value, $ttl); } /** * Delete an item from the cache by its unique key. * * Equivalent to \Psr\SimpleCache\CacheInterface::delete() * <code> * public function delete(string $key): bool; * </code> * * @param string $key The unique cache key of the item to delete. * * @return bool True if the item was successfully removed. False if there was an error. * * @throws InvalidArgumentException * MUST be thrown if the $key string is not a legal value. */ public function delete_data(string $key): bool { return $this->cache->delete($key); } } PK������ZG������Cache/Redis.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie\Cache; use Redis as NativeRedis; /** * Caches data to redis * * Registered for URLs with the "redis" protocol * * For example, `redis://localhost:6379/?timeout=3600&prefix=sp_&dbIndex=0` will * connect to redis on `localhost` on port 6379. All tables will be * prefixed with `simple_primary-` and data will expire after 3600 seconds * * @package SimplePie * @subpackage Caching * @uses Redis * @deprecated since SimplePie 1.8.0, use implementation of "Psr\SimpleCache\CacheInterface" instead */ class Redis implements Base { /** * Redis instance * * @var NativeRedis */ protected $cache; /** * Options * * @var array */ protected $options; /** * Cache name * * @var string */ protected $name; /** * Create a new cache object * * @param string $location Location string (from SimplePie::$cache_location) * @param string $name Unique ID for the cache * @param Base::TYPE_FEED|Base::TYPE_IMAGE $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data */ public function __construct($location, $name, $options = null) { //$this->cache = \flow\simple\cache\Redis::getRedisClientInstance(); $parsed = \SimplePie\Cache::parse_URL($location); $redis = new NativeRedis(); $redis->connect($parsed['host'], $parsed['port']); if (isset($parsed['pass'])) { $redis->auth($parsed['pass']); } if (isset($parsed['path'])) { $redis->select((int)substr($parsed['path'], 1)); } $this->cache = $redis; if (!is_null($options) && is_array($options)) { $this->options = $options; } else { $this->options = [ 'prefix' => 'rss:simple_primary:', 'expire' => 0, ]; } $this->name = $this->options['prefix'] . $name; } /** * @param NativeRedis $cache */ public function setRedisClient(NativeRedis $cache) { $this->cache = $cache; } /** * Save data to the cache * * @param array|\SimplePie\SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property * @return bool Successfulness */ public function save($data) { if ($data instanceof \SimplePie\SimplePie) { $data = $data->data; } $response = $this->cache->set($this->name, serialize($data)); if ($this->options['expire']) { $this->cache->expire($this->name, $this->options['expire']); } return $response; } /** * Retrieve the data saved to the cache * * @return array Data for SimplePie::$data */ public function load() { $data = $this->cache->get($this->name); if ($data !== false) { return unserialize($data); } return false; } /** * Retrieve the last modified time for the cache * * @return int Timestamp */ public function mtime() { $data = $this->cache->get($this->name); if ($data !== false) { return time(); } return false; } /** * Set the last modified time to the current time * * @return bool Success status */ public function touch() { $data = $this->cache->get($this->name); if ($data !== false) { $return = $this->cache->set($this->name, $data); if ($this->options['expire']) { return $this->cache->expire($this->name, $this->options['expire']); } return $return; } return false; } /** * Remove the cache * * @return bool Success status */ public function unlink() { return $this->cache->set($this->name, null); } } class_alias('SimplePie\Cache\Redis', 'SimplePie_Cache_Redis'); PK������Zio������Cache/BaseDataCache.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2022 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie\Cache; use InvalidArgumentException; /** * Adapter for deprecated \SimplePie\Cache\Base implementations * * @package SimplePie * @subpackage Caching * @internal */ final class BaseDataCache implements DataCache { /** * @var Base */ private $cache; public function __construct(Base $cache) { $this->cache = $cache; } /** * Fetches a value from the cache. * * Equivalent to \Psr\SimpleCache\CacheInterface::get() * <code> * public function get(string $key, mixed $default = null): mixed; * </code> * * @param string $key The unique key of this item in the cache. * @param mixed $default Default value to return if the key does not exist. * * @return array|mixed The value of the item from the cache, or $default in case of cache miss. * * @throws InvalidArgumentException * MUST be thrown if the $key string is not a legal value. */ public function get_data(string $key, $default = null) { $data = $this->cache->load(); if (!is_array($data)) { return $default; } // ignore data if internal cache expiration time is not set if (!array_key_exists('__cache_expiration_time', $data)) { return $default; } // ignore data if internal cache expiration time is expired if ($data['__cache_expiration_time'] < time()) { return $default; } // remove internal cache expiration time unset($data['__cache_expiration_time']); return $data; } /** * Persists data in the cache, uniquely referenced by a key with an optional expiration TTL time. * * Equivalent to \Psr\SimpleCache\CacheInterface::set() * <code> * public function set(string $key, mixed $value, null|int|\DateInterval $ttl = null): bool; * </code> * * @param string $key The key of the item to store. * @param array $value The value of the item to store, must be serializable. * @param null|int $ttl Optional. The TTL value of this item. If no value is sent and * the driver supports TTL then the library may set a default value * for it or let the driver take care of that. * * @return bool True on success and false on failure. * * @throws InvalidArgumentException * MUST be thrown if the $key string is not a legal value. */ public function set_data(string $key, array $value, ?int $ttl = null): bool { if ($ttl === null) { $ttl = 3600; } // place internal cache expiration time $value['__cache_expiration_time'] = time() + $ttl; return $this->cache->save($value); } /** * Delete an item from the cache by its unique key. * * Equivalent to \Psr\SimpleCache\CacheInterface::delete() * <code> * public function delete(string $key): bool; * </code> * * @param string $key The unique cache key of the item to delete. * * @return bool True if the item was successfully removed. False if there was an error. * * @throws InvalidArgumentException * MUST be thrown if the $key string is not a legal value. */ public function delete_data(string $key): bool { return $this->cache->unlink(); } } PK������Zytw��w����Cache/DataCache.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2022 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie\Cache; use InvalidArgumentException; /** * Subset of PSR-16 Cache client for caching data arrays * * Only get(), set() and delete() methods are used, * but not has(), getMultiple(), setMultiple() or deleteMultiple(). * * The methods names must be different, but should be compatible to the * methods of \Psr\SimpleCache\CacheInterface. * * @package SimplePie * @subpackage Caching * @internal */ interface DataCache { /** * Fetches a value from the cache. * * Equivalent to \Psr\SimpleCache\CacheInterface::get() * <code> * public function get(string $key, mixed $default = null): mixed; * </code> * * @param string $key The unique key of this item in the cache. * @param mixed $default Default value to return if the key does not exist. * * @return array|mixed The value of the item from the cache, or $default in case of cache miss. * * @throws InvalidArgumentException * MUST be thrown if the $key string is not a legal value. */ public function get_data(string $key, $default = null); /** * Persists data in the cache, uniquely referenced by a key with an optional expiration TTL time. * * Equivalent to \Psr\SimpleCache\CacheInterface::set() * <code> * public function set(string $key, mixed $value, null|int|\DateInterval $ttl = null): bool; * </code> * * @param string $key The key of the item to store. * @param array $value The value of the item to store, must be serializable. * @param null|int $ttl Optional. The TTL value of this item. If no value is sent and * the driver supports TTL then the library may set a default value * for it or let the driver take care of that. * * @return bool True on success and false on failure. * * @throws InvalidArgumentException * MUST be thrown if the $key string is not a legal value. */ public function set_data(string $key, array $value, ?int $ttl = null): bool; /** * Delete an item from the cache by its unique key. * * Equivalent to \Psr\SimpleCache\CacheInterface::delete() * <code> * public function delete(string $key): bool; * </code> * * @param string $key The unique cache key of the item to delete. * * @return bool True if the item was successfully removed. False if there was an error. * * @throws InvalidArgumentException * MUST be thrown if the $key string is not a legal value. */ public function delete_data(string $key): bool; } PK������Z������Cache/File.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie\Cache; /** * Caches data to the filesystem * * @package SimplePie * @subpackage Caching * @deprecated since SimplePie 1.8.0, use implementation of "Psr\SimpleCache\CacheInterface" instead */ class File implements Base { /** * Location string * * @see SimplePie::$cache_location * @var string */ protected $location; /** * Filename * * @var string */ protected $filename; /** * File extension * * @var string */ protected $extension; /** * File path * * @var string */ protected $name; /** * Create a new cache object * * @param string $location Location string (from SimplePie::$cache_location) * @param string $name Unique ID for the cache * @param Base::TYPE_FEED|Base::TYPE_IMAGE $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data */ public function __construct($location, $name, $type) { $this->location = $location; $this->filename = $name; $this->extension = $type; $this->name = "$this->location/$this->filename.$this->extension"; } /** * Save data to the cache * * @param array|\SimplePie\SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property * @return bool Successfulness */ public function save($data) { if (file_exists($this->name) && is_writable($this->name) || file_exists($this->location) && is_writable($this->location)) { if ($data instanceof \SimplePie\SimplePie) { $data = $data->data; } $data = serialize($data); return (bool) file_put_contents($this->name, $data); } return false; } /** * Retrieve the data saved to the cache * * @return array Data for SimplePie::$data */ public function load() { if (file_exists($this->name) && is_readable($this->name)) { return unserialize(file_get_contents($this->name)); } return false; } /** * Retrieve the last modified time for the cache * * @return int Timestamp */ public function mtime() { return @filemtime($this->name); } /** * Set the last modified time to the current time * * @return bool Success status */ public function touch() { return @touch($this->name); } /** * Remove the cache * * @return bool Success status */ public function unlink() { if (file_exists($this->name)) { return unlink($this->name); } return false; } } class_alias('SimplePie\Cache\File', 'SimplePie_Cache_File'); PK������Z\C$ ��$ ����Cache/NameFilter.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2022 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie\Cache; /** * Interface for creating a cache filename * * @package SimplePie * @subpackage Caching */ interface NameFilter { /** * Method to create cache filename with. * * The returning name MUST follow the rules for keys in PSR-16. * * @link https://www.php-fig.org/psr/psr-16/ * * The returning name MUST be a string of at least one character * that uniquely identifies a cached item, MUST only contain the * characters A-Z, a-z, 0-9, _, and . in any order in UTF-8 encoding * and MUST not longer then 64 characters. The following characters * are reserved for future extensions and MUST NOT be used: {}()/\@: * * A provided implementing library MAY support additional characters * and encodings or longer lengths, but MUST support at least that * minimum. * * @param string $name The name for the cache will be most likly an url with query string * * @return string the new cache name */ public function filter(string $name): string; } PK������Z0j������Cache/Memcached.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie\Cache; use Memcached as NativeMemcached; /** * Caches data to memcached * * Registered for URLs with the "memcached" protocol * * For example, `memcached://localhost:11211/?timeout=3600&prefix=sp_` will * connect to memcached on `localhost` on port 11211. All tables will be * prefixed with `sp_` and data will expire after 3600 seconds * * @package SimplePie * @subpackage Caching * @author Paul L. McNeely * @uses Memcached * @deprecated since SimplePie 1.8.0, use implementation of "Psr\SimpleCache\CacheInterface" instead */ class Memcached implements Base { /** * NativeMemcached instance * @var NativeMemcached */ protected $cache; /** * Options * @var array */ protected $options; /** * Cache name * @var string */ protected $name; /** * Create a new cache object * @param string $location Location string (from SimplePie::$cache_location) * @param string $name Unique ID for the cache * @param Base::TYPE_FEED|Base::TYPE_IMAGE $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data */ public function __construct($location, $name, $type) { $this->options = [ 'host' => '127.0.0.1', 'port' => 11211, 'extras' => [ 'timeout' => 3600, // one hour 'prefix' => 'simplepie_', ], ]; $this->options = array_replace_recursive($this->options, \SimplePie\Cache::parse_URL($location)); $this->name = $this->options['extras']['prefix'] . md5("$name:$type"); $this->cache = new NativeMemcached(); $this->cache->addServer($this->options['host'], (int)$this->options['port']); } /** * Save data to the cache * @param array|\SimplePie\SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property * @return bool Successfulness */ public function save($data) { if ($data instanceof \SimplePie\SimplePie) { $data = $data->data; } return $this->setData(serialize($data)); } /** * Retrieve the data saved to the cache * @return array Data for SimplePie::$data */ public function load() { $data = $this->cache->get($this->name); if ($data !== false) { return unserialize($data); } return false; } /** * Retrieve the last modified time for the cache * @return int Timestamp */ public function mtime() { $data = $this->cache->get($this->name . '_mtime'); return (int) $data; } /** * Set the last modified time to the current time * @return bool Success status */ public function touch() { $data = $this->cache->get($this->name); return $this->setData($data); } /** * Remove the cache * @return bool Success status */ public function unlink() { return $this->cache->delete($this->name, 0); } /** * Set the last modified time and data to NativeMemcached * @return bool Success status */ private function setData($data) { if ($data !== false) { $this->cache->set($this->name . '_mtime', time(), (int)$this->options['extras']['timeout']); return $this->cache->set($this->name, $data, (int)$this->options['extras']['timeout']); } return false; } } class_alias('SimplePie\Cache\Memcached', 'SimplePie_Cache_Memcached'); PK������Z q<��<����Cache/MySQL.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie\Cache; /** * Caches data to a MySQL database * * Registered for URLs with the "mysql" protocol * * For example, `mysql://root:password@localhost:3306/mydb?prefix=sp_` will * connect to the `mydb` database on `localhost` on port 3306, with the user * `root` and the password `password`. All tables will be prefixed with `sp_` * * @package SimplePie * @subpackage Caching * @deprecated since SimplePie 1.8.0, use implementation of "Psr\SimpleCache\CacheInterface" instead */ class MySQL extends DB { /** * PDO instance * * @var \PDO */ protected $mysql; /** * Options * * @var array */ protected $options; /** * Cache ID * * @var string */ protected $id; /** * Create a new cache object * * @param string $location Location string (from SimplePie::$cache_location) * @param string $name Unique ID for the cache * @param Base::TYPE_FEED|Base::TYPE_IMAGE $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data */ public function __construct($location, $name, $type) { $this->options = [ 'user' => null, 'pass' => null, 'host' => '127.0.0.1', 'port' => '3306', 'path' => '', 'extras' => [ 'prefix' => '', 'cache_purge_time' => 2592000 ], ]; $this->options = array_replace_recursive($this->options, \SimplePie\Cache::parse_URL($location)); // Path is prefixed with a "/" $this->options['dbname'] = substr($this->options['path'], 1); try { $this->mysql = new \PDO("mysql:dbname={$this->options['dbname']};host={$this->options['host']};port={$this->options['port']}", $this->options['user'], $this->options['pass'], [\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8']); } catch (\PDOException $e) { $this->mysql = null; return; } $this->id = $name . $type; if (!$query = $this->mysql->query('SHOW TABLES')) { $this->mysql = null; return; } $db = []; while ($row = $query->fetchColumn()) { $db[] = $row; } if (!in_array($this->options['extras']['prefix'] . 'cache_data', $db)) { $query = $this->mysql->exec('CREATE TABLE `' . $this->options['extras']['prefix'] . 'cache_data` (`id` TEXT CHARACTER SET utf8 NOT NULL, `items` SMALLINT NOT NULL DEFAULT 0, `data` BLOB NOT NULL, `mtime` INT UNSIGNED NOT NULL, UNIQUE (`id`(125)))'); if ($query === false) { trigger_error("Can't create " . $this->options['extras']['prefix'] . "cache_data table, check permissions", \E_USER_WARNING); $this->mysql = null; return; } } if (!in_array($this->options['extras']['prefix'] . 'items', $db)) { $query = $this->mysql->exec('CREATE TABLE `' . $this->options['extras']['prefix'] . 'items` (`feed_id` TEXT CHARACTER SET utf8 NOT NULL, `id` TEXT CHARACTER SET utf8 NOT NULL, `data` MEDIUMBLOB NOT NULL, `posted` INT UNSIGNED NOT NULL, INDEX `feed_id` (`feed_id`(125)))'); if ($query === false) { trigger_error("Can't create " . $this->options['extras']['prefix'] . "items table, check permissions", \E_USER_WARNING); $this->mysql = null; return; } } } /** * Save data to the cache * * @param array|\SimplePie\SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property * @return bool Successfulness */ public function save($data) { if ($this->mysql === null) { return false; } $query = $this->mysql->prepare('DELETE i, cd FROM `' . $this->options['extras']['prefix'] . 'cache_data` cd, ' . '`' . $this->options['extras']['prefix'] . 'items` i ' . 'WHERE cd.id = i.feed_id ' . 'AND cd.mtime < (unix_timestamp() - :purge_time)'); $query->bindValue(':purge_time', $this->options['extras']['cache_purge_time']); if (!$query->execute()) { return false; } if ($data instanceof \SimplePie\SimplePie) { $data = clone $data; $prepared = self::prepare_simplepie_object_for_cache($data); $query = $this->mysql->prepare('SELECT COUNT(*) FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :feed'); $query->bindValue(':feed', $this->id); if ($query->execute()) { if ($query->fetchColumn() > 0) { $items = count($prepared[1]); if ($items) { $sql = 'UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `items` = :items, `data` = :data, `mtime` = :time WHERE `id` = :feed'; $query = $this->mysql->prepare($sql); $query->bindValue(':items', $items); } else { $sql = 'UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `data` = :data, `mtime` = :time WHERE `id` = :feed'; $query = $this->mysql->prepare($sql); } $query->bindValue(':data', $prepared[0]); $query->bindValue(':time', time()); $query->bindValue(':feed', $this->id); if (!$query->execute()) { return false; } } else { $query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(:feed, :count, :data, :time)'); $query->bindValue(':feed', $this->id); $query->bindValue(':count', count($prepared[1])); $query->bindValue(':data', $prepared[0]); $query->bindValue(':time', time()); if (!$query->execute()) { return false; } } $ids = array_keys($prepared[1]); if (!empty($ids)) { foreach ($ids as $id) { $database_ids[] = $this->mysql->quote($id); } $query = $this->mysql->prepare('SELECT `id` FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `id` = ' . implode(' OR `id` = ', $database_ids) . ' AND `feed_id` = :feed'); $query->bindValue(':feed', $this->id); if ($query->execute()) { $existing_ids = []; while ($row = $query->fetchColumn()) { $existing_ids[] = $row; } $new_ids = array_diff($ids, $existing_ids); foreach ($new_ids as $new_id) { if (!($date = $prepared[1][$new_id]->get_date('U'))) { $date = time(); } $query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'items` (`feed_id`, `id`, `data`, `posted`) VALUES(:feed, :id, :data, :date)'); $query->bindValue(':feed', $this->id); $query->bindValue(':id', $new_id); $query->bindValue(':data', serialize($prepared[1][$new_id]->data)); $query->bindValue(':date', $date); if (!$query->execute()) { return false; } } return true; } } else { return true; } } } else { $query = $this->mysql->prepare('SELECT `id` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :feed'); $query->bindValue(':feed', $this->id); if ($query->execute()) { if ($query->rowCount() > 0) { $query = $this->mysql->prepare('UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `items` = 0, `data` = :data, `mtime` = :time WHERE `id` = :feed'); $query->bindValue(':data', serialize($data)); $query->bindValue(':time', time()); $query->bindValue(':feed', $this->id); if ($query->execute()) { return true; } } else { $query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(:id, 0, :data, :time)'); $query->bindValue(':id', $this->id); $query->bindValue(':data', serialize($data)); $query->bindValue(':time', time()); if ($query->execute()) { return true; } } } } return false; } /** * Retrieve the data saved to the cache * * @return array Data for SimplePie::$data */ public function load() { if ($this->mysql === null) { return false; } $query = $this->mysql->prepare('SELECT `items`, `data` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id'); $query->bindValue(':id', $this->id); if ($query->execute() && ($row = $query->fetch())) { $data = unserialize($row[1]); if (isset($this->options['items'][0])) { $items = (int) $this->options['items'][0]; } else { $items = (int) $row[0]; } if ($items !== 0) { if (isset($data['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['feed'][0])) { $feed = &$data['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['feed'][0]; } elseif (isset($data['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['feed'][0])) { $feed = &$data['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['feed'][0]; } elseif (isset($data['child'][\SimplePie\SimplePie::NAMESPACE_RDF]['RDF'][0])) { $feed = &$data['child'][\SimplePie\SimplePie::NAMESPACE_RDF]['RDF'][0]; } elseif (isset($data['child'][\SimplePie\SimplePie::NAMESPACE_RSS_20]['rss'][0])) { $feed = &$data['child'][\SimplePie\SimplePie::NAMESPACE_RSS_20]['rss'][0]; } else { $feed = null; } if ($feed !== null) { $sql = 'SELECT `data` FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `feed_id` = :feed ORDER BY `posted` DESC'; if ($items > 0) { $sql .= ' LIMIT ' . $items; } $query = $this->mysql->prepare($sql); $query->bindValue(':feed', $this->id); if ($query->execute()) { while ($row = $query->fetchColumn()) { $feed['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['entry'][] = unserialize($row); } } else { return false; } } } return $data; } return false; } /** * Retrieve the last modified time for the cache * * @return int Timestamp */ public function mtime() { if ($this->mysql === null) { return false; } $query = $this->mysql->prepare('SELECT `mtime` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id'); $query->bindValue(':id', $this->id); if ($query->execute() && ($time = $query->fetchColumn())) { return $time; } return false; } /** * Set the last modified time to the current time * * @return bool Success status */ public function touch() { if ($this->mysql === null) { return false; } $query = $this->mysql->prepare('UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `mtime` = :time WHERE `id` = :id'); $query->bindValue(':time', time()); $query->bindValue(':id', $this->id); return $query->execute() && $query->rowCount() > 0; } /** * Remove the cache * * @return bool Success status */ public function unlink() { if ($this->mysql === null) { return false; } $query = $this->mysql->prepare('DELETE FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id'); $query->bindValue(':id', $this->id); $query2 = $this->mysql->prepare('DELETE FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `feed_id` = :id'); $query2->bindValue(':id', $this->id); return $query->execute() && $query2->execute(); } } class_alias('SimplePie\Cache\MySQL', 'SimplePie_Cache_MySQL'); PK������Zȷ}* ��* ����Cache/CallableNameFilter.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2022 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie\Cache; /** * Creating a cache filename with callables * * @package SimplePie * @subpackage Caching */ final class CallableNameFilter implements NameFilter { /** * @var callable */ private $callable; public function __construct(callable $callable) { $this->callable = $callable; } /** * Method to create cache filename with. * * The returning name MUST follow the rules for keys in PSR-16. * * @link https://www.php-fig.org/psr/psr-16/ * * The returning name MUST be a string of at least one character * that uniquely identifies a cached item, MUST only contain the * characters A-Z, a-z, 0-9, _, and . in any order in UTF-8 encoding * and MUST not longer then 64 characters. The following characters * are reserved for future extensions and MUST NOT be used: {}()/\@: * * A provided implementing library MAY support additional characters * and encodings or longer lengths, but MUST support at least that * minimum. * * @param string $name The name for the cache will be most likly an url with query string * * @return string the new cache name */ public function filter(string $name): string { return call_user_func($this->callable, $name); } } PK������Z3}������Cache/Base.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie\Cache; /** * Base for cache objects * * Classes to be used with {@see \SimplePie\Cache::register()} are expected * to implement this interface. * * @package SimplePie * @subpackage Caching * @deprecated since SimplePie 1.8.0, use "Psr\SimpleCache\CacheInterface" instead */ interface Base { /** * Feed cache type * * @var string */ public const TYPE_FEED = 'spc'; /** * Image cache type * * @var string */ public const TYPE_IMAGE = 'spi'; /** * Create a new cache object * * @param string $location Location string (from SimplePie::$cache_location) * @param string $name Unique ID for the cache * @param Base::TYPE_FEED|Base::TYPE_IMAGE $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data */ public function __construct($location, $name, $type); /** * Save data to the cache * * @param array|\SimplePie\SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property * @return bool Successfulness */ public function save($data); /** * Retrieve the data saved to the cache * * @return array Data for SimplePie::$data */ public function load(); /** * Retrieve the last modified time for the cache * * @return int Timestamp */ public function mtime(); /** * Set the last modified time to the current time * * @return bool Success status */ public function touch(); /** * Remove the cache * * @return bool Success status */ public function unlink(); } class_alias('SimplePie\Cache\Base', 'SimplePie_Cache_Base'); PK������Z ������Cache/Memcache.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie\Cache; use Memcache as NativeMemcache; /** * Caches data to memcache * * Registered for URLs with the "memcache" protocol * * For example, `memcache://localhost:11211/?timeout=3600&prefix=sp_` will * connect to memcache on `localhost` on port 11211. All tables will be * prefixed with `sp_` and data will expire after 3600 seconds * * @package SimplePie * @subpackage Caching * @uses Memcache * @deprecated since SimplePie 1.8.0, use implementation of "Psr\SimpleCache\CacheInterface" instead */ class Memcache implements Base { /** * Memcache instance * * @var Memcache */ protected $cache; /** * Options * * @var array */ protected $options; /** * Cache name * * @var string */ protected $name; /** * Create a new cache object * * @param string $location Location string (from SimplePie::$cache_location) * @param string $name Unique ID for the cache * @param Base::TYPE_FEED|Base::TYPE_IMAGE $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data */ public function __construct($location, $name, $type) { $this->options = [ 'host' => '127.0.0.1', 'port' => 11211, 'extras' => [ 'timeout' => 3600, // one hour 'prefix' => 'simplepie_', ], ]; $this->options = array_replace_recursive($this->options, \SimplePie\Cache::parse_URL($location)); $this->name = $this->options['extras']['prefix'] . md5("$name:$type"); $this->cache = new NativeMemcache(); $this->cache->addServer($this->options['host'], (int) $this->options['port']); } /** * Save data to the cache * * @param array|\SimplePie\SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property * @return bool Successfulness */ public function save($data) { if ($data instanceof \SimplePie\SimplePie) { $data = $data->data; } return $this->cache->set($this->name, serialize($data), MEMCACHE_COMPRESSED, (int) $this->options['extras']['timeout']); } /** * Retrieve the data saved to the cache * * @return array Data for SimplePie::$data */ public function load() { $data = $this->cache->get($this->name); if ($data !== false) { return unserialize($data); } return false; } /** * Retrieve the last modified time for the cache * * @return int Timestamp */ public function mtime() { $data = $this->cache->get($this->name); if ($data !== false) { // essentially ignore the mtime because Memcache expires on its own return time(); } return false; } /** * Set the last modified time to the current time * * @return bool Success status */ public function touch() { $data = $this->cache->get($this->name); if ($data !== false) { return $this->cache->set($this->name, $data, MEMCACHE_COMPRESSED, (int) $this->options['extras']['timeout']); } return false; } /** * Remove the cache * * @return bool Success status */ public function unlink() { return $this->cache->delete($this->name, 0); } } class_alias('SimplePie\Cache\Memcache', 'SimplePie_Cache_Memcache'); PK������Zs ;:��;:����HTTP/Parser.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie\HTTP; /** * HTTP Response Parser * * @package SimplePie * @subpackage HTTP */ class Parser { /** * HTTP Version * * @var float */ public $http_version = 0.0; /** * Status code * * @var int */ public $status_code = 0; /** * Reason phrase * * @var string */ public $reason = ''; /** * Key/value pairs of the headers * * @var array */ public $headers = []; /** * Body of the response * * @var string */ public $body = ''; private const STATE_HTTP_VERSION = 'http_version'; private const STATE_STATUS = 'status'; private const STATE_REASON = 'reason'; private const STATE_NEW_LINE = 'new_line'; private const STATE_BODY = 'body'; private const STATE_NAME = 'name'; private const STATE_VALUE = 'value'; private const STATE_VALUE_CHAR = 'value_char'; private const STATE_QUOTE = 'quote'; private const STATE_QUOTE_ESCAPED = 'quote_escaped'; private const STATE_QUOTE_CHAR = 'quote_char'; private const STATE_CHUNKED = 'chunked'; private const STATE_EMIT = 'emit'; private const STATE_ERROR = false; /** * Current state of the state machine * * @var self::STATE_* */ protected $state = self::STATE_HTTP_VERSION; /** * Input data * * @var string */ protected $data = ''; /** * Input data length (to avoid calling strlen() everytime this is needed) * * @var int */ protected $data_length = 0; /** * Current position of the pointer * * @var int */ protected $position = 0; /** * Name of the hedaer currently being parsed * * @var string */ protected $name = ''; /** * Value of the hedaer currently being parsed * * @var string */ protected $value = ''; /** * Create an instance of the class with the input data * * @param string $data Input data */ public function __construct($data) { $this->data = $data; $this->data_length = strlen($this->data); } /** * Parse the input data * * @return bool true on success, false on failure */ public function parse() { while ($this->state && $this->state !== self::STATE_EMIT && $this->has_data()) { $state = $this->state; $this->$state(); } $this->data = ''; if ($this->state === self::STATE_EMIT || $this->state === self::STATE_BODY) { return true; } $this->http_version = ''; $this->status_code = 0; $this->reason = ''; $this->headers = []; $this->body = ''; return false; } /** * Check whether there is data beyond the pointer * * @return bool true if there is further data, false if not */ protected function has_data() { return (bool) ($this->position < $this->data_length); } /** * See if the next character is LWS * * @return bool true if the next character is LWS, false if not */ protected function is_linear_whitespace() { return (bool) ($this->data[$this->position] === "\x09" || $this->data[$this->position] === "\x20" || ($this->data[$this->position] === "\x0A" && isset($this->data[$this->position + 1]) && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20"))); } /** * Parse the HTTP version */ protected function http_version() { if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/') { $len = strspn($this->data, '0123456789.', 5); $this->http_version = substr($this->data, 5, $len); $this->position += 5 + $len; if (substr_count($this->http_version, '.') <= 1) { $this->http_version = (float) $this->http_version; $this->position += strspn($this->data, "\x09\x20", $this->position); $this->state = self::STATE_STATUS; } else { $this->state = self::STATE_ERROR; } } else { $this->state = self::STATE_ERROR; } } /** * Parse the status code */ protected function status() { if ($len = strspn($this->data, '0123456789', $this->position)) { $this->status_code = (int) substr($this->data, $this->position, $len); $this->position += $len; $this->state = self::STATE_REASON; } else { $this->state = self::STATE_ERROR; } } /** * Parse the reason phrase */ protected function reason() { $len = strcspn($this->data, "\x0A", $this->position); $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20"); $this->position += $len + 1; $this->state = self::STATE_NEW_LINE; } /** * Deal with a new line, shifting data around as needed */ protected function new_line() { $this->value = trim($this->value, "\x0D\x20"); if ($this->name !== '' && $this->value !== '') { $this->name = strtolower($this->name); // We should only use the last Content-Type header. c.f. issue #1 if (isset($this->headers[$this->name]) && $this->name !== 'content-type') { $this->headers[$this->name] .= ', ' . $this->value; } else { $this->headers[$this->name] = $this->value; } } $this->name = ''; $this->value = ''; if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A") { $this->position += 2; $this->state = self::STATE_BODY; } elseif ($this->data[$this->position] === "\x0A") { $this->position++; $this->state = self::STATE_BODY; } else { $this->state = self::STATE_NAME; } } /** * Parse a header name */ protected function name() { $len = strcspn($this->data, "\x0A:", $this->position); if (isset($this->data[$this->position + $len])) { if ($this->data[$this->position + $len] === "\x0A") { $this->position += $len; $this->state = self::STATE_NEW_LINE; } else { $this->name = substr($this->data, $this->position, $len); $this->position += $len + 1; $this->state = self::STATE_VALUE; } } else { $this->state = self::STATE_ERROR; } } /** * Parse LWS, replacing consecutive LWS characters with a single space */ protected function linear_whitespace() { do { if (substr($this->data, $this->position, 2) === "\x0D\x0A") { $this->position += 2; } elseif ($this->data[$this->position] === "\x0A") { $this->position++; } $this->position += strspn($this->data, "\x09\x20", $this->position); } while ($this->has_data() && $this->is_linear_whitespace()); $this->value .= "\x20"; } /** * See what state to move to while within non-quoted header values */ protected function value() { if ($this->is_linear_whitespace()) { $this->linear_whitespace(); } else { switch ($this->data[$this->position]) { case '"': // Workaround for ETags: we have to include the quotes as // part of the tag. if (strtolower($this->name) === 'etag') { $this->value .= '"'; $this->position++; $this->state = self::STATE_VALUE_CHAR; break; } $this->position++; $this->state = self::STATE_QUOTE; break; case "\x0A": $this->position++; $this->state = self::STATE_NEW_LINE; break; default: $this->state = self::STATE_VALUE_CHAR; break; } } } /** * Parse a header value while outside quotes */ protected function value_char() { $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position); $this->value .= substr($this->data, $this->position, $len); $this->position += $len; $this->state = self::STATE_VALUE; } /** * See what state to move to while within quoted header values */ protected function quote() { if ($this->is_linear_whitespace()) { $this->linear_whitespace(); } else { switch ($this->data[$this->position]) { case '"': $this->position++; $this->state = self::STATE_VALUE; break; case "\x0A": $this->position++; $this->state = self::STATE_NEW_LINE; break; case '\\': $this->position++; $this->state = self::STATE_QUOTE_ESCAPED; break; default: $this->state = self::STATE_QUOTE_CHAR; break; } } } /** * Parse a header value while within quotes */ protected function quote_char() { $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position); $this->value .= substr($this->data, $this->position, $len); $this->position += $len; $this->state = self::STATE_VALUE; } /** * Parse an escaped character within quotes */ protected function quote_escaped() { $this->value .= $this->data[$this->position]; $this->position++; $this->state = self::STATE_QUOTE; } /** * Parse the body */ protected function body() { $this->body = substr($this->data, $this->position); if (!empty($this->headers['transfer-encoding'])) { unset($this->headers['transfer-encoding']); $this->state = self::STATE_CHUNKED; } else { $this->state = self::STATE_EMIT; } } /** * Parsed a "Transfer-Encoding: chunked" body */ protected function chunked() { if (!preg_match('/^([0-9a-f]+)[^\r\n]*\r\n/i', trim($this->body))) { $this->state = self::STATE_EMIT; return; } $decoded = ''; $encoded = $this->body; while (true) { $is_chunked = (bool) preg_match('/^([0-9a-f]+)[^\r\n]*\r\n/i', $encoded, $matches); if (!$is_chunked) { // Looks like it's not chunked after all $this->state = self::STATE_EMIT; return; } $length = hexdec(trim($matches[1])); if ($length === 0) { // Ignore trailer headers $this->state = self::STATE_EMIT; $this->body = $decoded; return; } $chunk_length = strlen($matches[0]); $decoded .= substr($encoded, $chunk_length, $length); $encoded = substr($encoded, $chunk_length + $length + 2); // BC for PHP < 8.0: substr() can return bool instead of string $encoded = ($encoded === false) ? '' : $encoded; if (trim($encoded) === '0' || empty($encoded)) { $this->state = self::STATE_EMIT; $this->body = $decoded; return; } } } /** * Prepare headers (take care of proxies headers) * * @param string $headers Raw headers * @param integer $count Redirection count. Default to 1. * * @return string */ public static function prepareHeaders($headers, $count = 1) { $data = explode("\r\n\r\n", $headers, $count); $data = array_pop($data); if (false !== stripos($data, "HTTP/1.0 200 Connection established\r\n")) { $exploded = explode("\r\n\r\n", $data, 2); $data = end($exploded); } if (false !== stripos($data, "HTTP/1.1 200 Connection established\r\n")) { $exploded = explode("\r\n\r\n", $data, 2); $data = end($exploded); } return $data; } } class_alias('SimplePie\HTTP\Parser', 'SimplePie_HTTP_Parser'); PK������Zwli��i�� ��Rating.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie; /** * Handles `<media:rating>` or `<itunes:explicit>` tags as defined in Media RSS and iTunes RSS respectively * * Used by {@see \SimplePie\Enclosure::get_rating()} and {@see \SimplePie\Enclosure::get_ratings()} * * This class can be overloaded with {@see \SimplePie\SimplePie::set_rating_class()} * * @package SimplePie * @subpackage API */ class Rating { /** * Rating scheme * * @var string * @see get_scheme() */ public $scheme; /** * Rating value * * @var string * @see get_value() */ public $value; /** * Constructor, used to input the data * * For documentation on all the parameters, see the corresponding * properties and their accessors */ public function __construct($scheme = null, $value = null) { $this->scheme = $scheme; $this->value = $value; } /** * String-ified version * * @return string */ public function __toString() { // There is no $this->data here return md5(serialize($this)); } /** * Get the organizational scheme for the rating * * @return string|null */ public function get_scheme() { if ($this->scheme !== null) { return $this->scheme; } return null; } /** * Get the value of the rating * * @return string|null */ public function get_value() { if ($this->value !== null) { return $this->value; } return null; } } class_alias('SimplePie\Rating', 'SimplePie_Rating'); PK������ZZ !��!�� ��Author.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie; /** * Manages all author-related data * * Used by {@see Item::get_author()} and {@see SimplePie::get_authors()} * * This class can be overloaded with {@see SimplePie::set_author_class()} * * @package SimplePie * @subpackage API */ class Author { /** * Author's name * * @var string * @see get_name() */ public $name; /** * Author's link * * @var string * @see get_link() */ public $link; /** * Author's email address * * @var string * @see get_email() */ public $email; /** * Constructor, used to input the data * * @param string $name * @param string $link * @param string $email */ public function __construct($name = null, $link = null, $email = null) { $this->name = $name; $this->link = $link; $this->email = $email; } /** * String-ified version * * @return string */ public function __toString() { // There is no $this->data here return md5(serialize($this)); } /** * Author's name * * @return string|null */ public function get_name() { if ($this->name !== null) { return $this->name; } return null; } /** * Author's link * * @return string|null */ public function get_link() { if ($this->link !== null) { return $this->link; } return null; } /** * Author's email address * * @return string|null */ public function get_email() { if ($this->email !== null) { return $this->email; } return null; } } class_alias('SimplePie\Author', 'SimplePie_Author'); PK������Z~���� ��Copyright.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie; /** * Manages `<media:copyright>` copyright tags as defined in Media RSS * * Used by {@see \SimplePie\Enclosure::get_copyright()} * * This class can be overloaded with {@see \SimplePie\SimplePie::set_copyright_class()} * * @package SimplePie * @subpackage API */ class Copyright { /** * Copyright URL * * @var string * @see get_url() */ public $url; /** * Attribution * * @var string * @see get_attribution() */ public $label; /** * Constructor, used to input the data * * For documentation on all the parameters, see the corresponding * properties and their accessors */ public function __construct($url = null, $label = null) { $this->url = $url; $this->label = $label; } /** * String-ified version * * @return string */ public function __toString() { // There is no $this->data here return md5(serialize($this)); } /** * Get the copyright URL * * @return string|null URL to copyright information */ public function get_url() { if ($this->url !== null) { return $this->url; } return null; } /** * Get the attribution text * * @return string|null */ public function get_attribution() { if ($this->label !== null) { return $this->label; } return null; } } class_alias('SimplePie\Copyright', 'SimplePie_Copyright'); PK������ZB!"��!"�� ��Net/IPv6.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie\Net; /** * Class to validate and to work with IPv6 addresses. * * @package SimplePie * @subpackage HTTP * @copyright 2003-2005 The PHP Group * @license http://www.opensource.org/licenses/bsd-license.php * @link http://pear.php.net/package/Net_IPv6 * @author Alexander Merz <alexander.merz@web.de> * @author elfrink at introweb dot nl * @author Josh Peck <jmp at joshpeck dot org> * @author Sam Sneddon <geoffers@gmail.com> */ class IPv6 { /** * Uncompresses an IPv6 address * * RFC 4291 allows you to compress concecutive zero pieces in an address to * '::'. This method expects a valid IPv6 address and expands the '::' to * the required number of zero pieces. * * Example: FF01::101 -> FF01:0:0:0:0:0:0:101 * ::1 -> 0:0:0:0:0:0:0:1 * * @author Alexander Merz <alexander.merz@web.de> * @author elfrink at introweb dot nl * @author Josh Peck <jmp at joshpeck dot org> * @copyright 2003-2005 The PHP Group * @license http://www.opensource.org/licenses/bsd-license.php * @param string $ip An IPv6 address * @return string The uncompressed IPv6 address */ public static function uncompress($ip) { $c1 = -1; $c2 = -1; if (substr_count($ip, '::') === 1) { [$ip1, $ip2] = explode('::', $ip); if ($ip1 === '') { $c1 = -1; } else { $c1 = substr_count($ip1, ':'); } if ($ip2 === '') { $c2 = -1; } else { $c2 = substr_count($ip2, ':'); } if (strpos($ip2, '.') !== false) { $c2++; } // :: if ($c1 === -1 && $c2 === -1) { $ip = '0:0:0:0:0:0:0:0'; } // ::xxx elseif ($c1 === -1) { $fill = str_repeat('0:', 7 - $c2); $ip = str_replace('::', $fill, $ip); } // xxx:: elseif ($c2 === -1) { $fill = str_repeat(':0', 7 - $c1); $ip = str_replace('::', $fill, $ip); } // xxx::xxx else { $fill = ':' . str_repeat('0:', 6 - $c2 - $c1); $ip = str_replace('::', $fill, $ip); } } return $ip; } /** * Compresses an IPv6 address * * RFC 4291 allows you to compress concecutive zero pieces in an address to * '::'. This method expects a valid IPv6 address and compresses consecutive * zero pieces to '::'. * * Example: FF01:0:0:0:0:0:0:101 -> FF01::101 * 0:0:0:0:0:0:0:1 -> ::1 * * @see uncompress() * @param string $ip An IPv6 address * @return string The compressed IPv6 address */ public static function compress($ip) { // Prepare the IP to be compressed $ip = self::uncompress($ip); $ip_parts = self::split_v6_v4($ip); // Replace all leading zeros $ip_parts[0] = preg_replace('/(^|:)0+([0-9])/', '\1\2', $ip_parts[0]); // Find bunches of zeros if (preg_match_all('/(?:^|:)(?:0(?::|$))+/', $ip_parts[0], $matches, PREG_OFFSET_CAPTURE)) { $max = 0; $pos = null; foreach ($matches[0] as $match) { if (strlen($match[0]) > $max) { $max = strlen($match[0]); $pos = $match[1]; } } $ip_parts[0] = substr_replace($ip_parts[0], '::', $pos, $max); } if ($ip_parts[1] !== '') { return implode(':', $ip_parts); } return $ip_parts[0]; } /** * Splits an IPv6 address into the IPv6 and IPv4 representation parts * * RFC 4291 allows you to represent the last two parts of an IPv6 address * using the standard IPv4 representation * * Example: 0:0:0:0:0:0:13.1.68.3 * 0:0:0:0:0:FFFF:129.144.52.38 * * @param string $ip An IPv6 address * @return array [0] contains the IPv6 represented part, and [1] the IPv4 represented part */ private static function split_v6_v4($ip) { if (strpos($ip, '.') !== false) { $pos = strrpos($ip, ':'); $ipv6_part = substr($ip, 0, $pos); $ipv4_part = substr($ip, $pos + 1); return [$ipv6_part, $ipv4_part]; } return [$ip, '']; } /** * Checks an IPv6 address * * Checks if the given IP is a valid IPv6 address * * @param string $ip An IPv6 address * @return bool true if $ip is a valid IPv6 address */ public static function check_ipv6($ip) { $ip = self::uncompress($ip); [$ipv6, $ipv4] = self::split_v6_v4($ip); $ipv6 = explode(':', $ipv6); $ipv4 = explode('.', $ipv4); if (count($ipv6) === 8 && count($ipv4) === 1 || count($ipv6) === 6 && count($ipv4) === 4) { foreach ($ipv6 as $ipv6_part) { // The section can't be empty if ($ipv6_part === '') { return false; } // Nor can it be over four characters if (strlen($ipv6_part) > 4) { return false; } // Remove leading zeros (this is safe because of the above) $ipv6_part = ltrim($ipv6_part, '0'); if ($ipv6_part === '') { $ipv6_part = '0'; } // Check the value is valid $value = hexdec($ipv6_part); if (dechex($value) !== strtolower($ipv6_part) || $value < 0 || $value > 0xFFFF) { return false; } } if (count($ipv4) === 4) { foreach ($ipv4 as $ipv4_part) { $value = (int) $ipv4_part; if ((string) $value !== $ipv4_part || $value < 0 || $value > 0xFF) { return false; } } } return true; } return false; } /** * Checks if the given IP is a valid IPv6 address * * @codeCoverageIgnore * @deprecated Use {@see IPv6::check_ipv6()} instead * @see check_ipv6 * @param string $ip An IPv6 address * @return bool true if $ip is a valid IPv6 address */ public static function checkIPv6($ip) { return self::check_ipv6($ip); } } class_alias('SimplePie\Net\IPv6', 'SimplePie_Net_IPv6'); PK������ZDsT 5b��5b�� ��Sanitize.phpnu�W+A��������<?php /** * SimplePie * * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package SimplePie * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue * @author Ryan Parman * @author Sam Sneddon * @author Ryan McCue * @link http://simplepie.org/ SimplePie * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ namespace SimplePie; use InvalidArgumentException; use SimplePie\Cache\Base; use SimplePie\Cache\BaseDataCache; use SimplePie\Cache\CallableNameFilter; use SimplePie\Cache\DataCache; use SimplePie\Cache\NameFilter; /** * Used for data cleanup and post-processing * * * This class can be overloaded with {@see \SimplePie\SimplePie::set_sanitize_class()} * * @package SimplePie * @todo Move to using an actual HTML parser (this will allow tags to be properly stripped, and to switch between HTML and XHTML), this will also make it easier to shorten a string while preserving HTML tags */ class Sanitize implements RegistryAware { // Private vars public $base; // Options public $remove_div = true; public $image_handler = ''; public $strip_htmltags = ['base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style']; public $encode_instead_of_strip = false; public $strip_attributes = ['bgsound', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc']; public $rename_attributes = []; public $add_attributes = ['audio' => ['preload' => 'none'], 'iframe' => ['sandbox' => 'allow-scripts allow-same-origin'], 'video' => ['preload' => 'none']]; public $strip_comments = false; public $output_encoding = 'UTF-8'; public $enable_cache = true; public $cache_location = './cache'; public $cache_name_function = 'md5'; /** * @var NameFilter */ private $cache_namefilter; public $timeout = 10; public $useragent = ''; public $force_fsockopen = false; public $replace_url_attributes = null; public $registry; /** * @var DataCache|null */ private $cache = null; /** * @var int Cache duration (in seconds) */ private $cache_duration = 3600; /** * List of domains for which to force HTTPS. * @see \SimplePie\Sanitize::set_https_domains() * Array is a tree split at DNS levels. Example: * array('biz' => true, 'com' => array('example' => true), 'net' => array('example' => array('www' => true))) */ public $https_domains = []; public function __construct() { // Set defaults $this->set_url_replacements(null); } public function remove_div($enable = true) { $this->remove_div = (bool) $enable; } public function set_image_handler($page = false) { if ($page) { $this->image_handler = (string) $page; } else { $this->image_handler = false; } } public function set_registry(\SimplePie\Registry $registry)/* : void */ { $this->registry = $registry; } public function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie\Cache', ?DataCache $cache = null) { if (isset($enable_cache)) { $this->enable_cache = (bool) $enable_cache; } if ($cache_location) { $this->cache_location = (string) $cache_location; } if (!is_string($cache_name_function) && !is_object($cache_name_function) && !$cache_name_function instanceof NameFilter) { throw new InvalidArgumentException(sprintf( '%s(): Argument #3 ($cache_name_function) must be of type %s', __METHOD__, NameFilter::class ), 1); } // BC: $cache_name_function could be a callable as string if (is_string($cache_name_function)) { // trigger_error(sprintf('Providing $cache_name_function as string in "%s()" is deprecated since SimplePie 1.8.0, provide as "%s" instead.', __METHOD__, NameFilter::class), \E_USER_DEPRECATED); $this->cache_name_function = (string) $cache_name_function; $cache_name_function = new CallableNameFilter($cache_name_function); } $this->cache_namefilter = $cache_name_function; if ($cache !== null) { $this->cache = $cache; } } public function pass_file_data($file_class = 'SimplePie\File', $timeout = 10, $useragent = '', $force_fsockopen = false) { if ($timeout) { $this->timeout = (string) $timeout; } if ($useragent) { $this->useragent = (string) $useragent; } if ($force_fsockopen) { $this->force_fsockopen = (string) $force_fsockopen; } } public function strip_htmltags($tags = ['base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style']) { if ($tags) { if (is_array($tags)) { $this->strip_htmltags = $tags; } else { $this->strip_htmltags = explode(',', $tags); } } else { $this->strip_htmltags = false; } } public function encode_instead_of_strip($encode = false) { $this->encode_instead_of_strip = (bool) $encode; } public function rename_attributes($attribs = []) { if ($attribs) { if (is_array($attribs)) { $this->rename_attributes = $attribs; } else { $this->rename_attributes = explode(',', $attribs); } } else { $this->rename_attributes = false; } } public function strip_attributes($attribs = ['bgsound', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc']) { if ($attribs) { if (is_array($attribs)) { $this->strip_attributes = $attribs; } else { $this->strip_attributes = explode(',', $attribs); } } else { $this->strip_attributes = false; } } public function add_attributes($attribs = ['audio' => ['preload' => 'none'], 'iframe' => ['sandbox' => 'allow-scripts allow-same-origin'], 'video' => ['preload' => 'none']]) { if ($attribs) { if (is_array($attribs)) { $this->add_attributes = $attribs; } else { $this->add_attributes = explode(',', $attribs); } } else { $this->add_attributes = false; } } public function strip_comments($strip = false) { $this->strip_comments = (bool) $strip; } public function set_output_encoding($encoding = 'UTF-8') { $this->output_encoding = (string) $encoding; } /** * Set element/attribute key/value pairs of HTML attributes * containing URLs that need to be resolved relative to the feed * * Defaults to |a|@href, |area|@href, |audio|@src, |blockquote|@cite, * |del|@cite, |form|@action, |img|@longdesc, |img|@src, |input|@src, * |ins|@cite, |q|@cite, |source|@src, |video|@src * * @since 1.0 * @param array|null $element_attribute Element/attribute key/value pairs, null for default */ public function set_url_replacements($element_attribute = null) { if ($element_attribute === null) { $element_attribute = [ 'a' => 'href', 'area' => 'href', 'audio' => 'src', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => [ 'longdesc', 'src' ], 'input' => 'src', 'ins' => 'cite', 'q' => 'cite', 'source' => 'src', 'video' => [ 'poster', 'src' ] ]; } $this->replace_url_attributes = (array) $element_attribute; } /** * Set the list of domains for which to force HTTPS. * @see \SimplePie\Misc::https_url() * Example array('biz', 'example.com', 'example.org', 'www.example.net'); */ public function set_https_domains($domains) { $this->https_domains = []; foreach ($domains as $domain) { $domain = trim($domain, ". \t\n\r\0\x0B"); $segments = array_reverse(explode('.', $domain)); $node = &$this->https_domains; foreach ($segments as $segment) {//Build a tree if ($node === true) { break; } if (!isset($node[$segment])) { $node[$segment] = []; } $node = &$node[$segment]; } $node = true; } } /** * Check if the domain is in the list of forced HTTPS. */ protected function is_https_domain($domain) { $domain = trim($domain, '. '); $segments = array_reverse(explode('.', $domain)); $node = &$this->https_domains; foreach ($segments as $segment) {//Explore the tree if (isset($node[$segment])) { $node = &$node[$segment]; } else { break; } } return $node === true; } /** * Force HTTPS for selected Web sites. */ public function https_url($url) { return (strtolower(substr($url, 0, 7)) === 'http://') && $this->is_https_domain(parse_url($url, PHP_URL_HOST)) ? substr_replace($url, 's', 4, 0) : //Add the 's' to HTTPS $url; } public function sanitize($data, $type, $base = '') { $data = trim($data); if ($data !== '' || $type & \SimplePie\SimplePie::CONSTRUCT_IRI) { if ($type & \SimplePie\SimplePie::CONSTRUCT_MAYBE_HTML) { if (preg_match('/(&(#(x[0-9a-fA-F]+|[0-9]+)|[a-zA-Z0-9]+)|<\/[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*' . \SimplePie\SimplePie::PCRE_HTML_ATTRIBUTE . '>)/', $data)) { $type |= \SimplePie\SimplePie::CONSTRUCT_HTML; } else { $type |= \SimplePie\SimplePie::CONSTRUCT_TEXT; } } if ($type & \SimplePie\SimplePie::CONSTRUCT_BASE64) { $data = base64_decode($data); } if ($type & (\SimplePie\SimplePie::CONSTRUCT_HTML | \SimplePie\SimplePie::CONSTRUCT_XHTML)) { if (!class_exists('DOMDocument')) { throw new \SimplePie\Exception('DOMDocument not found, unable to use sanitizer'); } $document = new \DOMDocument(); $document->encoding = 'UTF-8'; $data = $this->preprocess($data, $type); set_error_handler(['SimplePie\Misc', 'silence_errors']); $document->loadHTML($data); restore_error_handler(); $xpath = new \DOMXPath($document); // Strip comments if ($this->strip_comments) { $comments = $xpath->query('//comment()'); foreach ($comments as $comment) { $comment->parentNode->removeChild($comment); } } // Strip out HTML tags and attributes that might cause various security problems. // Based on recommendations by Mark Pilgrim at: // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely if ($this->strip_htmltags) { foreach ($this->strip_htmltags as $tag) { $this->strip_tag($tag, $document, $xpath, $type); } } if ($this->rename_attributes) { foreach ($this->rename_attributes as $attrib) { $this->rename_attr($attrib, $xpath); } } if ($this->strip_attributes) { foreach ($this->strip_attributes as $attrib) { $this->strip_attr($attrib, $xpath); } } if ($this->add_attributes) { foreach ($this->add_attributes as $tag => $valuePairs) { $this->add_attr($tag, $valuePairs, $document); } } // Replace relative URLs $this->base = $base; foreach ($this->replace_url_attributes as $element => $attributes) { $this->replace_urls($document, $element, $attributes); } // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags. if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache) { $images = $document->getElementsByTagName('img'); foreach ($images as $img) { if ($img->hasAttribute('src')) { $image_url = $this->cache_namefilter->filter($img->getAttribute('src')); $cache = $this->get_cache($image_url); if ($cache->get_data($image_url, false)) { $img->setAttribute('src', $this->image_handler . $image_url); } else { $file = $this->registry->create(File::class, [$img->getAttribute('src'), $this->timeout, 5, ['X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']], $this->useragent, $this->force_fsockopen]); $headers = $file->headers; if ($file->success && ($file->method & \SimplePie\SimplePie::FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300))) { if ($cache->set_data($image_url, ['headers' => $file->headers, 'body' => $file->body], $this->cache_duration)) { $img->setAttribute('src', $this->image_handler . $image_url); } else { trigger_error("$this->cache_location is not writable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING); } } } } } } // Get content node $div = $document->getElementsByTagName('body')->item(0)->firstChild; // Finally, convert to a HTML string $data = trim($document->saveHTML($div)); if ($this->remove_div) { $data = preg_replace('/^<div' . \SimplePie\SimplePie::PCRE_XML_ATTRIBUTE . '>/', '', $data); $data = preg_replace('/<\/div>$/', '', $data); } else { $data = preg_replace('/^<div' . \SimplePie\SimplePie::PCRE_XML_ATTRIBUTE . '>/', '<div>', $data); } $data = str_replace('</source>', '', $data); } if ($type & \SimplePie\SimplePie::CONSTRUCT_IRI) { $absolute = $this->registry->call(Misc::class, 'absolutize_url', [$data, $base]); if ($absolute !== false) { $data = $absolute; } } if ($type & (\SimplePie\SimplePie::CONSTRUCT_TEXT | \SimplePie\SimplePie::CONSTRUCT_IRI)) { $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8'); } if ($this->output_encoding !== 'UTF-8') { $data = $this->registry->call(Misc::class, 'change_encoding', [$data, 'UTF-8', $this->output_encoding]); } } return $data; } protected function preprocess($html, $type) { $ret = ''; $html = preg_replace('%</?(?:html|body)[^>]*?'.'>%is', '', $html); if ($type & ~\SimplePie\SimplePie::CONSTRUCT_XHTML) { // Atom XHTML constructs are wrapped with a div by default // Note: No protection if $html contains a stray </div>! $html = '<div>' . $html . '</div>'; $ret .= '<!DOCTYPE html>'; $content_type = 'text/html'; } else { $ret .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'; $content_type = 'application/xhtml+xml'; } $ret .= '<html><head>'; $ret .= '<meta http-equiv="Content-Type" content="' . $content_type . '; charset=utf-8" />'; $ret .= '</head><body>' . $html . '</body></html>'; return $ret; } public function replace_urls($document, $tag, $attributes) { if (!is_array($attributes)) { $attributes = [$attributes]; } if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags)) { $elements = $document->getElementsByTagName($tag); foreach ($elements as $element) { foreach ($attributes as $attribute) { if ($element->hasAttribute($attribute)) { $value = $this->registry->call(Misc::class, 'absolutize_url', [$element->getAttribute($attribute), $this->base]); if ($value !== false) { $value = $this->https_url($value); $element->setAttribute($attribute, $value); } } } } } } public function do_strip_htmltags($match) { if ($this->encode_instead_of_strip) { if (isset($match[4]) && !in_array(strtolower($match[1]), ['script', 'style'])) { $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8'); $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8'); return "<$match[1]$match[2]>$match[3]</$match[1]>"; } else { return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8'); } } elseif (isset($match[4]) && !in_array(strtolower($match[1]), ['script', 'style'])) { return $match[4]; } else { return ''; } } protected function strip_tag($tag, $document, $xpath, $type) { $elements = $xpath->query('body//' . $tag); if ($this->encode_instead_of_strip) { foreach ($elements as $element) { $fragment = $document->createDocumentFragment(); // For elements which aren't script or style, include the tag itself if (!in_array($tag, ['script', 'style'])) { $text = '<' . $tag; if ($element->hasAttributes()) { $attrs = []; foreach ($element->attributes as $name => $attr) { $value = $attr->value; // In XHTML, empty values should never exist, so we repeat the value if (empty($value) && ($type & \SimplePie\SimplePie::CONSTRUCT_XHTML)) { $value = $name; } // For HTML, empty is fine elseif (empty($value) && ($type & \SimplePie\SimplePie::CONSTRUCT_HTML)) { $attrs[] = $name; continue; } // Standard attribute text $attrs[] = $name . '="' . $attr->value . '"'; } $text .= ' ' . implode(' ', $attrs); } $text .= '>'; $fragment->appendChild(new \DOMText($text)); } $number = $element->childNodes->length; for ($i = $number; $i > 0; $i--) { $child = $element->childNodes->item(0); $fragment->appendChild($child); } if (!in_array($tag, ['script', 'style'])) { $fragment->appendChild(new \DOMText('</' . $tag . '>')); } $element->parentNode->replaceChild($fragment, $element); } return; } elseif (in_array($tag, ['script', 'style'])) { foreach ($elements as $element) { $element->parentNode->removeChild($element); } return; } else { foreach ($elements as $element) { $fragment = $document->createDocumentFragment(); $number = $element->childNodes->length; for ($i = $number; $i > 0; $i--) { $child = $element->childNodes->item(0); $fragment->appendChild($child); } $element->parentNode->replaceChild($fragment, $element); } } } protected function strip_attr($attrib, $xpath) { $elements = $xpath->query('//*[@' . $attrib . ']'); foreach ($elements as $element) { $element->removeAttribute($attrib); } } protected function rename_attr($attrib, $xpath) { $elements = $xpath->query('//*[@' . $attrib . ']'); foreach ($elements as $element) { $element->setAttribute('data-sanitized-' . $attrib, $element->getAttribute($attrib)); $element->removeAttribute($attrib); } } protected function add_attr($tag, $valuePairs, $document) { $elements = $document->getElementsByTagName($tag); foreach ($elements as $element) { foreach ($valuePairs as $attrib => $value) { $element->setAttribute($attrib, $value); } } } /** * Get a DataCache * * @param string $image_url Only needed for BC, can be removed in SimplePie 2.0.0 * * @return DataCache */ private function get_cache($image_url = '') { if ($this->cache === null) { // @trigger_error(sprintf('Not providing as PSR-16 cache implementation is deprecated since SimplePie 1.8.0, please use "SimplePie\SimplePie::set_cache()".'), \E_USER_DEPRECATED); $cache = $this->registry->call(Cache::class, 'get_handler', [ $this->cache_location, $image_url, Base::TYPE_IMAGE ]); return new BaseDataCache($cache); } return $this->cache; } } class_alias('SimplePie\Sanitize', 'SimplePie_Sanitize'); PK������ZF&bc��c����Core32/XSalsa20.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_XSalsa20', false)) { return; } /** * Class ParagonIE_Sodium_Core32_XSalsa20 */ abstract class ParagonIE_Sodium_Core32_XSalsa20 extends ParagonIE_Sodium_Core32_HSalsa20 { /** * Expand a key and nonce into an xsalsa20 keystream. * * @internal You should not use this directly from another application * * @param int $len * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function xsalsa20($len, $nonce, $key) { $ret = self::salsa20( $len, self::substr($nonce, 16, 8), self::hsalsa20($nonce, $key) ); return $ret; } /** * Encrypt a string with XSalsa20. Doesn't provide integrity. * * @internal You should not use this directly from another application * * @param string $message * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function xsalsa20_xor($message, $nonce, $key) { return self::xorStrings( $message, self::xsalsa20( self::strlen($message), $nonce, $key ) ); } } PK������ZLTn�n���Core32/Curve25519.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_Curve25519', false)) { return; } /** * Class ParagonIE_Sodium_Core32_Curve25519 * * Implements Curve25519 core functions * * Based on the ref10 curve25519 code provided by libsodium * * @ref https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c */ abstract class ParagonIE_Sodium_Core32_Curve25519 extends ParagonIE_Sodium_Core32_Curve25519_H { /** * Get a field element of size 10 with a value of 0 * * @internal You should not use this directly from another application * * @return ParagonIE_Sodium_Core32_Curve25519_Fe * @throws SodiumException * @throws TypeError */ public static function fe_0() { return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray( array( new ParagonIE_Sodium_Core32_Int32(), new ParagonIE_Sodium_Core32_Int32(), new ParagonIE_Sodium_Core32_Int32(), new ParagonIE_Sodium_Core32_Int32(), new ParagonIE_Sodium_Core32_Int32(), new ParagonIE_Sodium_Core32_Int32(), new ParagonIE_Sodium_Core32_Int32(), new ParagonIE_Sodium_Core32_Int32(), new ParagonIE_Sodium_Core32_Int32(), new ParagonIE_Sodium_Core32_Int32() ) ); } /** * Get a field element of size 10 with a value of 1 * * @internal You should not use this directly from another application * * @return ParagonIE_Sodium_Core32_Curve25519_Fe * @throws SodiumException * @throws TypeError */ public static function fe_1() { return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray( array( ParagonIE_Sodium_Core32_Int32::fromInt(1), new ParagonIE_Sodium_Core32_Int32(), new ParagonIE_Sodium_Core32_Int32(), new ParagonIE_Sodium_Core32_Int32(), new ParagonIE_Sodium_Core32_Int32(), new ParagonIE_Sodium_Core32_Int32(), new ParagonIE_Sodium_Core32_Int32(), new ParagonIE_Sodium_Core32_Int32(), new ParagonIE_Sodium_Core32_Int32(), new ParagonIE_Sodium_Core32_Int32() ) ); } /** * Add two field elements. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g * @return ParagonIE_Sodium_Core32_Curve25519_Fe * @throws SodiumException * @throws TypeError * @psalm-suppress MixedAssignment * @psalm-suppress MixedMethodCall */ public static function fe_add( ParagonIE_Sodium_Core32_Curve25519_Fe $f, ParagonIE_Sodium_Core32_Curve25519_Fe $g ) { $arr = array(); for ($i = 0; $i < 10; ++$i) { $arr[$i] = $f[$i]->addInt32($g[$i]); } /** @var array<int, ParagonIE_Sodium_Core32_Int32> $arr */ return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray($arr); } /** * Constant-time conditional move. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g * @param int $b * @return ParagonIE_Sodium_Core32_Curve25519_Fe * @throws SodiumException * @throws TypeError * @psalm-suppress MixedAssignment * @psalm-suppress MixedMethodCall */ public static function fe_cmov( ParagonIE_Sodium_Core32_Curve25519_Fe $f, ParagonIE_Sodium_Core32_Curve25519_Fe $g, $b = 0 ) { /** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */ $h = array(); for ($i = 0; $i < 10; ++$i) { if (!($f[$i] instanceof ParagonIE_Sodium_Core32_Int32)) { throw new TypeError('Expected Int32'); } if (!($g[$i] instanceof ParagonIE_Sodium_Core32_Int32)) { throw new TypeError('Expected Int32'); } $h[$i] = $f[$i]->xorInt32( $f[$i]->xorInt32($g[$i])->mask($b) ); } /** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */ return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray($h); } /** * Create a copy of a field element. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f * @return ParagonIE_Sodium_Core32_Curve25519_Fe */ public static function fe_copy(ParagonIE_Sodium_Core32_Curve25519_Fe $f) { $h = clone $f; return $h; } /** * Give: 32-byte string. * Receive: A field element object to use for internal calculations. * * @internal You should not use this directly from another application * * @param string $s * @return ParagonIE_Sodium_Core32_Curve25519_Fe * @throws RangeException * @throws SodiumException * @throws TypeError * @psalm-suppress MixedMethodCall */ public static function fe_frombytes($s) { if (self::strlen($s) !== 32) { throw new RangeException('Expected a 32-byte string.'); } /** @var ParagonIE_Sodium_Core32_Int32 $h0 */ $h0 = ParagonIE_Sodium_Core32_Int32::fromInt( self::load_4($s) ); /** @var ParagonIE_Sodium_Core32_Int32 $h1 */ $h1 = ParagonIE_Sodium_Core32_Int32::fromInt( self::load_3(self::substr($s, 4, 3)) << 6 ); /** @var ParagonIE_Sodium_Core32_Int32 $h2 */ $h2 = ParagonIE_Sodium_Core32_Int32::fromInt( self::load_3(self::substr($s, 7, 3)) << 5 ); /** @var ParagonIE_Sodium_Core32_Int32 $h3 */ $h3 = ParagonIE_Sodium_Core32_Int32::fromInt( self::load_3(self::substr($s, 10, 3)) << 3 ); /** @var ParagonIE_Sodium_Core32_Int32 $h4 */ $h4 = ParagonIE_Sodium_Core32_Int32::fromInt( self::load_3(self::substr($s, 13, 3)) << 2 ); /** @var ParagonIE_Sodium_Core32_Int32 $h5 */ $h5 = ParagonIE_Sodium_Core32_Int32::fromInt( self::load_4(self::substr($s, 16, 4)) ); /** @var ParagonIE_Sodium_Core32_Int32 $h6 */ $h6 = ParagonIE_Sodium_Core32_Int32::fromInt( self::load_3(self::substr($s, 20, 3)) << 7 ); /** @var ParagonIE_Sodium_Core32_Int32 $h7 */ $h7 = ParagonIE_Sodium_Core32_Int32::fromInt( self::load_3(self::substr($s, 23, 3)) << 5 ); /** @var ParagonIE_Sodium_Core32_Int32 $h8 */ $h8 = ParagonIE_Sodium_Core32_Int32::fromInt( self::load_3(self::substr($s, 26, 3)) << 4 ); /** @var ParagonIE_Sodium_Core32_Int32 $h9 */ $h9 = ParagonIE_Sodium_Core32_Int32::fromInt( (self::load_3(self::substr($s, 29, 3)) & 8388607) << 2 ); $carry9 = $h9->addInt(1 << 24)->shiftRight(25); $h0 = $h0->addInt32($carry9->mulInt(19, 5)); $h9 = $h9->subInt32($carry9->shiftLeft(25)); $carry1 = $h1->addInt(1 << 24)->shiftRight(25); $h2 = $h2->addInt32($carry1); $h1 = $h1->subInt32($carry1->shiftLeft(25)); $carry3 = $h3->addInt(1 << 24)->shiftRight(25); $h4 = $h4->addInt32($carry3); $h3 = $h3->subInt32($carry3->shiftLeft(25)); $carry5 = $h5->addInt(1 << 24)->shiftRight(25); $h6 = $h6->addInt32($carry5); $h5 = $h5->subInt32($carry5->shiftLeft(25)); $carry7 = $h7->addInt(1 << 24)->shiftRight(25); $h8 = $h8->addInt32($carry7); $h7 = $h7->subInt32($carry7->shiftLeft(25)); $carry0 = $h0->addInt(1 << 25)->shiftRight(26); $h1 = $h1->addInt32($carry0); $h0 = $h0->subInt32($carry0->shiftLeft(26)); $carry2 = $h2->addInt(1 << 25)->shiftRight(26); $h3 = $h3->addInt32($carry2); $h2 = $h2->subInt32($carry2->shiftLeft(26)); $carry4 = $h4->addInt(1 << 25)->shiftRight(26); $h5 = $h5->addInt32($carry4); $h4 = $h4->subInt32($carry4->shiftLeft(26)); $carry6 = $h6->addInt(1 << 25)->shiftRight(26); $h7 = $h7->addInt32($carry6); $h6 = $h6->subInt32($carry6->shiftLeft(26)); $carry8 = $h8->addInt(1 << 25)->shiftRight(26); $h9 = $h9->addInt32($carry8); $h8 = $h8->subInt32($carry8->shiftLeft(26)); return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray( array($h0, $h1, $h2,$h3, $h4, $h5, $h6, $h7, $h8, $h9) ); } /** * Convert a field element to a byte string. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe $h * @return string * @throws SodiumException * @throws TypeError * @psalm-suppress MixedAssignment * @psalm-suppress MixedMethodCall */ public static function fe_tobytes(ParagonIE_Sodium_Core32_Curve25519_Fe $h) { /** * @var ParagonIE_Sodium_Core32_Int64[] $f * @var ParagonIE_Sodium_Core32_Int64 $q */ $f = array(); for ($i = 0; $i < 10; ++$i) { $f[$i] = $h[$i]->toInt64(); } $q = $f[9]->mulInt(19, 5)->addInt(1 << 14)->shiftRight(25) ->addInt64($f[0])->shiftRight(26) ->addInt64($f[1])->shiftRight(25) ->addInt64($f[2])->shiftRight(26) ->addInt64($f[3])->shiftRight(25) ->addInt64($f[4])->shiftRight(26) ->addInt64($f[5])->shiftRight(25) ->addInt64($f[6])->shiftRight(26) ->addInt64($f[7])->shiftRight(25) ->addInt64($f[8])->shiftRight(26) ->addInt64($f[9])->shiftRight(25); $f[0] = $f[0]->addInt64($q->mulInt(19, 5)); $carry0 = $f[0]->shiftRight(26); $f[1] = $f[1]->addInt64($carry0); $f[0] = $f[0]->subInt64($carry0->shiftLeft(26)); $carry1 = $f[1]->shiftRight(25); $f[2] = $f[2]->addInt64($carry1); $f[1] = $f[1]->subInt64($carry1->shiftLeft(25)); $carry2 = $f[2]->shiftRight(26); $f[3] = $f[3]->addInt64($carry2); $f[2] = $f[2]->subInt64($carry2->shiftLeft(26)); $carry3 = $f[3]->shiftRight(25); $f[4] = $f[4]->addInt64($carry3); $f[3] = $f[3]->subInt64($carry3->shiftLeft(25)); $carry4 = $f[4]->shiftRight(26); $f[5] = $f[5]->addInt64($carry4); $f[4] = $f[4]->subInt64($carry4->shiftLeft(26)); $carry5 = $f[5]->shiftRight(25); $f[6] = $f[6]->addInt64($carry5); $f[5] = $f[5]->subInt64($carry5->shiftLeft(25)); $carry6 = $f[6]->shiftRight(26); $f[7] = $f[7]->addInt64($carry6); $f[6] = $f[6]->subInt64($carry6->shiftLeft(26)); $carry7 = $f[7]->shiftRight(25); $f[8] = $f[8]->addInt64($carry7); $f[7] = $f[7]->subInt64($carry7->shiftLeft(25)); $carry8 = $f[8]->shiftRight(26); $f[9] = $f[9]->addInt64($carry8); $f[8] = $f[8]->subInt64($carry8->shiftLeft(26)); $carry9 = $f[9]->shiftRight(25); $f[9] = $f[9]->subInt64($carry9->shiftLeft(25)); $h0 = $f[0]->toInt32()->toInt(); $h1 = $f[1]->toInt32()->toInt(); $h2 = $f[2]->toInt32()->toInt(); $h3 = $f[3]->toInt32()->toInt(); $h4 = $f[4]->toInt32()->toInt(); $h5 = $f[5]->toInt32()->toInt(); $h6 = $f[6]->toInt32()->toInt(); $h7 = $f[7]->toInt32()->toInt(); $h8 = $f[8]->toInt32()->toInt(); $h9 = $f[9]->toInt32()->toInt(); /** * @var array<int, int> */ $s = array( (int) (($h0 >> 0) & 0xff), (int) (($h0 >> 8) & 0xff), (int) (($h0 >> 16) & 0xff), (int) ((($h0 >> 24) | ($h1 << 2)) & 0xff), (int) (($h1 >> 6) & 0xff), (int) (($h1 >> 14) & 0xff), (int) ((($h1 >> 22) | ($h2 << 3)) & 0xff), (int) (($h2 >> 5) & 0xff), (int) (($h2 >> 13) & 0xff), (int) ((($h2 >> 21) | ($h3 << 5)) & 0xff), (int) (($h3 >> 3) & 0xff), (int) (($h3 >> 11) & 0xff), (int) ((($h3 >> 19) | ($h4 << 6)) & 0xff), (int) (($h4 >> 2) & 0xff), (int) (($h4 >> 10) & 0xff), (int) (($h4 >> 18) & 0xff), (int) (($h5 >> 0) & 0xff), (int) (($h5 >> 8) & 0xff), (int) (($h5 >> 16) & 0xff), (int) ((($h5 >> 24) | ($h6 << 1)) & 0xff), (int) (($h6 >> 7) & 0xff), (int) (($h6 >> 15) & 0xff), (int) ((($h6 >> 23) | ($h7 << 3)) & 0xff), (int) (($h7 >> 5) & 0xff), (int) (($h7 >> 13) & 0xff), (int) ((($h7 >> 21) | ($h8 << 4)) & 0xff), (int) (($h8 >> 4) & 0xff), (int) (($h8 >> 12) & 0xff), (int) ((($h8 >> 20) | ($h9 << 6)) & 0xff), (int) (($h9 >> 2) & 0xff), (int) (($h9 >> 10) & 0xff), (int) (($h9 >> 18) & 0xff) ); return self::intArrayToString($s); } /** * Is a field element negative? (1 = yes, 0 = no. Used in calculations.) * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f * @return int * @throws SodiumException * @throws TypeError */ public static function fe_isnegative(ParagonIE_Sodium_Core32_Curve25519_Fe $f) { $str = self::fe_tobytes($f); return (int) (self::chrToInt($str[0]) & 1); } /** * Returns 0 if this field element results in all NUL bytes. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f * @return bool * @throws SodiumException * @throws TypeError */ public static function fe_isnonzero(ParagonIE_Sodium_Core32_Curve25519_Fe $f) { static $zero; if ($zero === null) { $zero = str_repeat("\x00", 32); } $str = self::fe_tobytes($f); /** @var string $zero */ return !self::verify_32($str, $zero); } /** * Multiply two field elements * * h = f * g * * @internal You should not use this directly from another application * * @security Is multiplication a source of timing leaks? If so, can we do * anything to prevent that from happening? * * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g * @return ParagonIE_Sodium_Core32_Curve25519_Fe * @throws SodiumException * @throws TypeError */ public static function fe_mul( ParagonIE_Sodium_Core32_Curve25519_Fe $f, ParagonIE_Sodium_Core32_Curve25519_Fe $g ) { /** * @var ParagonIE_Sodium_Core32_Int32[] $f * @var ParagonIE_Sodium_Core32_Int32[] $g * @var ParagonIE_Sodium_Core32_Int64 $f0 * @var ParagonIE_Sodium_Core32_Int64 $f1 * @var ParagonIE_Sodium_Core32_Int64 $f2 * @var ParagonIE_Sodium_Core32_Int64 $f3 * @var ParagonIE_Sodium_Core32_Int64 $f4 * @var ParagonIE_Sodium_Core32_Int64 $f5 * @var ParagonIE_Sodium_Core32_Int64 $f6 * @var ParagonIE_Sodium_Core32_Int64 $f7 * @var ParagonIE_Sodium_Core32_Int64 $f8 * @var ParagonIE_Sodium_Core32_Int64 $f9 * @var ParagonIE_Sodium_Core32_Int64 $g0 * @var ParagonIE_Sodium_Core32_Int64 $g1 * @var ParagonIE_Sodium_Core32_Int64 $g2 * @var ParagonIE_Sodium_Core32_Int64 $g3 * @var ParagonIE_Sodium_Core32_Int64 $g4 * @var ParagonIE_Sodium_Core32_Int64 $g5 * @var ParagonIE_Sodium_Core32_Int64 $g6 * @var ParagonIE_Sodium_Core32_Int64 $g7 * @var ParagonIE_Sodium_Core32_Int64 $g8 * @var ParagonIE_Sodium_Core32_Int64 $g9 */ $f0 = $f[0]->toInt64(); $f1 = $f[1]->toInt64(); $f2 = $f[2]->toInt64(); $f3 = $f[3]->toInt64(); $f4 = $f[4]->toInt64(); $f5 = $f[5]->toInt64(); $f6 = $f[6]->toInt64(); $f7 = $f[7]->toInt64(); $f8 = $f[8]->toInt64(); $f9 = $f[9]->toInt64(); $g0 = $g[0]->toInt64(); $g1 = $g[1]->toInt64(); $g2 = $g[2]->toInt64(); $g3 = $g[3]->toInt64(); $g4 = $g[4]->toInt64(); $g5 = $g[5]->toInt64(); $g6 = $g[6]->toInt64(); $g7 = $g[7]->toInt64(); $g8 = $g[8]->toInt64(); $g9 = $g[9]->toInt64(); $g1_19 = $g1->mulInt(19, 5); /* 2^4 <= 19 <= 2^5, but we only want 5 bits */ $g2_19 = $g2->mulInt(19, 5); $g3_19 = $g3->mulInt(19, 5); $g4_19 = $g4->mulInt(19, 5); $g5_19 = $g5->mulInt(19, 5); $g6_19 = $g6->mulInt(19, 5); $g7_19 = $g7->mulInt(19, 5); $g8_19 = $g8->mulInt(19, 5); $g9_19 = $g9->mulInt(19, 5); $f1_2 = $f1->shiftLeft(1); $f3_2 = $f3->shiftLeft(1); $f5_2 = $f5->shiftLeft(1); $f7_2 = $f7->shiftLeft(1); $f9_2 = $f9->shiftLeft(1); $f0g0 = $f0->mulInt64($g0, 27); $f0g1 = $f0->mulInt64($g1, 27); $f0g2 = $f0->mulInt64($g2, 27); $f0g3 = $f0->mulInt64($g3, 27); $f0g4 = $f0->mulInt64($g4, 27); $f0g5 = $f0->mulInt64($g5, 27); $f0g6 = $f0->mulInt64($g6, 27); $f0g7 = $f0->mulInt64($g7, 27); $f0g8 = $f0->mulInt64($g8, 27); $f0g9 = $f0->mulInt64($g9, 27); $f1g0 = $f1->mulInt64($g0, 27); $f1g1_2 = $f1_2->mulInt64($g1, 27); $f1g2 = $f1->mulInt64($g2, 27); $f1g3_2 = $f1_2->mulInt64($g3, 27); $f1g4 = $f1->mulInt64($g4, 30); $f1g5_2 = $f1_2->mulInt64($g5, 30); $f1g6 = $f1->mulInt64($g6, 30); $f1g7_2 = $f1_2->mulInt64($g7, 30); $f1g8 = $f1->mulInt64($g8, 30); $f1g9_38 = $g9_19->mulInt64($f1_2, 30); $f2g0 = $f2->mulInt64($g0, 30); $f2g1 = $f2->mulInt64($g1, 29); $f2g2 = $f2->mulInt64($g2, 30); $f2g3 = $f2->mulInt64($g3, 29); $f2g4 = $f2->mulInt64($g4, 30); $f2g5 = $f2->mulInt64($g5, 29); $f2g6 = $f2->mulInt64($g6, 30); $f2g7 = $f2->mulInt64($g7, 29); $f2g8_19 = $g8_19->mulInt64($f2, 30); $f2g9_19 = $g9_19->mulInt64($f2, 30); $f3g0 = $f3->mulInt64($g0, 30); $f3g1_2 = $f3_2->mulInt64($g1, 30); $f3g2 = $f3->mulInt64($g2, 30); $f3g3_2 = $f3_2->mulInt64($g3, 30); $f3g4 = $f3->mulInt64($g4, 30); $f3g5_2 = $f3_2->mulInt64($g5, 30); $f3g6 = $f3->mulInt64($g6, 30); $f3g7_38 = $g7_19->mulInt64($f3_2, 30); $f3g8_19 = $g8_19->mulInt64($f3, 30); $f3g9_38 = $g9_19->mulInt64($f3_2, 30); $f4g0 = $f4->mulInt64($g0, 30); $f4g1 = $f4->mulInt64($g1, 30); $f4g2 = $f4->mulInt64($g2, 30); $f4g3 = $f4->mulInt64($g3, 30); $f4g4 = $f4->mulInt64($g4, 30); $f4g5 = $f4->mulInt64($g5, 30); $f4g6_19 = $g6_19->mulInt64($f4, 30); $f4g7_19 = $g7_19->mulInt64($f4, 30); $f4g8_19 = $g8_19->mulInt64($f4, 30); $f4g9_19 = $g9_19->mulInt64($f4, 30); $f5g0 = $f5->mulInt64($g0, 30); $f5g1_2 = $f5_2->mulInt64($g1, 30); $f5g2 = $f5->mulInt64($g2, 30); $f5g3_2 = $f5_2->mulInt64($g3, 30); $f5g4 = $f5->mulInt64($g4, 30); $f5g5_38 = $g5_19->mulInt64($f5_2, 30); $f5g6_19 = $g6_19->mulInt64($f5, 30); $f5g7_38 = $g7_19->mulInt64($f5_2, 30); $f5g8_19 = $g8_19->mulInt64($f5, 30); $f5g9_38 = $g9_19->mulInt64($f5_2, 30); $f6g0 = $f6->mulInt64($g0, 30); $f6g1 = $f6->mulInt64($g1, 30); $f6g2 = $f6->mulInt64($g2, 30); $f6g3 = $f6->mulInt64($g3, 30); $f6g4_19 = $g4_19->mulInt64($f6, 30); $f6g5_19 = $g5_19->mulInt64($f6, 30); $f6g6_19 = $g6_19->mulInt64($f6, 30); $f6g7_19 = $g7_19->mulInt64($f6, 30); $f6g8_19 = $g8_19->mulInt64($f6, 30); $f6g9_19 = $g9_19->mulInt64($f6, 30); $f7g0 = $f7->mulInt64($g0, 30); $f7g1_2 = $g1->mulInt64($f7_2, 30); $f7g2 = $f7->mulInt64($g2, 30); $f7g3_38 = $g3_19->mulInt64($f7_2, 30); $f7g4_19 = $g4_19->mulInt64($f7, 30); $f7g5_38 = $g5_19->mulInt64($f7_2, 30); $f7g6_19 = $g6_19->mulInt64($f7, 30); $f7g7_38 = $g7_19->mulInt64($f7_2, 30); $f7g8_19 = $g8_19->mulInt64($f7, 30); $f7g9_38 = $g9_19->mulInt64($f7_2, 30); $f8g0 = $f8->mulInt64($g0, 30); $f8g1 = $f8->mulInt64($g1, 29); $f8g2_19 = $g2_19->mulInt64($f8, 30); $f8g3_19 = $g3_19->mulInt64($f8, 30); $f8g4_19 = $g4_19->mulInt64($f8, 30); $f8g5_19 = $g5_19->mulInt64($f8, 30); $f8g6_19 = $g6_19->mulInt64($f8, 30); $f8g7_19 = $g7_19->mulInt64($f8, 30); $f8g8_19 = $g8_19->mulInt64($f8, 30); $f8g9_19 = $g9_19->mulInt64($f8, 30); $f9g0 = $f9->mulInt64($g0, 30); $f9g1_38 = $g1_19->mulInt64($f9_2, 30); $f9g2_19 = $g2_19->mulInt64($f9, 30); $f9g3_38 = $g3_19->mulInt64($f9_2, 30); $f9g4_19 = $g4_19->mulInt64($f9, 30); $f9g5_38 = $g5_19->mulInt64($f9_2, 30); $f9g6_19 = $g6_19->mulInt64($f9, 30); $f9g7_38 = $g7_19->mulInt64($f9_2, 30); $f9g8_19 = $g8_19->mulInt64($f9, 30); $f9g9_38 = $g9_19->mulInt64($f9_2, 30); // $h0 = $f0g0 + $f1g9_38 + $f2g8_19 + $f3g7_38 + $f4g6_19 + $f5g5_38 + $f6g4_19 + $f7g3_38 + $f8g2_19 + $f9g1_38; $h0 = $f0g0->addInt64($f1g9_38)->addInt64($f2g8_19)->addInt64($f3g7_38) ->addInt64($f4g6_19)->addInt64($f5g5_38)->addInt64($f6g4_19) ->addInt64($f7g3_38)->addInt64($f8g2_19)->addInt64($f9g1_38); // $h1 = $f0g1 + $f1g0 + $f2g9_19 + $f3g8_19 + $f4g7_19 + $f5g6_19 + $f6g5_19 + $f7g4_19 + $f8g3_19 + $f9g2_19; $h1 = $f0g1->addInt64($f1g0)->addInt64($f2g9_19)->addInt64($f3g8_19) ->addInt64($f4g7_19)->addInt64($f5g6_19)->addInt64($f6g5_19) ->addInt64($f7g4_19)->addInt64($f8g3_19)->addInt64($f9g2_19); // $h2 = $f0g2 + $f1g1_2 + $f2g0 + $f3g9_38 + $f4g8_19 + $f5g7_38 + $f6g6_19 + $f7g5_38 + $f8g4_19 + $f9g3_38; $h2 = $f0g2->addInt64($f1g1_2)->addInt64($f2g0)->addInt64($f3g9_38) ->addInt64($f4g8_19)->addInt64($f5g7_38)->addInt64($f6g6_19) ->addInt64($f7g5_38)->addInt64($f8g4_19)->addInt64($f9g3_38); // $h3 = $f0g3 + $f1g2 + $f2g1 + $f3g0 + $f4g9_19 + $f5g8_19 + $f6g7_19 + $f7g6_19 + $f8g5_19 + $f9g4_19; $h3 = $f0g3->addInt64($f1g2)->addInt64($f2g1)->addInt64($f3g0) ->addInt64($f4g9_19)->addInt64($f5g8_19)->addInt64($f6g7_19) ->addInt64($f7g6_19)->addInt64($f8g5_19)->addInt64($f9g4_19); // $h4 = $f0g4 + $f1g3_2 + $f2g2 + $f3g1_2 + $f4g0 + $f5g9_38 + $f6g8_19 + $f7g7_38 + $f8g6_19 + $f9g5_38; $h4 = $f0g4->addInt64($f1g3_2)->addInt64($f2g2)->addInt64($f3g1_2) ->addInt64($f4g0)->addInt64($f5g9_38)->addInt64($f6g8_19) ->addInt64($f7g7_38)->addInt64($f8g6_19)->addInt64($f9g5_38); // $h5 = $f0g5 + $f1g4 + $f2g3 + $f3g2 + $f4g1 + $f5g0 + $f6g9_19 + $f7g8_19 + $f8g7_19 + $f9g6_19; $h5 = $f0g5->addInt64($f1g4)->addInt64($f2g3)->addInt64($f3g2) ->addInt64($f4g1)->addInt64($f5g0)->addInt64($f6g9_19) ->addInt64($f7g8_19)->addInt64($f8g7_19)->addInt64($f9g6_19); // $h6 = $f0g6 + $f1g5_2 + $f2g4 + $f3g3_2 + $f4g2 + $f5g1_2 + $f6g0 + $f7g9_38 + $f8g8_19 + $f9g7_38; $h6 = $f0g6->addInt64($f1g5_2)->addInt64($f2g4)->addInt64($f3g3_2) ->addInt64($f4g2)->addInt64($f5g1_2)->addInt64($f6g0) ->addInt64($f7g9_38)->addInt64($f8g8_19)->addInt64($f9g7_38); // $h7 = $f0g7 + $f1g6 + $f2g5 + $f3g4 + $f4g3 + $f5g2 + $f6g1 + $f7g0 + $f8g9_19 + $f9g8_19; $h7 = $f0g7->addInt64($f1g6)->addInt64($f2g5)->addInt64($f3g4) ->addInt64($f4g3)->addInt64($f5g2)->addInt64($f6g1) ->addInt64($f7g0)->addInt64($f8g9_19)->addInt64($f9g8_19); // $h8 = $f0g8 + $f1g7_2 + $f2g6 + $f3g5_2 + $f4g4 + $f5g3_2 + $f6g2 + $f7g1_2 + $f8g0 + $f9g9_38; $h8 = $f0g8->addInt64($f1g7_2)->addInt64($f2g6)->addInt64($f3g5_2) ->addInt64($f4g4)->addInt64($f5g3_2)->addInt64($f6g2) ->addInt64($f7g1_2)->addInt64($f8g0)->addInt64($f9g9_38); // $h9 = $f0g9 + $f1g8 + $f2g7 + $f3g6 + $f4g5 + $f5g4 + $f6g3 + $f7g2 + $f8g1 + $f9g0 ; $h9 = $f0g9->addInt64($f1g8)->addInt64($f2g7)->addInt64($f3g6) ->addInt64($f4g5)->addInt64($f5g4)->addInt64($f6g3) ->addInt64($f7g2)->addInt64($f8g1)->addInt64($f9g0); /** * @var ParagonIE_Sodium_Core32_Int64 $h0 * @var ParagonIE_Sodium_Core32_Int64 $h1 * @var ParagonIE_Sodium_Core32_Int64 $h2 * @var ParagonIE_Sodium_Core32_Int64 $h3 * @var ParagonIE_Sodium_Core32_Int64 $h4 * @var ParagonIE_Sodium_Core32_Int64 $h5 * @var ParagonIE_Sodium_Core32_Int64 $h6 * @var ParagonIE_Sodium_Core32_Int64 $h7 * @var ParagonIE_Sodium_Core32_Int64 $h8 * @var ParagonIE_Sodium_Core32_Int64 $h9 * @var ParagonIE_Sodium_Core32_Int64 $carry0 * @var ParagonIE_Sodium_Core32_Int64 $carry1 * @var ParagonIE_Sodium_Core32_Int64 $carry2 * @var ParagonIE_Sodium_Core32_Int64 $carry3 * @var ParagonIE_Sodium_Core32_Int64 $carry4 * @var ParagonIE_Sodium_Core32_Int64 $carry5 * @var ParagonIE_Sodium_Core32_Int64 $carry6 * @var ParagonIE_Sodium_Core32_Int64 $carry7 * @var ParagonIE_Sodium_Core32_Int64 $carry8 * @var ParagonIE_Sodium_Core32_Int64 $carry9 */ $carry0 = $h0->addInt(1 << 25)->shiftRight(26); $h1 = $h1->addInt64($carry0); $h0 = $h0->subInt64($carry0->shiftLeft(26)); $carry4 = $h4->addInt(1 << 25)->shiftRight(26); $h5 = $h5->addInt64($carry4); $h4 = $h4->subInt64($carry4->shiftLeft(26)); $carry1 = $h1->addInt(1 << 24)->shiftRight(25); $h2 = $h2->addInt64($carry1); $h1 = $h1->subInt64($carry1->shiftLeft(25)); $carry5 = $h5->addInt(1 << 24)->shiftRight(25); $h6 = $h6->addInt64($carry5); $h5 = $h5->subInt64($carry5->shiftLeft(25)); $carry2 = $h2->addInt(1 << 25)->shiftRight(26); $h3 = $h3->addInt64($carry2); $h2 = $h2->subInt64($carry2->shiftLeft(26)); $carry6 = $h6->addInt(1 << 25)->shiftRight(26); $h7 = $h7->addInt64($carry6); $h6 = $h6->subInt64($carry6->shiftLeft(26)); $carry3 = $h3->addInt(1 << 24)->shiftRight(25); $h4 = $h4->addInt64($carry3); $h3 = $h3->subInt64($carry3->shiftLeft(25)); $carry7 = $h7->addInt(1 << 24)->shiftRight(25); $h8 = $h8->addInt64($carry7); $h7 = $h7->subInt64($carry7->shiftLeft(25)); $carry4 = $h4->addInt(1 << 25)->shiftRight(26); $h5 = $h5->addInt64($carry4); $h4 = $h4->subInt64($carry4->shiftLeft(26)); $carry8 = $h8->addInt(1 << 25)->shiftRight(26); $h9 = $h9->addInt64($carry8); $h8 = $h8->subInt64($carry8->shiftLeft(26)); $carry9 = $h9->addInt(1 << 24)->shiftRight(25); $h0 = $h0->addInt64($carry9->mulInt(19, 5)); $h9 = $h9->subInt64($carry9->shiftLeft(25)); $carry0 = $h0->addInt(1 << 25)->shiftRight(26); $h1 = $h1->addInt64($carry0); $h0 = $h0->subInt64($carry0->shiftLeft(26)); return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray( array( $h0->toInt32(), $h1->toInt32(), $h2->toInt32(), $h3->toInt32(), $h4->toInt32(), $h5->toInt32(), $h6->toInt32(), $h7->toInt32(), $h8->toInt32(), $h9->toInt32() ) ); } /** * Get the negative values for each piece of the field element. * * h = -f * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f * @return ParagonIE_Sodium_Core32_Curve25519_Fe * @psalm-suppress MixedAssignment * @psalm-suppress MixedMethodCall */ public static function fe_neg(ParagonIE_Sodium_Core32_Curve25519_Fe $f) { $h = new ParagonIE_Sodium_Core32_Curve25519_Fe(); for ($i = 0; $i < 10; ++$i) { $h[$i] = $h[$i]->subInt32($f[$i]); } return $h; } /** * Square a field element * * h = f * f * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f * @return ParagonIE_Sodium_Core32_Curve25519_Fe * @throws SodiumException * @throws TypeError * @psalm-suppress MixedMethodCall */ public static function fe_sq(ParagonIE_Sodium_Core32_Curve25519_Fe $f) { $f0 = $f[0]->toInt64(); $f1 = $f[1]->toInt64(); $f2 = $f[2]->toInt64(); $f3 = $f[3]->toInt64(); $f4 = $f[4]->toInt64(); $f5 = $f[5]->toInt64(); $f6 = $f[6]->toInt64(); $f7 = $f[7]->toInt64(); $f8 = $f[8]->toInt64(); $f9 = $f[9]->toInt64(); $f0_2 = $f0->shiftLeft(1); $f1_2 = $f1->shiftLeft(1); $f2_2 = $f2->shiftLeft(1); $f3_2 = $f3->shiftLeft(1); $f4_2 = $f4->shiftLeft(1); $f5_2 = $f5->shiftLeft(1); $f6_2 = $f6->shiftLeft(1); $f7_2 = $f7->shiftLeft(1); $f5_38 = $f5->mulInt(38, 6); $f6_19 = $f6->mulInt(19, 5); $f7_38 = $f7->mulInt(38, 6); $f8_19 = $f8->mulInt(19, 5); $f9_38 = $f9->mulInt(38, 6); $f0f0 = $f0->mulInt64($f0, 28); $f0f1_2 = $f0_2->mulInt64($f1, 28); $f0f2_2 = $f0_2->mulInt64($f2, 28); $f0f3_2 = $f0_2->mulInt64($f3, 28); $f0f4_2 = $f0_2->mulInt64($f4, 28); $f0f5_2 = $f0_2->mulInt64($f5, 28); $f0f6_2 = $f0_2->mulInt64($f6, 28); $f0f7_2 = $f0_2->mulInt64($f7, 28); $f0f8_2 = $f0_2->mulInt64($f8, 28); $f0f9_2 = $f0_2->mulInt64($f9, 28); $f1f1_2 = $f1_2->mulInt64($f1, 28); $f1f2_2 = $f1_2->mulInt64($f2, 28); $f1f3_4 = $f1_2->mulInt64($f3_2, 28); $f1f4_2 = $f1_2->mulInt64($f4, 28); $f1f5_4 = $f1_2->mulInt64($f5_2, 30); $f1f6_2 = $f1_2->mulInt64($f6, 28); $f1f7_4 = $f1_2->mulInt64($f7_2, 28); $f1f8_2 = $f1_2->mulInt64($f8, 28); $f1f9_76 = $f9_38->mulInt64($f1_2, 30); $f2f2 = $f2->mulInt64($f2, 28); $f2f3_2 = $f2_2->mulInt64($f3, 28); $f2f4_2 = $f2_2->mulInt64($f4, 28); $f2f5_2 = $f2_2->mulInt64($f5, 28); $f2f6_2 = $f2_2->mulInt64($f6, 28); $f2f7_2 = $f2_2->mulInt64($f7, 28); $f2f8_38 = $f8_19->mulInt64($f2_2, 30); $f2f9_38 = $f9_38->mulInt64($f2, 30); $f3f3_2 = $f3_2->mulInt64($f3, 28); $f3f4_2 = $f3_2->mulInt64($f4, 28); $f3f5_4 = $f3_2->mulInt64($f5_2, 30); $f3f6_2 = $f3_2->mulInt64($f6, 28); $f3f7_76 = $f7_38->mulInt64($f3_2, 30); $f3f8_38 = $f8_19->mulInt64($f3_2, 30); $f3f9_76 = $f9_38->mulInt64($f3_2, 30); $f4f4 = $f4->mulInt64($f4, 28); $f4f5_2 = $f4_2->mulInt64($f5, 28); $f4f6_38 = $f6_19->mulInt64($f4_2, 30); $f4f7_38 = $f7_38->mulInt64($f4, 30); $f4f8_38 = $f8_19->mulInt64($f4_2, 30); $f4f9_38 = $f9_38->mulInt64($f4, 30); $f5f5_38 = $f5_38->mulInt64($f5, 30); $f5f6_38 = $f6_19->mulInt64($f5_2, 30); $f5f7_76 = $f7_38->mulInt64($f5_2, 30); $f5f8_38 = $f8_19->mulInt64($f5_2, 30); $f5f9_76 = $f9_38->mulInt64($f5_2, 30); $f6f6_19 = $f6_19->mulInt64($f6, 30); $f6f7_38 = $f7_38->mulInt64($f6, 30); $f6f8_38 = $f8_19->mulInt64($f6_2, 30); $f6f9_38 = $f9_38->mulInt64($f6, 30); $f7f7_38 = $f7_38->mulInt64($f7, 28); $f7f8_38 = $f8_19->mulInt64($f7_2, 30); $f7f9_76 = $f9_38->mulInt64($f7_2, 30); $f8f8_19 = $f8_19->mulInt64($f8, 30); $f8f9_38 = $f9_38->mulInt64($f8, 30); $f9f9_38 = $f9_38->mulInt64($f9, 28); $h0 = $f0f0->addInt64($f1f9_76)->addInt64($f2f8_38)->addInt64($f3f7_76)->addInt64($f4f6_38)->addInt64($f5f5_38); $h1 = $f0f1_2->addInt64($f2f9_38)->addInt64($f3f8_38)->addInt64($f4f7_38)->addInt64($f5f6_38); $h2 = $f0f2_2->addInt64($f1f1_2)->addInt64($f3f9_76)->addInt64($f4f8_38)->addInt64($f5f7_76)->addInt64($f6f6_19); $h3 = $f0f3_2->addInt64($f1f2_2)->addInt64($f4f9_38)->addInt64($f5f8_38)->addInt64($f6f7_38); $h4 = $f0f4_2->addInt64($f1f3_4)->addInt64($f2f2)->addInt64($f5f9_76)->addInt64($f6f8_38)->addInt64($f7f7_38); $h5 = $f0f5_2->addInt64($f1f4_2)->addInt64($f2f3_2)->addInt64($f6f9_38)->addInt64($f7f8_38); $h6 = $f0f6_2->addInt64($f1f5_4)->addInt64($f2f4_2)->addInt64($f3f3_2)->addInt64($f7f9_76)->addInt64($f8f8_19); $h7 = $f0f7_2->addInt64($f1f6_2)->addInt64($f2f5_2)->addInt64($f3f4_2)->addInt64($f8f9_38); $h8 = $f0f8_2->addInt64($f1f7_4)->addInt64($f2f6_2)->addInt64($f3f5_4)->addInt64($f4f4)->addInt64($f9f9_38); $h9 = $f0f9_2->addInt64($f1f8_2)->addInt64($f2f7_2)->addInt64($f3f6_2)->addInt64($f4f5_2); /** * @var ParagonIE_Sodium_Core32_Int64 $h0 * @var ParagonIE_Sodium_Core32_Int64 $h1 * @var ParagonIE_Sodium_Core32_Int64 $h2 * @var ParagonIE_Sodium_Core32_Int64 $h3 * @var ParagonIE_Sodium_Core32_Int64 $h4 * @var ParagonIE_Sodium_Core32_Int64 $h5 * @var ParagonIE_Sodium_Core32_Int64 $h6 * @var ParagonIE_Sodium_Core32_Int64 $h7 * @var ParagonIE_Sodium_Core32_Int64 $h8 * @var ParagonIE_Sodium_Core32_Int64 $h9 */ $carry0 = $h0->addInt(1 << 25)->shiftRight(26); $h1 = $h1->addInt64($carry0); $h0 = $h0->subInt64($carry0->shiftLeft(26)); $carry4 = $h4->addInt(1 << 25)->shiftRight(26); $h5 = $h5->addInt64($carry4); $h4 = $h4->subInt64($carry4->shiftLeft(26)); $carry1 = $h1->addInt(1 << 24)->shiftRight(25); $h2 = $h2->addInt64($carry1); $h1 = $h1->subInt64($carry1->shiftLeft(25)); $carry5 = $h5->addInt(1 << 24)->shiftRight(25); $h6 = $h6->addInt64($carry5); $h5 = $h5->subInt64($carry5->shiftLeft(25)); $carry2 = $h2->addInt(1 << 25)->shiftRight(26); $h3 = $h3->addInt64($carry2); $h2 = $h2->subInt64($carry2->shiftLeft(26)); $carry6 = $h6->addInt(1 << 25)->shiftRight(26); $h7 = $h7->addInt64($carry6); $h6 = $h6->subInt64($carry6->shiftLeft(26)); $carry3 = $h3->addInt(1 << 24)->shiftRight(25); $h4 = $h4->addInt64($carry3); $h3 = $h3->subInt64($carry3->shiftLeft(25)); $carry7 = $h7->addInt(1 << 24)->shiftRight(25); $h8 = $h8->addInt64($carry7); $h7 = $h7->subInt64($carry7->shiftLeft(25)); $carry4 = $h4->addInt(1 << 25)->shiftRight(26); $h5 = $h5->addInt64($carry4); $h4 = $h4->subInt64($carry4->shiftLeft(26)); $carry8 = $h8->addInt(1 << 25)->shiftRight(26); $h9 = $h9->addInt64($carry8); $h8 = $h8->subInt64($carry8->shiftLeft(26)); $carry9 = $h9->addInt(1 << 24)->shiftRight(25); $h0 = $h0->addInt64($carry9->mulInt(19, 5)); $h9 = $h9->subInt64($carry9->shiftLeft(25)); $carry0 = $h0->addInt(1 << 25)->shiftRight(26); $h1 = $h1->addInt64($carry0); $h0 = $h0->subInt64($carry0->shiftLeft(26)); return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray( array( $h0->toInt32(), $h1->toInt32(), $h2->toInt32(), $h3->toInt32(), $h4->toInt32(), $h5->toInt32(), $h6->toInt32(), $h7->toInt32(), $h8->toInt32(), $h9->toInt32() ) ); } /** * Square and double a field element * * h = 2 * f * f * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f * @return ParagonIE_Sodium_Core32_Curve25519_Fe * @throws SodiumException * @throws TypeError * @psalm-suppress MixedMethodCall */ public static function fe_sq2(ParagonIE_Sodium_Core32_Curve25519_Fe $f) { $f0 = $f[0]->toInt64(); $f1 = $f[1]->toInt64(); $f2 = $f[2]->toInt64(); $f3 = $f[3]->toInt64(); $f4 = $f[4]->toInt64(); $f5 = $f[5]->toInt64(); $f6 = $f[6]->toInt64(); $f7 = $f[7]->toInt64(); $f8 = $f[8]->toInt64(); $f9 = $f[9]->toInt64(); $f0_2 = $f0->shiftLeft(1); $f1_2 = $f1->shiftLeft(1); $f2_2 = $f2->shiftLeft(1); $f3_2 = $f3->shiftLeft(1); $f4_2 = $f4->shiftLeft(1); $f5_2 = $f5->shiftLeft(1); $f6_2 = $f6->shiftLeft(1); $f7_2 = $f7->shiftLeft(1); $f5_38 = $f5->mulInt(38, 6); /* 1.959375*2^30 */ $f6_19 = $f6->mulInt(19, 5); /* 1.959375*2^30 */ $f7_38 = $f7->mulInt(38, 6); /* 1.959375*2^30 */ $f8_19 = $f8->mulInt(19, 5); /* 1.959375*2^30 */ $f9_38 = $f9->mulInt(38, 6); /* 1.959375*2^30 */ $f0f0 = $f0->mulInt64($f0, 28); $f0f1_2 = $f0_2->mulInt64($f1, 28); $f0f2_2 = $f0_2->mulInt64($f2, 28); $f0f3_2 = $f0_2->mulInt64($f3, 28); $f0f4_2 = $f0_2->mulInt64($f4, 28); $f0f5_2 = $f0_2->mulInt64($f5, 28); $f0f6_2 = $f0_2->mulInt64($f6, 28); $f0f7_2 = $f0_2->mulInt64($f7, 28); $f0f8_2 = $f0_2->mulInt64($f8, 28); $f0f9_2 = $f0_2->mulInt64($f9, 28); $f1f1_2 = $f1_2->mulInt64($f1, 28); $f1f2_2 = $f1_2->mulInt64($f2, 28); $f1f3_4 = $f1_2->mulInt64($f3_2, 29); $f1f4_2 = $f1_2->mulInt64($f4, 28); $f1f5_4 = $f1_2->mulInt64($f5_2, 29); $f1f6_2 = $f1_2->mulInt64($f6, 28); $f1f7_4 = $f1_2->mulInt64($f7_2, 29); $f1f8_2 = $f1_2->mulInt64($f8, 28); $f1f9_76 = $f9_38->mulInt64($f1_2, 29); $f2f2 = $f2->mulInt64($f2, 28); $f2f3_2 = $f2_2->mulInt64($f3, 28); $f2f4_2 = $f2_2->mulInt64($f4, 28); $f2f5_2 = $f2_2->mulInt64($f5, 28); $f2f6_2 = $f2_2->mulInt64($f6, 28); $f2f7_2 = $f2_2->mulInt64($f7, 28); $f2f8_38 = $f8_19->mulInt64($f2_2, 29); $f2f9_38 = $f9_38->mulInt64($f2, 29); $f3f3_2 = $f3_2->mulInt64($f3, 28); $f3f4_2 = $f3_2->mulInt64($f4, 28); $f3f5_4 = $f3_2->mulInt64($f5_2, 28); $f3f6_2 = $f3_2->mulInt64($f6, 28); $f3f7_76 = $f7_38->mulInt64($f3_2, 29); $f3f8_38 = $f8_19->mulInt64($f3_2, 29); $f3f9_76 = $f9_38->mulInt64($f3_2, 29); $f4f4 = $f4->mulInt64($f4, 28); $f4f5_2 = $f4_2->mulInt64($f5, 28); $f4f6_38 = $f6_19->mulInt64($f4_2, 29); $f4f7_38 = $f7_38->mulInt64($f4, 29); $f4f8_38 = $f8_19->mulInt64($f4_2, 29); $f4f9_38 = $f9_38->mulInt64($f4, 29); $f5f5_38 = $f5_38->mulInt64($f5, 29); $f5f6_38 = $f6_19->mulInt64($f5_2, 29); $f5f7_76 = $f7_38->mulInt64($f5_2, 29); $f5f8_38 = $f8_19->mulInt64($f5_2, 29); $f5f9_76 = $f9_38->mulInt64($f5_2, 29); $f6f6_19 = $f6_19->mulInt64($f6, 29); $f6f7_38 = $f7_38->mulInt64($f6, 29); $f6f8_38 = $f8_19->mulInt64($f6_2, 29); $f6f9_38 = $f9_38->mulInt64($f6, 29); $f7f7_38 = $f7_38->mulInt64($f7, 29); $f7f8_38 = $f8_19->mulInt64($f7_2, 29); $f7f9_76 = $f9_38->mulInt64($f7_2, 29); $f8f8_19 = $f8_19->mulInt64($f8, 29); $f8f9_38 = $f9_38->mulInt64($f8, 29); $f9f9_38 = $f9_38->mulInt64($f9, 29); $h0 = $f0f0->addInt64($f1f9_76)->addInt64($f2f8_38)->addInt64($f3f7_76)->addInt64($f4f6_38)->addInt64($f5f5_38); $h1 = $f0f1_2->addInt64($f2f9_38)->addInt64($f3f8_38)->addInt64($f4f7_38)->addInt64($f5f6_38); $h2 = $f0f2_2->addInt64($f1f1_2)->addInt64($f3f9_76)->addInt64($f4f8_38)->addInt64($f5f7_76)->addInt64($f6f6_19); $h3 = $f0f3_2->addInt64($f1f2_2)->addInt64($f4f9_38)->addInt64($f5f8_38)->addInt64($f6f7_38); $h4 = $f0f4_2->addInt64($f1f3_4)->addInt64($f2f2)->addInt64($f5f9_76)->addInt64($f6f8_38)->addInt64($f7f7_38); $h5 = $f0f5_2->addInt64($f1f4_2)->addInt64($f2f3_2)->addInt64($f6f9_38)->addInt64($f7f8_38); $h6 = $f0f6_2->addInt64($f1f5_4)->addInt64($f2f4_2)->addInt64($f3f3_2)->addInt64($f7f9_76)->addInt64($f8f8_19); $h7 = $f0f7_2->addInt64($f1f6_2)->addInt64($f2f5_2)->addInt64($f3f4_2)->addInt64($f8f9_38); $h8 = $f0f8_2->addInt64($f1f7_4)->addInt64($f2f6_2)->addInt64($f3f5_4)->addInt64($f4f4)->addInt64($f9f9_38); $h9 = $f0f9_2->addInt64($f1f8_2)->addInt64($f2f7_2)->addInt64($f3f6_2)->addInt64($f4f5_2); /** * @var ParagonIE_Sodium_Core32_Int64 $h0 * @var ParagonIE_Sodium_Core32_Int64 $h1 * @var ParagonIE_Sodium_Core32_Int64 $h2 * @var ParagonIE_Sodium_Core32_Int64 $h3 * @var ParagonIE_Sodium_Core32_Int64 $h4 * @var ParagonIE_Sodium_Core32_Int64 $h5 * @var ParagonIE_Sodium_Core32_Int64 $h6 * @var ParagonIE_Sodium_Core32_Int64 $h7 * @var ParagonIE_Sodium_Core32_Int64 $h8 * @var ParagonIE_Sodium_Core32_Int64 $h9 */ $h0 = $h0->shiftLeft(1); $h1 = $h1->shiftLeft(1); $h2 = $h2->shiftLeft(1); $h3 = $h3->shiftLeft(1); $h4 = $h4->shiftLeft(1); $h5 = $h5->shiftLeft(1); $h6 = $h6->shiftLeft(1); $h7 = $h7->shiftLeft(1); $h8 = $h8->shiftLeft(1); $h9 = $h9->shiftLeft(1); $carry0 = $h0->addInt(1 << 25)->shiftRight(26); $h1 = $h1->addInt64($carry0); $h0 = $h0->subInt64($carry0->shiftLeft(26)); $carry4 = $h4->addInt(1 << 25)->shiftRight(26); $h5 = $h5->addInt64($carry4); $h4 = $h4->subInt64($carry4->shiftLeft(26)); $carry1 = $h1->addInt(1 << 24)->shiftRight(25); $h2 = $h2->addInt64($carry1); $h1 = $h1->subInt64($carry1->shiftLeft(25)); $carry5 = $h5->addInt(1 << 24)->shiftRight(25); $h6 = $h6->addInt64($carry5); $h5 = $h5->subInt64($carry5->shiftLeft(25)); $carry2 = $h2->addInt(1 << 25)->shiftRight(26); $h3 = $h3->addInt64($carry2); $h2 = $h2->subInt64($carry2->shiftLeft(26)); $carry6 = $h6->addInt(1 << 25)->shiftRight(26); $h7 = $h7->addInt64($carry6); $h6 = $h6->subInt64($carry6->shiftLeft(26)); $carry3 = $h3->addInt(1 << 24)->shiftRight(25); $h4 = $h4->addInt64($carry3); $h3 = $h3->subInt64($carry3->shiftLeft(25)); $carry7 = $h7->addInt(1 << 24)->shiftRight(25); $h8 = $h8->addInt64($carry7); $h7 = $h7->subInt64($carry7->shiftLeft(25)); $carry4 = $h4->addInt(1 << 25)->shiftRight(26); $h5 = $h5->addInt64($carry4); $h4 = $h4->subInt64($carry4->shiftLeft(26)); $carry8 = $h8->addInt(1 << 25)->shiftRight(26); $h9 = $h9->addInt64($carry8); $h8 = $h8->subInt64($carry8->shiftLeft(26)); $carry9 = $h9->addInt(1 << 24)->shiftRight(25); $h0 = $h0->addInt64($carry9->mulInt(19, 5)); $h9 = $h9->subInt64($carry9->shiftLeft(25)); $carry0 = $h0->addInt(1 << 25)->shiftRight(26); $h1 = $h1->addInt64($carry0); $h0 = $h0->subInt64($carry0->shiftLeft(26)); return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray( array( $h0->toInt32(), $h1->toInt32(), $h2->toInt32(), $h3->toInt32(), $h4->toInt32(), $h5->toInt32(), $h6->toInt32(), $h7->toInt32(), $h8->toInt32(), $h9->toInt32() ) ); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe $Z * @return ParagonIE_Sodium_Core32_Curve25519_Fe * @throws SodiumException * @throws TypeError */ public static function fe_invert(ParagonIE_Sodium_Core32_Curve25519_Fe $Z) { $z = clone $Z; $t0 = self::fe_sq($z); $t1 = self::fe_sq($t0); $t1 = self::fe_sq($t1); $t1 = self::fe_mul($z, $t1); $t0 = self::fe_mul($t0, $t1); $t2 = self::fe_sq($t0); $t1 = self::fe_mul($t1, $t2); $t2 = self::fe_sq($t1); for ($i = 1; $i < 5; ++$i) { $t2 = self::fe_sq($t2); } $t1 = self::fe_mul($t2, $t1); $t2 = self::fe_sq($t1); for ($i = 1; $i < 10; ++$i) { $t2 = self::fe_sq($t2); } $t2 = self::fe_mul($t2, $t1); $t3 = self::fe_sq($t2); for ($i = 1; $i < 20; ++$i) { $t3 = self::fe_sq($t3); } $t2 = self::fe_mul($t3, $t2); $t2 = self::fe_sq($t2); for ($i = 1; $i < 10; ++$i) { $t2 = self::fe_sq($t2); } $t1 = self::fe_mul($t2, $t1); $t2 = self::fe_sq($t1); for ($i = 1; $i < 50; ++$i) { $t2 = self::fe_sq($t2); } $t2 = self::fe_mul($t2, $t1); $t3 = self::fe_sq($t2); for ($i = 1; $i < 100; ++$i) { $t3 = self::fe_sq($t3); } $t2 = self::fe_mul($t3, $t2); $t2 = self::fe_sq($t2); for ($i = 1; $i < 50; ++$i) { $t2 = self::fe_sq($t2); } $t1 = self::fe_mul($t2, $t1); $t1 = self::fe_sq($t1); for ($i = 1; $i < 5; ++$i) { $t1 = self::fe_sq($t1); } return self::fe_mul($t1, $t0); } /** * @internal You should not use this directly from another application * * @ref https://github.com/jedisct1/libsodium/blob/68564326e1e9dc57ef03746f85734232d20ca6fb/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1054-L1106 * * @param ParagonIE_Sodium_Core32_Curve25519_Fe $z * @return ParagonIE_Sodium_Core32_Curve25519_Fe * @throws SodiumException * @throws TypeError */ public static function fe_pow22523(ParagonIE_Sodium_Core32_Curve25519_Fe $z) { # fe_sq(t0, z); # fe_sq(t1, t0); # fe_sq(t1, t1); # fe_mul(t1, z, t1); # fe_mul(t0, t0, t1); # fe_sq(t0, t0); # fe_mul(t0, t1, t0); # fe_sq(t1, t0); $t0 = self::fe_sq($z); $t1 = self::fe_sq($t0); $t1 = self::fe_sq($t1); $t1 = self::fe_mul($z, $t1); $t0 = self::fe_mul($t0, $t1); $t0 = self::fe_sq($t0); $t0 = self::fe_mul($t1, $t0); $t1 = self::fe_sq($t0); # for (i = 1; i < 5; ++i) { # fe_sq(t1, t1); # } for ($i = 1; $i < 5; ++$i) { $t1 = self::fe_sq($t1); } # fe_mul(t0, t1, t0); # fe_sq(t1, t0); $t0 = self::fe_mul($t1, $t0); $t1 = self::fe_sq($t0); # for (i = 1; i < 10; ++i) { # fe_sq(t1, t1); # } for ($i = 1; $i < 10; ++$i) { $t1 = self::fe_sq($t1); } # fe_mul(t1, t1, t0); # fe_sq(t2, t1); $t1 = self::fe_mul($t1, $t0); $t2 = self::fe_sq($t1); # for (i = 1; i < 20; ++i) { # fe_sq(t2, t2); # } for ($i = 1; $i < 20; ++$i) { $t2 = self::fe_sq($t2); } # fe_mul(t1, t2, t1); # fe_sq(t1, t1); $t1 = self::fe_mul($t2, $t1); $t1 = self::fe_sq($t1); # for (i = 1; i < 10; ++i) { # fe_sq(t1, t1); # } for ($i = 1; $i < 10; ++$i) { $t1 = self::fe_sq($t1); } # fe_mul(t0, t1, t0); # fe_sq(t1, t0); $t0 = self::fe_mul($t1, $t0); $t1 = self::fe_sq($t0); # for (i = 1; i < 50; ++i) { # fe_sq(t1, t1); # } for ($i = 1; $i < 50; ++$i) { $t1 = self::fe_sq($t1); } # fe_mul(t1, t1, t0); # fe_sq(t2, t1); $t1 = self::fe_mul($t1, $t0); $t2 = self::fe_sq($t1); # for (i = 1; i < 100; ++i) { # fe_sq(t2, t2); # } for ($i = 1; $i < 100; ++$i) { $t2 = self::fe_sq($t2); } # fe_mul(t1, t2, t1); # fe_sq(t1, t1); $t1 = self::fe_mul($t2, $t1); $t1 = self::fe_sq($t1); # for (i = 1; i < 50; ++i) { # fe_sq(t1, t1); # } for ($i = 1; $i < 50; ++$i) { $t1 = self::fe_sq($t1); } # fe_mul(t0, t1, t0); # fe_sq(t0, t0); # fe_sq(t0, t0); # fe_mul(out, t0, z); $t0 = self::fe_mul($t1, $t0); $t0 = self::fe_sq($t0); $t0 = self::fe_sq($t0); return self::fe_mul($t0, $z); } /** * Subtract two field elements. * * h = f - g * * Preconditions: * |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. * |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. * * Postconditions: * |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g * @return ParagonIE_Sodium_Core32_Curve25519_Fe * @throws SodiumException * @throws TypeError * @psalm-suppress MixedMethodCall * @psalm-suppress MixedTypeCoercion */ public static function fe_sub(ParagonIE_Sodium_Core32_Curve25519_Fe $f, ParagonIE_Sodium_Core32_Curve25519_Fe $g) { return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray( array( $f[0]->subInt32($g[0]), $f[1]->subInt32($g[1]), $f[2]->subInt32($g[2]), $f[3]->subInt32($g[3]), $f[4]->subInt32($g[4]), $f[5]->subInt32($g[5]), $f[6]->subInt32($g[6]), $f[7]->subInt32($g[7]), $f[8]->subInt32($g[8]), $f[9]->subInt32($g[9]) ) ); } /** * Add two group elements. * * r = p + q * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 * @throws SodiumException * @throws TypeError */ public static function ge_add( ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p, ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q ) { $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1(); $r->X = self::fe_add($p->Y, $p->X); $r->Y = self::fe_sub($p->Y, $p->X); $r->Z = self::fe_mul($r->X, $q->YplusX); $r->Y = self::fe_mul($r->Y, $q->YminusX); $r->T = self::fe_mul($q->T2d, $p->T); $r->X = self::fe_mul($p->Z, $q->Z); $t0 = self::fe_add($r->X, $r->X); $r->X = self::fe_sub($r->Z, $r->Y); $r->Y = self::fe_add($r->Z, $r->Y); $r->Z = self::fe_add($t0, $r->T); $r->T = self::fe_sub($t0, $r->T); return $r; } /** * @internal You should not use this directly from another application * * @ref https://github.com/jedisct1/libsodium/blob/157c4a80c13b117608aeae12178b2d38825f9f8f/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1185-L1215 * @param string $a * @return array<int, mixed> * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArrayOffset */ public static function slide($a) { if (self::strlen($a) < 256) { if (self::strlen($a) < 16) { $a = str_pad($a, 256, '0', STR_PAD_RIGHT); } } /** @var array<int, int> $r */ $r = array(); for ($i = 0; $i < 256; ++$i) { $r[$i] = (int) (1 & ( self::chrToInt($a[$i >> 3]) >> ($i & 7) ) ); } for ($i = 0;$i < 256;++$i) { if ($r[$i]) { for ($b = 1;$b <= 6 && $i + $b < 256;++$b) { if ($r[$i + $b]) { if ($r[$i] + ($r[$i + $b] << $b) <= 15) { $r[$i] += $r[$i + $b] << $b; $r[$i + $b] = 0; } elseif ($r[$i] - ($r[$i + $b] << $b) >= -15) { $r[$i] -= $r[$i + $b] << $b; for ($k = $i + $b; $k < 256; ++$k) { if (!$r[$k]) { $r[$k] = 1; break; } $r[$k] = 0; } } else { break; } } } } } return $r; } /** * @internal You should not use this directly from another application * * @param string $s * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3 * @throws SodiumException * @throws TypeError */ public static function ge_frombytes_negate_vartime($s) { static $d = null; if (!$d) { $d = ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray( array( ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[0]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[1]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[2]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[3]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[4]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[5]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[6]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[7]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[8]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[9]) ) ); } /** @var ParagonIE_Sodium_Core32_Curve25519_Fe $d */ # fe_frombytes(h->Y,s); # fe_1(h->Z); $h = new ParagonIE_Sodium_Core32_Curve25519_Ge_P3( self::fe_0(), self::fe_frombytes($s), self::fe_1() ); # fe_sq(u,h->Y); # fe_mul(v,u,d); # fe_sub(u,u,h->Z); /* u = y^2-1 */ # fe_add(v,v,h->Z); /* v = dy^2+1 */ $u = self::fe_sq($h->Y); /** @var ParagonIE_Sodium_Core32_Curve25519_Fe $d */ $v = self::fe_mul($u, $d); $u = self::fe_sub($u, $h->Z); /* u = y^2 - 1 */ $v = self::fe_add($v, $h->Z); /* v = dy^2 + 1 */ # fe_sq(v3,v); # fe_mul(v3,v3,v); /* v3 = v^3 */ # fe_sq(h->X,v3); # fe_mul(h->X,h->X,v); # fe_mul(h->X,h->X,u); /* x = uv^7 */ $v3 = self::fe_sq($v); $v3 = self::fe_mul($v3, $v); /* v3 = v^3 */ $h->X = self::fe_sq($v3); $h->X = self::fe_mul($h->X, $v); $h->X = self::fe_mul($h->X, $u); /* x = uv^7 */ # fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */ # fe_mul(h->X,h->X,v3); # fe_mul(h->X,h->X,u); /* x = uv^3(uv^7)^((q-5)/8) */ $h->X = self::fe_pow22523($h->X); /* x = (uv^7)^((q-5)/8) */ $h->X = self::fe_mul($h->X, $v3); $h->X = self::fe_mul($h->X, $u); /* x = uv^3(uv^7)^((q-5)/8) */ # fe_sq(vxx,h->X); # fe_mul(vxx,vxx,v); # fe_sub(check,vxx,u); /* vx^2-u */ $vxx = self::fe_sq($h->X); $vxx = self::fe_mul($vxx, $v); $check = self::fe_sub($vxx, $u); /* vx^2 - u */ # if (fe_isnonzero(check)) { # fe_add(check,vxx,u); /* vx^2+u */ # if (fe_isnonzero(check)) { # return -1; # } # fe_mul(h->X,h->X,sqrtm1); # } if (self::fe_isnonzero($check)) { $check = self::fe_add($vxx, $u); /* vx^2 + u */ if (self::fe_isnonzero($check)) { throw new RangeException('Internal check failed.'); } $h->X = self::fe_mul( $h->X, ParagonIE_Sodium_Core32_Curve25519_Fe::fromIntArray(self::$sqrtm1) ); } # if (fe_isnegative(h->X) == (s[31] >> 7)) { # fe_neg(h->X,h->X); # } $i = self::chrToInt($s[31]); if (self::fe_isnegative($h->X) === ($i >> 7)) { $h->X = self::fe_neg($h->X); } # fe_mul(h->T,h->X,h->Y); $h->T = self::fe_mul($h->X, $h->Y); return $h; } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 * @throws SodiumException * @throws TypeError */ public static function ge_madd( ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R, ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p, ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q ) { $r = clone $R; $r->X = self::fe_add($p->Y, $p->X); $r->Y = self::fe_sub($p->Y, $p->X); $r->Z = self::fe_mul($r->X, $q->yplusx); $r->Y = self::fe_mul($r->Y, $q->yminusx); $r->T = self::fe_mul($q->xy2d, $p->T); $t0 = self::fe_add(clone $p->Z, clone $p->Z); $r->X = self::fe_sub($r->Z, $r->Y); $r->Y = self::fe_add($r->Z, $r->Y); $r->Z = self::fe_add($t0, $r->T); $r->T = self::fe_sub($t0, $r->T); return $r; } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 * @throws SodiumException * @throws TypeError */ public static function ge_msub( ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R, ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p, ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q ) { $r = clone $R; $r->X = self::fe_add($p->Y, $p->X); $r->Y = self::fe_sub($p->Y, $p->X); $r->Z = self::fe_mul($r->X, $q->yminusx); $r->Y = self::fe_mul($r->Y, $q->yplusx); $r->T = self::fe_mul($q->xy2d, $p->T); $t0 = self::fe_add($p->Z, $p->Z); $r->X = self::fe_sub($r->Z, $r->Y); $r->Y = self::fe_add($r->Z, $r->Y); $r->Z = self::fe_sub($t0, $r->T); $r->T = self::fe_add($t0, $r->T); return $r; } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2 * @throws SodiumException * @throws TypeError */ public static function ge_p1p1_to_p2(ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p) { $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P2(); $r->X = self::fe_mul($p->X, $p->T); $r->Y = self::fe_mul($p->Y, $p->Z); $r->Z = self::fe_mul($p->Z, $p->T); return $r; } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3 * @throws SodiumException * @throws TypeError */ public static function ge_p1p1_to_p3(ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p) { $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P3(); $r->X = self::fe_mul($p->X, $p->T); $r->Y = self::fe_mul($p->Y, $p->Z); $r->Z = self::fe_mul($p->Z, $p->T); $r->T = self::fe_mul($p->X, $p->Y); return $r; } /** * @internal You should not use this directly from another application * * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2 * @throws SodiumException * @throws TypeError */ public static function ge_p2_0() { return new ParagonIE_Sodium_Core32_Curve25519_Ge_P2( self::fe_0(), self::fe_1(), self::fe_1() ); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $p * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 * @throws SodiumException * @throws TypeError */ public static function ge_p2_dbl(ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $p) { $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1(); $r->X = self::fe_sq($p->X); $r->Z = self::fe_sq($p->Y); $r->T = self::fe_sq2($p->Z); $r->Y = self::fe_add($p->X, $p->Y); $t0 = self::fe_sq($r->Y); $r->Y = self::fe_add($r->Z, $r->X); $r->Z = self::fe_sub($r->Z, $r->X); $r->X = self::fe_sub($t0, $r->Y); $r->T = self::fe_sub($r->T, $r->Z); return $r; } /** * @internal You should not use this directly from another application * * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3 * @throws SodiumException * @throws TypeError */ public static function ge_p3_0() { return new ParagonIE_Sodium_Core32_Curve25519_Ge_P3( self::fe_0(), self::fe_1(), self::fe_1(), self::fe_0() ); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p * @return ParagonIE_Sodium_Core32_Curve25519_Ge_Cached * @throws SodiumException * @throws TypeError */ public static function ge_p3_to_cached(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p) { static $d2 = null; if ($d2 === null) { $d2 = ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray( array( ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[0]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[1]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[2]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[3]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[4]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[5]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[6]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[7]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[8]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[9]) ) ); } /** @var ParagonIE_Sodium_Core32_Curve25519_Fe $d2 */ $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_Cached(); $r->YplusX = self::fe_add($p->Y, $p->X); $r->YminusX = self::fe_sub($p->Y, $p->X); $r->Z = self::fe_copy($p->Z); $r->T2d = self::fe_mul($p->T, $d2); return $r; } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2 */ public static function ge_p3_to_p2(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p) { return new ParagonIE_Sodium_Core32_Curve25519_Ge_P2( $p->X, $p->Y, $p->Z ); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $h * @return string * @throws SodiumException * @throws TypeError */ public static function ge_p3_tobytes(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $h) { $recip = self::fe_invert($h->Z); $x = self::fe_mul($h->X, $recip); $y = self::fe_mul($h->Y, $recip); $s = self::fe_tobytes($y); $s[31] = self::intToChr( self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7) ); return $s; } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 * @throws SodiumException * @throws TypeError */ public static function ge_p3_dbl(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p) { $q = self::ge_p3_to_p2($p); return self::ge_p2_dbl($q); } /** * @return ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp * @throws SodiumException * @throws TypeError */ public static function ge_precomp_0() { return new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp( self::fe_1(), self::fe_1(), self::fe_0() ); } /** * @internal You should not use this directly from another application * * @param int $b * @param int $c * @return int * @psalm-suppress MixedReturnStatement */ public static function equal($b, $c) { $b0 = $b & 0xffff; $b1 = ($b >> 16) & 0xffff; $c0 = $c & 0xffff; $c1 = ($c >> 16) & 0xffff; $d0 = (($b0 ^ $c0) - 1) >> 31; $d1 = (($b1 ^ $c1) - 1) >> 31; return ($d0 & $d1) & 1; } /** * @internal You should not use this directly from another application * * @param string|int $char * @return int (1 = yes, 0 = no) * @throws SodiumException * @throws TypeError */ public static function negative($char) { if (is_int($char)) { return $char < 0 ? 1 : 0; } /** @var string $char */ $x = self::chrToInt(self::substr($char, 0, 1)); return (int) ($x >> 31); } /** * Conditional move * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $t * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $u * @param int $b * @return ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp * @throws SodiumException * @throws TypeError */ public static function cmov( ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $t, ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $u, $b ) { if (!is_int($b)) { throw new InvalidArgumentException('Expected an integer.'); } return new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp( self::fe_cmov($t->yplusx, $u->yplusx, $b), self::fe_cmov($t->yminusx, $u->yminusx, $b), self::fe_cmov($t->xy2d, $u->xy2d, $b) ); } /** * @internal You should not use this directly from another application * * @param int $pos * @param int $b * @return ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayOffset * @psalm-suppress MixedArgument */ public static function ge_select($pos = 0, $b = 0) { static $base = null; if ($base === null) { $base = array(); foreach (self::$base as $i => $bas) { for ($j = 0; $j < 8; ++$j) { $base[$i][$j] = new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp( ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray( array( ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][0]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][1]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][2]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][3]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][4]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][5]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][6]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][7]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][8]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][9]) ) ), ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray( array( ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][0]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][1]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][2]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][3]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][4]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][5]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][6]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][7]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][8]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][9]) ) ), ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray( array( ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][0]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][1]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][2]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][3]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][4]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][5]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][6]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][7]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][8]), ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][9]) ) ) ); } } } if (!is_int($pos)) { throw new InvalidArgumentException('Position must be an integer'); } if ($pos < 0 || $pos > 31) { throw new RangeException('Position is out of range [0, 31]'); } $bnegative = self::negative($b); $babs = $b - (((-$bnegative) & $b) << 1); $t = self::ge_precomp_0(); for ($i = 0; $i < 8; ++$i) { $t = self::cmov( $t, $base[$pos][$i], -self::equal($babs, $i + 1) ); } $minusT = new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp( self::fe_copy($t->yminusx), self::fe_copy($t->yplusx), self::fe_neg($t->xy2d) ); return self::cmov($t, $minusT, -$bnegative); } /** * Subtract two group elements. * * r = p - q * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 * @throws SodiumException * @throws TypeError */ public static function ge_sub( ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p, ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q ) { $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1(); $r->X = self::fe_add($p->Y, $p->X); $r->Y = self::fe_sub($p->Y, $p->X); $r->Z = self::fe_mul($r->X, $q->YminusX); $r->Y = self::fe_mul($r->Y, $q->YplusX); $r->T = self::fe_mul($q->T2d, $p->T); $r->X = self::fe_mul($p->Z, $q->Z); $t0 = self::fe_add($r->X, $r->X); $r->X = self::fe_sub($r->Z, $r->Y); $r->Y = self::fe_add($r->Z, $r->Y); $r->Z = self::fe_sub($t0, $r->T); $r->T = self::fe_add($t0, $r->T); return $r; } /** * Convert a group element to a byte string. * * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $h * @return string * @throws SodiumException * @throws TypeError */ public static function ge_tobytes(ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $h) { $recip = self::fe_invert($h->Z); $x = self::fe_mul($h->X, $recip); $y = self::fe_mul($h->Y, $recip); $s = self::fe_tobytes($y); $s[31] = self::intToChr( self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7) ); return $s; } /** * @internal You should not use this directly from another application * * @param string $a * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A * @param string $b * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2 * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArrayAccess */ public static function ge_double_scalarmult_vartime( $a, ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A, $b ) { /** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Cached> $Ai */ $Ai = array(); static $Bi = array(); /** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp> $Bi */ if (!$Bi) { for ($i = 0; $i < 8; ++$i) { $Bi[$i] = new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp( ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray( array( ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][0]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][1]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][2]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][3]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][4]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][5]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][6]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][7]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][8]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][9]) ) ), ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray( array( ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][0]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][1]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][2]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][3]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][4]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][5]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][6]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][7]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][8]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][9]) ) ), ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray( array( ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][0]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][1]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][2]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][3]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][4]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][5]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][6]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][7]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][8]), ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][9]) ) ) ); } } for ($i = 0; $i < 8; ++$i) { $Ai[$i] = new ParagonIE_Sodium_Core32_Curve25519_Ge_Cached( self::fe_0(), self::fe_0(), self::fe_0(), self::fe_0() ); } /** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Cached> $Ai */ # slide(aslide,a); # slide(bslide,b); /** @var array<int, int> $aslide */ $aslide = self::slide($a); /** @var array<int, int> $bslide */ $bslide = self::slide($b); # ge_p3_to_cached(&Ai[0],A); # ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t); $Ai[0] = self::ge_p3_to_cached($A); $t = self::ge_p3_dbl($A); $A2 = self::ge_p1p1_to_p3($t); # ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[1],&u); # ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[2],&u); # ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[3],&u); # ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[4],&u); # ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[5],&u); # ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[6],&u); # ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[7],&u); for ($i = 0; $i < 7; ++$i) { $t = self::ge_add($A2, $Ai[$i]); $u = self::ge_p1p1_to_p3($t); $Ai[$i + 1] = self::ge_p3_to_cached($u); } # ge_p2_0(r); $r = self::ge_p2_0(); # for (i = 255;i >= 0;--i) { # if (aslide[i] || bslide[i]) break; # } $i = 255; for (; $i >= 0; --$i) { if ($aslide[$i] || $bslide[$i]) { break; } } # for (;i >= 0;--i) { for (; $i >= 0; --$i) { # ge_p2_dbl(&t,r); $t = self::ge_p2_dbl($r); # if (aslide[i] > 0) { if ($aslide[$i] > 0) { # ge_p1p1_to_p3(&u,&t); # ge_add(&t,&u,&Ai[aslide[i]/2]); $u = self::ge_p1p1_to_p3($t); $t = self::ge_add( $u, $Ai[(int) floor($aslide[$i] / 2)] ); # } else if (aslide[i] < 0) { } elseif ($aslide[$i] < 0) { # ge_p1p1_to_p3(&u,&t); # ge_sub(&t,&u,&Ai[(-aslide[i])/2]); $u = self::ge_p1p1_to_p3($t); $t = self::ge_sub( $u, $Ai[(int) floor(-$aslide[$i] / 2)] ); } /** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp> $Bi */ # if (bslide[i] > 0) { if ($bslide[$i] > 0) { # ge_p1p1_to_p3(&u,&t); # ge_madd(&t,&u,&Bi[bslide[i]/2]); $u = self::ge_p1p1_to_p3($t); /** @var int $index */ $index = (int) floor($bslide[$i] / 2); /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $thisB */ $thisB = $Bi[$index]; $t = self::ge_madd($t, $u, $thisB); # } else if (bslide[i] < 0) { } elseif ($bslide[$i] < 0) { # ge_p1p1_to_p3(&u,&t); # ge_msub(&t,&u,&Bi[(-bslide[i])/2]); $u = self::ge_p1p1_to_p3($t); /** @var int $index */ $index = (int) floor(-$bslide[$i] / 2); /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $thisB */ $thisB = $Bi[$index]; $t = self::ge_msub($t, $u, $thisB); } # ge_p1p1_to_p2(r,&t); $r = self::ge_p1p1_to_p2($t); } return $r; } /** * @internal You should not use this directly from another application * * @param string $a * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3 * @psalm-suppress MixedAssignment * @psalm-suppress MixedOperand * @throws SodiumException * @throws TypeError */ public static function ge_scalarmult_base($a) { /** @var array<int, int> $e */ $e = array(); $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1(); for ($i = 0; $i < 32; ++$i) { /** @var int $dbl */ $dbl = (int) $i << 1; $e[$dbl] = (int) self::chrToInt($a[$i]) & 15; $e[$dbl + 1] = (int) (self::chrToInt($a[$i]) >> 4) & 15; } /** @var int $carry */ $carry = 0; for ($i = 0; $i < 63; ++$i) { $e[$i] += $carry; $carry = $e[$i] + 8; $carry >>= 4; $e[$i] -= $carry << 4; } /** @var array<int, int> $e */ $e[63] += (int) $carry; $h = self::ge_p3_0(); for ($i = 1; $i < 64; $i += 2) { $t = self::ge_select((int) floor($i / 2), (int) $e[$i]); $r = self::ge_madd($r, $h, $t); $h = self::ge_p1p1_to_p3($r); } $r = self::ge_p3_dbl($h); $s = self::ge_p1p1_to_p2($r); $r = self::ge_p2_dbl($s); $s = self::ge_p1p1_to_p2($r); $r = self::ge_p2_dbl($s); $s = self::ge_p1p1_to_p2($r); $r = self::ge_p2_dbl($s); $h = self::ge_p1p1_to_p3($r); for ($i = 0; $i < 64; $i += 2) { $t = self::ge_select($i >> 1, (int) $e[$i]); $r = self::ge_madd($r, $h, $t); $h = self::ge_p1p1_to_p3($r); } return $h; } /** * Calculates (ab + c) mod l * where l = 2^252 + 27742317777372353535851937790883648493 * * @internal You should not use this directly from another application * * @param string $a * @param string $b * @param string $c * @return string * @throws SodiumException * @throws TypeError */ public static function sc_muladd($a, $b, $c) { $a0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($a, 0, 3))); $a1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 2, 4)) >> 5)); $a2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($a, 5, 3)) >> 2)); $a3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 7, 4)) >> 7)); $a4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 10, 4)) >> 4)); $a5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($a, 13, 3)) >> 1)); $a6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 15, 4)) >> 6)); $a7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($a, 18, 3)) >> 3)); $a8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($a, 21, 3))); $a9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($a, 23, 4)) >> 5)); $a10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($a, 26, 3)) >> 2)); $a11 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff & (self::load_4(self::substr($a, 28, 4)) >> 7)); $b0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($b, 0, 3))); $b1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 2, 4)) >> 5)); $b2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($b, 5, 3)) >> 2)); $b3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 7, 4)) >> 7)); $b4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 10, 4)) >> 4)); $b5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($b, 13, 3)) >> 1)); $b6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 15, 4)) >> 6)); $b7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($b, 18, 3)) >> 3)); $b8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($b, 21, 3))); $b9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($b, 23, 4)) >> 5)); $b10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($b, 26, 3)) >> 2)); $b11 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff & (self::load_4(self::substr($b, 28, 4)) >> 7)); $c0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($c, 0, 3))); $c1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 2, 4)) >> 5)); $c2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($c, 5, 3)) >> 2)); $c3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 7, 4)) >> 7)); $c4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 10, 4)) >> 4)); $c5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($c, 13, 3)) >> 1)); $c6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 15, 4)) >> 6)); $c7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($c, 18, 3)) >> 3)); $c8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($c, 21, 3))); $c9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($c, 23, 4)) >> 5)); $c10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($c, 26, 3)) >> 2)); $c11 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff & (self::load_4(self::substr($c, 28, 4)) >> 7)); /* Can't really avoid the pyramid here: */ /** * @var ParagonIE_Sodium_Core32_Int64 $s0 * @var ParagonIE_Sodium_Core32_Int64 $s1 * @var ParagonIE_Sodium_Core32_Int64 $s2 * @var ParagonIE_Sodium_Core32_Int64 $s3 * @var ParagonIE_Sodium_Core32_Int64 $s4 * @var ParagonIE_Sodium_Core32_Int64 $s5 * @var ParagonIE_Sodium_Core32_Int64 $s6 * @var ParagonIE_Sodium_Core32_Int64 $s7 * @var ParagonIE_Sodium_Core32_Int64 $s8 * @var ParagonIE_Sodium_Core32_Int64 $s9 * @var ParagonIE_Sodium_Core32_Int64 $s10 * @var ParagonIE_Sodium_Core32_Int64 $s11 * @var ParagonIE_Sodium_Core32_Int64 $s12 * @var ParagonIE_Sodium_Core32_Int64 $s13 * @var ParagonIE_Sodium_Core32_Int64 $s14 * @var ParagonIE_Sodium_Core32_Int64 $s15 * @var ParagonIE_Sodium_Core32_Int64 $s16 * @var ParagonIE_Sodium_Core32_Int64 $s17 * @var ParagonIE_Sodium_Core32_Int64 $s18 * @var ParagonIE_Sodium_Core32_Int64 $s19 * @var ParagonIE_Sodium_Core32_Int64 $s20 * @var ParagonIE_Sodium_Core32_Int64 $s21 * @var ParagonIE_Sodium_Core32_Int64 $s22 * @var ParagonIE_Sodium_Core32_Int64 $s23 */ $s0 = $c0->addInt64($a0->mulInt64($b0, 24)); $s1 = $c1->addInt64($a0->mulInt64($b1, 24))->addInt64($a1->mulInt64($b0, 24)); $s2 = $c2->addInt64($a0->mulInt64($b2, 24))->addInt64($a1->mulInt64($b1, 24))->addInt64($a2->mulInt64($b0, 24)); $s3 = $c3->addInt64($a0->mulInt64($b3, 24))->addInt64($a1->mulInt64($b2, 24))->addInt64($a2->mulInt64($b1, 24)) ->addInt64($a3->mulInt64($b0, 24)); $s4 = $c4->addInt64($a0->mulInt64($b4, 24))->addInt64($a1->mulInt64($b3, 24))->addInt64($a2->mulInt64($b2, 24)) ->addInt64($a3->mulInt64($b1, 24))->addInt64($a4->mulInt64($b0, 24)); $s5 = $c5->addInt64($a0->mulInt64($b5, 24))->addInt64($a1->mulInt64($b4, 24))->addInt64($a2->mulInt64($b3, 24)) ->addInt64($a3->mulInt64($b2, 24))->addInt64($a4->mulInt64($b1, 24))->addInt64($a5->mulInt64($b0, 24)); $s6 = $c6->addInt64($a0->mulInt64($b6, 24))->addInt64($a1->mulInt64($b5, 24))->addInt64($a2->mulInt64($b4, 24)) ->addInt64($a3->mulInt64($b3, 24))->addInt64($a4->mulInt64($b2, 24))->addInt64($a5->mulInt64($b1, 24)) ->addInt64($a6->mulInt64($b0, 24)); $s7 = $c7->addInt64($a0->mulInt64($b7, 24))->addInt64($a1->mulInt64($b6, 24))->addInt64($a2->mulInt64($b5, 24)) ->addInt64($a3->mulInt64($b4, 24))->addInt64($a4->mulInt64($b3, 24))->addInt64($a5->mulInt64($b2, 24)) ->addInt64($a6->mulInt64($b1, 24))->addInt64($a7->mulInt64($b0, 24)); $s8 = $c8->addInt64($a0->mulInt64($b8, 24))->addInt64($a1->mulInt64($b7, 24))->addInt64($a2->mulInt64($b6, 24)) ->addInt64($a3->mulInt64($b5, 24))->addInt64($a4->mulInt64($b4, 24))->addInt64($a5->mulInt64($b3, 24)) ->addInt64($a6->mulInt64($b2, 24))->addInt64($a7->mulInt64($b1, 24))->addInt64($a8->mulInt64($b0, 24)); $s9 = $c9->addInt64($a0->mulInt64($b9, 24))->addInt64($a1->mulInt64($b8, 24))->addInt64($a2->mulInt64($b7, 24)) ->addInt64($a3->mulInt64($b6, 24))->addInt64($a4->mulInt64($b5, 24))->addInt64($a5->mulInt64($b4, 24)) ->addInt64($a6->mulInt64($b3, 24))->addInt64($a7->mulInt64($b2, 24))->addInt64($a8->mulInt64($b1, 24)) ->addInt64($a9->mulInt64($b0, 24)); $s10 = $c10->addInt64($a0->mulInt64($b10, 24))->addInt64($a1->mulInt64($b9, 24))->addInt64($a2->mulInt64($b8, 24)) ->addInt64($a3->mulInt64($b7, 24))->addInt64($a4->mulInt64($b6, 24))->addInt64($a5->mulInt64($b5, 24)) ->addInt64($a6->mulInt64($b4, 24))->addInt64($a7->mulInt64($b3, 24))->addInt64($a8->mulInt64($b2, 24)) ->addInt64($a9->mulInt64($b1, 24))->addInt64($a10->mulInt64($b0, 24)); $s11 = $c11->addInt64($a0->mulInt64($b11, 24))->addInt64($a1->mulInt64($b10, 24))->addInt64($a2->mulInt64($b9, 24)) ->addInt64($a3->mulInt64($b8, 24))->addInt64($a4->mulInt64($b7, 24))->addInt64($a5->mulInt64($b6, 24)) ->addInt64($a6->mulInt64($b5, 24))->addInt64($a7->mulInt64($b4, 24))->addInt64($a8->mulInt64($b3, 24)) ->addInt64($a9->mulInt64($b2, 24))->addInt64($a10->mulInt64($b1, 24))->addInt64($a11->mulInt64($b0, 24)); $s12 = $a1->mulInt64($b11, 24)->addInt64($a2->mulInt64($b10, 24))->addInt64($a3->mulInt64($b9, 24)) ->addInt64($a4->mulInt64($b8, 24))->addInt64($a5->mulInt64($b7, 24))->addInt64($a6->mulInt64($b6, 24)) ->addInt64($a7->mulInt64($b5, 24))->addInt64($a8->mulInt64($b4, 24))->addInt64($a9->mulInt64($b3, 24)) ->addInt64($a10->mulInt64($b2, 24))->addInt64($a11->mulInt64($b1, 24)); $s13 = $a2->mulInt64($b11, 24)->addInt64($a3->mulInt64($b10, 24))->addInt64($a4->mulInt64($b9, 24)) ->addInt64($a5->mulInt64($b8, 24))->addInt64($a6->mulInt64($b7, 24))->addInt64($a7->mulInt64($b6, 24)) ->addInt64($a8->mulInt64($b5, 24))->addInt64($a9->mulInt64($b4, 24))->addInt64($a10->mulInt64($b3, 24)) ->addInt64($a11->mulInt64($b2, 24)); $s14 = $a3->mulInt64($b11, 24)->addInt64($a4->mulInt64($b10, 24))->addInt64($a5->mulInt64($b9, 24)) ->addInt64($a6->mulInt64($b8, 24))->addInt64($a7->mulInt64($b7, 24))->addInt64($a8->mulInt64($b6, 24)) ->addInt64($a9->mulInt64($b5, 24))->addInt64($a10->mulInt64($b4, 24))->addInt64($a11->mulInt64($b3, 24)); $s15 = $a4->mulInt64($b11, 24)->addInt64($a5->mulInt64($b10, 24))->addInt64($a6->mulInt64($b9, 24)) ->addInt64($a7->mulInt64($b8, 24))->addInt64($a8->mulInt64($b7, 24))->addInt64($a9->mulInt64($b6, 24)) ->addInt64($a10->mulInt64($b5, 24))->addInt64($a11->mulInt64($b4, 24)); $s16 = $a5->mulInt64($b11, 24)->addInt64($a6->mulInt64($b10, 24))->addInt64($a7->mulInt64($b9, 24)) ->addInt64($a8->mulInt64($b8, 24))->addInt64($a9->mulInt64($b7, 24))->addInt64($a10->mulInt64($b6, 24)) ->addInt64($a11->mulInt64($b5, 24)); $s17 = $a6->mulInt64($b11, 24)->addInt64($a7->mulInt64($b10, 24))->addInt64($a8->mulInt64($b9, 24)) ->addInt64($a9->mulInt64($b8, 24))->addInt64($a10->mulInt64($b7, 24))->addInt64($a11->mulInt64($b6, 24)); $s18 = $a7->mulInt64($b11, 24)->addInt64($a8->mulInt64($b10, 24))->addInt64($a9->mulInt64($b9, 24)) ->addInt64($a10->mulInt64($b8, 24))->addInt64($a11->mulInt64($b7, 24)); $s19 = $a8->mulInt64($b11, 24)->addInt64($a9->mulInt64($b10, 24))->addInt64($a10->mulInt64($b9, 24)) ->addInt64($a11->mulInt64($b8, 24)); $s20 = $a9->mulInt64($b11, 24)->addInt64($a10->mulInt64($b10, 24))->addInt64($a11->mulInt64($b9, 24)); $s21 = $a10->mulInt64($b11, 24)->addInt64($a11->mulInt64($b10, 24)); $s22 = $a11->mulInt64($b11, 24); $s23 = new ParagonIE_Sodium_Core32_Int64(); $carry0 = $s0->addInt(1 << 20)->shiftRight(21); $s1 = $s1->addInt64($carry0); $s0 = $s0->subInt64($carry0->shiftLeft(21)); $carry2 = $s2->addInt(1 << 20)->shiftRight(21); $s3 = $s3->addInt64($carry2); $s2 = $s2->subInt64($carry2->shiftLeft(21)); $carry4 = $s4->addInt(1 << 20)->shiftRight(21); $s5 = $s5->addInt64($carry4); $s4 = $s4->subInt64($carry4->shiftLeft(21)); $carry6 = $s6->addInt(1 << 20)->shiftRight(21); $s7 = $s7->addInt64($carry6); $s6 = $s6->subInt64($carry6->shiftLeft(21)); $carry8 = $s8->addInt(1 << 20)->shiftRight(21); $s9 = $s9->addInt64($carry8); $s8 = $s8->subInt64($carry8->shiftLeft(21)); $carry10 = $s10->addInt(1 << 20)->shiftRight(21); $s11 = $s11->addInt64($carry10); $s10 = $s10->subInt64($carry10->shiftLeft(21)); $carry12 = $s12->addInt(1 << 20)->shiftRight(21); $s13 = $s13->addInt64($carry12); $s12 = $s12->subInt64($carry12->shiftLeft(21)); $carry14 = $s14->addInt(1 << 20)->shiftRight(21); $s15 = $s15->addInt64($carry14); $s14 = $s14->subInt64($carry14->shiftLeft(21)); $carry16 = $s16->addInt(1 << 20)->shiftRight(21); $s17 = $s17->addInt64($carry16); $s16 = $s16->subInt64($carry16->shiftLeft(21)); $carry18 = $s18->addInt(1 << 20)->shiftRight(21); $s19 = $s19->addInt64($carry18); $s18 = $s18->subInt64($carry18->shiftLeft(21)); $carry20 = $s20->addInt(1 << 20)->shiftRight(21); $s21 = $s21->addInt64($carry20); $s20 = $s20->subInt64($carry20->shiftLeft(21)); $carry22 = $s22->addInt(1 << 20)->shiftRight(21); $s23 = $s23->addInt64($carry22); $s22 = $s22->subInt64($carry22->shiftLeft(21)); $carry1 = $s1->addInt(1 << 20)->shiftRight(21); $s2 = $s2->addInt64($carry1); $s1 = $s1->subInt64($carry1->shiftLeft(21)); $carry3 = $s3->addInt(1 << 20)->shiftRight(21); $s4 = $s4->addInt64($carry3); $s3 = $s3->subInt64($carry3->shiftLeft(21)); $carry5 = $s5->addInt(1 << 20)->shiftRight(21); $s6 = $s6->addInt64($carry5); $s5 = $s5->subInt64($carry5->shiftLeft(21)); $carry7 = $s7->addInt(1 << 20)->shiftRight(21); $s8 = $s8->addInt64($carry7); $s7 = $s7->subInt64($carry7->shiftLeft(21)); $carry9 = $s9->addInt(1 << 20)->shiftRight(21); $s10 = $s10->addInt64($carry9); $s9 = $s9->subInt64($carry9->shiftLeft(21)); $carry11 = $s11->addInt(1 << 20)->shiftRight(21); $s12 = $s12->addInt64($carry11); $s11 = $s11->subInt64($carry11->shiftLeft(21)); $carry13 = $s13->addInt(1 << 20)->shiftRight(21); $s14 = $s14->addInt64($carry13); $s13 = $s13->subInt64($carry13->shiftLeft(21)); $carry15 = $s15->addInt(1 << 20)->shiftRight(21); $s16 = $s16->addInt64($carry15); $s15 = $s15->subInt64($carry15->shiftLeft(21)); $carry17 = $s17->addInt(1 << 20)->shiftRight(21); $s18 = $s18->addInt64($carry17); $s17 = $s17->subInt64($carry17->shiftLeft(21)); $carry19 = $s19->addInt(1 << 20)->shiftRight(21); $s20 = $s20->addInt64($carry19); $s19 = $s19->subInt64($carry19->shiftLeft(21)); $carry21 = $s21->addInt(1 << 20)->shiftRight(21); $s22 = $s22->addInt64($carry21); $s21 = $s21->subInt64($carry21->shiftLeft(21)); $s11 = $s11->addInt64($s23->mulInt(666643, 20)); $s12 = $s12->addInt64($s23->mulInt(470296, 19)); $s13 = $s13->addInt64($s23->mulInt(654183, 20)); $s14 = $s14->subInt64($s23->mulInt(997805, 20)); $s15 = $s15->addInt64($s23->mulInt(136657, 18)); $s16 = $s16->subInt64($s23->mulInt(683901, 20)); $s10 = $s10->addInt64($s22->mulInt(666643, 20)); $s11 = $s11->addInt64($s22->mulInt(470296, 19)); $s12 = $s12->addInt64($s22->mulInt(654183, 20)); $s13 = $s13->subInt64($s22->mulInt(997805, 20)); $s14 = $s14->addInt64($s22->mulInt(136657, 18)); $s15 = $s15->subInt64($s22->mulInt(683901, 20)); $s9 = $s9->addInt64($s21->mulInt(666643, 20)); $s10 = $s10->addInt64($s21->mulInt(470296, 19)); $s11 = $s11->addInt64($s21->mulInt(654183, 20)); $s12 = $s12->subInt64($s21->mulInt(997805, 20)); $s13 = $s13->addInt64($s21->mulInt(136657, 18)); $s14 = $s14->subInt64($s21->mulInt(683901, 20)); $s8 = $s8->addInt64($s20->mulInt(666643, 20)); $s9 = $s9->addInt64($s20->mulInt(470296, 19)); $s10 = $s10->addInt64($s20->mulInt(654183, 20)); $s11 = $s11->subInt64($s20->mulInt(997805, 20)); $s12 = $s12->addInt64($s20->mulInt(136657, 18)); $s13 = $s13->subInt64($s20->mulInt(683901, 20)); $s7 = $s7->addInt64($s19->mulInt(666643, 20)); $s8 = $s8->addInt64($s19->mulInt(470296, 19)); $s9 = $s9->addInt64($s19->mulInt(654183, 20)); $s10 = $s10->subInt64($s19->mulInt(997805, 20)); $s11 = $s11->addInt64($s19->mulInt(136657, 18)); $s12 = $s12->subInt64($s19->mulInt(683901, 20)); $s6 = $s6->addInt64($s18->mulInt(666643, 20)); $s7 = $s7->addInt64($s18->mulInt(470296, 19)); $s8 = $s8->addInt64($s18->mulInt(654183, 20)); $s9 = $s9->subInt64($s18->mulInt(997805, 20)); $s10 = $s10->addInt64($s18->mulInt(136657, 18)); $s11 = $s11->subInt64($s18->mulInt(683901, 20)); $carry6 = $s6->addInt(1 << 20)->shiftRight(21); $s7 = $s7->addInt64($carry6); $s6 = $s6->subInt64($carry6->shiftLeft(21)); $carry8 = $s8->addInt(1 << 20)->shiftRight(21); $s9 = $s9->addInt64($carry8); $s8 = $s8->subInt64($carry8->shiftLeft(21)); $carry10 = $s10->addInt(1 << 20)->shiftRight(21); $s11 = $s11->addInt64($carry10); $s10 = $s10->subInt64($carry10->shiftLeft(21)); $carry12 = $s12->addInt(1 << 20)->shiftRight(21); $s13 = $s13->addInt64($carry12); $s12 = $s12->subInt64($carry12->shiftLeft(21)); $carry14 = $s14->addInt(1 << 20)->shiftRight(21); $s15 = $s15->addInt64($carry14); $s14 = $s14->subInt64($carry14->shiftLeft(21)); $carry16 = $s16->addInt(1 << 20)->shiftRight(21); $s17 = $s17->addInt64($carry16); $s16 = $s16->subInt64($carry16->shiftLeft(21)); $carry7 = $s7->addInt(1 << 20)->shiftRight(21); $s8 = $s8->addInt64($carry7); $s7 = $s7->subInt64($carry7->shiftLeft(21)); $carry9 = $s9->addInt(1 << 20)->shiftRight(21); $s10 = $s10->addInt64($carry9); $s9 = $s9->subInt64($carry9->shiftLeft(21)); $carry11 = $s11->addInt(1 << 20)->shiftRight(21); $s12 = $s12->addInt64($carry11); $s11 = $s11->subInt64($carry11->shiftLeft(21)); $carry13 = $s13->addInt(1 << 20)->shiftRight(21); $s14 = $s14->addInt64($carry13); $s13 = $s13->subInt64($carry13->shiftLeft(21)); $carry15 = $s15->addInt(1 << 20)->shiftRight(21); $s16 = $s16->addInt64($carry15); $s15 = $s15->subInt64($carry15->shiftLeft(21)); $s5 = $s5->addInt64($s17->mulInt(666643, 20)); $s6 = $s6->addInt64($s17->mulInt(470296, 19)); $s7 = $s7->addInt64($s17->mulInt(654183, 20)); $s8 = $s8->subInt64($s17->mulInt(997805, 20)); $s9 = $s9->addInt64($s17->mulInt(136657, 18)); $s10 = $s10->subInt64($s17->mulInt(683901, 20)); $s4 = $s4->addInt64($s16->mulInt(666643, 20)); $s5 = $s5->addInt64($s16->mulInt(470296, 19)); $s6 = $s6->addInt64($s16->mulInt(654183, 20)); $s7 = $s7->subInt64($s16->mulInt(997805, 20)); $s8 = $s8->addInt64($s16->mulInt(136657, 18)); $s9 = $s9->subInt64($s16->mulInt(683901, 20)); $s3 = $s3->addInt64($s15->mulInt(666643, 20)); $s4 = $s4->addInt64($s15->mulInt(470296, 19)); $s5 = $s5->addInt64($s15->mulInt(654183, 20)); $s6 = $s6->subInt64($s15->mulInt(997805, 20)); $s7 = $s7->addInt64($s15->mulInt(136657, 18)); $s8 = $s8->subInt64($s15->mulInt(683901, 20)); $s2 = $s2->addInt64($s14->mulInt(666643, 20)); $s3 = $s3->addInt64($s14->mulInt(470296, 19)); $s4 = $s4->addInt64($s14->mulInt(654183, 20)); $s5 = $s5->subInt64($s14->mulInt(997805, 20)); $s6 = $s6->addInt64($s14->mulInt(136657, 18)); $s7 = $s7->subInt64($s14->mulInt(683901, 20)); $s1 = $s1->addInt64($s13->mulInt(666643, 20)); $s2 = $s2->addInt64($s13->mulInt(470296, 19)); $s3 = $s3->addInt64($s13->mulInt(654183, 20)); $s4 = $s4->subInt64($s13->mulInt(997805, 20)); $s5 = $s5->addInt64($s13->mulInt(136657, 18)); $s6 = $s6->subInt64($s13->mulInt(683901, 20)); $s0 = $s0->addInt64($s12->mulInt(666643, 20)); $s1 = $s1->addInt64($s12->mulInt(470296, 19)); $s2 = $s2->addInt64($s12->mulInt(654183, 20)); $s3 = $s3->subInt64($s12->mulInt(997805, 20)); $s4 = $s4->addInt64($s12->mulInt(136657, 18)); $s5 = $s5->subInt64($s12->mulInt(683901, 20)); $s12 = new ParagonIE_Sodium_Core32_Int64(); $carry0 = $s0->addInt(1 << 20)->shiftRight(21); $s1 = $s1->addInt64($carry0); $s0 = $s0->subInt64($carry0->shiftLeft(21)); $carry2 = $s2->addInt(1 << 20)->shiftRight(21); $s3 = $s3->addInt64($carry2); $s2 = $s2->subInt64($carry2->shiftLeft(21)); $carry4 = $s4->addInt(1 << 20)->shiftRight(21); $s5 = $s5->addInt64($carry4); $s4 = $s4->subInt64($carry4->shiftLeft(21)); $carry6 = $s6->addInt(1 << 20)->shiftRight(21); $s7 = $s7->addInt64($carry6); $s6 = $s6->subInt64($carry6->shiftLeft(21)); $carry8 = $s8->addInt(1 << 20)->shiftRight(21); $s9 = $s9->addInt64($carry8); $s8 = $s8->subInt64($carry8->shiftLeft(21)); $carry10 = $s10->addInt(1 << 20)->shiftRight(21); $s11 = $s11->addInt64($carry10); $s10 = $s10->subInt64($carry10->shiftLeft(21)); $carry1 = $s1->addInt(1 << 20)->shiftRight(21); $s2 = $s2->addInt64($carry1); $s1 = $s1->subInt64($carry1->shiftLeft(21)); $carry3 = $s3->addInt(1 << 20)->shiftRight(21); $s4 = $s4->addInt64($carry3); $s3 = $s3->subInt64($carry3->shiftLeft(21)); $carry5 = $s5->addInt(1 << 20)->shiftRight(21); $s6 = $s6->addInt64($carry5); $s5 = $s5->subInt64($carry5->shiftLeft(21)); $carry7 = $s7->addInt(1 << 20)->shiftRight(21); $s8 = $s8->addInt64($carry7); $s7 = $s7->subInt64($carry7->shiftLeft(21)); $carry9 = $s9->addInt(1 << 20)->shiftRight(21); $s10 = $s10->addInt64($carry9); $s9 = $s9->subInt64($carry9->shiftLeft(21)); $carry11 = $s11->addInt(1 << 20)->shiftRight(21); $s12 = $s12->addInt64($carry11); $s11 = $s11->subInt64($carry11->shiftLeft(21)); $s0 = $s0->addInt64($s12->mulInt(666643, 20)); $s1 = $s1->addInt64($s12->mulInt(470296, 19)); $s2 = $s2->addInt64($s12->mulInt(654183, 20)); $s3 = $s3->subInt64($s12->mulInt(997805, 20)); $s4 = $s4->addInt64($s12->mulInt(136657, 18)); $s5 = $s5->subInt64($s12->mulInt(683901, 20)); $s12 = new ParagonIE_Sodium_Core32_Int64(); $carry0 = $s0->shiftRight(21); $s1 = $s1->addInt64($carry0); $s0 = $s0->subInt64($carry0->shiftLeft(21)); $carry1 = $s1->shiftRight(21); $s2 = $s2->addInt64($carry1); $s1 = $s1->subInt64($carry1->shiftLeft(21)); $carry2 = $s2->shiftRight(21); $s3 = $s3->addInt64($carry2); $s2 = $s2->subInt64($carry2->shiftLeft(21)); $carry3 = $s3->shiftRight(21); $s4 = $s4->addInt64($carry3); $s3 = $s3->subInt64($carry3->shiftLeft(21)); $carry4 = $s4->shiftRight(21); $s5 = $s5->addInt64($carry4); $s4 = $s4->subInt64($carry4->shiftLeft(21)); $carry5 = $s5->shiftRight(21); $s6 = $s6->addInt64($carry5); $s5 = $s5->subInt64($carry5->shiftLeft(21)); $carry6 = $s6->shiftRight(21); $s7 = $s7->addInt64($carry6); $s6 = $s6->subInt64($carry6->shiftLeft(21)); $carry7 = $s7->shiftRight(21); $s8 = $s8->addInt64($carry7); $s7 = $s7->subInt64($carry7->shiftLeft(21)); $carry8 = $s8->shiftRight(21); $s9 = $s9->addInt64($carry8); $s8 = $s8->subInt64($carry8->shiftLeft(21)); $carry9 = $s9->shiftRight(21); $s10 = $s10->addInt64($carry9); $s9 = $s9->subInt64($carry9->shiftLeft(21)); $carry10 = $s10->shiftRight(21); $s11 = $s11->addInt64($carry10); $s10 = $s10->subInt64($carry10->shiftLeft(21)); $carry11 = $s11->shiftRight(21); $s12 = $s12->addInt64($carry11); $s11 = $s11->subInt64($carry11->shiftLeft(21)); $s0 = $s0->addInt64($s12->mulInt(666643, 20)); $s1 = $s1->addInt64($s12->mulInt(470296, 19)); $s2 = $s2->addInt64($s12->mulInt(654183, 20)); $s3 = $s3->subInt64($s12->mulInt(997805, 20)); $s4 = $s4->addInt64($s12->mulInt(136657, 18)); $s5 = $s5->subInt64($s12->mulInt(683901, 20)); $carry0 = $s0->shiftRight(21); $s1 = $s1->addInt64($carry0); $s0 = $s0->subInt64($carry0->shiftLeft(21)); $carry1 = $s1->shiftRight(21); $s2 = $s2->addInt64($carry1); $s1 = $s1->subInt64($carry1->shiftLeft(21)); $carry2 = $s2->shiftRight(21); $s3 = $s3->addInt64($carry2); $s2 = $s2->subInt64($carry2->shiftLeft(21)); $carry3 = $s3->shiftRight(21); $s4 = $s4->addInt64($carry3); $s3 = $s3->subInt64($carry3->shiftLeft(21)); $carry4 = $s4->shiftRight(21); $s5 = $s5->addInt64($carry4); $s4 = $s4->subInt64($carry4->shiftLeft(21)); $carry5 = $s5->shiftRight(21); $s6 = $s6->addInt64($carry5); $s5 = $s5->subInt64($carry5->shiftLeft(21)); $carry6 = $s6->shiftRight(21); $s7 = $s7->addInt64($carry6); $s6 = $s6->subInt64($carry6->shiftLeft(21)); $carry7 = $s7->shiftRight(21); $s8 = $s8->addInt64($carry7); $s7 = $s7->subInt64($carry7->shiftLeft(21)); $carry8 = $s10->shiftRight(21); $s9 = $s9->addInt64($carry8); $s8 = $s8->subInt64($carry8->shiftLeft(21)); $carry9 = $s9->shiftRight(21); $s10 = $s10->addInt64($carry9); $s9 = $s9->subInt64($carry9->shiftLeft(21)); $carry10 = $s10->shiftRight(21); $s11 = $s11->addInt64($carry10); $s10 = $s10->subInt64($carry10->shiftLeft(21)); $S0 = $s0->toInt(); $S1 = $s1->toInt(); $S2 = $s2->toInt(); $S3 = $s3->toInt(); $S4 = $s4->toInt(); $S5 = $s5->toInt(); $S6 = $s6->toInt(); $S7 = $s7->toInt(); $S8 = $s8->toInt(); $S9 = $s9->toInt(); $S10 = $s10->toInt(); $S11 = $s11->toInt(); /** * @var array<int, int> */ $arr = array( (int) (0xff & ($S0 >> 0)), (int) (0xff & ($S0 >> 8)), (int) (0xff & (($S0 >> 16) | ($S1 << 5))), (int) (0xff & ($S1 >> 3)), (int) (0xff & ($S1 >> 11)), (int) (0xff & (($S1 >> 19) | ($S2 << 2))), (int) (0xff & ($S2 >> 6)), (int) (0xff & (($S2 >> 14) | ($S3 << 7))), (int) (0xff & ($S3 >> 1)), (int) (0xff & ($S3 >> 9)), (int) (0xff & (($S3 >> 17) | ($S4 << 4))), (int) (0xff & ($S4 >> 4)), (int) (0xff & ($S4 >> 12)), (int) (0xff & (($S4 >> 20) | ($S5 << 1))), (int) (0xff & ($S5 >> 7)), (int) (0xff & (($S5 >> 15) | ($S6 << 6))), (int) (0xff & ($S6 >> 2)), (int) (0xff & ($S6 >> 10)), (int) (0xff & (($S6 >> 18) | ($S7 << 3))), (int) (0xff & ($S7 >> 5)), (int) (0xff & ($S7 >> 13)), (int) (0xff & ($S8 >> 0)), (int) (0xff & ($S8 >> 8)), (int) (0xff & (($S8 >> 16) | ($S9 << 5))), (int) (0xff & ($S9 >> 3)), (int) (0xff & ($S9 >> 11)), (int) (0xff & (($S9 >> 19) | ($S10 << 2))), (int) (0xff & ($S10 >> 6)), (int) (0xff & (($S10 >> 14) | ($S11 << 7))), (int) (0xff & ($S11 >> 1)), (int) (0xff & ($S11 >> 9)), (int) (0xff & ($S11 >> 17)) ); return self::intArrayToString($arr); } /** * @internal You should not use this directly from another application * * @param string $s * @return string * @throws SodiumException * @throws TypeError */ public static function sc_reduce($s) { /** * @var ParagonIE_Sodium_Core32_Int64 $s0 * @var ParagonIE_Sodium_Core32_Int64 $s1 * @var ParagonIE_Sodium_Core32_Int64 $s2 * @var ParagonIE_Sodium_Core32_Int64 $s3 * @var ParagonIE_Sodium_Core32_Int64 $s4 * @var ParagonIE_Sodium_Core32_Int64 $s5 * @var ParagonIE_Sodium_Core32_Int64 $s6 * @var ParagonIE_Sodium_Core32_Int64 $s7 * @var ParagonIE_Sodium_Core32_Int64 $s8 * @var ParagonIE_Sodium_Core32_Int64 $s9 * @var ParagonIE_Sodium_Core32_Int64 $s10 * @var ParagonIE_Sodium_Core32_Int64 $s11 * @var ParagonIE_Sodium_Core32_Int64 $s12 * @var ParagonIE_Sodium_Core32_Int64 $s13 * @var ParagonIE_Sodium_Core32_Int64 $s14 * @var ParagonIE_Sodium_Core32_Int64 $s15 * @var ParagonIE_Sodium_Core32_Int64 $s16 * @var ParagonIE_Sodium_Core32_Int64 $s17 * @var ParagonIE_Sodium_Core32_Int64 $s18 * @var ParagonIE_Sodium_Core32_Int64 $s19 * @var ParagonIE_Sodium_Core32_Int64 $s20 * @var ParagonIE_Sodium_Core32_Int64 $s21 * @var ParagonIE_Sodium_Core32_Int64 $s22 * @var ParagonIE_Sodium_Core32_Int64 $s23 */ $s0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($s, 0, 3))); $s1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 2, 4)) >> 5)); $s2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 5, 3)) >> 2)); $s3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 7, 4)) >> 7)); $s4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 10, 4)) >> 4)); $s5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 13, 3)) >> 1)); $s6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 15, 4)) >> 6)); $s7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 18, 4)) >> 3)); $s8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($s, 21, 3))); $s9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 23, 4)) >> 5)); $s10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 26, 3)) >> 2)); $s11 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 28, 4)) >> 7)); $s12 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 31, 4)) >> 4)); $s13 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 34, 3)) >> 1)); $s14 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 36, 4)) >> 6)); $s15 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 39, 4)) >> 3)); $s16 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & self::load_3(self::substr($s, 42, 3))); $s17 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 44, 4)) >> 5)); $s18 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 47, 3)) >> 2)); $s19 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 49, 4)) >> 7)); $s20 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 52, 4)) >> 4)); $s21 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_3(self::substr($s, 55, 3)) >> 1)); $s22 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 & (self::load_4(self::substr($s, 57, 4)) >> 6)); $s23 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff & (self::load_4(self::substr($s, 60, 4)) >> 3)); $s11 = $s11->addInt64($s23->mulInt(666643, 20)); $s12 = $s12->addInt64($s23->mulInt(470296, 19)); $s13 = $s13->addInt64($s23->mulInt(654183, 20)); $s14 = $s14->subInt64($s23->mulInt(997805, 20)); $s15 = $s15->addInt64($s23->mulInt(136657, 18)); $s16 = $s16->subInt64($s23->mulInt(683901, 20)); $s10 = $s10->addInt64($s22->mulInt(666643, 20)); $s11 = $s11->addInt64($s22->mulInt(470296, 19)); $s12 = $s12->addInt64($s22->mulInt(654183, 20)); $s13 = $s13->subInt64($s22->mulInt(997805, 20)); $s14 = $s14->addInt64($s22->mulInt(136657, 18)); $s15 = $s15->subInt64($s22->mulInt(683901, 20)); $s9 = $s9->addInt64($s21->mulInt(666643, 20)); $s10 = $s10->addInt64($s21->mulInt(470296, 19)); $s11 = $s11->addInt64($s21->mulInt(654183, 20)); $s12 = $s12->subInt64($s21->mulInt(997805, 20)); $s13 = $s13->addInt64($s21->mulInt(136657, 18)); $s14 = $s14->subInt64($s21->mulInt(683901, 20)); $s8 = $s8->addInt64($s20->mulInt(666643, 20)); $s9 = $s9->addInt64($s20->mulInt(470296, 19)); $s10 = $s10->addInt64($s20->mulInt(654183, 20)); $s11 = $s11->subInt64($s20->mulInt(997805, 20)); $s12 = $s12->addInt64($s20->mulInt(136657, 18)); $s13 = $s13->subInt64($s20->mulInt(683901, 20)); $s7 = $s7->addInt64($s19->mulInt(666643, 20)); $s8 = $s8->addInt64($s19->mulInt(470296, 19)); $s9 = $s9->addInt64($s19->mulInt(654183, 20)); $s10 = $s10->subInt64($s19->mulInt(997805, 20)); $s11 = $s11->addInt64($s19->mulInt(136657, 18)); $s12 = $s12->subInt64($s19->mulInt(683901, 20)); $s6 = $s6->addInt64($s18->mulInt(666643, 20)); $s7 = $s7->addInt64($s18->mulInt(470296, 19)); $s8 = $s8->addInt64($s18->mulInt(654183, 20)); $s9 = $s9->subInt64($s18->mulInt(997805, 20)); $s10 = $s10->addInt64($s18->mulInt(136657, 18)); $s11 = $s11->subInt64($s18->mulInt(683901, 20)); $carry6 = $s6->addInt(1 << 20)->shiftRight(21); $s7 = $s7->addInt64($carry6); $s6 = $s6->subInt64($carry6->shiftLeft(21)); $carry8 = $s8->addInt(1 << 20)->shiftRight(21); $s9 = $s9->addInt64($carry8); $s8 = $s8->subInt64($carry8->shiftLeft(21)); $carry10 = $s10->addInt(1 << 20)->shiftRight(21); $s11 = $s11->addInt64($carry10); $s10 = $s10->subInt64($carry10->shiftLeft(21)); $carry12 = $s12->addInt(1 << 20)->shiftRight(21); $s13 = $s13->addInt64($carry12); $s12 = $s12->subInt64($carry12->shiftLeft(21)); $carry14 = $s14->addInt(1 << 20)->shiftRight(21); $s15 = $s15->addInt64($carry14); $s14 = $s14->subInt64($carry14->shiftLeft(21)); $carry16 = $s16->addInt(1 << 20)->shiftRight(21); $s17 = $s17->addInt64($carry16); $s16 = $s16->subInt64($carry16->shiftLeft(21)); $carry7 = $s7->addInt(1 << 20)->shiftRight(21); $s8 = $s8->addInt64($carry7); $s7 = $s7->subInt64($carry7->shiftLeft(21)); $carry9 = $s9->addInt(1 << 20)->shiftRight(21); $s10 = $s10->addInt64($carry9); $s9 = $s9->subInt64($carry9->shiftLeft(21)); $carry11 = $s11->addInt(1 << 20)->shiftRight(21); $s12 = $s12->addInt64($carry11); $s11 = $s11->subInt64($carry11->shiftLeft(21)); $carry13 = $s13->addInt(1 << 20)->shiftRight(21); $s14 = $s14->addInt64($carry13); $s13 = $s13->subInt64($carry13->shiftLeft(21)); $carry15 = $s15->addInt(1 << 20)->shiftRight(21); $s16 = $s16->addInt64($carry15); $s15 = $s15->subInt64($carry15->shiftLeft(21)); $s5 = $s5->addInt64($s17->mulInt(666643, 20)); $s6 = $s6->addInt64($s17->mulInt(470296, 19)); $s7 = $s7->addInt64($s17->mulInt(654183, 20)); $s8 = $s8->subInt64($s17->mulInt(997805, 20)); $s9 = $s9->addInt64($s17->mulInt(136657, 18)); $s10 = $s10->subInt64($s17->mulInt(683901, 20)); $s4 = $s4->addInt64($s16->mulInt(666643, 20)); $s5 = $s5->addInt64($s16->mulInt(470296, 19)); $s6 = $s6->addInt64($s16->mulInt(654183, 20)); $s7 = $s7->subInt64($s16->mulInt(997805, 20)); $s8 = $s8->addInt64($s16->mulInt(136657, 18)); $s9 = $s9->subInt64($s16->mulInt(683901, 20)); $s3 = $s3->addInt64($s15->mulInt(666643, 20)); $s4 = $s4->addInt64($s15->mulInt(470296, 19)); $s5 = $s5->addInt64($s15->mulInt(654183, 20)); $s6 = $s6->subInt64($s15->mulInt(997805, 20)); $s7 = $s7->addInt64($s15->mulInt(136657, 18)); $s8 = $s8->subInt64($s15->mulInt(683901, 20)); $s2 = $s2->addInt64($s14->mulInt(666643, 20)); $s3 = $s3->addInt64($s14->mulInt(470296, 19)); $s4 = $s4->addInt64($s14->mulInt(654183, 20)); $s5 = $s5->subInt64($s14->mulInt(997805, 20)); $s6 = $s6->addInt64($s14->mulInt(136657, 18)); $s7 = $s7->subInt64($s14->mulInt(683901, 20)); $s1 = $s1->addInt64($s13->mulInt(666643, 20)); $s2 = $s2->addInt64($s13->mulInt(470296, 19)); $s3 = $s3->addInt64($s13->mulInt(654183, 20)); $s4 = $s4->subInt64($s13->mulInt(997805, 20)); $s5 = $s5->addInt64($s13->mulInt(136657, 18)); $s6 = $s6->subInt64($s13->mulInt(683901, 20)); $s0 = $s0->addInt64($s12->mulInt(666643, 20)); $s1 = $s1->addInt64($s12->mulInt(470296, 19)); $s2 = $s2->addInt64($s12->mulInt(654183, 20)); $s3 = $s3->subInt64($s12->mulInt(997805, 20)); $s4 = $s4->addInt64($s12->mulInt(136657, 18)); $s5 = $s5->subInt64($s12->mulInt(683901, 20)); $s12 = new ParagonIE_Sodium_Core32_Int64(); $carry0 = $s0->addInt(1 << 20)->shiftRight(21); $s1 = $s1->addInt64($carry0); $s0 = $s0->subInt64($carry0->shiftLeft(21)); $carry2 = $s2->addInt(1 << 20)->shiftRight(21); $s3 = $s3->addInt64($carry2); $s2 = $s2->subInt64($carry2->shiftLeft(21)); $carry4 = $s4->addInt(1 << 20)->shiftRight(21); $s5 = $s5->addInt64($carry4); $s4 = $s4->subInt64($carry4->shiftLeft(21)); $carry6 = $s6->addInt(1 << 20)->shiftRight(21); $s7 = $s7->addInt64($carry6); $s6 = $s6->subInt64($carry6->shiftLeft(21)); $carry8 = $s8->addInt(1 << 20)->shiftRight(21); $s9 = $s9->addInt64($carry8); $s8 = $s8->subInt64($carry8->shiftLeft(21)); $carry10 = $s10->addInt(1 << 20)->shiftRight(21); $s11 = $s11->addInt64($carry10); $s10 = $s10->subInt64($carry10->shiftLeft(21)); $carry1 = $s1->addInt(1 << 20)->shiftRight(21); $s2 = $s2->addInt64($carry1); $s1 = $s1->subInt64($carry1->shiftLeft(21)); $carry3 = $s3->addInt(1 << 20)->shiftRight(21); $s4 = $s4->addInt64($carry3); $s3 = $s3->subInt64($carry3->shiftLeft(21)); $carry5 = $s5->addInt(1 << 20)->shiftRight(21); $s6 = $s6->addInt64($carry5); $s5 = $s5->subInt64($carry5->shiftLeft(21)); $carry7 = $s7->addInt(1 << 20)->shiftRight(21); $s8 = $s8->addInt64($carry7); $s7 = $s7->subInt64($carry7->shiftLeft(21)); $carry9 = $s9->addInt(1 << 20)->shiftRight(21); $s10 = $s10->addInt64($carry9); $s9 = $s9->subInt64($carry9->shiftLeft(21)); $carry11 = $s11->addInt(1 << 20)->shiftRight(21); $s12 = $s12->addInt64($carry11); $s11 = $s11->subInt64($carry11->shiftLeft(21)); $s0 = $s0->addInt64($s12->mulInt(666643, 20)); $s1 = $s1->addInt64($s12->mulInt(470296, 19)); $s2 = $s2->addInt64($s12->mulInt(654183, 20)); $s3 = $s3->subInt64($s12->mulInt(997805, 20)); $s4 = $s4->addInt64($s12->mulInt(136657, 18)); $s5 = $s5->subInt64($s12->mulInt(683901, 20)); $s12 = new ParagonIE_Sodium_Core32_Int64(); $carry0 = $s0->shiftRight(21); $s1 = $s1->addInt64($carry0); $s0 = $s0->subInt64($carry0->shiftLeft(21)); $carry1 = $s1->shiftRight(21); $s2 = $s2->addInt64($carry1); $s1 = $s1->subInt64($carry1->shiftLeft(21)); $carry2 = $s2->shiftRight(21); $s3 = $s3->addInt64($carry2); $s2 = $s2->subInt64($carry2->shiftLeft(21)); $carry3 = $s3->shiftRight(21); $s4 = $s4->addInt64($carry3); $s3 = $s3->subInt64($carry3->shiftLeft(21)); $carry4 = $s4->shiftRight(21); $s5 = $s5->addInt64($carry4); $s4 = $s4->subInt64($carry4->shiftLeft(21)); $carry5 = $s5->shiftRight(21); $s6 = $s6->addInt64($carry5); $s5 = $s5->subInt64($carry5->shiftLeft(21)); $carry6 = $s6->shiftRight(21); $s7 = $s7->addInt64($carry6); $s6 = $s6->subInt64($carry6->shiftLeft(21)); $carry7 = $s7->shiftRight(21); $s8 = $s8->addInt64($carry7); $s7 = $s7->subInt64($carry7->shiftLeft(21)); $carry8 = $s8->shiftRight(21); $s9 = $s9->addInt64($carry8); $s8 = $s8->subInt64($carry8->shiftLeft(21)); $carry9 = $s9->shiftRight(21); $s10 = $s10->addInt64($carry9); $s9 = $s9->subInt64($carry9->shiftLeft(21)); $carry10 = $s10->shiftRight(21); $s11 = $s11->addInt64($carry10); $s10 = $s10->subInt64($carry10->shiftLeft(21)); $carry11 = $s11->shiftRight(21); $s12 = $s12->addInt64($carry11); $s11 = $s11->subInt64($carry11->shiftLeft(21)); $s0 = $s0->addInt64($s12->mulInt(666643, 20)); $s1 = $s1->addInt64($s12->mulInt(470296, 19)); $s2 = $s2->addInt64($s12->mulInt(654183, 20)); $s3 = $s3->subInt64($s12->mulInt(997805, 20)); $s4 = $s4->addInt64($s12->mulInt(136657, 18)); $s5 = $s5->subInt64($s12->mulInt(683901, 20)); $carry0 = $s0->shiftRight(21); $s1 = $s1->addInt64($carry0); $s0 = $s0->subInt64($carry0->shiftLeft(21)); $carry1 = $s1->shiftRight(21); $s2 = $s2->addInt64($carry1); $s1 = $s1->subInt64($carry1->shiftLeft(21)); $carry2 = $s2->shiftRight(21); $s3 = $s3->addInt64($carry2); $s2 = $s2->subInt64($carry2->shiftLeft(21)); $carry3 = $s3->shiftRight(21); $s4 = $s4->addInt64($carry3); $s3 = $s3->subInt64($carry3->shiftLeft(21)); $carry4 = $s4->shiftRight(21); $s5 = $s5->addInt64($carry4); $s4 = $s4->subInt64($carry4->shiftLeft(21)); $carry5 = $s5->shiftRight(21); $s6 = $s6->addInt64($carry5); $s5 = $s5->subInt64($carry5->shiftLeft(21)); $carry6 = $s6->shiftRight(21); $s7 = $s7->addInt64($carry6); $s6 = $s6->subInt64($carry6->shiftLeft(21)); $carry7 = $s7->shiftRight(21); $s8 = $s8->addInt64($carry7); $s7 = $s7->subInt64($carry7->shiftLeft(21)); $carry8 = $s8->shiftRight(21); $s9 = $s9->addInt64($carry8); $s8 = $s8->subInt64($carry8->shiftLeft(21)); $carry9 = $s9->shiftRight(21); $s10 = $s10->addInt64($carry9); $s9 = $s9->subInt64($carry9->shiftLeft(21)); $carry10 = $s10->shiftRight(21); $s11 = $s11->addInt64($carry10); $s10 = $s10->subInt64($carry10->shiftLeft(21)); $S0 = $s0->toInt32()->toInt(); $S1 = $s1->toInt32()->toInt(); $S2 = $s2->toInt32()->toInt(); $S3 = $s3->toInt32()->toInt(); $S4 = $s4->toInt32()->toInt(); $S5 = $s5->toInt32()->toInt(); $S6 = $s6->toInt32()->toInt(); $S7 = $s7->toInt32()->toInt(); $S8 = $s8->toInt32()->toInt(); $S9 = $s9->toInt32()->toInt(); $S10 = $s10->toInt32()->toInt(); $S11 = $s11->toInt32()->toInt(); /** * @var array<int, int> */ $arr = array( (int) ($S0 >> 0), (int) ($S0 >> 8), (int) (($S0 >> 16) | ($S1 << 5)), (int) ($S1 >> 3), (int) ($S1 >> 11), (int) (($S1 >> 19) | ($S2 << 2)), (int) ($S2 >> 6), (int) (($S2 >> 14) | ($S3 << 7)), (int) ($S3 >> 1), (int) ($S3 >> 9), (int) (($S3 >> 17) | ($S4 << 4)), (int) ($S4 >> 4), (int) ($S4 >> 12), (int) (($S4 >> 20) | ($S5 << 1)), (int) ($S5 >> 7), (int) (($S5 >> 15) | ($S6 << 6)), (int) ($S6 >> 2), (int) ($S6 >> 10), (int) (($S6 >> 18) | ($S7 << 3)), (int) ($S7 >> 5), (int) ($S7 >> 13), (int) ($S8 >> 0), (int) ($S8 >> 8), (int) (($S8 >> 16) | ($S9 << 5)), (int) ($S9 >> 3), (int) ($S9 >> 11), (int) (($S9 >> 19) | ($S10 << 2)), (int) ($S10 >> 6), (int) (($S10 >> 14) | ($S11 << 7)), (int) ($S11 >> 1), (int) ($S11 >> 9), (int) $S11 >> 17 ); return self::intArrayToString($arr); } /** * multiply by the order of the main subgroup l = 2^252+27742317777372353535851937790883648493 * * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3 * @throws SodiumException * @throws TypeError */ public static function ge_mul_l(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A) { $aslide = array( 13, 0, 0, 0, 0, -1, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, -5, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, -13, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, -13, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, -13, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 3, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ); /** @var array<int, ParagonIE_Sodium_Core32_Curve25519_Ge_Cached> $Ai size 8 */ $Ai = array(); # ge_p3_to_cached(&Ai[0], A); $Ai[0] = self::ge_p3_to_cached($A); # ge_p3_dbl(&t, A); $t = self::ge_p3_dbl($A); # ge_p1p1_to_p3(&A2, &t); $A2 = self::ge_p1p1_to_p3($t); for ($i = 1; $i < 8; ++$i) { # ge_add(&t, &A2, &Ai[0]); $t = self::ge_add($A2, $Ai[$i - 1]); # ge_p1p1_to_p3(&u, &t); $u = self::ge_p1p1_to_p3($t); # ge_p3_to_cached(&Ai[i], &u); $Ai[$i] = self::ge_p3_to_cached($u); } $r = self::ge_p3_0(); for ($i = 252; $i >= 0; --$i) { $t = self::ge_p3_dbl($r); if ($aslide[$i] > 0) { # ge_p1p1_to_p3(&u, &t); $u = self::ge_p1p1_to_p3($t); # ge_add(&t, &u, &Ai[aslide[i] / 2]); $t = self::ge_add($u, $Ai[(int)($aslide[$i] / 2)]); } elseif ($aslide[$i] < 0) { # ge_p1p1_to_p3(&u, &t); $u = self::ge_p1p1_to_p3($t); # ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]); $t = self::ge_sub($u, $Ai[(int)(-$aslide[$i] / 2)]); } } # ge_p1p1_to_p3(r, &t); return self::ge_p1p1_to_p3($t); } } PK������Z~ɯ8��8����Core32/ChaCha20.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_ChaCha20', false)) { return; } /** * Class ParagonIE_Sodium_Core32_ChaCha20 */ class ParagonIE_Sodium_Core32_ChaCha20 extends ParagonIE_Sodium_Core32_Util { /** * The ChaCha20 quarter round function. Works on four 32-bit integers. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Int32 $a * @param ParagonIE_Sodium_Core32_Int32 $b * @param ParagonIE_Sodium_Core32_Int32 $c * @param ParagonIE_Sodium_Core32_Int32 $d * @return array<int, ParagonIE_Sodium_Core32_Int32> * @throws SodiumException * @throws TypeError */ protected static function quarterRound( ParagonIE_Sodium_Core32_Int32 $a, ParagonIE_Sodium_Core32_Int32 $b, ParagonIE_Sodium_Core32_Int32 $c, ParagonIE_Sodium_Core32_Int32 $d ) { /** @var ParagonIE_Sodium_Core32_Int32 $a */ /** @var ParagonIE_Sodium_Core32_Int32 $b */ /** @var ParagonIE_Sodium_Core32_Int32 $c */ /** @var ParagonIE_Sodium_Core32_Int32 $d */ # a = PLUS(a,b); d = ROTATE(XOR(d,a),16); $a = $a->addInt32($b); $d = $d->xorInt32($a)->rotateLeft(16); # c = PLUS(c,d); b = ROTATE(XOR(b,c),12); $c = $c->addInt32($d); $b = $b->xorInt32($c)->rotateLeft(12); # a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); $a = $a->addInt32($b); $d = $d->xorInt32($a)->rotateLeft(8); # c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); $c = $c->addInt32($d); $b = $b->xorInt32($c)->rotateLeft(7); return array($a, $b, $c, $d); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_ChaCha20_Ctx $ctx * @param string $message * * @return string * @throws SodiumException * @throws TypeError */ public static function encryptBytes( ParagonIE_Sodium_Core32_ChaCha20_Ctx $ctx, $message = '' ) { $bytes = self::strlen($message); /** @var ParagonIE_Sodium_Core32_Int32 $x0 */ /** @var ParagonIE_Sodium_Core32_Int32 $x1 */ /** @var ParagonIE_Sodium_Core32_Int32 $x2 */ /** @var ParagonIE_Sodium_Core32_Int32 $x3 */ /** @var ParagonIE_Sodium_Core32_Int32 $x4 */ /** @var ParagonIE_Sodium_Core32_Int32 $x5 */ /** @var ParagonIE_Sodium_Core32_Int32 $x6 */ /** @var ParagonIE_Sodium_Core32_Int32 $x7 */ /** @var ParagonIE_Sodium_Core32_Int32 $x8 */ /** @var ParagonIE_Sodium_Core32_Int32 $x9 */ /** @var ParagonIE_Sodium_Core32_Int32 $x10 */ /** @var ParagonIE_Sodium_Core32_Int32 $x11 */ /** @var ParagonIE_Sodium_Core32_Int32 $x12 */ /** @var ParagonIE_Sodium_Core32_Int32 $x13 */ /** @var ParagonIE_Sodium_Core32_Int32 $x14 */ /** @var ParagonIE_Sodium_Core32_Int32 $x15 */ /* j0 = ctx->input[0]; j1 = ctx->input[1]; j2 = ctx->input[2]; j3 = ctx->input[3]; j4 = ctx->input[4]; j5 = ctx->input[5]; j6 = ctx->input[6]; j7 = ctx->input[7]; j8 = ctx->input[8]; j9 = ctx->input[9]; j10 = ctx->input[10]; j11 = ctx->input[11]; j12 = ctx->input[12]; j13 = ctx->input[13]; j14 = ctx->input[14]; j15 = ctx->input[15]; */ /** @var ParagonIE_Sodium_Core32_Int32 $j0 */ $j0 = $ctx[0]; /** @var ParagonIE_Sodium_Core32_Int32 $j1 */ $j1 = $ctx[1]; /** @var ParagonIE_Sodium_Core32_Int32 $j2 */ $j2 = $ctx[2]; /** @var ParagonIE_Sodium_Core32_Int32 $j3 */ $j3 = $ctx[3]; /** @var ParagonIE_Sodium_Core32_Int32 $j4 */ $j4 = $ctx[4]; /** @var ParagonIE_Sodium_Core32_Int32 $j5 */ $j5 = $ctx[5]; /** @var ParagonIE_Sodium_Core32_Int32 $j6 */ $j6 = $ctx[6]; /** @var ParagonIE_Sodium_Core32_Int32 $j7 */ $j7 = $ctx[7]; /** @var ParagonIE_Sodium_Core32_Int32 $j8 */ $j8 = $ctx[8]; /** @var ParagonIE_Sodium_Core32_Int32 $j9 */ $j9 = $ctx[9]; /** @var ParagonIE_Sodium_Core32_Int32 $j10 */ $j10 = $ctx[10]; /** @var ParagonIE_Sodium_Core32_Int32 $j11 */ $j11 = $ctx[11]; /** @var ParagonIE_Sodium_Core32_Int32 $j12 */ $j12 = $ctx[12]; /** @var ParagonIE_Sodium_Core32_Int32 $j13 */ $j13 = $ctx[13]; /** @var ParagonIE_Sodium_Core32_Int32 $j14 */ $j14 = $ctx[14]; /** @var ParagonIE_Sodium_Core32_Int32 $j15 */ $j15 = $ctx[15]; $c = ''; for (;;) { if ($bytes < 64) { $message .= str_repeat("\x00", 64 - $bytes); } $x0 = clone $j0; $x1 = clone $j1; $x2 = clone $j2; $x3 = clone $j3; $x4 = clone $j4; $x5 = clone $j5; $x6 = clone $j6; $x7 = clone $j7; $x8 = clone $j8; $x9 = clone $j9; $x10 = clone $j10; $x11 = clone $j11; $x12 = clone $j12; $x13 = clone $j13; $x14 = clone $j14; $x15 = clone $j15; # for (i = 20; i > 0; i -= 2) { for ($i = 20; $i > 0; $i -= 2) { # QUARTERROUND( x0, x4, x8, x12) list($x0, $x4, $x8, $x12) = self::quarterRound($x0, $x4, $x8, $x12); # QUARTERROUND( x1, x5, x9, x13) list($x1, $x5, $x9, $x13) = self::quarterRound($x1, $x5, $x9, $x13); # QUARTERROUND( x2, x6, x10, x14) list($x2, $x6, $x10, $x14) = self::quarterRound($x2, $x6, $x10, $x14); # QUARTERROUND( x3, x7, x11, x15) list($x3, $x7, $x11, $x15) = self::quarterRound($x3, $x7, $x11, $x15); # QUARTERROUND( x0, x5, x10, x15) list($x0, $x5, $x10, $x15) = self::quarterRound($x0, $x5, $x10, $x15); # QUARTERROUND( x1, x6, x11, x12) list($x1, $x6, $x11, $x12) = self::quarterRound($x1, $x6, $x11, $x12); # QUARTERROUND( x2, x7, x8, x13) list($x2, $x7, $x8, $x13) = self::quarterRound($x2, $x7, $x8, $x13); # QUARTERROUND( x3, x4, x9, x14) list($x3, $x4, $x9, $x14) = self::quarterRound($x3, $x4, $x9, $x14); } /* x0 = PLUS(x0, j0); x1 = PLUS(x1, j1); x2 = PLUS(x2, j2); x3 = PLUS(x3, j3); x4 = PLUS(x4, j4); x5 = PLUS(x5, j5); x6 = PLUS(x6, j6); x7 = PLUS(x7, j7); x8 = PLUS(x8, j8); x9 = PLUS(x9, j9); x10 = PLUS(x10, j10); x11 = PLUS(x11, j11); x12 = PLUS(x12, j12); x13 = PLUS(x13, j13); x14 = PLUS(x14, j14); x15 = PLUS(x15, j15); */ $x0 = $x0->addInt32($j0); $x1 = $x1->addInt32($j1); $x2 = $x2->addInt32($j2); $x3 = $x3->addInt32($j3); $x4 = $x4->addInt32($j4); $x5 = $x5->addInt32($j5); $x6 = $x6->addInt32($j6); $x7 = $x7->addInt32($j7); $x8 = $x8->addInt32($j8); $x9 = $x9->addInt32($j9); $x10 = $x10->addInt32($j10); $x11 = $x11->addInt32($j11); $x12 = $x12->addInt32($j12); $x13 = $x13->addInt32($j13); $x14 = $x14->addInt32($j14); $x15 = $x15->addInt32($j15); /* x0 = XOR(x0, LOAD32_LE(m + 0)); x1 = XOR(x1, LOAD32_LE(m + 4)); x2 = XOR(x2, LOAD32_LE(m + 8)); x3 = XOR(x3, LOAD32_LE(m + 12)); x4 = XOR(x4, LOAD32_LE(m + 16)); x5 = XOR(x5, LOAD32_LE(m + 20)); x6 = XOR(x6, LOAD32_LE(m + 24)); x7 = XOR(x7, LOAD32_LE(m + 28)); x8 = XOR(x8, LOAD32_LE(m + 32)); x9 = XOR(x9, LOAD32_LE(m + 36)); x10 = XOR(x10, LOAD32_LE(m + 40)); x11 = XOR(x11, LOAD32_LE(m + 44)); x12 = XOR(x12, LOAD32_LE(m + 48)); x13 = XOR(x13, LOAD32_LE(m + 52)); x14 = XOR(x14, LOAD32_LE(m + 56)); x15 = XOR(x15, LOAD32_LE(m + 60)); */ $x0 = $x0->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 0, 4))); $x1 = $x1->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 4, 4))); $x2 = $x2->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 8, 4))); $x3 = $x3->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 12, 4))); $x4 = $x4->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 16, 4))); $x5 = $x5->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 20, 4))); $x6 = $x6->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 24, 4))); $x7 = $x7->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 28, 4))); $x8 = $x8->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 32, 4))); $x9 = $x9->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 36, 4))); $x10 = $x10->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 40, 4))); $x11 = $x11->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 44, 4))); $x12 = $x12->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 48, 4))); $x13 = $x13->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 52, 4))); $x14 = $x14->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 56, 4))); $x15 = $x15->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 60, 4))); /* j12 = PLUSONE(j12); if (!j12) { j13 = PLUSONE(j13); } */ /** @var ParagonIE_Sodium_Core32_Int32 $j12 */ $j12 = $j12->addInt(1); if ($j12->limbs[0] === 0 && $j12->limbs[1] === 0) { $j13 = $j13->addInt(1); } /* STORE32_LE(c + 0, x0); STORE32_LE(c + 4, x1); STORE32_LE(c + 8, x2); STORE32_LE(c + 12, x3); STORE32_LE(c + 16, x4); STORE32_LE(c + 20, x5); STORE32_LE(c + 24, x6); STORE32_LE(c + 28, x7); STORE32_LE(c + 32, x8); STORE32_LE(c + 36, x9); STORE32_LE(c + 40, x10); STORE32_LE(c + 44, x11); STORE32_LE(c + 48, x12); STORE32_LE(c + 52, x13); STORE32_LE(c + 56, x14); STORE32_LE(c + 60, x15); */ $block = $x0->toReverseString() . $x1->toReverseString() . $x2->toReverseString() . $x3->toReverseString() . $x4->toReverseString() . $x5->toReverseString() . $x6->toReverseString() . $x7->toReverseString() . $x8->toReverseString() . $x9->toReverseString() . $x10->toReverseString() . $x11->toReverseString() . $x12->toReverseString() . $x13->toReverseString() . $x14->toReverseString() . $x15->toReverseString(); /* Partial block */ if ($bytes < 64) { $c .= self::substr($block, 0, $bytes); break; } /* Full block */ $c .= $block; $bytes -= 64; if ($bytes <= 0) { break; } $message = self::substr($message, 64); } /* end for(;;) loop */ $ctx[12] = $j12; $ctx[13] = $j13; return $c; } /** * @internal You should not use this directly from another application * * @param int $len * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function stream($len = 64, $nonce = '', $key = '') { return self::encryptBytes( new ParagonIE_Sodium_Core32_ChaCha20_Ctx($key, $nonce), str_repeat("\x00", $len) ); } /** * @internal You should not use this directly from another application * * @param int $len * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function ietfStream($len, $nonce = '', $key = '') { return self::encryptBytes( new ParagonIE_Sodium_Core32_ChaCha20_IetfCtx($key, $nonce), str_repeat("\x00", $len) ); } /** * @internal You should not use this directly from another application * * @param string $message * @param string $nonce * @param string $key * @param string $ic * @return string * @throws SodiumException * @throws TypeError */ public static function ietfStreamXorIc($message, $nonce = '', $key = '', $ic = '') { return self::encryptBytes( new ParagonIE_Sodium_Core32_ChaCha20_IetfCtx($key, $nonce, $ic), $message ); } /** * @internal You should not use this directly from another application * * @param string $message * @param string $nonce * @param string $key * @param string $ic * @return string * @throws SodiumException * @throws TypeError */ public static function streamXorIc($message, $nonce = '', $key = '', $ic = '') { return self::encryptBytes( new ParagonIE_Sodium_Core32_ChaCha20_Ctx($key, $nonce, $ic), $message ); } } PK������Z@(,,��,����Core32/Salsa20.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_Salsa20', false)) { return; } /** * Class ParagonIE_Sodium_Core32_Salsa20 */ abstract class ParagonIE_Sodium_Core32_Salsa20 extends ParagonIE_Sodium_Core32_Util { const ROUNDS = 20; /** * Calculate an salsa20 hash of a single block * * @internal You should not use this directly from another application * * @param string $in * @param string $k * @param string|null $c * @return string * @throws SodiumException * @throws TypeError */ public static function core_salsa20($in, $k, $c = null) { /** * @var ParagonIE_Sodium_Core32_Int32 $x0 * @var ParagonIE_Sodium_Core32_Int32 $x1 * @var ParagonIE_Sodium_Core32_Int32 $x2 * @var ParagonIE_Sodium_Core32_Int32 $x3 * @var ParagonIE_Sodium_Core32_Int32 $x4 * @var ParagonIE_Sodium_Core32_Int32 $x5 * @var ParagonIE_Sodium_Core32_Int32 $x6 * @var ParagonIE_Sodium_Core32_Int32 $x7 * @var ParagonIE_Sodium_Core32_Int32 $x8 * @var ParagonIE_Sodium_Core32_Int32 $x9 * @var ParagonIE_Sodium_Core32_Int32 $x10 * @var ParagonIE_Sodium_Core32_Int32 $x11 * @var ParagonIE_Sodium_Core32_Int32 $x12 * @var ParagonIE_Sodium_Core32_Int32 $x13 * @var ParagonIE_Sodium_Core32_Int32 $x14 * @var ParagonIE_Sodium_Core32_Int32 $x15 * @var ParagonIE_Sodium_Core32_Int32 $j0 * @var ParagonIE_Sodium_Core32_Int32 $j1 * @var ParagonIE_Sodium_Core32_Int32 $j2 * @var ParagonIE_Sodium_Core32_Int32 $j3 * @var ParagonIE_Sodium_Core32_Int32 $j4 * @var ParagonIE_Sodium_Core32_Int32 $j5 * @var ParagonIE_Sodium_Core32_Int32 $j6 * @var ParagonIE_Sodium_Core32_Int32 $j7 * @var ParagonIE_Sodium_Core32_Int32 $j8 * @var ParagonIE_Sodium_Core32_Int32 $j9 * @var ParagonIE_Sodium_Core32_Int32 $j10 * @var ParagonIE_Sodium_Core32_Int32 $j11 * @var ParagonIE_Sodium_Core32_Int32 $j12 * @var ParagonIE_Sodium_Core32_Int32 $j13 * @var ParagonIE_Sodium_Core32_Int32 $j14 * @var ParagonIE_Sodium_Core32_Int32 $j15 */ if (self::strlen($k) < 32) { throw new RangeException('Key must be 32 bytes long'); } if ($c === null) { $x0 = new ParagonIE_Sodium_Core32_Int32(array(0x6170, 0x7865)); $x5 = new ParagonIE_Sodium_Core32_Int32(array(0x3320, 0x646e)); $x10 = new ParagonIE_Sodium_Core32_Int32(array(0x7962, 0x2d32)); $x15 = new ParagonIE_Sodium_Core32_Int32(array(0x6b20, 0x6574)); } else { $x0 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 0, 4)); $x5 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 4, 4)); $x10 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 8, 4)); $x15 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 12, 4)); } $x1 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 0, 4)); $x2 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 4, 4)); $x3 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 8, 4)); $x4 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 12, 4)); $x6 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 0, 4)); $x7 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 4, 4)); $x8 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 8, 4)); $x9 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 12, 4)); $x11 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 16, 4)); $x12 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 20, 4)); $x13 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 24, 4)); $x14 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 28, 4)); $j0 = clone $x0; $j1 = clone $x1; $j2 = clone $x2; $j3 = clone $x3; $j4 = clone $x4; $j5 = clone $x5; $j6 = clone $x6; $j7 = clone $x7; $j8 = clone $x8; $j9 = clone $x9; $j10 = clone $x10; $j11 = clone $x11; $j12 = clone $x12; $j13 = clone $x13; $j14 = clone $x14; $j15 = clone $x15; for ($i = self::ROUNDS; $i > 0; $i -= 2) { $x4 = $x4->xorInt32($x0->addInt32($x12)->rotateLeft(7)); $x8 = $x8->xorInt32($x4->addInt32($x0)->rotateLeft(9)); $x12 = $x12->xorInt32($x8->addInt32($x4)->rotateLeft(13)); $x0 = $x0->xorInt32($x12->addInt32($x8)->rotateLeft(18)); $x9 = $x9->xorInt32($x5->addInt32($x1)->rotateLeft(7)); $x13 = $x13->xorInt32($x9->addInt32($x5)->rotateLeft(9)); $x1 = $x1->xorInt32($x13->addInt32($x9)->rotateLeft(13)); $x5 = $x5->xorInt32($x1->addInt32($x13)->rotateLeft(18)); $x14 = $x14->xorInt32($x10->addInt32($x6)->rotateLeft(7)); $x2 = $x2->xorInt32($x14->addInt32($x10)->rotateLeft(9)); $x6 = $x6->xorInt32($x2->addInt32($x14)->rotateLeft(13)); $x10 = $x10->xorInt32($x6->addInt32($x2)->rotateLeft(18)); $x3 = $x3->xorInt32($x15->addInt32($x11)->rotateLeft(7)); $x7 = $x7->xorInt32($x3->addInt32($x15)->rotateLeft(9)); $x11 = $x11->xorInt32($x7->addInt32($x3)->rotateLeft(13)); $x15 = $x15->xorInt32($x11->addInt32($x7)->rotateLeft(18)); $x1 = $x1->xorInt32($x0->addInt32($x3)->rotateLeft(7)); $x2 = $x2->xorInt32($x1->addInt32($x0)->rotateLeft(9)); $x3 = $x3->xorInt32($x2->addInt32($x1)->rotateLeft(13)); $x0 = $x0->xorInt32($x3->addInt32($x2)->rotateLeft(18)); $x6 = $x6->xorInt32($x5->addInt32($x4)->rotateLeft(7)); $x7 = $x7->xorInt32($x6->addInt32($x5)->rotateLeft(9)); $x4 = $x4->xorInt32($x7->addInt32($x6)->rotateLeft(13)); $x5 = $x5->xorInt32($x4->addInt32($x7)->rotateLeft(18)); $x11 = $x11->xorInt32($x10->addInt32($x9)->rotateLeft(7)); $x8 = $x8->xorInt32($x11->addInt32($x10)->rotateLeft(9)); $x9 = $x9->xorInt32($x8->addInt32($x11)->rotateLeft(13)); $x10 = $x10->xorInt32($x9->addInt32($x8)->rotateLeft(18)); $x12 = $x12->xorInt32($x15->addInt32($x14)->rotateLeft(7)); $x13 = $x13->xorInt32($x12->addInt32($x15)->rotateLeft(9)); $x14 = $x14->xorInt32($x13->addInt32($x12)->rotateLeft(13)); $x15 = $x15->xorInt32($x14->addInt32($x13)->rotateLeft(18)); } $x0 = $x0->addInt32($j0); $x1 = $x1->addInt32($j1); $x2 = $x2->addInt32($j2); $x3 = $x3->addInt32($j3); $x4 = $x4->addInt32($j4); $x5 = $x5->addInt32($j5); $x6 = $x6->addInt32($j6); $x7 = $x7->addInt32($j7); $x8 = $x8->addInt32($j8); $x9 = $x9->addInt32($j9); $x10 = $x10->addInt32($j10); $x11 = $x11->addInt32($j11); $x12 = $x12->addInt32($j12); $x13 = $x13->addInt32($j13); $x14 = $x14->addInt32($j14); $x15 = $x15->addInt32($j15); return $x0->toReverseString() . $x1->toReverseString() . $x2->toReverseString() . $x3->toReverseString() . $x4->toReverseString() . $x5->toReverseString() . $x6->toReverseString() . $x7->toReverseString() . $x8->toReverseString() . $x9->toReverseString() . $x10->toReverseString() . $x11->toReverseString() . $x12->toReverseString() . $x13->toReverseString() . $x14->toReverseString() . $x15->toReverseString(); } /** * @internal You should not use this directly from another application * * @param int $len * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function salsa20($len, $nonce, $key) { if (self::strlen($key) !== 32) { throw new RangeException('Key must be 32 bytes long'); } $kcopy = '' . $key; $in = self::substr($nonce, 0, 8) . str_repeat("\0", 8); $c = ''; while ($len >= 64) { $c .= self::core_salsa20($in, $kcopy, null); $u = 1; // Internal counter. for ($i = 8; $i < 16; ++$i) { $u += self::chrToInt($in[$i]); $in[$i] = self::intToChr($u & 0xff); $u >>= 8; } $len -= 64; } if ($len > 0) { $c .= self::substr( self::core_salsa20($in, $kcopy, null), 0, $len ); } try { ParagonIE_Sodium_Compat::memzero($kcopy); } catch (SodiumException $ex) { $kcopy = null; } return $c; } /** * @internal You should not use this directly from another application * * @param string $m * @param string $n * @param int $ic * @param string $k * @return string * @throws SodiumException * @throws TypeError */ public static function salsa20_xor_ic($m, $n, $ic, $k) { $mlen = self::strlen($m); if ($mlen < 1) { return ''; } $kcopy = self::substr($k, 0, 32); $in = self::substr($n, 0, 8); // Initialize the counter $in .= ParagonIE_Sodium_Core32_Util::store64_le($ic); $c = ''; while ($mlen >= 64) { $block = self::core_salsa20($in, $kcopy, null); $c .= self::xorStrings( self::substr($m, 0, 64), self::substr($block, 0, 64) ); $u = 1; for ($i = 8; $i < 16; ++$i) { $u += self::chrToInt($in[$i]); $in[$i] = self::intToChr($u & 0xff); $u >>= 8; } $mlen -= 64; $m = self::substr($m, 64); } if ($mlen) { $block = self::core_salsa20($in, $kcopy, null); $c .= self::xorStrings( self::substr($m, 0, $mlen), self::substr($block, 0, $mlen) ); } try { ParagonIE_Sodium_Compat::memzero($block); ParagonIE_Sodium_Compat::memzero($kcopy); } catch (SodiumException $ex) { $block = null; $kcopy = null; } return $c; } /** * @internal You should not use this directly from another application * * @param string $message * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function salsa20_xor($message, $nonce, $key) { return self::xorStrings( $message, self::salsa20( self::strlen($message), $nonce, $key ) ); } } PK������ZxH��H����Core32/SecretStream/State.phpnu�W+A��������<?php /** * Class ParagonIE_Sodium_Core32_SecretStream_State */ class ParagonIE_Sodium_Core32_SecretStream_State { /** @var string $key */ protected $key; /** @var int $counter */ protected $counter; /** @var string $nonce */ protected $nonce; /** @var string $_pad */ protected $_pad; /** * ParagonIE_Sodium_Core32_SecretStream_State constructor. * @param string $key * @param string|null $nonce */ public function __construct($key, $nonce = null) { $this->key = $key; $this->counter = 1; if (is_null($nonce)) { $nonce = str_repeat("\0", 12); } $this->nonce = str_pad($nonce, 12, "\0", STR_PAD_RIGHT);; $this->_pad = str_repeat("\0", 4); } /** * @return self */ public function counterReset() { $this->counter = 1; $this->_pad = str_repeat("\0", 4); return $this; } /** * @return string */ public function getKey() { return $this->key; } /** * @return string */ public function getCounter() { return ParagonIE_Sodium_Core32_Util::store32_le($this->counter); } /** * @return string */ public function getNonce() { if (!is_string($this->nonce)) { $this->nonce = str_repeat("\0", 12); } if (ParagonIE_Sodium_Core32_Util::strlen($this->nonce) !== 12) { $this->nonce = str_pad($this->nonce, 12, "\0", STR_PAD_RIGHT); } return $this->nonce; } /** * @return string */ public function getCombinedNonce() { return $this->getCounter() . ParagonIE_Sodium_Core32_Util::substr($this->getNonce(), 0, 8); } /** * @return self */ public function incrementCounter() { ++$this->counter; return $this; } /** * @return bool */ public function needsRekey() { return ($this->counter & 0xffff) === 0; } /** * @param string $newKeyAndNonce * @return self */ public function rekey($newKeyAndNonce) { $this->key = ParagonIE_Sodium_Core32_Util::substr($newKeyAndNonce, 0, 32); $this->nonce = str_pad( ParagonIE_Sodium_Core32_Util::substr($newKeyAndNonce, 32), 12, "\0", STR_PAD_RIGHT ); return $this; } /** * @param string $str * @return self */ public function xorNonce($str) { $this->nonce = ParagonIE_Sodium_Core32_Util::xorStrings( $this->getNonce(), str_pad( ParagonIE_Sodium_Core32_Util::substr($str, 0, 8), 12, "\0", STR_PAD_RIGHT ) ); return $this; } /** * @param string $string * @return self */ public static function fromString($string) { $state = new ParagonIE_Sodium_Core32_SecretStream_State( ParagonIE_Sodium_Core32_Util::substr($string, 0, 32) ); $state->counter = ParagonIE_Sodium_Core32_Util::load_4( ParagonIE_Sodium_Core32_Util::substr($string, 32, 4) ); $state->nonce = ParagonIE_Sodium_Core32_Util::substr($string, 36, 12); $state->_pad = ParagonIE_Sodium_Core32_Util::substr($string, 48, 8); return $state; } /** * @return string */ public function toString() { return $this->key . $this->getCounter() . $this->nonce . $this->_pad; } } PK������ZXv(��(����Core32/ChaCha20/Ctx.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_ChaCha20_Ctx', false)) { return; } /** * Class ParagonIE_Sodium_Core32_ChaCha20_Ctx */ class ParagonIE_Sodium_Core32_ChaCha20_Ctx extends ParagonIE_Sodium_Core32_Util implements ArrayAccess { /** * @var SplFixedArray internally, <int, ParagonIE_Sodium_Core32_Int32> */ protected $container; /** * ParagonIE_Sodium_Core_ChaCha20_Ctx constructor. * * @internal You should not use this directly from another application * * @param string $key ChaCha20 key. * @param string $iv Initialization Vector (a.k.a. nonce). * @param string $counter The initial counter value. * Defaults to 8 0x00 bytes. * @throws InvalidArgumentException * @throws SodiumException * @throws TypeError */ public function __construct($key = '', $iv = '', $counter = '') { if (self::strlen($key) !== 32) { throw new InvalidArgumentException('ChaCha20 expects a 256-bit key.'); } if (self::strlen($iv) !== 8) { throw new InvalidArgumentException('ChaCha20 expects a 64-bit nonce.'); } $this->container = new SplFixedArray(16); /* "expand 32-byte k" as per ChaCha20 spec */ $this->container[0] = new ParagonIE_Sodium_Core32_Int32(array(0x6170, 0x7865)); $this->container[1] = new ParagonIE_Sodium_Core32_Int32(array(0x3320, 0x646e)); $this->container[2] = new ParagonIE_Sodium_Core32_Int32(array(0x7962, 0x2d32)); $this->container[3] = new ParagonIE_Sodium_Core32_Int32(array(0x6b20, 0x6574)); $this->container[4] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 0, 4)); $this->container[5] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 4, 4)); $this->container[6] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 8, 4)); $this->container[7] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 12, 4)); $this->container[8] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 16, 4)); $this->container[9] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 20, 4)); $this->container[10] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 24, 4)); $this->container[11] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 28, 4)); if (empty($counter)) { $this->container[12] = new ParagonIE_Sodium_Core32_Int32(); $this->container[13] = new ParagonIE_Sodium_Core32_Int32(); } else { $this->container[12] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($counter, 0, 4)); $this->container[13] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($counter, 4, 4)); } $this->container[14] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($iv, 0, 4)); $this->container[15] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($iv, 4, 4)); } /** * @internal You should not use this directly from another application * * @param int $offset * @param int|ParagonIE_Sodium_Core32_Int32 $value * @return void */ #[ReturnTypeWillChange] public function offsetSet($offset, $value) { if (!is_int($offset)) { throw new InvalidArgumentException('Expected an integer'); } if ($value instanceof ParagonIE_Sodium_Core32_Int32) { /* } elseif (is_int($value)) { $value = ParagonIE_Sodium_Core32_Int32::fromInt($value); */ } else { throw new InvalidArgumentException('Expected an integer'); } $this->container[$offset] = $value; } /** * @internal You should not use this directly from another application * * @param int $offset * @return bool * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->container[$offset]); } /** * @internal You should not use this directly from another application * * @param int $offset * @return void * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->container[$offset]); } /** * @internal You should not use this directly from another application * * @param int $offset * @return mixed|null * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetGet($offset) { return isset($this->container[$offset]) ? $this->container[$offset] : null; } } PK������Z������Core32/ChaCha20/IetfCtx.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_ChaCha20_IetfCtx', false)) { return; } /** * Class ParagonIE_Sodium_Core32_ChaCha20_IetfCtx */ class ParagonIE_Sodium_Core32_ChaCha20_IetfCtx extends ParagonIE_Sodium_Core32_ChaCha20_Ctx { /** * ParagonIE_Sodium_Core_ChaCha20_IetfCtx constructor. * * @internal You should not use this directly from another application * * @param string $key ChaCha20 key. * @param string $iv Initialization Vector (a.k.a. nonce). * @param string $counter The initial counter value. * Defaults to 4 0x00 bytes. * @throws InvalidArgumentException * @throws SodiumException * @throws TypeError */ public function __construct($key = '', $iv = '', $counter = '') { if (self::strlen($iv) !== 12) { throw new InvalidArgumentException('ChaCha20 expects a 96-bit nonce in IETF mode.'); } parent::__construct($key, self::substr($iv, 0, 8), $counter); if (!empty($counter)) { $this->container[12] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($counter, 0, 4)); } $this->container[13] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($iv, 0, 4)); $this->container[14] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($iv, 4, 4)); $this->container[15] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($iv, 8, 4)); } } PK������ZX]>��]>����Core32/Poly1305/State.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_Poly1305_State', false)) { return; } /** * Class ParagonIE_Sodium_Core32_Poly1305_State */ class ParagonIE_Sodium_Core32_Poly1305_State extends ParagonIE_Sodium_Core32_Util { /** * @var array<int, int> */ protected $buffer = array(); /** * @var bool */ protected $final = false; /** * @var array<int, ParagonIE_Sodium_Core32_Int32> */ public $h; /** * @var int */ protected $leftover = 0; /** * @var array<int, ParagonIE_Sodium_Core32_Int32> */ public $r; /** * @var array<int, ParagonIE_Sodium_Core32_Int64> */ public $pad; /** * ParagonIE_Sodium_Core32_Poly1305_State constructor. * * @internal You should not use this directly from another application * * @param string $key * @throws InvalidArgumentException * @throws SodiumException * @throws TypeError */ public function __construct($key = '') { if (self::strlen($key) < 32) { throw new InvalidArgumentException( 'Poly1305 requires a 32-byte key' ); } /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ $this->r = array( // st->r[0] = ... ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 0, 4)) ->setUnsignedInt(true) ->mask(0x3ffffff), // st->r[1] = ... ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 3, 4)) ->setUnsignedInt(true) ->shiftRight(2) ->mask(0x3ffff03), // st->r[2] = ... ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 6, 4)) ->setUnsignedInt(true) ->shiftRight(4) ->mask(0x3ffc0ff), // st->r[3] = ... ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 9, 4)) ->setUnsignedInt(true) ->shiftRight(6) ->mask(0x3f03fff), // st->r[4] = ... ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 12, 4)) ->setUnsignedInt(true) ->shiftRight(8) ->mask(0x00fffff) ); /* h = 0 */ $this->h = array( new ParagonIE_Sodium_Core32_Int32(array(0, 0), true), new ParagonIE_Sodium_Core32_Int32(array(0, 0), true), new ParagonIE_Sodium_Core32_Int32(array(0, 0), true), new ParagonIE_Sodium_Core32_Int32(array(0, 0), true), new ParagonIE_Sodium_Core32_Int32(array(0, 0), true) ); /* save pad for later */ $this->pad = array( ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 16, 4)) ->setUnsignedInt(true)->toInt64(), ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 20, 4)) ->setUnsignedInt(true)->toInt64(), ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 24, 4)) ->setUnsignedInt(true)->toInt64(), ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 28, 4)) ->setUnsignedInt(true)->toInt64(), ); $this->leftover = 0; $this->final = false; } /** * @internal You should not use this directly from another application * * @param string $message * @return self * @throws SodiumException * @throws TypeError */ public function update($message = '') { $bytes = self::strlen($message); /* handle leftover */ if ($this->leftover) { /** @var int $want */ $want = ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE - $this->leftover; if ($want > $bytes) { $want = $bytes; } for ($i = 0; $i < $want; ++$i) { $mi = self::chrToInt($message[$i]); $this->buffer[$this->leftover + $i] = $mi; } // We snip off the leftmost bytes. $message = self::substr($message, $want); $bytes = self::strlen($message); $this->leftover += $want; if ($this->leftover < ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) { // We still don't have enough to run $this->blocks() return $this; } $this->blocks( self::intArrayToString($this->buffer), ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE ); $this->leftover = 0; } /* process full blocks */ if ($bytes >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) { /** @var int $want */ $want = $bytes & ~(ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE - 1); if ($want >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) { /** @var string $block */ $block = self::substr($message, 0, $want); if (self::strlen($block) >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) { $this->blocks($block, $want); $message = self::substr($message, $want); $bytes = self::strlen($message); } } } /* store leftover */ if ($bytes) { for ($i = 0; $i < $bytes; ++$i) { $mi = self::chrToInt($message[$i]); $this->buffer[$this->leftover + $i] = $mi; } $this->leftover = (int) $this->leftover + $bytes; } return $this; } /** * @internal You should not use this directly from another application * * @param string $message * @param int $bytes * @return self * @throws SodiumException * @throws TypeError */ public function blocks($message, $bytes) { if (self::strlen($message) < 16) { $message = str_pad($message, 16, "\x00", STR_PAD_RIGHT); } $hibit = ParagonIE_Sodium_Core32_Int32::fromInt((int) ($this->final ? 0 : 1 << 24)); /* 1 << 128 */ $hibit->setUnsignedInt(true); $zero = new ParagonIE_Sodium_Core32_Int64(array(0, 0, 0, 0), true); /** * @var ParagonIE_Sodium_Core32_Int64 $d0 * @var ParagonIE_Sodium_Core32_Int64 $d1 * @var ParagonIE_Sodium_Core32_Int64 $d2 * @var ParagonIE_Sodium_Core32_Int64 $d3 * @var ParagonIE_Sodium_Core32_Int64 $d4 * @var ParagonIE_Sodium_Core32_Int64 $r0 * @var ParagonIE_Sodium_Core32_Int64 $r1 * @var ParagonIE_Sodium_Core32_Int64 $r2 * @var ParagonIE_Sodium_Core32_Int64 $r3 * @var ParagonIE_Sodium_Core32_Int64 $r4 * * @var ParagonIE_Sodium_Core32_Int32 $h0 * @var ParagonIE_Sodium_Core32_Int32 $h1 * @var ParagonIE_Sodium_Core32_Int32 $h2 * @var ParagonIE_Sodium_Core32_Int32 $h3 * @var ParagonIE_Sodium_Core32_Int32 $h4 */ $r0 = $this->r[0]->toInt64(); $r1 = $this->r[1]->toInt64(); $r2 = $this->r[2]->toInt64(); $r3 = $this->r[3]->toInt64(); $r4 = $this->r[4]->toInt64(); $s1 = $r1->toInt64()->mulInt(5, 3); $s2 = $r2->toInt64()->mulInt(5, 3); $s3 = $r3->toInt64()->mulInt(5, 3); $s4 = $r4->toInt64()->mulInt(5, 3); $h0 = $this->h[0]; $h1 = $this->h[1]; $h2 = $this->h[2]; $h3 = $this->h[3]; $h4 = $this->h[4]; while ($bytes >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) { /* h += m[i] */ $h0 = $h0->addInt32( ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 0, 4)) ->mask(0x3ffffff) )->toInt64(); $h1 = $h1->addInt32( ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 3, 4)) ->shiftRight(2) ->mask(0x3ffffff) )->toInt64(); $h2 = $h2->addInt32( ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 6, 4)) ->shiftRight(4) ->mask(0x3ffffff) )->toInt64(); $h3 = $h3->addInt32( ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 9, 4)) ->shiftRight(6) ->mask(0x3ffffff) )->toInt64(); $h4 = $h4->addInt32( ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 12, 4)) ->shiftRight(8) ->orInt32($hibit) )->toInt64(); /* h *= r */ $d0 = $zero ->addInt64($h0->mulInt64($r0, 27)) ->addInt64($s4->mulInt64($h1, 27)) ->addInt64($s3->mulInt64($h2, 27)) ->addInt64($s2->mulInt64($h3, 27)) ->addInt64($s1->mulInt64($h4, 27)); $d1 = $zero ->addInt64($h0->mulInt64($r1, 27)) ->addInt64($h1->mulInt64($r0, 27)) ->addInt64($s4->mulInt64($h2, 27)) ->addInt64($s3->mulInt64($h3, 27)) ->addInt64($s2->mulInt64($h4, 27)); $d2 = $zero ->addInt64($h0->mulInt64($r2, 27)) ->addInt64($h1->mulInt64($r1, 27)) ->addInt64($h2->mulInt64($r0, 27)) ->addInt64($s4->mulInt64($h3, 27)) ->addInt64($s3->mulInt64($h4, 27)); $d3 = $zero ->addInt64($h0->mulInt64($r3, 27)) ->addInt64($h1->mulInt64($r2, 27)) ->addInt64($h2->mulInt64($r1, 27)) ->addInt64($h3->mulInt64($r0, 27)) ->addInt64($s4->mulInt64($h4, 27)); $d4 = $zero ->addInt64($h0->mulInt64($r4, 27)) ->addInt64($h1->mulInt64($r3, 27)) ->addInt64($h2->mulInt64($r2, 27)) ->addInt64($h3->mulInt64($r1, 27)) ->addInt64($h4->mulInt64($r0, 27)); /* (partial) h %= p */ $c = $d0->shiftRight(26); $h0 = $d0->toInt32()->mask(0x3ffffff); $d1 = $d1->addInt64($c); $c = $d1->shiftRight(26); $h1 = $d1->toInt32()->mask(0x3ffffff); $d2 = $d2->addInt64($c); $c = $d2->shiftRight(26); $h2 = $d2->toInt32()->mask(0x3ffffff); $d3 = $d3->addInt64($c); $c = $d3->shiftRight(26); $h3 = $d3->toInt32()->mask(0x3ffffff); $d4 = $d4->addInt64($c); $c = $d4->shiftRight(26); $h4 = $d4->toInt32()->mask(0x3ffffff); $h0 = $h0->addInt32($c->toInt32()->mulInt(5, 3)); $c = $h0->shiftRight(26); $h0 = $h0->mask(0x3ffffff); $h1 = $h1->addInt32($c); // Chop off the left 32 bytes. $message = self::substr( $message, ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE ); $bytes -= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE; } /** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */ $this->h = array($h0, $h1, $h2, $h3, $h4); return $this; } /** * @internal You should not use this directly from another application * * @return string * @throws SodiumException * @throws TypeError */ public function finish() { /* process the remaining block */ if ($this->leftover) { $i = $this->leftover; $this->buffer[$i++] = 1; for (; $i < ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE; ++$i) { $this->buffer[$i] = 0; } $this->final = true; $this->blocks( self::substr( self::intArrayToString($this->buffer), 0, ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE ), $b = ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE ); } /** * @var ParagonIE_Sodium_Core32_Int32 $f * @var ParagonIE_Sodium_Core32_Int32 $g0 * @var ParagonIE_Sodium_Core32_Int32 $g1 * @var ParagonIE_Sodium_Core32_Int32 $g2 * @var ParagonIE_Sodium_Core32_Int32 $g3 * @var ParagonIE_Sodium_Core32_Int32 $g4 * @var ParagonIE_Sodium_Core32_Int32 $h0 * @var ParagonIE_Sodium_Core32_Int32 $h1 * @var ParagonIE_Sodium_Core32_Int32 $h2 * @var ParagonIE_Sodium_Core32_Int32 $h3 * @var ParagonIE_Sodium_Core32_Int32 $h4 */ $h0 = $this->h[0]; $h1 = $this->h[1]; $h2 = $this->h[2]; $h3 = $this->h[3]; $h4 = $this->h[4]; $c = $h1->shiftRight(26); # $c = $h1 >> 26; $h1 = $h1->mask(0x3ffffff); # $h1 &= 0x3ffffff; $h2 = $h2->addInt32($c); # $h2 += $c; $c = $h2->shiftRight(26); # $c = $h2 >> 26; $h2 = $h2->mask(0x3ffffff); # $h2 &= 0x3ffffff; $h3 = $h3->addInt32($c); # $h3 += $c; $c = $h3->shiftRight(26); # $c = $h3 >> 26; $h3 = $h3->mask(0x3ffffff); # $h3 &= 0x3ffffff; $h4 = $h4->addInt32($c); # $h4 += $c; $c = $h4->shiftRight(26); # $c = $h4 >> 26; $h4 = $h4->mask(0x3ffffff); # $h4 &= 0x3ffffff; $h0 = $h0->addInt32($c->mulInt(5, 3)); # $h0 += self::mul($c, 5); $c = $h0->shiftRight(26); # $c = $h0 >> 26; $h0 = $h0->mask(0x3ffffff); # $h0 &= 0x3ffffff; $h1 = $h1->addInt32($c); # $h1 += $c; /* compute h + -p */ $g0 = $h0->addInt(5); $c = $g0->shiftRight(26); $g0 = $g0->mask(0x3ffffff); $g1 = $h1->addInt32($c); $c = $g1->shiftRight(26); $g1 = $g1->mask(0x3ffffff); $g2 = $h2->addInt32($c); $c = $g2->shiftRight(26); $g2 = $g2->mask(0x3ffffff); $g3 = $h3->addInt32($c); $c = $g3->shiftRight(26); $g3 = $g3->mask(0x3ffffff); $g4 = $h4->addInt32($c)->subInt(1 << 26); # $mask = ($g4 >> 31) - 1; /* select h if h < p, or h + -p if h >= p */ $mask = (int) (($g4->toInt() >> 31) + 1); $g0 = $g0->mask($mask); $g1 = $g1->mask($mask); $g2 = $g2->mask($mask); $g3 = $g3->mask($mask); $g4 = $g4->mask($mask); /** @var int $mask */ $mask = ~$mask; $h0 = $h0->mask($mask)->orInt32($g0); $h1 = $h1->mask($mask)->orInt32($g1); $h2 = $h2->mask($mask)->orInt32($g2); $h3 = $h3->mask($mask)->orInt32($g3); $h4 = $h4->mask($mask)->orInt32($g4); /* h = h % (2^128) */ $h0 = $h0->orInt32($h1->shiftLeft(26)); $h1 = $h1->shiftRight(6)->orInt32($h2->shiftLeft(20)); $h2 = $h2->shiftRight(12)->orInt32($h3->shiftLeft(14)); $h3 = $h3->shiftRight(18)->orInt32($h4->shiftLeft(8)); /* mac = (h + pad) % (2^128) */ $f = $h0->toInt64()->addInt64($this->pad[0]); $h0 = $f->toInt32(); $f = $h1->toInt64()->addInt64($this->pad[1])->addInt($h0->overflow); $h1 = $f->toInt32(); $f = $h2->toInt64()->addInt64($this->pad[2])->addInt($h1->overflow); $h2 = $f->toInt32(); $f = $h3->toInt64()->addInt64($this->pad[3])->addInt($h2->overflow); $h3 = $f->toInt32(); return $h0->toReverseString() . $h1->toReverseString() . $h2->toReverseString() . $h3->toReverseString(); } } PK������Z[(������Core32/SipHash.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_SipHash', false)) { return; } /** * Class ParagonIE_SodiumCompat_Core32_SipHash * * Only uses 32-bit arithmetic, while the original SipHash used 64-bit integers */ class ParagonIE_Sodium_Core32_SipHash extends ParagonIE_Sodium_Core32_Util { /** * @internal You should not use this directly from another application * * @param array<int, ParagonIE_Sodium_Core32_Int64> $v * @return array<int, ParagonIE_Sodium_Core32_Int64> */ public static function sipRound(array $v) { # v0 += v1; $v[0] = $v[0]->addInt64($v[1]); # v1 = ROTL(v1, 13); $v[1] = $v[1]->rotateLeft(13); # v1 ^= v0; $v[1] = $v[1]->xorInt64($v[0]); # v0=ROTL(v0,32); $v[0] = $v[0]->rotateLeft(32); # v2 += v3; $v[2] = $v[2]->addInt64($v[3]); # v3=ROTL(v3,16); $v[3] = $v[3]->rotateLeft(16); # v3 ^= v2; $v[3] = $v[3]->xorInt64($v[2]); # v0 += v3; $v[0] = $v[0]->addInt64($v[3]); # v3=ROTL(v3,21); $v[3] = $v[3]->rotateLeft(21); # v3 ^= v0; $v[3] = $v[3]->xorInt64($v[0]); # v2 += v1; $v[2] = $v[2]->addInt64($v[1]); # v1=ROTL(v1,17); $v[1] = $v[1]->rotateLeft(17); # v1 ^= v2; $v[1] = $v[1]->xorInt64($v[2]); # v2=ROTL(v2,32) $v[2] = $v[2]->rotateLeft(32); return $v; } /** * @internal You should not use this directly from another application * * @param string $in * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function sipHash24($in, $key) { $inlen = self::strlen($in); # /* "somepseudorandomlygeneratedbytes" */ # u64 v0 = 0x736f6d6570736575ULL; # u64 v1 = 0x646f72616e646f6dULL; # u64 v2 = 0x6c7967656e657261ULL; # u64 v3 = 0x7465646279746573ULL; $v = array( new ParagonIE_Sodium_Core32_Int64( array(0x736f, 0x6d65, 0x7073, 0x6575) ), new ParagonIE_Sodium_Core32_Int64( array(0x646f, 0x7261, 0x6e64, 0x6f6d) ), new ParagonIE_Sodium_Core32_Int64( array(0x6c79, 0x6765, 0x6e65, 0x7261) ), new ParagonIE_Sodium_Core32_Int64( array(0x7465, 0x6462, 0x7974, 0x6573) ) ); # u64 k0 = LOAD64_LE( k ); # u64 k1 = LOAD64_LE( k + 8 ); $k = array( ParagonIE_Sodium_Core32_Int64::fromReverseString( self::substr($key, 0, 8) ), ParagonIE_Sodium_Core32_Int64::fromReverseString( self::substr($key, 8, 8) ) ); # b = ( ( u64 )inlen ) << 56; $b = new ParagonIE_Sodium_Core32_Int64( array(($inlen << 8) & 0xffff, 0, 0, 0) ); # v3 ^= k1; $v[3] = $v[3]->xorInt64($k[1]); # v2 ^= k0; $v[2] = $v[2]->xorInt64($k[0]); # v1 ^= k1; $v[1] = $v[1]->xorInt64($k[1]); # v0 ^= k0; $v[0] = $v[0]->xorInt64($k[0]); $left = $inlen; # for ( ; in != end; in += 8 ) while ($left >= 8) { # m = LOAD64_LE( in ); $m = ParagonIE_Sodium_Core32_Int64::fromReverseString( self::substr($in, 0, 8) ); # v3 ^= m; $v[3] = $v[3]->xorInt64($m); # SIPROUND; # SIPROUND; $v = self::sipRound($v); $v = self::sipRound($v); # v0 ^= m; $v[0] = $v[0]->xorInt64($m); $in = self::substr($in, 8); $left -= 8; } # switch( left ) # { # case 7: b |= ( ( u64 )in[ 6] ) << 48; # case 6: b |= ( ( u64 )in[ 5] ) << 40; # case 5: b |= ( ( u64 )in[ 4] ) << 32; # case 4: b |= ( ( u64 )in[ 3] ) << 24; # case 3: b |= ( ( u64 )in[ 2] ) << 16; # case 2: b |= ( ( u64 )in[ 1] ) << 8; # case 1: b |= ( ( u64 )in[ 0] ); break; # case 0: break; # } switch ($left) { case 7: $b = $b->orInt64( ParagonIE_Sodium_Core32_Int64::fromInts( 0, self::chrToInt($in[6]) << 16 ) ); case 6: $b = $b->orInt64( ParagonIE_Sodium_Core32_Int64::fromInts( 0, self::chrToInt($in[5]) << 8 ) ); case 5: $b = $b->orInt64( ParagonIE_Sodium_Core32_Int64::fromInts( 0, self::chrToInt($in[4]) ) ); case 4: $b = $b->orInt64( ParagonIE_Sodium_Core32_Int64::fromInts( self::chrToInt($in[3]) << 24, 0 ) ); case 3: $b = $b->orInt64( ParagonIE_Sodium_Core32_Int64::fromInts( self::chrToInt($in[2]) << 16, 0 ) ); case 2: $b = $b->orInt64( ParagonIE_Sodium_Core32_Int64::fromInts( self::chrToInt($in[1]) << 8, 0 ) ); case 1: $b = $b->orInt64( ParagonIE_Sodium_Core32_Int64::fromInts( self::chrToInt($in[0]), 0 ) ); case 0: break; } # v3 ^= b; $v[3] = $v[3]->xorInt64($b); # SIPROUND; # SIPROUND; $v = self::sipRound($v); $v = self::sipRound($v); # v0 ^= b; $v[0] = $v[0]->xorInt64($b); // Flip the lower 8 bits of v2 which is ($v[4], $v[5]) in our implementation # v2 ^= 0xff; $v[2]->limbs[3] ^= 0xff; # SIPROUND; # SIPROUND; # SIPROUND; # SIPROUND; $v = self::sipRound($v); $v = self::sipRound($v); $v = self::sipRound($v); $v = self::sipRound($v); # b = v0 ^ v1 ^ v2 ^ v3; # STORE64_LE( out, b ); return $v[0] ->xorInt64($v[1]) ->xorInt64($v[2]) ->xorInt64($v[3]) ->toReverseString(); } } PK������ZHw=��w=����Core32/Ed25519.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_Ed25519', false)) { return; } if (!class_exists('ParagonIE_Sodium_Core32_Curve25519')) { require_once dirname(__FILE__) . '/Curve25519.php'; } /** * Class ParagonIE_Sodium_Core32_Ed25519 */ abstract class ParagonIE_Sodium_Core32_Ed25519 extends ParagonIE_Sodium_Core32_Curve25519 { const KEYPAIR_BYTES = 96; const SEED_BYTES = 32; /** * @internal You should not use this directly from another application * * @return string (96 bytes) * @throws Exception * @throws SodiumException * @throws TypeError */ public static function keypair() { $seed = random_bytes(self::SEED_BYTES); $pk = ''; $sk = ''; self::seed_keypair($pk, $sk, $seed); return $sk . $pk; } /** * @internal You should not use this directly from another application * * @param string $pk * @param string $sk * @param string $seed * @return string * @throws SodiumException * @throws TypeError */ public static function seed_keypair(&$pk, &$sk, $seed) { if (self::strlen($seed) !== self::SEED_BYTES) { throw new RangeException('crypto_sign keypair seed must be 32 bytes long'); } /** @var string $pk */ $pk = self::publickey_from_secretkey($seed); $sk = $seed . $pk; return $sk; } /** * @internal You should not use this directly from another application * * @param string $keypair * @return string * @throws TypeError */ public static function secretkey($keypair) { if (self::strlen($keypair) !== self::KEYPAIR_BYTES) { throw new RangeException('crypto_sign keypair must be 96 bytes long'); } return self::substr($keypair, 0, 64); } /** * @internal You should not use this directly from another application * * @param string $keypair * @return string * @throws RangeException * @throws TypeError */ public static function publickey($keypair) { if (self::strlen($keypair) !== self::KEYPAIR_BYTES) { throw new RangeException('crypto_sign keypair must be 96 bytes long'); } return self::substr($keypair, 64, 32); } /** * @internal You should not use this directly from another application * * @param string $sk * @return string * @throws SodiumException * @throws TypeError */ public static function publickey_from_secretkey($sk) { /** @var string $sk */ $sk = hash('sha512', self::substr($sk, 0, 32), true); $sk[0] = self::intToChr( self::chrToInt($sk[0]) & 248 ); $sk[31] = self::intToChr( (self::chrToInt($sk[31]) & 63) | 64 ); return self::sk_to_pk($sk); } /** * @param string $pk * @return string * @throws SodiumException * @throws TypeError */ public static function pk_to_curve25519($pk) { if (self::small_order($pk)) { throw new SodiumException('Public key is on a small order'); } $A = self::ge_frombytes_negate_vartime($pk); $p1 = self::ge_mul_l($A); if (!self::fe_isnonzero($p1->X)) { throw new SodiumException('Unexpected zero result'); } # fe_1(one_minus_y); # fe_sub(one_minus_y, one_minus_y, A.Y); # fe_invert(one_minus_y, one_minus_y); $one_minux_y = self::fe_invert( self::fe_sub( self::fe_1(), $A->Y ) ); # fe_1(x); # fe_add(x, x, A.Y); # fe_mul(x, x, one_minus_y); $x = self::fe_mul( self::fe_add(self::fe_1(), $A->Y), $one_minux_y ); # fe_tobytes(curve25519_pk, x); return self::fe_tobytes($x); } /** * @internal You should not use this directly from another application * * @param string $sk * @return string * @throws SodiumException * @throws TypeError */ public static function sk_to_pk($sk) { return self::ge_p3_tobytes( self::ge_scalarmult_base( self::substr($sk, 0, 32) ) ); } /** * @internal You should not use this directly from another application * * @param string $message * @param string $sk * @return string * @throws SodiumException * @throws TypeError */ public static function sign($message, $sk) { /** @var string $signature */ $signature = self::sign_detached($message, $sk); return $signature . $message; } /** * @internal You should not use this directly from another application * * @param string $message A signed message * @param string $pk Public key * @return string Message (without signature) * @throws SodiumException * @throws TypeError */ public static function sign_open($message, $pk) { /** @var string $signature */ $signature = self::substr($message, 0, 64); /** @var string $message */ $message = self::substr($message, 64); if (self::verify_detached($signature, $message, $pk)) { return $message; } throw new SodiumException('Invalid signature'); } /** * @internal You should not use this directly from another application * * @param string $message * @param string $sk * @return string * @throws SodiumException * @throws TypeError * @psalm-suppress PossiblyInvalidArgument */ public static function sign_detached($message, $sk) { # crypto_hash_sha512(az, sk, 32); $az = hash('sha512', self::substr($sk, 0, 32), true); # az[0] &= 248; # az[31] &= 63; # az[31] |= 64; $az[0] = self::intToChr(self::chrToInt($az[0]) & 248); $az[31] = self::intToChr((self::chrToInt($az[31]) & 63) | 64); # crypto_hash_sha512_init(&hs); # crypto_hash_sha512_update(&hs, az + 32, 32); # crypto_hash_sha512_update(&hs, m, mlen); # crypto_hash_sha512_final(&hs, nonce); $hs = hash_init('sha512'); self::hash_update($hs, self::substr($az, 32, 32)); self::hash_update($hs, $message); $nonceHash = hash_final($hs, true); # memmove(sig + 32, sk + 32, 32); $pk = self::substr($sk, 32, 32); # sc_reduce(nonce); # ge_scalarmult_base(&R, nonce); # ge_p3_tobytes(sig, &R); $nonce = self::sc_reduce($nonceHash) . self::substr($nonceHash, 32); $sig = self::ge_p3_tobytes( self::ge_scalarmult_base($nonce) ); # crypto_hash_sha512_init(&hs); # crypto_hash_sha512_update(&hs, sig, 64); # crypto_hash_sha512_update(&hs, m, mlen); # crypto_hash_sha512_final(&hs, hram); $hs = hash_init('sha512'); self::hash_update($hs, self::substr($sig, 0, 32)); self::hash_update($hs, self::substr($pk, 0, 32)); self::hash_update($hs, $message); $hramHash = hash_final($hs, true); # sc_reduce(hram); # sc_muladd(sig + 32, hram, az, nonce); $hram = self::sc_reduce($hramHash); $sigAfter = self::sc_muladd($hram, $az, $nonce); $sig = self::substr($sig, 0, 32) . self::substr($sigAfter, 0, 32); try { ParagonIE_Sodium_Compat::memzero($az); } catch (SodiumException $ex) { $az = null; } return $sig; } /** * @internal You should not use this directly from another application * * @param string $sig * @param string $message * @param string $pk * @return bool * @throws SodiumException * @throws TypeError */ public static function verify_detached($sig, $message, $pk) { if (self::strlen($sig) < 64) { throw new SodiumException('Signature is too short'); } if ((self::chrToInt($sig[63]) & 240) && self::check_S_lt_L(self::substr($sig, 32, 32))) { throw new SodiumException('S < L - Invalid signature'); } if (self::small_order($sig)) { throw new SodiumException('Signature is on too small of an order'); } if ((self::chrToInt($sig[63]) & 224) !== 0) { throw new SodiumException('Invalid signature'); } $d = 0; for ($i = 0; $i < 32; ++$i) { $d |= self::chrToInt($pk[$i]); } if ($d === 0) { throw new SodiumException('All zero public key'); } /** @var bool The original value of ParagonIE_Sodium_Compat::$fastMult */ $orig = ParagonIE_Sodium_Compat::$fastMult; // Set ParagonIE_Sodium_Compat::$fastMult to true to speed up verification. ParagonIE_Sodium_Compat::$fastMult = true; /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A */ $A = self::ge_frombytes_negate_vartime($pk); /** @var string $hDigest */ $hDigest = hash( 'sha512', self::substr($sig, 0, 32) . self::substr($pk, 0, 32) . $message, true ); /** @var string $h */ $h = self::sc_reduce($hDigest) . self::substr($hDigest, 32); /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $R */ $R = self::ge_double_scalarmult_vartime( $h, $A, self::substr($sig, 32) ); /** @var string $rcheck */ $rcheck = self::ge_tobytes($R); // Reset ParagonIE_Sodium_Compat::$fastMult to what it was before. ParagonIE_Sodium_Compat::$fastMult = $orig; return self::verify_32($rcheck, self::substr($sig, 0, 32)); } /** * @internal You should not use this directly from another application * * @param string $S * @return bool * @throws SodiumException * @throws TypeError */ public static function check_S_lt_L($S) { if (self::strlen($S) < 32) { throw new SodiumException('Signature must be 32 bytes'); } static $L = array( 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 ); /** @var array<int, int> $L */ $c = 0; $n = 1; $i = 32; do { --$i; $x = self::chrToInt($S[$i]); $c |= ( (($x - $L[$i]) >> 8) & $n ); $n &= ( (($x ^ $L[$i]) - 1) >> 8 ); } while ($i !== 0); return $c === 0; } /** * @param string $R * @return bool * @throws SodiumException * @throws TypeError */ public static function small_order($R) { static $blocklist = array( /* 0 (order 4) */ array( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), /* 1 (order 1) */ array( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), /* 2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */ array( 0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05 ), /* 55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */ array( 0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a ), /* p-1 (order 2) */ array( 0x13, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x85 ), /* p (order 4) */ array( 0xb4, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa ), /* p+1 (order 1) */ array( 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f ), /* p+2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */ array( 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f ), /* p+55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */ array( 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f ), /* 2p-1 (order 2) */ array( 0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ), /* 2p (order 4) */ array( 0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ), /* 2p+1 (order 1) */ array( 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ) ); /** @var array<int, array<int, int>> $blocklist */ $countBlocklist = count($blocklist); for ($i = 0; $i < $countBlocklist; ++$i) { $c = 0; for ($j = 0; $j < 32; ++$j) { $c |= self::chrToInt($R[$j]) ^ $blocklist[$i][$j]; } if ($c === 0) { return true; } } return false; } } PK������Z21������Core32/HChaCha20.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_HChaCha20', false)) { return; } /** * Class ParagonIE_Sodium_Core_HChaCha20 */ class ParagonIE_Sodium_Core32_HChaCha20 extends ParagonIE_Sodium_Core32_ChaCha20 { /** * @param string $in * @param string $key * @param string|null $c * @return string * @throws SodiumException * @throws TypeError */ public static function hChaCha20($in = '', $key = '', $c = null) { $ctx = array(); if ($c === null) { $ctx[0] = new ParagonIE_Sodium_Core32_Int32(array(0x6170, 0x7865)); $ctx[1] = new ParagonIE_Sodium_Core32_Int32(array(0x3320, 0x646e)); $ctx[2] = new ParagonIE_Sodium_Core32_Int32(array(0x7962, 0x2d32)); $ctx[3] = new ParagonIE_Sodium_Core32_Int32(array(0x6b20, 0x6574)); } else { $ctx[0] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 0, 4)); $ctx[1] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 4, 4)); $ctx[2] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 8, 4)); $ctx[3] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 12, 4)); } $ctx[4] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 0, 4)); $ctx[5] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 4, 4)); $ctx[6] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 8, 4)); $ctx[7] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 12, 4)); $ctx[8] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 16, 4)); $ctx[9] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 20, 4)); $ctx[10] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 24, 4)); $ctx[11] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 28, 4)); $ctx[12] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 0, 4)); $ctx[13] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 4, 4)); $ctx[14] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 8, 4)); $ctx[15] = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 12, 4)); return self::hChaCha20Bytes($ctx); } /** * @param array $ctx * @return string * @throws SodiumException * @throws TypeError */ protected static function hChaCha20Bytes(array $ctx) { /** @var ParagonIE_Sodium_Core32_Int32 $x0 */ $x0 = $ctx[0]; /** @var ParagonIE_Sodium_Core32_Int32 $x1 */ $x1 = $ctx[1]; /** @var ParagonIE_Sodium_Core32_Int32 $x2 */ $x2 = $ctx[2]; /** @var ParagonIE_Sodium_Core32_Int32 $x3 */ $x3 = $ctx[3]; /** @var ParagonIE_Sodium_Core32_Int32 $x4 */ $x4 = $ctx[4]; /** @var ParagonIE_Sodium_Core32_Int32 $x5 */ $x5 = $ctx[5]; /** @var ParagonIE_Sodium_Core32_Int32 $x6 */ $x6 = $ctx[6]; /** @var ParagonIE_Sodium_Core32_Int32 $x7 */ $x7 = $ctx[7]; /** @var ParagonIE_Sodium_Core32_Int32 $x8 */ $x8 = $ctx[8]; /** @var ParagonIE_Sodium_Core32_Int32 $x9 */ $x9 = $ctx[9]; /** @var ParagonIE_Sodium_Core32_Int32 $x10 */ $x10 = $ctx[10]; /** @var ParagonIE_Sodium_Core32_Int32 $x11 */ $x11 = $ctx[11]; /** @var ParagonIE_Sodium_Core32_Int32 $x12 */ $x12 = $ctx[12]; /** @var ParagonIE_Sodium_Core32_Int32 $x13 */ $x13 = $ctx[13]; /** @var ParagonIE_Sodium_Core32_Int32 $x14 */ $x14 = $ctx[14]; /** @var ParagonIE_Sodium_Core32_Int32 $x15 */ $x15 = $ctx[15]; for ($i = 0; $i < 10; ++$i) { # QUARTERROUND( x0, x4, x8, x12) list($x0, $x4, $x8, $x12) = self::quarterRound($x0, $x4, $x8, $x12); # QUARTERROUND( x1, x5, x9, x13) list($x1, $x5, $x9, $x13) = self::quarterRound($x1, $x5, $x9, $x13); # QUARTERROUND( x2, x6, x10, x14) list($x2, $x6, $x10, $x14) = self::quarterRound($x2, $x6, $x10, $x14); # QUARTERROUND( x3, x7, x11, x15) list($x3, $x7, $x11, $x15) = self::quarterRound($x3, $x7, $x11, $x15); # QUARTERROUND( x0, x5, x10, x15) list($x0, $x5, $x10, $x15) = self::quarterRound($x0, $x5, $x10, $x15); # QUARTERROUND( x1, x6, x11, x12) list($x1, $x6, $x11, $x12) = self::quarterRound($x1, $x6, $x11, $x12); # QUARTERROUND( x2, x7, x8, x13) list($x2, $x7, $x8, $x13) = self::quarterRound($x2, $x7, $x8, $x13); # QUARTERROUND( x3, x4, x9, x14) list($x3, $x4, $x9, $x14) = self::quarterRound($x3, $x4, $x9, $x14); } return $x0->toReverseString() . $x1->toReverseString() . $x2->toReverseString() . $x3->toReverseString() . $x12->toReverseString() . $x13->toReverseString() . $x14->toReverseString() . $x15->toReverseString(); } } PK������Z["+��"+����Core32/X25519.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_X25519', false)) { return; } /** * Class ParagonIE_Sodium_Core32_X25519 */ abstract class ParagonIE_Sodium_Core32_X25519 extends ParagonIE_Sodium_Core32_Curve25519 { /** * Alters the objects passed to this method in place. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g * @param int $b * @return void * @throws SodiumException * @throws TypeError * @psalm-suppress MixedMethodCall */ public static function fe_cswap( ParagonIE_Sodium_Core32_Curve25519_Fe $f, ParagonIE_Sodium_Core32_Curve25519_Fe $g, $b = 0 ) { $f0 = (int) $f[0]->toInt(); $f1 = (int) $f[1]->toInt(); $f2 = (int) $f[2]->toInt(); $f3 = (int) $f[3]->toInt(); $f4 = (int) $f[4]->toInt(); $f5 = (int) $f[5]->toInt(); $f6 = (int) $f[6]->toInt(); $f7 = (int) $f[7]->toInt(); $f8 = (int) $f[8]->toInt(); $f9 = (int) $f[9]->toInt(); $g0 = (int) $g[0]->toInt(); $g1 = (int) $g[1]->toInt(); $g2 = (int) $g[2]->toInt(); $g3 = (int) $g[3]->toInt(); $g4 = (int) $g[4]->toInt(); $g5 = (int) $g[5]->toInt(); $g6 = (int) $g[6]->toInt(); $g7 = (int) $g[7]->toInt(); $g8 = (int) $g[8]->toInt(); $g9 = (int) $g[9]->toInt(); $b = -$b; /** @var int $x0 */ $x0 = ($f0 ^ $g0) & $b; /** @var int $x1 */ $x1 = ($f1 ^ $g1) & $b; /** @var int $x2 */ $x2 = ($f2 ^ $g2) & $b; /** @var int $x3 */ $x3 = ($f3 ^ $g3) & $b; /** @var int $x4 */ $x4 = ($f4 ^ $g4) & $b; /** @var int $x5 */ $x5 = ($f5 ^ $g5) & $b; /** @var int $x6 */ $x6 = ($f6 ^ $g6) & $b; /** @var int $x7 */ $x7 = ($f7 ^ $g7) & $b; /** @var int $x8 */ $x8 = ($f8 ^ $g8) & $b; /** @var int $x9 */ $x9 = ($f9 ^ $g9) & $b; $f[0] = ParagonIE_Sodium_Core32_Int32::fromInt($f0 ^ $x0); $f[1] = ParagonIE_Sodium_Core32_Int32::fromInt($f1 ^ $x1); $f[2] = ParagonIE_Sodium_Core32_Int32::fromInt($f2 ^ $x2); $f[3] = ParagonIE_Sodium_Core32_Int32::fromInt($f3 ^ $x3); $f[4] = ParagonIE_Sodium_Core32_Int32::fromInt($f4 ^ $x4); $f[5] = ParagonIE_Sodium_Core32_Int32::fromInt($f5 ^ $x5); $f[6] = ParagonIE_Sodium_Core32_Int32::fromInt($f6 ^ $x6); $f[7] = ParagonIE_Sodium_Core32_Int32::fromInt($f7 ^ $x7); $f[8] = ParagonIE_Sodium_Core32_Int32::fromInt($f8 ^ $x8); $f[9] = ParagonIE_Sodium_Core32_Int32::fromInt($f9 ^ $x9); $g[0] = ParagonIE_Sodium_Core32_Int32::fromInt($g0 ^ $x0); $g[1] = ParagonIE_Sodium_Core32_Int32::fromInt($g1 ^ $x1); $g[2] = ParagonIE_Sodium_Core32_Int32::fromInt($g2 ^ $x2); $g[3] = ParagonIE_Sodium_Core32_Int32::fromInt($g3 ^ $x3); $g[4] = ParagonIE_Sodium_Core32_Int32::fromInt($g4 ^ $x4); $g[5] = ParagonIE_Sodium_Core32_Int32::fromInt($g5 ^ $x5); $g[6] = ParagonIE_Sodium_Core32_Int32::fromInt($g6 ^ $x6); $g[7] = ParagonIE_Sodium_Core32_Int32::fromInt($g7 ^ $x7); $g[8] = ParagonIE_Sodium_Core32_Int32::fromInt($g8 ^ $x8); $g[9] = ParagonIE_Sodium_Core32_Int32::fromInt($g9 ^ $x9); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f * @return ParagonIE_Sodium_Core32_Curve25519_Fe * @throws SodiumException * @throws TypeError * @psalm-suppress MixedAssignment * @psalm-suppress MixedMethodCall */ public static function fe_mul121666(ParagonIE_Sodium_Core32_Curve25519_Fe $f) { /** @var array<int, ParagonIE_Sodium_Core32_Int64> $h */ $h = array(); for ($i = 0; $i < 10; ++$i) { $h[$i] = $f[$i]->toInt64()->mulInt(121666, 17); } $carry9 = $h[9]->addInt(1 << 24)->shiftRight(25); $h[0] = $h[0]->addInt64($carry9->mulInt(19, 5)); $h[9] = $h[9]->subInt64($carry9->shiftLeft(25)); $carry1 = $h[1]->addInt(1 << 24)->shiftRight(25); $h[2] = $h[2]->addInt64($carry1); $h[1] = $h[1]->subInt64($carry1->shiftLeft(25)); $carry3 = $h[3]->addInt(1 << 24)->shiftRight(25); $h[4] = $h[4]->addInt64($carry3); $h[3] = $h[3]->subInt64($carry3->shiftLeft(25)); $carry5 = $h[5]->addInt(1 << 24)->shiftRight(25); $h[6] = $h[6]->addInt64($carry5); $h[5] = $h[5]->subInt64($carry5->shiftLeft(25)); $carry7 = $h[7]->addInt(1 << 24)->shiftRight(25); $h[8] = $h[8]->addInt64($carry7); $h[7] = $h[7]->subInt64($carry7->shiftLeft(25)); $carry0 = $h[0]->addInt(1 << 25)->shiftRight(26); $h[1] = $h[1]->addInt64($carry0); $h[0] = $h[0]->subInt64($carry0->shiftLeft(26)); $carry2 = $h[2]->addInt(1 << 25)->shiftRight(26); $h[3] = $h[3]->addInt64($carry2); $h[2] = $h[2]->subInt64($carry2->shiftLeft(26)); $carry4 = $h[4]->addInt(1 << 25)->shiftRight(26); $h[5] = $h[5]->addInt64($carry4); $h[4] = $h[4]->subInt64($carry4->shiftLeft(26)); $carry6 = $h[6]->addInt(1 << 25)->shiftRight(26); $h[7] = $h[7]->addInt64($carry6); $h[6] = $h[6]->subInt64($carry6->shiftLeft(26)); $carry8 = $h[8]->addInt(1 << 25)->shiftRight(26); $h[9] = $h[9]->addInt64($carry8); $h[8] = $h[8]->subInt64($carry8->shiftLeft(26)); for ($i = 0; $i < 10; ++$i) { $h[$i] = $h[$i]->toInt32(); } /** @var array<int, ParagonIE_Sodium_Core32_Int32> $h2 */ $h2 = $h; return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray($h2); } /** * @internal You should not use this directly from another application * * Inline comments preceded by # are from libsodium's ref10 code. * * @param string $n * @param string $p * @return string * @throws SodiumException * @throws TypeError */ public static function crypto_scalarmult_curve25519_ref10($n, $p) { # for (i = 0;i < 32;++i) e[i] = n[i]; $e = '' . $n; # e[0] &= 248; $e[0] = self::intToChr( self::chrToInt($e[0]) & 248 ); # e[31] &= 127; # e[31] |= 64; $e[31] = self::intToChr( (self::chrToInt($e[31]) & 127) | 64 ); # fe_frombytes(x1,p); $x1 = self::fe_frombytes($p); # fe_1(x2); $x2 = self::fe_1(); # fe_0(z2); $z2 = self::fe_0(); # fe_copy(x3,x1); $x3 = self::fe_copy($x1); # fe_1(z3); $z3 = self::fe_1(); # swap = 0; /** @var int $swap */ $swap = 0; # for (pos = 254;pos >= 0;--pos) { for ($pos = 254; $pos >= 0; --$pos) { # b = e[pos / 8] >> (pos & 7); /** @var int $b */ $b = self::chrToInt( $e[(int) floor($pos / 8)] ) >> ($pos & 7); # b &= 1; $b &= 1; # swap ^= b; $swap ^= $b; # fe_cswap(x2,x3,swap); self::fe_cswap($x2, $x3, $swap); # fe_cswap(z2,z3,swap); self::fe_cswap($z2, $z3, $swap); # swap = b; /** @var int $swap */ $swap = $b; # fe_sub(tmp0,x3,z3); $tmp0 = self::fe_sub($x3, $z3); # fe_sub(tmp1,x2,z2); $tmp1 = self::fe_sub($x2, $z2); # fe_add(x2,x2,z2); $x2 = self::fe_add($x2, $z2); # fe_add(z2,x3,z3); $z2 = self::fe_add($x3, $z3); # fe_mul(z3,tmp0,x2); $z3 = self::fe_mul($tmp0, $x2); # fe_mul(z2,z2,tmp1); $z2 = self::fe_mul($z2, $tmp1); # fe_sq(tmp0,tmp1); $tmp0 = self::fe_sq($tmp1); # fe_sq(tmp1,x2); $tmp1 = self::fe_sq($x2); # fe_add(x3,z3,z2); $x3 = self::fe_add($z3, $z2); # fe_sub(z2,z3,z2); $z2 = self::fe_sub($z3, $z2); # fe_mul(x2,tmp1,tmp0); $x2 = self::fe_mul($tmp1, $tmp0); # fe_sub(tmp1,tmp1,tmp0); $tmp1 = self::fe_sub($tmp1, $tmp0); # fe_sq(z2,z2); $z2 = self::fe_sq($z2); # fe_mul121666(z3,tmp1); $z3 = self::fe_mul121666($tmp1); # fe_sq(x3,x3); $x3 = self::fe_sq($x3); # fe_add(tmp0,tmp0,z3); $tmp0 = self::fe_add($tmp0, $z3); # fe_mul(z3,x1,z2); $z3 = self::fe_mul($x1, $z2); # fe_mul(z2,tmp1,tmp0); $z2 = self::fe_mul($tmp1, $tmp0); } # fe_cswap(x2,x3,swap); self::fe_cswap($x2, $x3, $swap); # fe_cswap(z2,z3,swap); self::fe_cswap($z2, $z3, $swap); # fe_invert(z2,z2); $z2 = self::fe_invert($z2); # fe_mul(x2,x2,z2); $x2 = self::fe_mul($x2, $z2); # fe_tobytes(q,x2); return (string) self::fe_tobytes($x2); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsY * @param ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsZ * @return ParagonIE_Sodium_Core32_Curve25519_Fe * @throws SodiumException * @throws TypeError */ public static function edwards_to_montgomery( ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsY, ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsZ ) { $tempX = self::fe_add($edwardsZ, $edwardsY); $tempZ = self::fe_sub($edwardsZ, $edwardsY); $tempZ = self::fe_invert($tempZ); return self::fe_mul($tempX, $tempZ); } /** * @internal You should not use this directly from another application * * @param string $n * @return string * @throws SodiumException * @throws TypeError */ public static function crypto_scalarmult_curve25519_ref10_base($n) { # for (i = 0;i < 32;++i) e[i] = n[i]; $e = '' . $n; # e[0] &= 248; $e[0] = self::intToChr( self::chrToInt($e[0]) & 248 ); # e[31] &= 127; # e[31] |= 64; $e[31] = self::intToChr( (self::chrToInt($e[31]) & 127) | 64 ); $A = self::ge_scalarmult_base($e); if ( !($A->Y instanceof ParagonIE_Sodium_Core32_Curve25519_Fe) || !($A->Z instanceof ParagonIE_Sodium_Core32_Curve25519_Fe) ) { throw new TypeError('Null points encountered'); } $pk = self::edwards_to_montgomery($A->Y, $A->Z); return self::fe_tobytes($pk); } } PK������Zw`2��2����Core32/Poly1305.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_Poly1305', false)) { return; } /** * Class ParagonIE_Sodium_Core32_Poly1305 */ abstract class ParagonIE_Sodium_Core32_Poly1305 extends ParagonIE_Sodium_Core32_Util { const BLOCK_SIZE = 16; /** * @internal You should not use this directly from another application * * @param string $m * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function onetimeauth($m, $key) { if (self::strlen($key) < 32) { throw new InvalidArgumentException( 'Key must be 32 bytes long.' ); } $state = new ParagonIE_Sodium_Core32_Poly1305_State( self::substr($key, 0, 32) ); return $state ->update($m) ->finish(); } /** * @internal You should not use this directly from another application * * @param string $mac * @param string $m * @param string $key * @return bool * @throws SodiumException * @throws TypeError */ public static function onetimeauth_verify($mac, $m, $key) { if (self::strlen($key) < 32) { throw new InvalidArgumentException( 'Key must be 32 bytes long.' ); } $state = new ParagonIE_Sodium_Core32_Poly1305_State( self::substr($key, 0, 32) ); $calc = $state ->update($m) ->finish(); return self::verify_16($calc, $mac); } } PK������Z6(4W��4W����Core32/BLAKE2b.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_BLAKE2b', false)) { return; } /** * Class ParagonIE_Sodium_Core_BLAKE2b * * Based on the work of Devi Mandiri in devi/salt. */ abstract class ParagonIE_Sodium_Core32_BLAKE2b extends ParagonIE_Sodium_Core_Util { /** * @var SplFixedArray */ public static $iv; /** * @var array<int, array<int, int>> */ public static $sigma = array( array( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), array( 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3), array( 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4), array( 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8), array( 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13), array( 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9), array( 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11), array( 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10), array( 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5), array( 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0), array( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), array( 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3) ); const BLOCKBYTES = 128; const OUTBYTES = 64; const KEYBYTES = 64; /** * Turn two 32-bit integers into a fixed array representing a 64-bit integer. * * @internal You should not use this directly from another application * * @param int $high * @param int $low * @return ParagonIE_Sodium_Core32_Int64 * @throws SodiumException * @throws TypeError */ public static function new64($high, $low) { return ParagonIE_Sodium_Core32_Int64::fromInts($low, $high); } /** * Convert an arbitrary number into an SplFixedArray of two 32-bit integers * that represents a 64-bit integer. * * @internal You should not use this directly from another application * * @param int $num * @return ParagonIE_Sodium_Core32_Int64 * @throws SodiumException * @throws TypeError */ protected static function to64($num) { list($hi, $lo) = self::numericTo64BitInteger($num); return self::new64($hi, $lo); } /** * Adds two 64-bit integers together, returning their sum as a SplFixedArray * containing two 32-bit integers (representing a 64-bit integer). * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Int64 $x * @param ParagonIE_Sodium_Core32_Int64 $y * @return ParagonIE_Sodium_Core32_Int64 */ protected static function add64($x, $y) { return $x->addInt64($y); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Int64 $x * @param ParagonIE_Sodium_Core32_Int64 $y * @param ParagonIE_Sodium_Core32_Int64 $z * @return ParagonIE_Sodium_Core32_Int64 */ public static function add364($x, $y, $z) { return $x->addInt64($y)->addInt64($z); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Int64 $x * @param ParagonIE_Sodium_Core32_Int64 $y * @return ParagonIE_Sodium_Core32_Int64 * @throws TypeError */ public static function xor64(ParagonIE_Sodium_Core32_Int64 $x, ParagonIE_Sodium_Core32_Int64 $y) { return $x->xorInt64($y); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Int64 $x * @param int $c * @return ParagonIE_Sodium_Core32_Int64 * @throws SodiumException * @throws TypeError */ public static function rotr64(ParagonIE_Sodium_Core32_Int64 $x, $c) { return $x->rotateRight($c); } /** * @internal You should not use this directly from another application * * @param SplFixedArray $x * @param int $i * @return ParagonIE_Sodium_Core32_Int64 * @throws SodiumException * @throws TypeError */ public static function load64($x, $i) { /** @var int $l */ $l = (int) ($x[$i]) | ((int) ($x[$i+1]) << 8) | ((int) ($x[$i+2]) << 16) | ((int) ($x[$i+3]) << 24); /** @var int $h */ $h = (int) ($x[$i+4]) | ((int) ($x[$i+5]) << 8) | ((int) ($x[$i+6]) << 16) | ((int) ($x[$i+7]) << 24); return self::new64($h, $l); } /** * @internal You should not use this directly from another application * * @param SplFixedArray $x * @param int $i * @param ParagonIE_Sodium_Core32_Int64 $u * @return void * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedAssignment * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayAssignment * @psalm-suppress MixedArrayOffset */ public static function store64(SplFixedArray $x, $i, ParagonIE_Sodium_Core32_Int64 $u) { $v = clone $u; $maxLength = $x->getSize() - 1; for ($j = 0; $j < 8; ++$j) { $k = 3 - ($j >> 1); $x[$i] = $v->limbs[$k] & 0xff; if (++$i > $maxLength) { return; } $v->limbs[$k] >>= 8; } } /** * This just sets the $iv static variable. * * @internal You should not use this directly from another application * * @return void * @throws SodiumException * @throws TypeError */ public static function pseudoConstructor() { static $called = false; if ($called) { return; } self::$iv = new SplFixedArray(8); self::$iv[0] = self::new64(0x6a09e667, 0xf3bcc908); self::$iv[1] = self::new64(0xbb67ae85, 0x84caa73b); self::$iv[2] = self::new64(0x3c6ef372, 0xfe94f82b); self::$iv[3] = self::new64(0xa54ff53a, 0x5f1d36f1); self::$iv[4] = self::new64(0x510e527f, 0xade682d1); self::$iv[5] = self::new64(0x9b05688c, 0x2b3e6c1f); self::$iv[6] = self::new64(0x1f83d9ab, 0xfb41bd6b); self::$iv[7] = self::new64(0x5be0cd19, 0x137e2179); $called = true; } /** * Returns a fresh BLAKE2 context. * * @internal You should not use this directly from another application * * @return SplFixedArray * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedAssignment * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayAssignment * @psalm-suppress MixedArrayOffset * @throws SodiumException * @throws TypeError */ protected static function context() { $ctx = new SplFixedArray(6); $ctx[0] = new SplFixedArray(8); // h $ctx[1] = new SplFixedArray(2); // t $ctx[2] = new SplFixedArray(2); // f $ctx[3] = new SplFixedArray(256); // buf $ctx[4] = 0; // buflen $ctx[5] = 0; // last_node (uint8_t) for ($i = 8; $i--;) { $ctx[0][$i] = self::$iv[$i]; } for ($i = 256; $i--;) { $ctx[3][$i] = 0; } $zero = self::new64(0, 0); $ctx[1][0] = $zero; $ctx[1][1] = $zero; $ctx[2][0] = $zero; $ctx[2][1] = $zero; return $ctx; } /** * @internal You should not use this directly from another application * * @param SplFixedArray $ctx * @param SplFixedArray $buf * @return void * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayAssignment * @psalm-suppress MixedAssignment */ protected static function compress(SplFixedArray $ctx, SplFixedArray $buf) { $m = new SplFixedArray(16); $v = new SplFixedArray(16); for ($i = 16; $i--;) { $m[$i] = self::load64($buf, $i << 3); } for ($i = 8; $i--;) { $v[$i] = $ctx[0][$i]; } $v[ 8] = self::$iv[0]; $v[ 9] = self::$iv[1]; $v[10] = self::$iv[2]; $v[11] = self::$iv[3]; $v[12] = self::xor64($ctx[1][0], self::$iv[4]); $v[13] = self::xor64($ctx[1][1], self::$iv[5]); $v[14] = self::xor64($ctx[2][0], self::$iv[6]); $v[15] = self::xor64($ctx[2][1], self::$iv[7]); for ($r = 0; $r < 12; ++$r) { $v = self::G($r, 0, 0, 4, 8, 12, $v, $m); $v = self::G($r, 1, 1, 5, 9, 13, $v, $m); $v = self::G($r, 2, 2, 6, 10, 14, $v, $m); $v = self::G($r, 3, 3, 7, 11, 15, $v, $m); $v = self::G($r, 4, 0, 5, 10, 15, $v, $m); $v = self::G($r, 5, 1, 6, 11, 12, $v, $m); $v = self::G($r, 6, 2, 7, 8, 13, $v, $m); $v = self::G($r, 7, 3, 4, 9, 14, $v, $m); } for ($i = 8; $i--;) { $ctx[0][$i] = self::xor64( $ctx[0][$i], self::xor64($v[$i], $v[$i+8]) ); } } /** * @internal You should not use this directly from another application * * @param int $r * @param int $i * @param int $a * @param int $b * @param int $c * @param int $d * @param SplFixedArray $v * @param SplFixedArray $m * @return SplFixedArray * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedArrayOffset */ public static function G($r, $i, $a, $b, $c, $d, SplFixedArray $v, SplFixedArray $m) { $v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][$i << 1]]); $v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 32); $v[$c] = self::add64($v[$c], $v[$d]); $v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 24); $v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][($i << 1) + 1]]); $v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 16); $v[$c] = self::add64($v[$c], $v[$d]); $v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 63); return $v; } /** * @internal You should not use this directly from another application * * @param SplFixedArray $ctx * @param int $inc * @return void * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayAssignment */ public static function increment_counter($ctx, $inc) { if ($inc < 0) { throw new SodiumException('Increasing by a negative number makes no sense.'); } $t = self::to64($inc); # S->t is $ctx[1] in our implementation # S->t[0] = ( uint64_t )( t >> 0 ); $ctx[1][0] = self::add64($ctx[1][0], $t); # S->t[1] += ( S->t[0] < inc ); if (!($ctx[1][0] instanceof ParagonIE_Sodium_Core32_Int64)) { throw new TypeError('Not an int64'); } /** @var ParagonIE_Sodium_Core32_Int64 $c*/ $c = $ctx[1][0]; if ($c->isLessThanInt($inc)) { $ctx[1][1] = self::add64($ctx[1][1], self::to64(1)); } } /** * @internal You should not use this directly from another application * * @param SplFixedArray $ctx * @param SplFixedArray $p * @param int $plen * @return void * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedAssignment * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayAssignment * @psalm-suppress MixedArrayOffset * @psalm-suppress MixedMethodCall * @psalm-suppress MixedOperand */ public static function update(SplFixedArray $ctx, SplFixedArray $p, $plen) { self::pseudoConstructor(); $offset = 0; while ($plen > 0) { $left = $ctx[4]; $fill = 256 - $left; if ($plen > $fill) { # memcpy( S->buf + left, in, fill ); /* Fill buffer */ for ($i = $fill; $i--;) { $ctx[3][$i + $left] = $p[$i + $offset]; } # S->buflen += fill; $ctx[4] += $fill; # blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); self::increment_counter($ctx, 128); # blake2b_compress( S, S->buf ); /* Compress */ self::compress($ctx, $ctx[3]); # memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); /* Shift buffer left */ for ($i = 128; $i--;) { $ctx[3][$i] = $ctx[3][$i + 128]; } # S->buflen -= BLAKE2B_BLOCKBYTES; $ctx[4] -= 128; # in += fill; $offset += $fill; # inlen -= fill; $plen -= $fill; } else { for ($i = $plen; $i--;) { $ctx[3][$i + $left] = $p[$i + $offset]; } $ctx[4] += $plen; $offset += $plen; $plen -= $plen; } } } /** * @internal You should not use this directly from another application * * @param SplFixedArray $ctx * @param SplFixedArray $out * @return SplFixedArray * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedAssignment * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayAssignment * @psalm-suppress MixedArrayOffset * @psalm-suppress MixedMethodCall * @psalm-suppress MixedOperand */ public static function finish(SplFixedArray $ctx, SplFixedArray $out) { self::pseudoConstructor(); if ($ctx[4] > 128) { self::increment_counter($ctx, 128); self::compress($ctx, $ctx[3]); $ctx[4] -= 128; if ($ctx[4] > 128) { throw new SodiumException('Failed to assert that buflen <= 128 bytes'); } for ($i = $ctx[4]; $i--;) { $ctx[3][$i] = $ctx[3][$i + 128]; } } self::increment_counter($ctx, $ctx[4]); $ctx[2][0] = self::new64(0xffffffff, 0xffffffff); for ($i = 256 - $ctx[4]; $i--;) { /** @var int $i */ $ctx[3][$i + $ctx[4]] = 0; } self::compress($ctx, $ctx[3]); $i = (int) (($out->getSize() - 1) / 8); for (; $i >= 0; --$i) { self::store64($out, $i << 3, $ctx[0][$i]); } return $out; } /** * @internal You should not use this directly from another application * * @param SplFixedArray|null $key * @param int $outlen * @param SplFixedArray|null $salt * @param SplFixedArray|null $personal * @return SplFixedArray * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedAssignment * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayAssignment * @psalm-suppress MixedMethodCall */ public static function init( $key = null, $outlen = 64, $salt = null, $personal = null ) { self::pseudoConstructor(); $klen = 0; if ($key !== null) { if (count($key) > 64) { throw new SodiumException('Invalid key size'); } $klen = count($key); } if ($outlen > 64) { throw new SodiumException('Invalid output size'); } $ctx = self::context(); $p = new SplFixedArray(64); // Zero our param buffer... for ($i = 64; --$i;) { $p[$i] = 0; } $p[0] = $outlen; // digest_length $p[1] = $klen; // key_length $p[2] = 1; // fanout $p[3] = 1; // depth if ($salt instanceof SplFixedArray) { // salt: [32] through [47] for ($i = 0; $i < 16; ++$i) { $p[32 + $i] = (int) $salt[$i]; } } if ($personal instanceof SplFixedArray) { // personal: [48] through [63] for ($i = 0; $i < 16; ++$i) { $p[48 + $i] = (int) $personal[$i]; } } $ctx[0][0] = self::xor64( $ctx[0][0], self::load64($p, 0) ); if ($salt instanceof SplFixedArray || $personal instanceof SplFixedArray) { // We need to do what blake2b_init_param() does: for ($i = 1; $i < 8; ++$i) { $ctx[0][$i] = self::xor64( $ctx[0][$i], self::load64($p, $i << 3) ); } } if ($klen > 0 && $key instanceof SplFixedArray) { $block = new SplFixedArray(128); for ($i = 128; $i--;) { $block[$i] = 0; } for ($i = $klen; $i--;) { $block[$i] = $key[$i]; } self::update($ctx, $block, 128); $ctx[4] = 128; } return $ctx; } /** * Convert a string into an SplFixedArray of integers * * @internal You should not use this directly from another application * * @param string $str * @return SplFixedArray * @psalm-suppress MixedArgumentTypeCoercion */ public static function stringToSplFixedArray($str = '') { $values = unpack('C*', $str); return SplFixedArray::fromArray(array_values($values)); } /** * Convert an SplFixedArray of integers into a string * * @internal You should not use this directly from another application * * @param SplFixedArray $a * @return string */ public static function SplFixedArrayToString(SplFixedArray $a) { /** * @var array<int, string|int> */ $arr = $a->toArray(); $c = $a->count(); array_unshift($arr, str_repeat('C', $c)); return (string) (call_user_func_array('pack', $arr)); } /** * @internal You should not use this directly from another application * * @param SplFixedArray $ctx * @return string * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayAssignment * @psalm-suppress MixedMethodCall */ public static function contextToString(SplFixedArray $ctx) { $str = ''; /** @var array<int, ParagonIE_Sodium_Core32_Int64> $ctxA */ $ctxA = $ctx[0]->toArray(); # uint64_t h[8]; for ($i = 0; $i < 8; ++$i) { if (!($ctxA[$i] instanceof ParagonIE_Sodium_Core32_Int64)) { throw new TypeError('Not an instance of Int64'); } /** @var ParagonIE_Sodium_Core32_Int64 $ctxAi */ $ctxAi = $ctxA[$i]; $str .= $ctxAi->toReverseString(); } # uint64_t t[2]; # uint64_t f[2]; for ($i = 1; $i < 3; ++$i) { /** @var array<int, ParagonIE_Sodium_Core32_Int64> $ctxA */ $ctxA = $ctx[$i]->toArray(); /** @var ParagonIE_Sodium_Core32_Int64 $ctxA1 */ $ctxA1 = $ctxA[0]; /** @var ParagonIE_Sodium_Core32_Int64 $ctxA2 */ $ctxA2 = $ctxA[1]; $str .= $ctxA1->toReverseString(); $str .= $ctxA2->toReverseString(); } # uint8_t buf[2 * 128]; $str .= self::SplFixedArrayToString($ctx[3]); /** @var int $ctx4 */ $ctx4 = $ctx[4]; # size_t buflen; $str .= implode('', array( self::intToChr($ctx4 & 0xff), self::intToChr(($ctx4 >> 8) & 0xff), self::intToChr(($ctx4 >> 16) & 0xff), self::intToChr(($ctx4 >> 24) & 0xff), "\x00\x00\x00\x00" /* self::intToChr(($ctx4 >> 32) & 0xff), self::intToChr(($ctx4 >> 40) & 0xff), self::intToChr(($ctx4 >> 48) & 0xff), self::intToChr(($ctx4 >> 56) & 0xff) */ )); # uint8_t last_node; return $str . self::intToChr($ctx[5]) . str_repeat("\x00", 23); } /** * Creates an SplFixedArray containing other SplFixedArray elements, from * a string (compatible with \Sodium\crypto_generichash_{init, update, final}) * * @internal You should not use this directly from another application * * @param string $string * @return SplFixedArray * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayAssignment */ public static function stringToContext($string) { $ctx = self::context(); # uint64_t h[8]; for ($i = 0; $i < 8; ++$i) { $ctx[0][$i] = ParagonIE_Sodium_Core32_Int64::fromReverseString( self::substr($string, (($i << 3) + 0), 8) ); } # uint64_t t[2]; # uint64_t f[2]; for ($i = 1; $i < 3; ++$i) { $ctx[$i][1] = ParagonIE_Sodium_Core32_Int64::fromReverseString( self::substr($string, 72 + (($i - 1) << 4), 8) ); $ctx[$i][0] = ParagonIE_Sodium_Core32_Int64::fromReverseString( self::substr($string, 64 + (($i - 1) << 4), 8) ); } # uint8_t buf[2 * 128]; $ctx[3] = self::stringToSplFixedArray(self::substr($string, 96, 256)); # uint8_t buf[2 * 128]; $int = 0; for ($i = 0; $i < 8; ++$i) { $int |= self::chrToInt($string[352 + $i]) << ($i << 3); } $ctx[4] = $int; return $ctx; } } PK������Z]D �� ����Core32/XChaCha20.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_XChaCha20', false)) { return; } /** * Class ParagonIE_Sodium_Core32_XChaCha20 */ class ParagonIE_Sodium_Core32_XChaCha20 extends ParagonIE_Sodium_Core32_HChaCha20 { /** * @internal You should not use this directly from another application * * @param int $len * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function stream($len = 64, $nonce = '', $key = '') { if (self::strlen($nonce) !== 24) { throw new SodiumException('Nonce must be 24 bytes long'); } return self::encryptBytes( new ParagonIE_Sodium_Core32_ChaCha20_Ctx( self::hChaCha20( self::substr($nonce, 0, 16), $key ), self::substr($nonce, 16, 8) ), str_repeat("\x00", $len) ); } /** * @internal You should not use this directly from another application * * @param string $message * @param string $nonce * @param string $key * @param string $ic * @return string * @throws SodiumException * @throws TypeError */ public static function streamXorIc($message, $nonce = '', $key = '', $ic = '') { if (self::strlen($nonce) !== 24) { throw new SodiumException('Nonce must be 24 bytes long'); } return self::encryptBytes( new ParagonIE_Sodium_Core32_ChaCha20_Ctx( self::hChaCha20(self::substr($nonce, 0, 16), $key), self::substr($nonce, 16, 8), $ic ), $message ); } /** * @internal You should not use this directly from another application * * @param string $message * @param string $nonce * @param string $key * @param string $ic * @return string * @throws SodiumException * @throws TypeError */ public static function ietfStreamXorIc($message, $nonce = '', $key = '', $ic = '') { return self::encryptBytes( new ParagonIE_Sodium_Core32_ChaCha20_IetfCtx( self::hChaCha20(self::substr($nonce, 0, 16), $key), "\x00\x00\x00\x00" . self::substr($nonce, 16, 8), $ic ), $message ); } } PK������Z``��`����Core32/Int32.phpnu�W+A��������<?php /** * Class ParagonIE_Sodium_Core32_Int32 * * Encapsulates a 32-bit integer. * * These are immutable. It always returns a new instance. */ class ParagonIE_Sodium_Core32_Int32 { /** * @var array<int, int> - two 16-bit integers * * 0 is the higher 16 bits * 1 is the lower 16 bits */ public $limbs = array(0, 0); /** * @var int */ public $overflow = 0; /** * @var bool */ public $unsignedInt = false; /** * ParagonIE_Sodium_Core32_Int32 constructor. * @param array $array * @param bool $unsignedInt */ public function __construct($array = array(0, 0), $unsignedInt = false) { $this->limbs = array( (int) $array[0], (int) $array[1] ); $this->overflow = 0; $this->unsignedInt = $unsignedInt; } /** * Adds two int32 objects * * @param ParagonIE_Sodium_Core32_Int32 $addend * @return ParagonIE_Sodium_Core32_Int32 */ public function addInt32(ParagonIE_Sodium_Core32_Int32 $addend) { $i0 = $this->limbs[0]; $i1 = $this->limbs[1]; $j0 = $addend->limbs[0]; $j1 = $addend->limbs[1]; $r1 = $i1 + ($j1 & 0xffff); $carry = $r1 >> 16; $r0 = $i0 + ($j0 & 0xffff) + $carry; $carry = $r0 >> 16; $r0 &= 0xffff; $r1 &= 0xffff; $return = new ParagonIE_Sodium_Core32_Int32( array($r0, $r1) ); $return->overflow = $carry; $return->unsignedInt = $this->unsignedInt; return $return; } /** * Adds a normal integer to an int32 object * * @param int $int * @return ParagonIE_Sodium_Core32_Int32 * @throws SodiumException * @throws TypeError */ public function addInt($int) { ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1); /** @var int $int */ $int = (int) $int; $int = (int) $int; $i0 = $this->limbs[0]; $i1 = $this->limbs[1]; $r1 = $i1 + ($int & 0xffff); $carry = $r1 >> 16; $r0 = $i0 + (($int >> 16) & 0xffff) + $carry; $carry = $r0 >> 16; $r0 &= 0xffff; $r1 &= 0xffff; $return = new ParagonIE_Sodium_Core32_Int32( array($r0, $r1) ); $return->overflow = $carry; $return->unsignedInt = $this->unsignedInt; return $return; } /** * @param int $b * @return int */ public function compareInt($b = 0) { $gt = 0; $eq = 1; $i = 2; $j = 0; while ($i > 0) { --$i; /** @var int $x1 */ $x1 = $this->limbs[$i]; /** @var int $x2 */ $x2 = ($b >> ($j << 4)) & 0xffff; /** @var int $gt */ $gt |= (($x2 - $x1) >> 8) & $eq; /** @var int $eq */ $eq &= (($x2 ^ $x1) - 1) >> 8; } return ($gt + $gt - $eq) + 1; } /** * @param int $m * @return ParagonIE_Sodium_Core32_Int32 */ public function mask($m = 0) { /** @var int $hi */ $hi = ((int) $m >> 16); $hi &= 0xffff; /** @var int $lo */ $lo = ((int) $m) & 0xffff; return new ParagonIE_Sodium_Core32_Int32( array( (int) ($this->limbs[0] & $hi), (int) ($this->limbs[1] & $lo) ), $this->unsignedInt ); } /** * @param array<int, int> $a * @param array<int, int> $b * @param int $baseLog2 * @return array<int, int> */ public function multiplyLong(array $a, array $b, $baseLog2 = 16) { $a_l = count($a); $b_l = count($b); /** @var array<int, int> $r */ $r = array_fill(0, $a_l + $b_l + 1, 0); $base = 1 << $baseLog2; for ($i = 0; $i < $a_l; ++$i) { $a_i = $a[$i]; for ($j = 0; $j < $a_l; ++$j) { $b_j = $b[$j]; $product = ($a_i * $b_j) + $r[$i + $j]; $carry = ((int) $product >> $baseLog2 & 0xffff); $r[$i + $j] = ((int) $product - (int) ($carry * $base)) & 0xffff; $r[$i + $j + 1] += $carry; } } return array_slice($r, 0, 5); } /** * @param int $int * @return ParagonIE_Sodium_Core32_Int32 */ public function mulIntFast($int) { // Handle negative numbers $aNeg = ($this->limbs[0] >> 15) & 1; $bNeg = ($int >> 31) & 1; $a = array_reverse($this->limbs); $b = array( $int & 0xffff, ($int >> 16) & 0xffff ); if ($aNeg) { for ($i = 0; $i < 2; ++$i) { $a[$i] = ($a[$i] ^ 0xffff) & 0xffff; } ++$a[0]; } if ($bNeg) { for ($i = 0; $i < 2; ++$i) { $b[$i] = ($b[$i] ^ 0xffff) & 0xffff; } ++$b[0]; } // Multiply $res = $this->multiplyLong($a, $b); // Re-apply negation to results if ($aNeg !== $bNeg) { for ($i = 0; $i < 2; ++$i) { $res[$i] = (0xffff ^ $res[$i]) & 0xffff; } // Handle integer overflow $c = 1; for ($i = 0; $i < 2; ++$i) { $res[$i] += $c; $c = $res[$i] >> 16; $res[$i] &= 0xffff; } } // Return our values $return = new ParagonIE_Sodium_Core32_Int32(); $return->limbs = array( $res[1] & 0xffff, $res[0] & 0xffff ); if (count($res) > 2) { $return->overflow = $res[2] & 0xffff; } $return->unsignedInt = $this->unsignedInt; return $return; } /** * @param ParagonIE_Sodium_Core32_Int32 $right * @return ParagonIE_Sodium_Core32_Int32 */ public function mulInt32Fast(ParagonIE_Sodium_Core32_Int32 $right) { $aNeg = ($this->limbs[0] >> 15) & 1; $bNeg = ($right->limbs[0] >> 15) & 1; $a = array_reverse($this->limbs); $b = array_reverse($right->limbs); if ($aNeg) { for ($i = 0; $i < 2; ++$i) { $a[$i] = ($a[$i] ^ 0xffff) & 0xffff; } ++$a[0]; } if ($bNeg) { for ($i = 0; $i < 2; ++$i) { $b[$i] = ($b[$i] ^ 0xffff) & 0xffff; } ++$b[0]; } $res = $this->multiplyLong($a, $b); if ($aNeg !== $bNeg) { if ($aNeg !== $bNeg) { for ($i = 0; $i < 2; ++$i) { $res[$i] = ($res[$i] ^ 0xffff) & 0xffff; } $c = 1; for ($i = 0; $i < 2; ++$i) { $res[$i] += $c; $c = $res[$i] >> 16; $res[$i] &= 0xffff; } } } $return = new ParagonIE_Sodium_Core32_Int32(); $return->limbs = array( $res[1] & 0xffff, $res[0] & 0xffff ); if (count($res) > 2) { $return->overflow = $res[2]; } return $return; } /** * @param int $int * @param int $size * @return ParagonIE_Sodium_Core32_Int32 * @throws SodiumException * @throws TypeError */ public function mulInt($int = 0, $size = 0) { ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1); ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2); if (ParagonIE_Sodium_Compat::$fastMult) { return $this->mulIntFast((int) $int); } /** @var int $int */ $int = (int) $int; /** @var int $size */ $size = (int) $size; if (!$size) { $size = 31; } /** @var int $size */ $a = clone $this; $return = new ParagonIE_Sodium_Core32_Int32(); $return->unsignedInt = $this->unsignedInt; // Initialize: $ret0 = 0; $ret1 = 0; $a0 = $a->limbs[0]; $a1 = $a->limbs[1]; /** @var int $size */ /** @var int $i */ for ($i = $size; $i >= 0; --$i) { $m = (int) (-($int & 1)); $x0 = $a0 & $m; $x1 = $a1 & $m; $ret1 += $x1; $c = $ret1 >> 16; $ret0 += $x0 + $c; $ret0 &= 0xffff; $ret1 &= 0xffff; $a1 = ($a1 << 1); $x1 = $a1 >> 16; $a0 = ($a0 << 1) | $x1; $a0 &= 0xffff; $a1 &= 0xffff; $int >>= 1; } $return->limbs[0] = $ret0; $return->limbs[1] = $ret1; return $return; } /** * @param ParagonIE_Sodium_Core32_Int32 $int * @param int $size * @return ParagonIE_Sodium_Core32_Int32 * @throws SodiumException * @throws TypeError */ public function mulInt32(ParagonIE_Sodium_Core32_Int32 $int, $size = 0) { ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2); if (ParagonIE_Sodium_Compat::$fastMult) { return $this->mulInt32Fast($int); } if (!$size) { $size = 31; } /** @var int $size */ $a = clone $this; $b = clone $int; $return = new ParagonIE_Sodium_Core32_Int32(); $return->unsignedInt = $this->unsignedInt; // Initialize: $ret0 = 0; $ret1 = 0; $a0 = $a->limbs[0]; $a1 = $a->limbs[1]; $b0 = $b->limbs[0]; $b1 = $b->limbs[1]; /** @var int $size */ /** @var int $i */ for ($i = $size; $i >= 0; --$i) { $m = (int) (-($b1 & 1)); $x0 = $a0 & $m; $x1 = $a1 & $m; $ret1 += $x1; $c = $ret1 >> 16; $ret0 += $x0 + $c; $ret0 &= 0xffff; $ret1 &= 0xffff; $a1 = ($a1 << 1); $x1 = $a1 >> 16; $a0 = ($a0 << 1) | $x1; $a0 &= 0xffff; $a1 &= 0xffff; $x0 = ($b0 & 1) << 16; $b0 = ($b0 >> 1); $b1 = (($b1 | $x0) >> 1); $b0 &= 0xffff; $b1 &= 0xffff; } $return->limbs[0] = $ret0; $return->limbs[1] = $ret1; return $return; } /** * OR this 32-bit integer with another. * * @param ParagonIE_Sodium_Core32_Int32 $b * @return ParagonIE_Sodium_Core32_Int32 */ public function orInt32(ParagonIE_Sodium_Core32_Int32 $b) { $return = new ParagonIE_Sodium_Core32_Int32(); $return->unsignedInt = $this->unsignedInt; $return->limbs = array( (int) ($this->limbs[0] | $b->limbs[0]), (int) ($this->limbs[1] | $b->limbs[1]) ); /** @var int overflow */ $return->overflow = $this->overflow | $b->overflow; return $return; } /** * @param int $b * @return bool */ public function isGreaterThan($b = 0) { return $this->compareInt($b) > 0; } /** * @param int $b * @return bool */ public function isLessThanInt($b = 0) { return $this->compareInt($b) < 0; } /** * @param int $c * @return ParagonIE_Sodium_Core32_Int32 * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArrayAccess */ public function rotateLeft($c = 0) { ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1); /** @var int $c */ $c = (int) $c; $return = new ParagonIE_Sodium_Core32_Int32(); $return->unsignedInt = $this->unsignedInt; $c &= 31; if ($c === 0) { // NOP, but we want a copy. $return->limbs = $this->limbs; } else { /** @var int $c */ /** @var int $idx_shift */ $idx_shift = ($c >> 4) & 1; /** @var int $sub_shift */ $sub_shift = $c & 15; /** @var array<int, int> $limbs */ $limbs =& $return->limbs; /** @var array<int, int> $myLimbs */ $myLimbs =& $this->limbs; for ($i = 1; $i >= 0; --$i) { /** @var int $j */ $j = ($i + $idx_shift) & 1; /** @var int $k */ $k = ($i + $idx_shift + 1) & 1; $limbs[$i] = (int) ( ( ((int) ($myLimbs[$j]) << $sub_shift) | ((int) ($myLimbs[$k]) >> (16 - $sub_shift)) ) & 0xffff ); } } return $return; } /** * Rotate to the right * * @param int $c * @return ParagonIE_Sodium_Core32_Int32 * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArrayAccess */ public function rotateRight($c = 0) { ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1); /** @var int $c */ $c = (int) $c; $return = new ParagonIE_Sodium_Core32_Int32(); $return->unsignedInt = $this->unsignedInt; $c &= 31; /** @var int $c */ if ($c === 0) { // NOP, but we want a copy. $return->limbs = $this->limbs; } else { /** @var int $c */ /** @var int $idx_shift */ $idx_shift = ($c >> 4) & 1; /** @var int $sub_shift */ $sub_shift = $c & 15; /** @var array<int, int> $limbs */ $limbs =& $return->limbs; /** @var array<int, int> $myLimbs */ $myLimbs =& $this->limbs; for ($i = 1; $i >= 0; --$i) { /** @var int $j */ $j = ($i - $idx_shift) & 1; /** @var int $k */ $k = ($i - $idx_shift - 1) & 1; $limbs[$i] = (int) ( ( ((int) ($myLimbs[$j]) >> (int) ($sub_shift)) | ((int) ($myLimbs[$k]) << (16 - (int) ($sub_shift))) ) & 0xffff ); } } return $return; } /** * @param bool $bool * @return self */ public function setUnsignedInt($bool = false) { $this->unsignedInt = !empty($bool); return $this; } /** * @param int $c * @return ParagonIE_Sodium_Core32_Int32 * @throws SodiumException * @throws TypeError */ public function shiftLeft($c = 0) { ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1); /** @var int $c */ $c = (int) $c; $return = new ParagonIE_Sodium_Core32_Int32(); $return->unsignedInt = $this->unsignedInt; $c &= 63; /** @var int $c */ if ($c === 0) { $return->limbs = $this->limbs; } elseif ($c < 0) { /** @var int $c */ return $this->shiftRight(-$c); } else { /** @var int $c */ /** @var int $tmp */ $tmp = $this->limbs[1] << $c; $return->limbs[1] = (int)($tmp & 0xffff); /** @var int $carry */ $carry = $tmp >> 16; /** @var int $tmp */ $tmp = ($this->limbs[0] << $c) | ($carry & 0xffff); $return->limbs[0] = (int) ($tmp & 0xffff); } return $return; } /** * @param int $c * @return ParagonIE_Sodium_Core32_Int32 * @throws SodiumException * @throws TypeError * @psalm-suppress MixedAssignment * @psalm-suppress MixedOperand */ public function shiftRight($c = 0) { ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1); /** @var int $c */ $c = (int) $c; $return = new ParagonIE_Sodium_Core32_Int32(); $return->unsignedInt = $this->unsignedInt; $c &= 63; /** @var int $c */ if ($c >= 16) { $return->limbs = array( (int) ($this->overflow & 0xffff), (int) ($this->limbs[0]) ); $return->overflow = $this->overflow >> 16; return $return->shiftRight($c & 15); } if ($c === 0) { $return->limbs = $this->limbs; } elseif ($c < 0) { /** @var int $c */ return $this->shiftLeft(-$c); } else { if (!is_int($c)) { throw new TypeError(); } /** @var int $c */ // $return->limbs[0] = (int) (($this->limbs[0] >> $c) & 0xffff); $carryLeft = (int) ($this->overflow & ((1 << ($c + 1)) - 1)); $return->limbs[0] = (int) ((($this->limbs[0] >> $c) | ($carryLeft << (16 - $c))) & 0xffff); $carryRight = (int) ($this->limbs[0] & ((1 << ($c + 1)) - 1)); $return->limbs[1] = (int) ((($this->limbs[1] >> $c) | ($carryRight << (16 - $c))) & 0xffff); $return->overflow >>= $c; } return $return; } /** * Subtract a normal integer from an int32 object. * * @param int $int * @return ParagonIE_Sodium_Core32_Int32 * @throws SodiumException * @throws TypeError */ public function subInt($int) { ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1); /** @var int $int */ $int = (int) $int; $return = new ParagonIE_Sodium_Core32_Int32(); $return->unsignedInt = $this->unsignedInt; /** @var int $tmp */ $tmp = $this->limbs[1] - ($int & 0xffff); /** @var int $carry */ $carry = $tmp >> 16; $return->limbs[1] = (int) ($tmp & 0xffff); /** @var int $tmp */ $tmp = $this->limbs[0] - (($int >> 16) & 0xffff) + $carry; $return->limbs[0] = (int) ($tmp & 0xffff); return $return; } /** * Subtract two int32 objects from each other * * @param ParagonIE_Sodium_Core32_Int32 $b * @return ParagonIE_Sodium_Core32_Int32 */ public function subInt32(ParagonIE_Sodium_Core32_Int32 $b) { $return = new ParagonIE_Sodium_Core32_Int32(); $return->unsignedInt = $this->unsignedInt; /** @var int $tmp */ $tmp = $this->limbs[1] - ($b->limbs[1] & 0xffff); /** @var int $carry */ $carry = $tmp >> 16; $return->limbs[1] = (int) ($tmp & 0xffff); /** @var int $tmp */ $tmp = $this->limbs[0] - ($b->limbs[0] & 0xffff) + $carry; $return->limbs[0] = (int) ($tmp & 0xffff); return $return; } /** * XOR this 32-bit integer with another. * * @param ParagonIE_Sodium_Core32_Int32 $b * @return ParagonIE_Sodium_Core32_Int32 */ public function xorInt32(ParagonIE_Sodium_Core32_Int32 $b) { $return = new ParagonIE_Sodium_Core32_Int32(); $return->unsignedInt = $this->unsignedInt; $return->limbs = array( (int) ($this->limbs[0] ^ $b->limbs[0]), (int) ($this->limbs[1] ^ $b->limbs[1]) ); return $return; } /** * @param int $signed * @return self * @throws SodiumException * @throws TypeError */ public static function fromInt($signed) { ParagonIE_Sodium_Core32_Util::declareScalarType($signed, 'int', 1);; /** @var int $signed */ $signed = (int) $signed; return new ParagonIE_Sodium_Core32_Int32( array( (int) (($signed >> 16) & 0xffff), (int) ($signed & 0xffff) ) ); } /** * @param string $string * @return self * @throws SodiumException * @throws TypeError */ public static function fromString($string) { ParagonIE_Sodium_Core32_Util::declareScalarType($string, 'string', 1); $string = (string) $string; if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 4) { throw new RangeException( 'String must be 4 bytes; ' . ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.' ); } $return = new ParagonIE_Sodium_Core32_Int32(); $return->limbs[0] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff) << 8); $return->limbs[0] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff); $return->limbs[1] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff) << 8); $return->limbs[1] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff); return $return; } /** * @param string $string * @return self * @throws SodiumException * @throws TypeError */ public static function fromReverseString($string) { ParagonIE_Sodium_Core32_Util::declareScalarType($string, 'string', 1); $string = (string) $string; if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 4) { throw new RangeException( 'String must be 4 bytes; ' . ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.' ); } $return = new ParagonIE_Sodium_Core32_Int32(); $return->limbs[0] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff) << 8); $return->limbs[0] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff); $return->limbs[1] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff) << 8); $return->limbs[1] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff); return $return; } /** * @return array<int, int> */ public function toArray() { return array((int) ($this->limbs[0] << 16 | $this->limbs[1])); } /** * @return string * @throws TypeError */ public function toString() { return ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[0] >> 8) & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[1] >> 8) & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] & 0xff); } /** * @return int */ public function toInt() { return (int) ( (($this->limbs[0] & 0xffff) << 16) | ($this->limbs[1] & 0xffff) ); } /** * @return ParagonIE_Sodium_Core32_Int32 */ public function toInt32() { $return = new ParagonIE_Sodium_Core32_Int32(); $return->limbs[0] = (int) ($this->limbs[0] & 0xffff); $return->limbs[1] = (int) ($this->limbs[1] & 0xffff); $return->unsignedInt = $this->unsignedInt; $return->overflow = (int) ($this->overflow & 0x7fffffff); return $return; } /** * @return ParagonIE_Sodium_Core32_Int64 */ public function toInt64() { $return = new ParagonIE_Sodium_Core32_Int64(); $return->unsignedInt = $this->unsignedInt; if ($this->unsignedInt) { $return->limbs[0] += (($this->overflow >> 16) & 0xffff); $return->limbs[1] += (($this->overflow) & 0xffff); } else { $neg = -(($this->limbs[0] >> 15) & 1); $return->limbs[0] = (int)($neg & 0xffff); $return->limbs[1] = (int)($neg & 0xffff); } $return->limbs[2] = (int) ($this->limbs[0] & 0xffff); $return->limbs[3] = (int) ($this->limbs[1] & 0xffff); return $return; } /** * @return string * @throws TypeError */ public function toReverseString() { return ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[1] >> 8) & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[0] >> 8) & 0xff); } /** * @return string */ public function __toString() { try { return $this->toString(); } catch (TypeError $ex) { // PHP engine can't handle exceptions from __toString() return ''; } } } PK������Zx)'������Core32/HSalsa20.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_HSalsa20', false)) { return; } /** * Class ParagonIE_Sodium_Core32_HSalsa20 */ abstract class ParagonIE_Sodium_Core32_HSalsa20 extends ParagonIE_Sodium_Core32_Salsa20 { /** * Calculate an hsalsa20 hash of a single block * * HSalsa20 doesn't have a counter and will never be used for more than * one block (used to derive a subkey for xsalsa20). * * @internal You should not use this directly from another application * * @param string $in * @param string $k * @param string|null $c * @return string * @throws SodiumException * @throws TypeError */ public static function hsalsa20($in, $k, $c = null) { /** * @var ParagonIE_Sodium_Core32_Int32 $x0 * @var ParagonIE_Sodium_Core32_Int32 $x1 * @var ParagonIE_Sodium_Core32_Int32 $x2 * @var ParagonIE_Sodium_Core32_Int32 $x3 * @var ParagonIE_Sodium_Core32_Int32 $x4 * @var ParagonIE_Sodium_Core32_Int32 $x5 * @var ParagonIE_Sodium_Core32_Int32 $x6 * @var ParagonIE_Sodium_Core32_Int32 $x7 * @var ParagonIE_Sodium_Core32_Int32 $x8 * @var ParagonIE_Sodium_Core32_Int32 $x9 * @var ParagonIE_Sodium_Core32_Int32 $x10 * @var ParagonIE_Sodium_Core32_Int32 $x11 * @var ParagonIE_Sodium_Core32_Int32 $x12 * @var ParagonIE_Sodium_Core32_Int32 $x13 * @var ParagonIE_Sodium_Core32_Int32 $x14 * @var ParagonIE_Sodium_Core32_Int32 $x15 * @var ParagonIE_Sodium_Core32_Int32 $j0 * @var ParagonIE_Sodium_Core32_Int32 $j1 * @var ParagonIE_Sodium_Core32_Int32 $j2 * @var ParagonIE_Sodium_Core32_Int32 $j3 * @var ParagonIE_Sodium_Core32_Int32 $j4 * @var ParagonIE_Sodium_Core32_Int32 $j5 * @var ParagonIE_Sodium_Core32_Int32 $j6 * @var ParagonIE_Sodium_Core32_Int32 $j7 * @var ParagonIE_Sodium_Core32_Int32 $j8 * @var ParagonIE_Sodium_Core32_Int32 $j9 * @var ParagonIE_Sodium_Core32_Int32 $j10 * @var ParagonIE_Sodium_Core32_Int32 $j11 * @var ParagonIE_Sodium_Core32_Int32 $j12 * @var ParagonIE_Sodium_Core32_Int32 $j13 * @var ParagonIE_Sodium_Core32_Int32 $j14 * @var ParagonIE_Sodium_Core32_Int32 $j15 */ if (self::strlen($k) < 32) { throw new RangeException('Key must be 32 bytes long'); } if ($c === null) { $x0 = new ParagonIE_Sodium_Core32_Int32(array(0x6170, 0x7865)); $x5 = new ParagonIE_Sodium_Core32_Int32(array(0x3320, 0x646e)); $x10 = new ParagonIE_Sodium_Core32_Int32(array(0x7962, 0x2d32)); $x15 = new ParagonIE_Sodium_Core32_Int32(array(0x6b20, 0x6574)); } else { $x0 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 0, 4)); $x5 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 4, 4)); $x10 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 8, 4)); $x15 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 12, 4)); } $x1 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 0, 4)); $x2 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 4, 4)); $x3 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 8, 4)); $x4 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 12, 4)); $x6 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 0, 4)); $x7 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 4, 4)); $x8 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 8, 4)); $x9 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 12, 4)); $x11 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 16, 4)); $x12 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 20, 4)); $x13 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 24, 4)); $x14 = ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 28, 4)); for ($i = self::ROUNDS; $i > 0; $i -= 2) { $x4 = $x4->xorInt32($x0->addInt32($x12)->rotateLeft(7)); $x8 = $x8->xorInt32($x4->addInt32($x0)->rotateLeft(9)); $x12 = $x12->xorInt32($x8->addInt32($x4)->rotateLeft(13)); $x0 = $x0->xorInt32($x12->addInt32($x8)->rotateLeft(18)); $x9 = $x9->xorInt32($x5->addInt32($x1)->rotateLeft(7)); $x13 = $x13->xorInt32($x9->addInt32($x5)->rotateLeft(9)); $x1 = $x1->xorInt32($x13->addInt32($x9)->rotateLeft(13)); $x5 = $x5->xorInt32($x1->addInt32($x13)->rotateLeft(18)); $x14 = $x14->xorInt32($x10->addInt32($x6)->rotateLeft(7)); $x2 = $x2->xorInt32($x14->addInt32($x10)->rotateLeft(9)); $x6 = $x6->xorInt32($x2->addInt32($x14)->rotateLeft(13)); $x10 = $x10->xorInt32($x6->addInt32($x2)->rotateLeft(18)); $x3 = $x3->xorInt32($x15->addInt32($x11)->rotateLeft(7)); $x7 = $x7->xorInt32($x3->addInt32($x15)->rotateLeft(9)); $x11 = $x11->xorInt32($x7->addInt32($x3)->rotateLeft(13)); $x15 = $x15->xorInt32($x11->addInt32($x7)->rotateLeft(18)); $x1 = $x1->xorInt32($x0->addInt32($x3)->rotateLeft(7)); $x2 = $x2->xorInt32($x1->addInt32($x0)->rotateLeft(9)); $x3 = $x3->xorInt32($x2->addInt32($x1)->rotateLeft(13)); $x0 = $x0->xorInt32($x3->addInt32($x2)->rotateLeft(18)); $x6 = $x6->xorInt32($x5->addInt32($x4)->rotateLeft(7)); $x7 = $x7->xorInt32($x6->addInt32($x5)->rotateLeft(9)); $x4 = $x4->xorInt32($x7->addInt32($x6)->rotateLeft(13)); $x5 = $x5->xorInt32($x4->addInt32($x7)->rotateLeft(18)); $x11 = $x11->xorInt32($x10->addInt32($x9)->rotateLeft(7)); $x8 = $x8->xorInt32($x11->addInt32($x10)->rotateLeft(9)); $x9 = $x9->xorInt32($x8->addInt32($x11)->rotateLeft(13)); $x10 = $x10->xorInt32($x9->addInt32($x8)->rotateLeft(18)); $x12 = $x12->xorInt32($x15->addInt32($x14)->rotateLeft(7)); $x13 = $x13->xorInt32($x12->addInt32($x15)->rotateLeft(9)); $x14 = $x14->xorInt32($x13->addInt32($x12)->rotateLeft(13)); $x15 = $x15->xorInt32($x14->addInt32($x13)->rotateLeft(18)); } return $x0->toReverseString() . $x5->toReverseString() . $x10->toReverseString() . $x15->toReverseString() . $x6->toReverseString() . $x7->toReverseString() . $x8->toReverseString() . $x9->toReverseString(); } } PK������Z՗ilz��z����Core32/Curve25519/Fe.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_Curve25519_Fe', false)) { return; } /** * Class ParagonIE_Sodium_Core32_Curve25519_Fe * * This represents a Field Element */ class ParagonIE_Sodium_Core32_Curve25519_Fe implements ArrayAccess { /** * @var array<int, ParagonIE_Sodium_Core32_Int32> */ protected $container = array(); /** * @var int */ protected $size = 10; /** * @internal You should not use this directly from another application * * @param array<int, ParagonIE_Sodium_Core32_Int32> $array * @param bool $save_indexes * @return self * @throws SodiumException * @throws TypeError */ public static function fromArray($array, $save_indexes = null) { $count = count($array); if ($save_indexes) { $keys = array_keys($array); } else { $keys = range(0, $count - 1); } $array = array_values($array); $obj = new ParagonIE_Sodium_Core32_Curve25519_Fe(); if ($save_indexes) { for ($i = 0; $i < $count; ++$i) { $array[$i]->overflow = 0; $obj->offsetSet($keys[$i], $array[$i]); } } else { for ($i = 0; $i < $count; ++$i) { if (!($array[$i] instanceof ParagonIE_Sodium_Core32_Int32)) { throw new TypeError('Expected ParagonIE_Sodium_Core32_Int32'); } $array[$i]->overflow = 0; $obj->offsetSet($i, $array[$i]); } } return $obj; } /** * @internal You should not use this directly from another application * * @param array<int, int> $array * @param bool $save_indexes * @return self * @throws SodiumException * @throws TypeError */ public static function fromIntArray($array, $save_indexes = null) { $count = count($array); if ($save_indexes) { $keys = array_keys($array); } else { $keys = range(0, $count - 1); } $array = array_values($array); $set = array(); /** @var int $i */ /** @var int $v */ foreach ($array as $i => $v) { $set[$i] = ParagonIE_Sodium_Core32_Int32::fromInt($v); } $obj = new ParagonIE_Sodium_Core32_Curve25519_Fe(); if ($save_indexes) { for ($i = 0; $i < $count; ++$i) { $set[$i]->overflow = 0; $obj->offsetSet($keys[$i], $set[$i]); } } else { for ($i = 0; $i < $count; ++$i) { $set[$i]->overflow = 0; $obj->offsetSet($i, $set[$i]); } } return $obj; } /** * @internal You should not use this directly from another application * * @param mixed $offset * @param mixed $value * @return void * @throws SodiumException * @throws TypeError */ #[ReturnTypeWillChange] public function offsetSet($offset, $value) { if (!($value instanceof ParagonIE_Sodium_Core32_Int32)) { throw new InvalidArgumentException('Expected an instance of ParagonIE_Sodium_Core32_Int32'); } if (is_null($offset)) { $this->container[] = $value; } else { ParagonIE_Sodium_Core32_Util::declareScalarType($offset, 'int', 1); $this->container[(int) $offset] = $value; } } /** * @internal You should not use this directly from another application * * @param mixed $offset * @return bool * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->container[$offset]); } /** * @internal You should not use this directly from another application * * @param mixed $offset * @return void * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->container[$offset]); } /** * @internal You should not use this directly from another application * * @param mixed $offset * @return ParagonIE_Sodium_Core32_Int32 * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetGet($offset) { if (!isset($this->container[$offset])) { $this->container[(int) $offset] = new ParagonIE_Sodium_Core32_Int32(); } /** @var ParagonIE_Sodium_Core32_Int32 $get */ $get = $this->container[$offset]; return $get; } /** * @internal You should not use this directly from another application * * @return array */ public function __debugInfo() { if (empty($this->container)) { return array(); } $c = array( (int) ($this->container[0]->toInt()), (int) ($this->container[1]->toInt()), (int) ($this->container[2]->toInt()), (int) ($this->container[3]->toInt()), (int) ($this->container[4]->toInt()), (int) ($this->container[5]->toInt()), (int) ($this->container[6]->toInt()), (int) ($this->container[7]->toInt()), (int) ($this->container[8]->toInt()), (int) ($this->container[9]->toInt()) ); return array(implode(', ', $c)); } } PK������Z珉��������Core32/Curve25519/README.mdnu�W+A��������# Curve25519 Data Structures These are PHP implementation of the [structs used in the ref10 curve25519 code](https://github.com/jedisct1/libsodium/blob/master/src/libsodium/include/sodium/private/curve25519_ref10.h). PK������Z% ���� ��Core32/Curve25519/Ge/Precomp.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp', false)) { return; } /** * Class ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp */ class ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp { /** * @var ParagonIE_Sodium_Core32_Curve25519_Fe */ public $yplusx; /** * @var ParagonIE_Sodium_Core32_Curve25519_Fe */ public $yminusx; /** * @var ParagonIE_Sodium_Core32_Curve25519_Fe */ public $xy2d; /** * ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp constructor. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe $yplusx * @param ParagonIE_Sodium_Core32_Curve25519_Fe $yminusx * @param ParagonIE_Sodium_Core32_Curve25519_Fe $xy2d * @throws SodiumException * @throws TypeError */ public function __construct( ParagonIE_Sodium_Core32_Curve25519_Fe $yplusx = null, ParagonIE_Sodium_Core32_Curve25519_Fe $yminusx = null, ParagonIE_Sodium_Core32_Curve25519_Fe $xy2d = null ) { if ($yplusx === null) { $yplusx = ParagonIE_Sodium_Core32_Curve25519::fe_0(); } $this->yplusx = $yplusx; if ($yminusx === null) { $yminusx = ParagonIE_Sodium_Core32_Curve25519::fe_0(); } $this->yminusx = $yminusx; if ($xy2d === null) { $xy2d = ParagonIE_Sodium_Core32_Curve25519::fe_0(); } $this->xy2d = $xy2d; } } PK������Z~g������Core32/Curve25519/Ge/P1p1.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1', false)) { return; } /** * Class ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 */ class ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 { /** * @var ParagonIE_Sodium_Core32_Curve25519_Fe */ public $X; /** * @var ParagonIE_Sodium_Core32_Curve25519_Fe */ public $Y; /** * @var ParagonIE_Sodium_Core32_Curve25519_Fe */ public $Z; /** * @var ParagonIE_Sodium_Core32_Curve25519_Fe */ public $T; /** * ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 constructor. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $x * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $y * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $z * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $t * * @throws SodiumException * @throws TypeError */ public function __construct( ParagonIE_Sodium_Core32_Curve25519_Fe $x = null, ParagonIE_Sodium_Core32_Curve25519_Fe $y = null, ParagonIE_Sodium_Core32_Curve25519_Fe $z = null, ParagonIE_Sodium_Core32_Curve25519_Fe $t = null ) { if ($x === null) { $x = ParagonIE_Sodium_Core32_Curve25519::fe_0(); } $this->X = $x; if ($y === null) { $y = ParagonIE_Sodium_Core32_Curve25519::fe_0(); } $this->Y = $y; if ($z === null) { $z = ParagonIE_Sodium_Core32_Curve25519::fe_0(); } $this->Z = $z; if ($t === null) { $t = ParagonIE_Sodium_Core32_Curve25519::fe_0(); } $this->T = $t; } } PK������Z}M �� ����Core32/Curve25519/Ge/Cached.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_Curve25519_Ge_Cached', false)) { return; } /** * Class ParagonIE_Sodium_Core32_Curve25519_Ge_Cached */ class ParagonIE_Sodium_Core32_Curve25519_Ge_Cached { /** * @var ParagonIE_Sodium_Core32_Curve25519_Fe */ public $YplusX; /** * @var ParagonIE_Sodium_Core32_Curve25519_Fe */ public $YminusX; /** * @var ParagonIE_Sodium_Core32_Curve25519_Fe */ public $Z; /** * @var ParagonIE_Sodium_Core32_Curve25519_Fe */ public $T2d; /** * ParagonIE_Sodium_Core32_Curve25519_Ge_Cached constructor. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $YplusX * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $YminusX * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $Z * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $T2d */ public function __construct( ParagonIE_Sodium_Core32_Curve25519_Fe $YplusX = null, ParagonIE_Sodium_Core32_Curve25519_Fe $YminusX = null, ParagonIE_Sodium_Core32_Curve25519_Fe $Z = null, ParagonIE_Sodium_Core32_Curve25519_Fe $T2d = null ) { if ($YplusX === null) { $YplusX = new ParagonIE_Sodium_Core32_Curve25519_Fe(); } $this->YplusX = $YplusX; if ($YminusX === null) { $YminusX = new ParagonIE_Sodium_Core32_Curve25519_Fe(); } $this->YminusX = $YminusX; if ($Z === null) { $Z = new ParagonIE_Sodium_Core32_Curve25519_Fe(); } $this->Z = $Z; if ($T2d === null) { $T2d = new ParagonIE_Sodium_Core32_Curve25519_Fe(); } $this->T2d = $T2d; } } PK������ZÍۤa��a����Core32/Curve25519/Ge/P2.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_Curve25519_Ge_P2', false)) { return; } /** * Class ParagonIE_Sodium_Core32_Curve25519_Ge_P2 */ class ParagonIE_Sodium_Core32_Curve25519_Ge_P2 { /** * @var ParagonIE_Sodium_Core32_Curve25519_Fe */ public $X; /** * @var ParagonIE_Sodium_Core32_Curve25519_Fe */ public $Y; /** * @var ParagonIE_Sodium_Core32_Curve25519_Fe */ public $Z; /** * ParagonIE_Sodium_Core32_Curve25519_Ge_P2 constructor. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $x * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $y * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $z */ public function __construct( ParagonIE_Sodium_Core32_Curve25519_Fe $x = null, ParagonIE_Sodium_Core32_Curve25519_Fe $y = null, ParagonIE_Sodium_Core32_Curve25519_Fe $z = null ) { if ($x === null) { $x = new ParagonIE_Sodium_Core32_Curve25519_Fe(); } $this->X = $x; if ($y === null) { $y = new ParagonIE_Sodium_Core32_Curve25519_Fe(); } $this->Y = $y; if ($z === null) { $z = new ParagonIE_Sodium_Core32_Curve25519_Fe(); } $this->Z = $z; } } PK������Z6VV������Core32/Curve25519/Ge/P3.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_Curve25519_Ge_P3', false)) { return; } /** * Class ParagonIE_Sodium_Core32_Curve25519_Ge_P3 */ class ParagonIE_Sodium_Core32_Curve25519_Ge_P3 { /** * @var ParagonIE_Sodium_Core32_Curve25519_Fe */ public $X; /** * @var ParagonIE_Sodium_Core32_Curve25519_Fe */ public $Y; /** * @var ParagonIE_Sodium_Core32_Curve25519_Fe */ public $Z; /** * @var ParagonIE_Sodium_Core32_Curve25519_Fe */ public $T; /** * ParagonIE_Sodium_Core32_Curve25519_Ge_P3 constructor. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $x * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $y * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $z * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $t */ public function __construct( ParagonIE_Sodium_Core32_Curve25519_Fe $x = null, ParagonIE_Sodium_Core32_Curve25519_Fe $y = null, ParagonIE_Sodium_Core32_Curve25519_Fe $z = null, ParagonIE_Sodium_Core32_Curve25519_Fe $t = null ) { if ($x === null) { $x = new ParagonIE_Sodium_Core32_Curve25519_Fe(); } $this->X = $x; if ($y === null) { $y = new ParagonIE_Sodium_Core32_Curve25519_Fe(); } $this->Y = $y; if ($z === null) { $z = new ParagonIE_Sodium_Core32_Curve25519_Fe(); } $this->Z = $z; if ($t === null) { $t = new ParagonIE_Sodium_Core32_Curve25519_Fe(); } $this->T = $t; } } PK������Z����Core32/Curve25519/H.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_Curve25519_H', false)) { return; } /** * Class ParagonIE_Sodium_Core32_Curve25519_H * * This just contains the constants in the ref10/base.h file */ class ParagonIE_Sodium_Core32_Curve25519_H extends ParagonIE_Sodium_Core32_Util { /** * See: libsodium's crypto_core/curve25519/ref10/base.h * * @var array<int, array<int, array<int, array<int, int>>>> Basically, int[32][8][3][10] */ protected static $base = array( array( array( array(25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605), array(-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378), array(-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546), ), array( array(-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303), array(-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081), array(26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697), ), array( array(15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024), array(16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574), array(30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357), ), array( array(-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540), array(23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397), array(7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325), ), array( array(10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380), array(4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306), array(19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942), ), array( array(-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777), array(-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737), array(-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652), ), array( array(5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766), array(-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701), array(28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300), ), array( array(14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726), array(-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955), array(27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425), ), ), array( array( array(-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171), array(27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510), array(17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660), ), array( array(-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639), array(29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963), array(5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950), ), array( array(-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568), array(12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335), array(25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628), ), array( array(-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007), array(-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772), array(-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653), ), array( array(2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567), array(13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686), array(21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372), ), array( array(-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887), array(-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954), array(-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953), ), array( array(24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833), array(-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532), array(-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876), ), array( array(2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268), array(33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214), array(1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038), ), ), array( array( array(6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800), array(4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645), array(-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664), ), array( array(1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933), array(-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182), array(-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222), ), array( array(-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991), array(20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880), array(9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092), ), array( array(-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295), array(19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788), array(8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553), ), array( array(-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026), array(11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347), array(-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033), ), array( array(-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395), array(-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278), array(1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890), ), array( array(32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995), array(-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596), array(-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891), ), array( array(31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060), array(11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608), array(-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606), ), ), array( array( array(7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389), array(-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016), array(-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341), ), array( array(-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505), array(14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553), array(-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655), ), array( array(15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220), array(12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631), array(-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099), ), array( array(26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556), array(14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749), array(236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930), ), array( array(1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391), array(5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253), array(20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066), ), array( array(24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958), array(-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082), array(-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383), ), array( array(-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521), array(-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807), array(23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948), ), array( array(9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134), array(-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455), array(27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629), ), ), array( array( array(-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069), array(-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746), array(24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919), ), array( array(11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837), array(8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906), array(-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771), ), array( array(-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817), array(10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098), array(10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409), ), array( array(-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504), array(-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727), array(28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420), ), array( array(-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003), array(-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605), array(-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384), ), array( array(-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701), array(-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683), array(29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708), ), array( array(-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563), array(-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260), array(-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387), ), array( array(-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672), array(23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686), array(-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665), ), ), array( array( array(11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182), array(-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277), array(14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628), ), array( array(-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474), array(-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539), array(-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822), ), array( array(-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970), array(19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756), array(-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508), ), array( array(-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683), array(-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655), array(-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158), ), array( array(-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125), array(-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839), array(-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664), ), array( array(27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294), array(-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899), array(-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070), ), array( array(3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294), array(-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949), array(-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083), ), array( array(31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420), array(-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940), array(29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396), ), ), array( array( array(-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567), array(20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127), array(-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294), ), array( array(-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887), array(22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964), array(16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195), ), array( array(9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244), array(24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999), array(-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762), ), array( array(-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274), array(-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236), array(-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605), ), array( array(-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761), array(-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884), array(-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482), ), array( array(-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638), array(-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490), array(-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170), ), array( array(5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736), array(10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124), array(-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392), ), array( array(8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029), array(6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048), array(28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958), ), ), array( array( array(24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593), array(26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071), array(-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692), ), array( array(11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687), array(-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441), array(-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001), ), array( array(-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460), array(-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007), array(-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762), ), array( array(15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005), array(-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674), array(4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035), ), array( array(7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590), array(-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957), array(-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812), ), array( array(33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740), array(-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122), array(-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158), ), array( array(8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885), array(26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140), array(19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857), ), array( array(801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155), array(19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260), array(19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483), ), ), array( array( array(-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677), array(32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815), array(22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751), ), array( array(-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203), array(-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208), array(1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230), ), array( array(16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850), array(-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389), array(-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968), ), array( array(-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689), array(14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880), array(5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304), ), array( array(30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632), array(-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412), array(20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566), ), array( array(-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038), array(-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232), array(-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943), ), array( array(17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856), array(23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738), array(15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971), ), array( array(-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718), array(-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697), array(-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883), ), ), array( array( array(5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912), array(-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358), array(3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849), ), array( array(29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307), array(-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977), array(-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335), ), array( array(-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644), array(-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616), array(-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735), ), array( array(-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099), array(29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341), array(-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336), ), array( array(-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646), array(31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425), array(-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388), ), array( array(-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743), array(-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822), array(-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462), ), array( array(18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985), array(9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702), array(-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797), ), array( array(21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293), array(27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100), array(19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688), ), ), array( array( array(12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186), array(2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610), array(-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707), ), array( array(7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220), array(915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025), array(32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044), ), array( array(32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992), array(-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027), array(21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197), ), array( array(8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901), array(31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952), array(19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878), ), array( array(-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390), array(32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730), array(2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730), ), array( array(-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180), array(-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272), array(-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715), ), array( array(-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970), array(-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772), array(-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865), ), array( array(15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750), array(20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373), array(32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348), ), ), array( array( array(9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144), array(-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195), array(5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086), ), array( array(-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684), array(-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518), array(-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233), ), array( array(-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793), array(-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794), array(580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435), ), array( array(23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921), array(13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518), array(2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563), ), array( array(14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278), array(-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024), array(4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030), ), array( array(10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783), array(27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717), array(6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844), ), array( array(14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333), array(16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048), array(22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760), ), array( array(-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760), array(-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757), array(-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112), ), ), array( array( array(-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468), array(3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184), array(10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289), ), array( array(15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066), array(24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882), array(13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226), ), array( array(16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101), array(29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279), array(-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811), ), array( array(27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709), array(20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714), array(-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121), ), array( array(9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464), array(12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847), array(13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400), ), array( array(4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414), array(-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158), array(17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045), ), array( array(-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415), array(-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459), array(-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079), ), array( array(21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412), array(-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743), array(-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836), ), ), array( array( array(12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022), array(18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429), array(-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065), ), array( array(30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861), array(10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000), array(-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101), ), array( array(32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815), array(29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642), array(10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966), ), array( array(25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574), array(-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742), array(-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689), ), array( array(12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020), array(-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772), array(3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982), ), array( array(-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953), array(-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218), array(-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265), ), array( array(29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073), array(-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325), array(-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798), ), array( array(-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870), array(-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863), array(-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927), ), ), array( array( array(-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267), array(-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663), array(22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862), ), array( array(-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673), array(15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943), array(15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020), ), array( array(-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238), array(11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064), array(14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795), ), array( array(15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052), array(-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904), array(29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531), ), array( array(-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979), array(-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841), array(10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431), ), array( array(10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324), array(-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940), array(10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320), ), array( array(-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184), array(14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114), array(30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878), ), array( array(12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784), array(-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091), array(-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585), ), ), array( array( array(-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208), array(10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864), array(17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661), ), array( array(7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233), array(26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212), array(-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525), ), array( array(-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068), array(9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397), array(-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988), ), array( array(5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889), array(32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038), array(14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697), ), array( array(20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875), array(-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905), array(-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656), ), array( array(11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818), array(27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714), array(10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203), ), array( array(20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931), array(-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024), array(-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084), ), array( array(-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204), array(20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817), array(27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667), ), ), array( array( array(11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504), array(-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768), array(-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255), ), array( array(6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790), array(1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438), array(-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333), ), array( array(17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971), array(31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905), array(29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409), ), array( array(12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409), array(6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499), array(-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363), ), array( array(28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664), array(-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324), array(-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940), ), array( array(13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990), array(-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914), array(-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290), ), array( array(24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257), array(-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433), array(-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236), ), array( array(-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045), array(11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093), array(-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347), ), ), array( array( array(-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191), array(-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507), array(-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906), ), array( array(3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018), array(-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109), array(-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926), ), array( array(-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528), array(8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625), array(-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286), ), array( array(2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033), array(27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866), array(21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896), ), array( array(30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075), array(26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347), array(-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437), ), array( array(-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165), array(-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588), array(-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193), ), array( array(-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017), array(-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883), array(21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961), ), array( array(8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043), array(29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663), array(-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362), ), ), array( array( array(-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860), array(2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466), array(-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063), ), array( array(-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997), array(-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295), array(-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369), ), array( array(9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385), array(18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109), array(2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906), ), array( array(4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424), array(-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185), array(7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962), ), array( array(-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325), array(10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593), array(696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404), ), array( array(-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644), array(17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801), array(26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804), ), array( array(-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884), array(-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577), array(-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849), ), array( array(32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473), array(-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644), array(-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319), ), ), array( array( array(-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599), array(-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768), array(-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084), ), array( array(-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328), array(-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369), array(20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920), ), array( array(12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815), array(-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025), array(-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397), ), array( array(-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448), array(6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981), array(30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165), ), array( array(32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501), array(17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073), array(-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861), ), array( array(14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845), array(-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211), array(18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870), ), array( array(10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096), array(33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803), array(-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168), ), array( array(30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965), array(-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505), array(18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598), ), ), array( array( array(5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782), array(5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900), array(-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479), ), array( array(-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208), array(8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232), array(17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719), ), array( array(16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271), array(-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326), array(-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132), ), array( array(14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300), array(8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570), array(15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670), ), array( array(-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994), array(-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913), array(31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317), ), array( array(-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730), array(842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096), array(-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078), ), array( array(-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411), array(-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905), array(-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654), ), array( array(-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870), array(-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498), array(12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579), ), ), array( array( array(14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677), array(10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647), array(-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743), ), array( array(-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468), array(21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375), array(-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155), ), array( array(6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725), array(-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612), array(-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943), ), array( array(-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944), array(30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928), array(9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406), ), array( array(22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139), array(-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963), array(-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693), ), array( array(1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734), array(-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680), array(-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410), ), array( array(-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931), array(-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654), array(22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710), ), array( array(29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180), array(-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684), array(-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895), ), ), array( array( array(22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501), array(-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413), array(6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880), ), array( array(-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874), array(22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962), array(-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899), ), array( array(21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152), array(9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063), array(7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080), ), array( array(-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146), array(-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183), array(-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133), ), array( array(-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421), array(-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622), array(-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197), ), array( array(2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663), array(31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753), array(4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755), ), array( array(-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862), array(-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118), array(26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171), ), array( array(15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380), array(16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824), array(28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270), ), ), array( array( array(-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438), array(-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584), array(-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562), ), array( array(30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471), array(18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610), array(19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269), ), array( array(-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650), array(14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369), array(19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461), ), array( array(30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462), array(-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793), array(-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218), ), array( array(-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226), array(18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019), array(-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037), ), array( array(31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171), array(-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132), array(-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841), ), array( array(21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181), array(-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210), array(-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040), ), array( array(3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935), array(24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105), array(-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814), ), ), array( array( array(793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852), array(5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581), array(-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646), ), array( array(10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844), array(10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025), array(27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453), ), array( array(-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068), array(4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192), array(-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921), ), array( array(-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259), array(-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426), array(-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072), ), array( array(-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305), array(13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832), array(28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943), ), array( array(-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011), array(24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447), array(17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494), ), array( array(-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245), array(-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859), array(28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915), ), array( array(16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707), array(10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848), array(-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224), ), ), array( array( array(-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391), array(15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215), array(-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101), ), array( array(23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713), array(21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849), array(-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930), ), array( array(-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940), array(-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031), array(-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404), ), array( array(-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243), array(-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116), array(-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525), ), array( array(-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509), array(-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883), array(15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865), ), array( array(-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660), array(4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273), array(-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138), ), array( array(-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560), array(-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135), array(2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941), ), array( array(-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739), array(18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756), array(-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819), ), ), array( array( array(-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347), array(-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028), array(21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075), ), array( array(16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799), array(-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609), array(-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817), ), array( array(-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989), array(-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523), array(4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278), ), array( array(31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045), array(19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377), array(24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480), ), array( array(17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016), array(510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426), array(18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525), ), array( array(13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396), array(9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080), array(12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892), ), array( array(15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275), array(11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074), array(20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140), ), array( array(-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717), array(-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101), array(24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127), ), ), array( array( array(-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632), array(-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415), array(-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160), ), array( array(31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876), array(22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625), array(-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478), ), array( array(27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164), array(26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595), array(-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248), ), array( array(-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858), array(15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193), array(8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184), ), array( array(-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942), array(-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635), array(21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948), ), array( array(11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935), array(-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415), array(-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416), ), array( array(-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018), array(4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778), array(366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659), ), array( array(-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385), array(18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503), array(476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329), ), ), array( array( array(20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056), array(-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838), array(24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948), ), array( array(-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691), array(-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118), array(-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517), ), array( array(-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269), array(-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904), array(-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589), ), array( array(-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193), array(-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910), array(-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930), ), array( array(-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667), array(25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481), array(-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876), ), array( array(22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640), array(-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278), array(-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112), ), array( array(26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272), array(17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012), array(-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221), ), array( array(30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046), array(13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345), array(-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310), ), ), array( array( array(19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937), array(31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636), array(-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008), ), array( array(-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429), array(-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576), array(31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066), ), array( array(-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490), array(-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104), array(33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053), ), array( array(31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275), array(-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511), array(22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095), ), array( array(-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439), array(23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939), array(-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424), ), array( array(2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310), array(3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608), array(-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079), ), array( array(-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101), array(21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418), array(18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576), ), array( array(30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356), array(9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996), array(-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099), ), ), array( array( array(-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728), array(-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658), array(-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242), ), array( array(-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001), array(-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766), array(18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373), ), array( array(26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458), array(-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628), array(-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657), ), array( array(-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062), array(25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616), array(31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014), ), array( array(24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383), array(-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814), array(-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718), ), array( array(30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417), array(2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222), array(33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444), ), array( array(-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597), array(23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970), array(1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799), ), array( array(-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647), array(13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511), array(-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032), ), ), array( array( array(9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834), array(-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461), array(29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062), ), array( array(-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516), array(-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547), array(-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240), ), array( array(-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038), array(-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741), array(16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103), ), array( array(-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747), array(-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323), array(31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016), ), array( array(-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373), array(15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228), array(-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141), ), array( array(16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399), array(11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831), array(-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376), ), array( array(-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313), array(-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958), array(-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577), ), array( array(-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743), array(29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684), array(-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476), ), ) ); /** * See: libsodium's crypto_core/curve25519/ref10/base2.h * * @var array<int, array<int, array<int, int>>> basically int[8][3] */ protected static $base2 = array( array( array(25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605), array(-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378), array(-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546), ), array( array(15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024), array(16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574), array(30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357), ), array( array(10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380), array(4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306), array(19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942), ), array( array(5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766), array(-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701), array(28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300), ), array( array(-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877), array(-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951), array(4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784), ), array( array(-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436), array(25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918), array(23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877), ), array( array(-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800), array(-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305), array(-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300), ), array( array(-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876), array(-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619), array(-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683), ) ); /** * 37095705934669439343138083508754565189542113879843219016388785533085940283555 * * @var array<int, int> */ protected static $d = array( -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116 ); /** * 2 * d = 16295367250680780974490674513165176452449235426866156013048779062215315747161 * * @var array<int, int> */ protected static $d2 = array( -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199 ); /** * sqrt(-1) * * @var array<int, int> */ protected static $sqrtm1 = array( -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482 ); } PK������Zڨ~T��������Core32/Util.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core32_Util', false)) { return; } /** * Class ParagonIE_Sodium_Core_Util */ abstract class ParagonIE_Sodium_Core32_Util extends ParagonIE_Sodium_Core_Util { } PK������Z=/y��y����Core32/Int64.phpnu�W+A��������<?php /** * Class ParagonIE_Sodium_Core32_Int64 * * Encapsulates a 64-bit integer. * * These are immutable. It always returns a new instance. */ class ParagonIE_Sodium_Core32_Int64 { /** * @var array<int, int> - four 16-bit integers */ public $limbs = array(0, 0, 0, 0); /** * @var int */ public $overflow = 0; /** * @var bool */ public $unsignedInt = false; /** * ParagonIE_Sodium_Core32_Int64 constructor. * @param array $array * @param bool $unsignedInt */ public function __construct($array = array(0, 0, 0, 0), $unsignedInt = false) { $this->limbs = array( (int) $array[0], (int) $array[1], (int) $array[2], (int) $array[3] ); $this->overflow = 0; $this->unsignedInt = $unsignedInt; } /** * Adds two int64 objects * * @param ParagonIE_Sodium_Core32_Int64 $addend * @return ParagonIE_Sodium_Core32_Int64 */ public function addInt64(ParagonIE_Sodium_Core32_Int64 $addend) { $i0 = $this->limbs[0]; $i1 = $this->limbs[1]; $i2 = $this->limbs[2]; $i3 = $this->limbs[3]; $j0 = $addend->limbs[0]; $j1 = $addend->limbs[1]; $j2 = $addend->limbs[2]; $j3 = $addend->limbs[3]; $r3 = $i3 + ($j3 & 0xffff); $carry = $r3 >> 16; $r2 = $i2 + ($j2 & 0xffff) + $carry; $carry = $r2 >> 16; $r1 = $i1 + ($j1 & 0xffff) + $carry; $carry = $r1 >> 16; $r0 = $i0 + ($j0 & 0xffff) + $carry; $carry = $r0 >> 16; $r0 &= 0xffff; $r1 &= 0xffff; $r2 &= 0xffff; $r3 &= 0xffff; $return = new ParagonIE_Sodium_Core32_Int64( array($r0, $r1, $r2, $r3) ); $return->overflow = $carry; $return->unsignedInt = $this->unsignedInt; return $return; } /** * Adds a normal integer to an int64 object * * @param int $int * @return ParagonIE_Sodium_Core32_Int64 * @throws SodiumException * @throws TypeError */ public function addInt($int) { ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1); /** @var int $int */ $int = (int) $int; $i0 = $this->limbs[0]; $i1 = $this->limbs[1]; $i2 = $this->limbs[2]; $i3 = $this->limbs[3]; $r3 = $i3 + ($int & 0xffff); $carry = $r3 >> 16; $r2 = $i2 + (($int >> 16) & 0xffff) + $carry; $carry = $r2 >> 16; $r1 = $i1 + $carry; $carry = $r1 >> 16; $r0 = $i0 + $carry; $carry = $r0 >> 16; $r0 &= 0xffff; $r1 &= 0xffff; $r2 &= 0xffff; $r3 &= 0xffff; $return = new ParagonIE_Sodium_Core32_Int64( array($r0, $r1, $r2, $r3) ); $return->overflow = $carry; $return->unsignedInt = $this->unsignedInt; return $return; } /** * @param int $b * @return int */ public function compareInt($b = 0) { $gt = 0; $eq = 1; $i = 4; $j = 0; while ($i > 0) { --$i; /** @var int $x1 */ $x1 = $this->limbs[$i]; /** @var int $x2 */ $x2 = ($b >> ($j << 4)) & 0xffff; /** int */ $gt |= (($x2 - $x1) >> 8) & $eq; /** int */ $eq &= (($x2 ^ $x1) - 1) >> 8; } return ($gt + $gt - $eq) + 1; } /** * @param int $b * @return bool */ public function isGreaterThan($b = 0) { return $this->compareInt($b) > 0; } /** * @param int $b * @return bool */ public function isLessThanInt($b = 0) { return $this->compareInt($b) < 0; } /** * @param int $hi * @param int $lo * @return ParagonIE_Sodium_Core32_Int64 */ public function mask64($hi = 0, $lo = 0) { /** @var int $a */ $a = ($hi >> 16) & 0xffff; /** @var int $b */ $b = ($hi) & 0xffff; /** @var int $c */ $c = ($lo >> 16) & 0xffff; /** @var int $d */ $d = ($lo & 0xffff); return new ParagonIE_Sodium_Core32_Int64( array( $this->limbs[0] & $a, $this->limbs[1] & $b, $this->limbs[2] & $c, $this->limbs[3] & $d ), $this->unsignedInt ); } /** * @param int $int * @param int $size * @return ParagonIE_Sodium_Core32_Int64 * @throws SodiumException * @throws TypeError * @psalm-suppress MixedAssignment */ public function mulInt($int = 0, $size = 0) { if (ParagonIE_Sodium_Compat::$fastMult) { return $this->mulIntFast($int); } ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1); ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2); /** @var int $int */ $int = (int) $int; /** @var int $size */ $size = (int) $size; if (!$size) { $size = 63; } $a = clone $this; $return = new ParagonIE_Sodium_Core32_Int64(); $return->unsignedInt = $this->unsignedInt; // Initialize: $ret0 = 0; $ret1 = 0; $ret2 = 0; $ret3 = 0; $a0 = $a->limbs[0]; $a1 = $a->limbs[1]; $a2 = $a->limbs[2]; $a3 = $a->limbs[3]; /** @var int $size */ /** @var int $i */ for ($i = $size; $i >= 0; --$i) { $mask = -($int & 1); $x0 = $a0 & $mask; $x1 = $a1 & $mask; $x2 = $a2 & $mask; $x3 = $a3 & $mask; $ret3 += $x3; $c = $ret3 >> 16; $ret2 += $x2 + $c; $c = $ret2 >> 16; $ret1 += $x1 + $c; $c = $ret1 >> 16; $ret0 += $x0 + $c; $ret0 &= 0xffff; $ret1 &= 0xffff; $ret2 &= 0xffff; $ret3 &= 0xffff; $a3 = $a3 << 1; $x3 = $a3 >> 16; $a2 = ($a2 << 1) | $x3; $x2 = $a2 >> 16; $a1 = ($a1 << 1) | $x2; $x1 = $a1 >> 16; $a0 = ($a0 << 1) | $x1; $a0 &= 0xffff; $a1 &= 0xffff; $a2 &= 0xffff; $a3 &= 0xffff; $int >>= 1; } $return->limbs[0] = $ret0; $return->limbs[1] = $ret1; $return->limbs[2] = $ret2; $return->limbs[3] = $ret3; return $return; } /** * @param ParagonIE_Sodium_Core32_Int64 $A * @param ParagonIE_Sodium_Core32_Int64 $B * @return array<int, ParagonIE_Sodium_Core32_Int64> * @throws SodiumException * @throws TypeError * @psalm-suppress MixedInferredReturnType */ public static function ctSelect( ParagonIE_Sodium_Core32_Int64 $A, ParagonIE_Sodium_Core32_Int64 $B ) { $a = clone $A; $b = clone $B; /** @var int $aNeg */ $aNeg = ($a->limbs[0] >> 15) & 1; /** @var int $bNeg */ $bNeg = ($b->limbs[0] >> 15) & 1; /** @var int $m */ $m = (-($aNeg & $bNeg)) | 1; /** @var int $swap */ $swap = $bNeg & ~$aNeg; /** @var int $d */ $d = -$swap; /* if ($bNeg && !$aNeg) { $a = clone $int; $b = clone $this; } elseif($bNeg && $aNeg) { $a = $this->mulInt(-1); $b = $int->mulInt(-1); } */ $x = $a->xorInt64($b)->mask64($d, $d); return array( $a->xorInt64($x)->mulInt($m), $b->xorInt64($x)->mulInt($m) ); } /** * @param array<int, int> $a * @param array<int, int> $b * @param int $baseLog2 * @return array<int, int> */ public function multiplyLong(array $a, array $b, $baseLog2 = 16) { $a_l = count($a); $b_l = count($b); /** @var array<int, int> $r */ $r = array_fill(0, $a_l + $b_l + 1, 0); $base = 1 << $baseLog2; for ($i = 0; $i < $a_l; ++$i) { $a_i = $a[$i]; for ($j = 0; $j < $a_l; ++$j) { $b_j = $b[$j]; $product = (($a_i * $b_j) + $r[$i + $j]); $carry = (((int) $product >> $baseLog2) & 0xffff); $r[$i + $j] = ((int) $product - (int) ($carry * $base)) & 0xffff; $r[$i + $j + 1] += $carry; } } return array_slice($r, 0, 5); } /** * @param int $int * @return ParagonIE_Sodium_Core32_Int64 */ public function mulIntFast($int) { // Handle negative numbers $aNeg = ($this->limbs[0] >> 15) & 1; $bNeg = ($int >> 31) & 1; $a = array_reverse($this->limbs); $b = array( $int & 0xffff, ($int >> 16) & 0xffff, -$bNeg & 0xffff, -$bNeg & 0xffff ); if ($aNeg) { for ($i = 0; $i < 4; ++$i) { $a[$i] = ($a[$i] ^ 0xffff) & 0xffff; } ++$a[0]; } if ($bNeg) { for ($i = 0; $i < 4; ++$i) { $b[$i] = ($b[$i] ^ 0xffff) & 0xffff; } ++$b[0]; } // Multiply $res = $this->multiplyLong($a, $b); // Re-apply negation to results if ($aNeg !== $bNeg) { for ($i = 0; $i < 4; ++$i) { $res[$i] = (0xffff ^ $res[$i]) & 0xffff; } // Handle integer overflow $c = 1; for ($i = 0; $i < 4; ++$i) { $res[$i] += $c; $c = $res[$i] >> 16; $res[$i] &= 0xffff; } } // Return our values $return = new ParagonIE_Sodium_Core32_Int64(); $return->limbs = array( $res[3] & 0xffff, $res[2] & 0xffff, $res[1] & 0xffff, $res[0] & 0xffff ); if (count($res) > 4) { $return->overflow = $res[4] & 0xffff; } $return->unsignedInt = $this->unsignedInt; return $return; } /** * @param ParagonIE_Sodium_Core32_Int64 $right * @return ParagonIE_Sodium_Core32_Int64 */ public function mulInt64Fast(ParagonIE_Sodium_Core32_Int64 $right) { $aNeg = ($this->limbs[0] >> 15) & 1; $bNeg = ($right->limbs[0] >> 15) & 1; $a = array_reverse($this->limbs); $b = array_reverse($right->limbs); if ($aNeg) { for ($i = 0; $i < 4; ++$i) { $a[$i] = ($a[$i] ^ 0xffff) & 0xffff; } ++$a[0]; } if ($bNeg) { for ($i = 0; $i < 4; ++$i) { $b[$i] = ($b[$i] ^ 0xffff) & 0xffff; } ++$b[0]; } $res = $this->multiplyLong($a, $b); if ($aNeg !== $bNeg) { if ($aNeg !== $bNeg) { for ($i = 0; $i < 4; ++$i) { $res[$i] = ($res[$i] ^ 0xffff) & 0xffff; } $c = 1; for ($i = 0; $i < 4; ++$i) { $res[$i] += $c; $c = $res[$i] >> 16; $res[$i] &= 0xffff; } } } $return = new ParagonIE_Sodium_Core32_Int64(); $return->limbs = array( $res[3] & 0xffff, $res[2] & 0xffff, $res[1] & 0xffff, $res[0] & 0xffff ); if (count($res) > 4) { $return->overflow = $res[4]; } return $return; } /** * @param ParagonIE_Sodium_Core32_Int64 $int * @param int $size * @return ParagonIE_Sodium_Core32_Int64 * @throws SodiumException * @throws TypeError * @psalm-suppress MixedAssignment */ public function mulInt64(ParagonIE_Sodium_Core32_Int64 $int, $size = 0) { if (ParagonIE_Sodium_Compat::$fastMult) { return $this->mulInt64Fast($int); } ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2); if (!$size) { $size = 63; } list($a, $b) = self::ctSelect($this, $int); $return = new ParagonIE_Sodium_Core32_Int64(); $return->unsignedInt = $this->unsignedInt; // Initialize: $ret0 = 0; $ret1 = 0; $ret2 = 0; $ret3 = 0; $a0 = $a->limbs[0]; $a1 = $a->limbs[1]; $a2 = $a->limbs[2]; $a3 = $a->limbs[3]; $b0 = $b->limbs[0]; $b1 = $b->limbs[1]; $b2 = $b->limbs[2]; $b3 = $b->limbs[3]; /** @var int $size */ /** @var int $i */ for ($i = (int) $size; $i >= 0; --$i) { $mask = -($b3 & 1); $x0 = $a0 & $mask; $x1 = $a1 & $mask; $x2 = $a2 & $mask; $x3 = $a3 & $mask; $ret3 += $x3; $c = $ret3 >> 16; $ret2 += $x2 + $c; $c = $ret2 >> 16; $ret1 += $x1 + $c; $c = $ret1 >> 16; $ret0 += $x0 + $c; $ret0 &= 0xffff; $ret1 &= 0xffff; $ret2 &= 0xffff; $ret3 &= 0xffff; $a3 = $a3 << 1; $x3 = $a3 >> 16; $a2 = ($a2 << 1) | $x3; $x2 = $a2 >> 16; $a1 = ($a1 << 1) | $x2; $x1 = $a1 >> 16; $a0 = ($a0 << 1) | $x1; $a0 &= 0xffff; $a1 &= 0xffff; $a2 &= 0xffff; $a3 &= 0xffff; $x0 = ($b0 & 1) << 16; $x1 = ($b1 & 1) << 16; $x2 = ($b2 & 1) << 16; $b0 = ($b0 >> 1); $b1 = (($b1 | $x0) >> 1); $b2 = (($b2 | $x1) >> 1); $b3 = (($b3 | $x2) >> 1); $b0 &= 0xffff; $b1 &= 0xffff; $b2 &= 0xffff; $b3 &= 0xffff; } $return->limbs[0] = $ret0; $return->limbs[1] = $ret1; $return->limbs[2] = $ret2; $return->limbs[3] = $ret3; return $return; } /** * OR this 64-bit integer with another. * * @param ParagonIE_Sodium_Core32_Int64 $b * @return ParagonIE_Sodium_Core32_Int64 */ public function orInt64(ParagonIE_Sodium_Core32_Int64 $b) { $return = new ParagonIE_Sodium_Core32_Int64(); $return->unsignedInt = $this->unsignedInt; $return->limbs = array( (int) ($this->limbs[0] | $b->limbs[0]), (int) ($this->limbs[1] | $b->limbs[1]), (int) ($this->limbs[2] | $b->limbs[2]), (int) ($this->limbs[3] | $b->limbs[3]) ); return $return; } /** * @param int $c * @return ParagonIE_Sodium_Core32_Int64 * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArrayAccess */ public function rotateLeft($c = 0) { ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1); /** @var int $c */ $c = (int) $c; $return = new ParagonIE_Sodium_Core32_Int64(); $return->unsignedInt = $this->unsignedInt; $c &= 63; if ($c === 0) { // NOP, but we want a copy. $return->limbs = $this->limbs; } else { /** @var array<int, int> $limbs */ $limbs =& $return->limbs; /** @var array<int, int> $myLimbs */ $myLimbs =& $this->limbs; /** @var int $idx_shift */ $idx_shift = ($c >> 4) & 3; /** @var int $sub_shift */ $sub_shift = $c & 15; for ($i = 3; $i >= 0; --$i) { /** @var int $j */ $j = ($i + $idx_shift) & 3; /** @var int $k */ $k = ($i + $idx_shift + 1) & 3; $limbs[$i] = (int) ( ( ((int) ($myLimbs[$j]) << $sub_shift) | ((int) ($myLimbs[$k]) >> (16 - $sub_shift)) ) & 0xffff ); } } return $return; } /** * Rotate to the right * * @param int $c * @return ParagonIE_Sodium_Core32_Int64 * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArrayAccess */ public function rotateRight($c = 0) { ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1); /** @var int $c */ $c = (int) $c; /** @var ParagonIE_Sodium_Core32_Int64 $return */ $return = new ParagonIE_Sodium_Core32_Int64(); $return->unsignedInt = $this->unsignedInt; $c &= 63; /** @var int $c */ if ($c === 0) { // NOP, but we want a copy. $return->limbs = $this->limbs; } else { /** @var array<int, int> $limbs */ $limbs =& $return->limbs; /** @var array<int, int> $myLimbs */ $myLimbs =& $this->limbs; /** @var int $idx_shift */ $idx_shift = ($c >> 4) & 3; /** @var int $sub_shift */ $sub_shift = $c & 15; for ($i = 3; $i >= 0; --$i) { /** @var int $j */ $j = ($i - $idx_shift) & 3; /** @var int $k */ $k = ($i - $idx_shift - 1) & 3; $limbs[$i] = (int) ( ( ((int) ($myLimbs[$j]) >> (int) ($sub_shift)) | ((int) ($myLimbs[$k]) << (16 - (int) ($sub_shift))) ) & 0xffff ); } } return $return; } /** * @param int $c * @return ParagonIE_Sodium_Core32_Int64 * @throws SodiumException * @throws TypeError */ public function shiftLeft($c = 0) { ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1); /** @var int $c */ $c = (int) $c; $return = new ParagonIE_Sodium_Core32_Int64(); $return->unsignedInt = $this->unsignedInt; $c &= 63; if ($c >= 16) { if ($c >= 48) { $return->limbs = array( $this->limbs[3], 0, 0, 0 ); } elseif ($c >= 32) { $return->limbs = array( $this->limbs[2], $this->limbs[3], 0, 0 ); } else { $return->limbs = array( $this->limbs[1], $this->limbs[2], $this->limbs[3], 0 ); } return $return->shiftLeft($c & 15); } if ($c === 0) { $return->limbs = $this->limbs; } elseif ($c < 0) { /** @var int $c */ return $this->shiftRight(-$c); } else { if (!is_int($c)) { throw new TypeError(); } /** @var int $carry */ $carry = 0; for ($i = 3; $i >= 0; --$i) { /** @var int $tmp */ $tmp = ($this->limbs[$i] << $c) | ($carry & 0xffff); $return->limbs[$i] = (int) ($tmp & 0xffff); /** @var int $carry */ $carry = $tmp >> 16; } } return $return; } /** * @param int $c * @return ParagonIE_Sodium_Core32_Int64 * @throws SodiumException * @throws TypeError */ public function shiftRight($c = 0) { ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1); $c = (int) $c; /** @var int $c */ $return = new ParagonIE_Sodium_Core32_Int64(); $return->unsignedInt = $this->unsignedInt; $c &= 63; $negative = -(($this->limbs[0] >> 15) & 1); if ($c >= 16) { if ($c >= 48) { $return->limbs = array( (int) ($negative & 0xffff), (int) ($negative & 0xffff), (int) ($negative & 0xffff), (int) $this->limbs[0] ); } elseif ($c >= 32) { $return->limbs = array( (int) ($negative & 0xffff), (int) ($negative & 0xffff), (int) $this->limbs[0], (int) $this->limbs[1] ); } else { $return->limbs = array( (int) ($negative & 0xffff), (int) $this->limbs[0], (int) $this->limbs[1], (int) $this->limbs[2] ); } return $return->shiftRight($c & 15); } if ($c === 0) { $return->limbs = $this->limbs; } elseif ($c < 0) { return $this->shiftLeft(-$c); } else { if (!is_int($c)) { throw new TypeError(); } /** @var int $carryRight */ $carryRight = ($negative & 0xffff); $mask = (int) (((1 << ($c + 1)) - 1) & 0xffff); for ($i = 0; $i < 4; ++$i) { $return->limbs[$i] = (int) ( (($this->limbs[$i] >> $c) | ($carryRight << (16 - $c))) & 0xffff ); $carryRight = (int) ($this->limbs[$i] & $mask); } } return $return; } /** * Subtract a normal integer from an int64 object. * * @param int $int * @return ParagonIE_Sodium_Core32_Int64 * @throws SodiumException * @throws TypeError */ public function subInt($int) { ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1); $int = (int) $int; $return = new ParagonIE_Sodium_Core32_Int64(); $return->unsignedInt = $this->unsignedInt; /** @var int $carry */ $carry = 0; for ($i = 3; $i >= 0; --$i) { /** @var int $tmp */ $tmp = $this->limbs[$i] - (($int >> 16) & 0xffff) + $carry; /** @var int $carry */ $carry = $tmp >> 16; $return->limbs[$i] = (int) ($tmp & 0xffff); } return $return; } /** * The difference between two Int64 objects. * * @param ParagonIE_Sodium_Core32_Int64 $b * @return ParagonIE_Sodium_Core32_Int64 */ public function subInt64(ParagonIE_Sodium_Core32_Int64 $b) { $return = new ParagonIE_Sodium_Core32_Int64(); $return->unsignedInt = $this->unsignedInt; /** @var int $carry */ $carry = 0; for ($i = 3; $i >= 0; --$i) { /** @var int $tmp */ $tmp = $this->limbs[$i] - $b->limbs[$i] + $carry; /** @var int $carry */ $carry = ($tmp >> 16); $return->limbs[$i] = (int) ($tmp & 0xffff); } return $return; } /** * XOR this 64-bit integer with another. * * @param ParagonIE_Sodium_Core32_Int64 $b * @return ParagonIE_Sodium_Core32_Int64 */ public function xorInt64(ParagonIE_Sodium_Core32_Int64 $b) { $return = new ParagonIE_Sodium_Core32_Int64(); $return->unsignedInt = $this->unsignedInt; $return->limbs = array( (int) ($this->limbs[0] ^ $b->limbs[0]), (int) ($this->limbs[1] ^ $b->limbs[1]), (int) ($this->limbs[2] ^ $b->limbs[2]), (int) ($this->limbs[3] ^ $b->limbs[3]) ); return $return; } /** * @param int $low * @param int $high * @return self * @throws SodiumException * @throws TypeError */ public static function fromInts($low, $high) { ParagonIE_Sodium_Core32_Util::declareScalarType($low, 'int', 1); ParagonIE_Sodium_Core32_Util::declareScalarType($high, 'int', 2); $high = (int) $high; $low = (int) $low; return new ParagonIE_Sodium_Core32_Int64( array( (int) (($high >> 16) & 0xffff), (int) ($high & 0xffff), (int) (($low >> 16) & 0xffff), (int) ($low & 0xffff) ) ); } /** * @param int $low * @return self * @throws SodiumException * @throws TypeError */ public static function fromInt($low) { ParagonIE_Sodium_Core32_Util::declareScalarType($low, 'int', 1); $low = (int) $low; return new ParagonIE_Sodium_Core32_Int64( array( 0, 0, (int) (($low >> 16) & 0xffff), (int) ($low & 0xffff) ) ); } /** * @return int */ public function toInt() { return (int) ( (($this->limbs[2] & 0xffff) << 16) | ($this->limbs[3] & 0xffff) ); } /** * @param string $string * @return self * @throws SodiumException * @throws TypeError */ public static function fromString($string) { ParagonIE_Sodium_Core32_Util::declareScalarType($string, 'string', 1); $string = (string) $string; if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 8) { throw new RangeException( 'String must be 8 bytes; ' . ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.' ); } $return = new ParagonIE_Sodium_Core32_Int64(); $return->limbs[0] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff) << 8); $return->limbs[0] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff); $return->limbs[1] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff) << 8); $return->limbs[1] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff); $return->limbs[2] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[4]) & 0xff) << 8); $return->limbs[2] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[5]) & 0xff); $return->limbs[3] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[6]) & 0xff) << 8); $return->limbs[3] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[7]) & 0xff); return $return; } /** * @param string $string * @return self * @throws SodiumException * @throws TypeError */ public static function fromReverseString($string) { ParagonIE_Sodium_Core32_Util::declareScalarType($string, 'string', 1); $string = (string) $string; if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 8) { throw new RangeException( 'String must be 8 bytes; ' . ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.' ); } $return = new ParagonIE_Sodium_Core32_Int64(); $return->limbs[0] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[7]) & 0xff) << 8); $return->limbs[0] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[6]) & 0xff); $return->limbs[1] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[5]) & 0xff) << 8); $return->limbs[1] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[4]) & 0xff); $return->limbs[2] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff) << 8); $return->limbs[2] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff); $return->limbs[3] = (int) ((ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff) << 8); $return->limbs[3] |= (ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff); return $return; } /** * @return array<int, int> */ public function toArray() { return array( (int) ((($this->limbs[0] & 0xffff) << 16) | ($this->limbs[1] & 0xffff)), (int) ((($this->limbs[2] & 0xffff) << 16) | ($this->limbs[3] & 0xffff)) ); } /** * @return ParagonIE_Sodium_Core32_Int32 */ public function toInt32() { $return = new ParagonIE_Sodium_Core32_Int32(); $return->limbs[0] = (int) ($this->limbs[2]); $return->limbs[1] = (int) ($this->limbs[3]); $return->unsignedInt = $this->unsignedInt; $return->overflow = (int) (ParagonIE_Sodium_Core32_Util::abs($this->limbs[1], 16) & 0xffff); return $return; } /** * @return ParagonIE_Sodium_Core32_Int64 */ public function toInt64() { $return = new ParagonIE_Sodium_Core32_Int64(); $return->limbs[0] = (int) ($this->limbs[0]); $return->limbs[1] = (int) ($this->limbs[1]); $return->limbs[2] = (int) ($this->limbs[2]); $return->limbs[3] = (int) ($this->limbs[3]); $return->unsignedInt = $this->unsignedInt; $return->overflow = ParagonIE_Sodium_Core32_Util::abs($this->overflow); return $return; } /** * @param bool $bool * @return self */ public function setUnsignedInt($bool = false) { $this->unsignedInt = !empty($bool); return $this; } /** * @return string * @throws TypeError */ public function toString() { return ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[0] >> 8) & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[1] >> 8) & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[2] >> 8) & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[2] & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[3] >> 8) & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[3] & 0xff); } /** * @return string * @throws TypeError */ public function toReverseString() { return ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[3] & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[3] >> 8) & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[2] & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[2] >> 8) & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[1] >> 8) & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] & 0xff) . ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[0] >> 8) & 0xff); } /** * @return string */ public function __toString() { try { return $this->toString(); } catch (TypeError $ex) { // PHP engine can't handle exceptions from __toString() return ''; } } } PK������Zl��������SodiumException.phpnu�W+A��������<?php if (!class_exists('SodiumException', false)) { /** * Class SodiumException */ class SodiumException extends Exception { } } PK������Z^���� ��Crypto.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Crypto', false)) { return; } /** * Class ParagonIE_Sodium_Crypto * * ATTENTION! * * If you are using this library, you should be using * ParagonIE_Sodium_Compat in your code, not this class. */ abstract class ParagonIE_Sodium_Crypto { const aead_chacha20poly1305_KEYBYTES = 32; const aead_chacha20poly1305_NSECBYTES = 0; const aead_chacha20poly1305_NPUBBYTES = 8; const aead_chacha20poly1305_ABYTES = 16; const aead_chacha20poly1305_IETF_KEYBYTES = 32; const aead_chacha20poly1305_IETF_NSECBYTES = 0; const aead_chacha20poly1305_IETF_NPUBBYTES = 12; const aead_chacha20poly1305_IETF_ABYTES = 16; const aead_xchacha20poly1305_IETF_KEYBYTES = 32; const aead_xchacha20poly1305_IETF_NSECBYTES = 0; const aead_xchacha20poly1305_IETF_NPUBBYTES = 24; const aead_xchacha20poly1305_IETF_ABYTES = 16; const box_curve25519xsalsa20poly1305_SEEDBYTES = 32; const box_curve25519xsalsa20poly1305_PUBLICKEYBYTES = 32; const box_curve25519xsalsa20poly1305_SECRETKEYBYTES = 32; const box_curve25519xsalsa20poly1305_BEFORENMBYTES = 32; const box_curve25519xsalsa20poly1305_NONCEBYTES = 24; const box_curve25519xsalsa20poly1305_MACBYTES = 16; const box_curve25519xsalsa20poly1305_BOXZEROBYTES = 16; const box_curve25519xsalsa20poly1305_ZEROBYTES = 32; const onetimeauth_poly1305_BYTES = 16; const onetimeauth_poly1305_KEYBYTES = 32; const secretbox_xsalsa20poly1305_KEYBYTES = 32; const secretbox_xsalsa20poly1305_NONCEBYTES = 24; const secretbox_xsalsa20poly1305_MACBYTES = 16; const secretbox_xsalsa20poly1305_BOXZEROBYTES = 16; const secretbox_xsalsa20poly1305_ZEROBYTES = 32; const secretbox_xchacha20poly1305_KEYBYTES = 32; const secretbox_xchacha20poly1305_NONCEBYTES = 24; const secretbox_xchacha20poly1305_MACBYTES = 16; const secretbox_xchacha20poly1305_BOXZEROBYTES = 16; const secretbox_xchacha20poly1305_ZEROBYTES = 32; const stream_salsa20_KEYBYTES = 32; /** * AEAD Decryption with ChaCha20-Poly1305 * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $ad * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function aead_chacha20poly1305_decrypt( $message = '', $ad = '', $nonce = '', $key = '' ) { /** @var int $len - Length of message (ciphertext + MAC) */ $len = ParagonIE_Sodium_Core_Util::strlen($message); /** @var int $clen - Length of ciphertext */ $clen = $len - self::aead_chacha20poly1305_ABYTES; /** @var int $adlen - Length of associated data */ $adlen = ParagonIE_Sodium_Core_Util::strlen($ad); /** @var string $mac - Message authentication code */ $mac = ParagonIE_Sodium_Core_Util::substr( $message, $clen, self::aead_chacha20poly1305_ABYTES ); /** @var string $ciphertext - The encrypted message (sans MAC) */ $ciphertext = ParagonIE_Sodium_Core_Util::substr($message, 0, $clen); /** @var string The first block of the chacha20 keystream, used as a poly1305 key */ $block0 = ParagonIE_Sodium_Core_ChaCha20::stream( 32, $nonce, $key ); /* Recalculate the Poly1305 authentication tag (MAC): */ $state = new ParagonIE_Sodium_Core_Poly1305_State($block0); try { ParagonIE_Sodium_Compat::memzero($block0); } catch (SodiumException $ex) { $block0 = null; } $state->update($ad); $state->update(ParagonIE_Sodium_Core_Util::store64_le($adlen)); $state->update($ciphertext); $state->update(ParagonIE_Sodium_Core_Util::store64_le($clen)); $computed_mac = $state->finish(); /* Compare the given MAC with the recalculated MAC: */ if (!ParagonIE_Sodium_Core_Util::verify_16($computed_mac, $mac)) { throw new SodiumException('Invalid MAC'); } // Here, we know that the MAC is valid, so we decrypt and return the plaintext return ParagonIE_Sodium_Core_ChaCha20::streamXorIc( $ciphertext, $nonce, $key, ParagonIE_Sodium_Core_Util::store64_le(1) ); } /** * AEAD Encryption with ChaCha20-Poly1305 * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $ad * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function aead_chacha20poly1305_encrypt( $message = '', $ad = '', $nonce = '', $key = '' ) { /** @var int $len - Length of the plaintext message */ $len = ParagonIE_Sodium_Core_Util::strlen($message); /** @var int $adlen - Length of the associated data */ $adlen = ParagonIE_Sodium_Core_Util::strlen($ad); /** @var string The first block of the chacha20 keystream, used as a poly1305 key */ $block0 = ParagonIE_Sodium_Core_ChaCha20::stream( 32, $nonce, $key ); $state = new ParagonIE_Sodium_Core_Poly1305_State($block0); try { ParagonIE_Sodium_Compat::memzero($block0); } catch (SodiumException $ex) { $block0 = null; } /** @var string $ciphertext - Raw encrypted data */ $ciphertext = ParagonIE_Sodium_Core_ChaCha20::streamXorIc( $message, $nonce, $key, ParagonIE_Sodium_Core_Util::store64_le(1) ); $state->update($ad); $state->update(ParagonIE_Sodium_Core_Util::store64_le($adlen)); $state->update($ciphertext); $state->update(ParagonIE_Sodium_Core_Util::store64_le($len)); return $ciphertext . $state->finish(); } /** * AEAD Decryption with ChaCha20-Poly1305, IETF mode (96-bit nonce) * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $ad * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function aead_chacha20poly1305_ietf_decrypt( $message = '', $ad = '', $nonce = '', $key = '' ) { /** @var int $adlen - Length of associated data */ $adlen = ParagonIE_Sodium_Core_Util::strlen($ad); /** @var int $len - Length of message (ciphertext + MAC) */ $len = ParagonIE_Sodium_Core_Util::strlen($message); /** @var int $clen - Length of ciphertext */ $clen = $len - self::aead_chacha20poly1305_IETF_ABYTES; /** @var string The first block of the chacha20 keystream, used as a poly1305 key */ $block0 = ParagonIE_Sodium_Core_ChaCha20::ietfStream( 32, $nonce, $key ); /** @var string $mac - Message authentication code */ $mac = ParagonIE_Sodium_Core_Util::substr( $message, $len - self::aead_chacha20poly1305_IETF_ABYTES, self::aead_chacha20poly1305_IETF_ABYTES ); /** @var string $ciphertext - The encrypted message (sans MAC) */ $ciphertext = ParagonIE_Sodium_Core_Util::substr( $message, 0, $len - self::aead_chacha20poly1305_IETF_ABYTES ); /* Recalculate the Poly1305 authentication tag (MAC): */ $state = new ParagonIE_Sodium_Core_Poly1305_State($block0); try { ParagonIE_Sodium_Compat::memzero($block0); } catch (SodiumException $ex) { $block0 = null; } $state->update($ad); $state->update(str_repeat("\x00", ((0x10 - $adlen) & 0xf))); $state->update($ciphertext); $state->update(str_repeat("\x00", (0x10 - $clen) & 0xf)); $state->update(ParagonIE_Sodium_Core_Util::store64_le($adlen)); $state->update(ParagonIE_Sodium_Core_Util::store64_le($clen)); $computed_mac = $state->finish(); /* Compare the given MAC with the recalculated MAC: */ if (!ParagonIE_Sodium_Core_Util::verify_16($computed_mac, $mac)) { throw new SodiumException('Invalid MAC'); } // Here, we know that the MAC is valid, so we decrypt and return the plaintext return ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc( $ciphertext, $nonce, $key, ParagonIE_Sodium_Core_Util::store64_le(1) ); } /** * AEAD Encryption with ChaCha20-Poly1305, IETF mode (96-bit nonce) * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $ad * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function aead_chacha20poly1305_ietf_encrypt( $message = '', $ad = '', $nonce = '', $key = '' ) { /** @var int $len - Length of the plaintext message */ $len = ParagonIE_Sodium_Core_Util::strlen($message); /** @var int $adlen - Length of the associated data */ $adlen = ParagonIE_Sodium_Core_Util::strlen($ad); /** @var string The first block of the chacha20 keystream, used as a poly1305 key */ $block0 = ParagonIE_Sodium_Core_ChaCha20::ietfStream( 32, $nonce, $key ); $state = new ParagonIE_Sodium_Core_Poly1305_State($block0); try { ParagonIE_Sodium_Compat::memzero($block0); } catch (SodiumException $ex) { $block0 = null; } /** @var string $ciphertext - Raw encrypted data */ $ciphertext = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc( $message, $nonce, $key, ParagonIE_Sodium_Core_Util::store64_le(1) ); $state->update($ad); $state->update(str_repeat("\x00", ((0x10 - $adlen) & 0xf))); $state->update($ciphertext); $state->update(str_repeat("\x00", ((0x10 - $len) & 0xf))); $state->update(ParagonIE_Sodium_Core_Util::store64_le($adlen)); $state->update(ParagonIE_Sodium_Core_Util::store64_le($len)); return $ciphertext . $state->finish(); } /** * AEAD Decryption with ChaCha20-Poly1305, IETF mode (96-bit nonce) * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $ad * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function aead_xchacha20poly1305_ietf_decrypt( $message = '', $ad = '', $nonce = '', $key = '' ) { $subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20( ParagonIE_Sodium_Core_Util::substr($nonce, 0, 16), $key ); $nonceLast = "\x00\x00\x00\x00" . ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8); return self::aead_chacha20poly1305_ietf_decrypt($message, $ad, $nonceLast, $subkey); } /** * AEAD Encryption with ChaCha20-Poly1305, IETF mode (96-bit nonce) * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $ad * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function aead_xchacha20poly1305_ietf_encrypt( $message = '', $ad = '', $nonce = '', $key = '' ) { $subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20( ParagonIE_Sodium_Core_Util::substr($nonce, 0, 16), $key ); $nonceLast = "\x00\x00\x00\x00" . ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8); return self::aead_chacha20poly1305_ietf_encrypt($message, $ad, $nonceLast, $subkey); } /** * HMAC-SHA-512-256 (a.k.a. the leftmost 256 bits of HMAC-SHA-512) * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $key * @return string * @throws TypeError */ public static function auth($message, $key) { return ParagonIE_Sodium_Core_Util::substr( hash_hmac('sha512', $message, $key, true), 0, 32 ); } /** * HMAC-SHA-512-256 validation. Constant-time via hash_equals(). * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $mac * @param string $message * @param string $key * @return bool * @throws SodiumException * @throws TypeError */ public static function auth_verify($mac, $message, $key) { return ParagonIE_Sodium_Core_Util::hashEquals( $mac, self::auth($message, $key) ); } /** * X25519 key exchange followed by XSalsa20Poly1305 symmetric encryption * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $plaintext * @param string $nonce * @param string $keypair * @return string * @throws SodiumException * @throws TypeError */ public static function box($plaintext, $nonce, $keypair) { $c = self::secretbox( $plaintext, $nonce, self::box_beforenm( self::box_secretkey($keypair), self::box_publickey($keypair) ) ); return $c; } /** * X25519-XSalsa20-Poly1305 with one ephemeral X25519 keypair. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $publicKey * @return string * @throws SodiumException * @throws TypeError */ public static function box_seal($message, $publicKey) { /** @var string $ephemeralKeypair */ $ephemeralKeypair = self::box_keypair(); /** @var string $ephemeralSK */ $ephemeralSK = self::box_secretkey($ephemeralKeypair); /** @var string $ephemeralPK */ $ephemeralPK = self::box_publickey($ephemeralKeypair); /** @var string $nonce */ $nonce = self::generichash( $ephemeralPK . $publicKey, '', 24 ); /** @var string $keypair - The combined keypair used in crypto_box() */ $keypair = self::box_keypair_from_secretkey_and_publickey($ephemeralSK, $publicKey); /** @var string $ciphertext Ciphertext + MAC from crypto_box */ $ciphertext = self::box($message, $nonce, $keypair); try { ParagonIE_Sodium_Compat::memzero($ephemeralKeypair); ParagonIE_Sodium_Compat::memzero($ephemeralSK); ParagonIE_Sodium_Compat::memzero($nonce); } catch (SodiumException $ex) { $ephemeralKeypair = null; $ephemeralSK = null; $nonce = null; } return $ephemeralPK . $ciphertext; } /** * Opens a message encrypted via box_seal(). * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $keypair * @return string * @throws SodiumException * @throws TypeError */ public static function box_seal_open($message, $keypair) { /** @var string $ephemeralPK */ $ephemeralPK = ParagonIE_Sodium_Core_Util::substr($message, 0, 32); /** @var string $ciphertext (ciphertext + MAC) */ $ciphertext = ParagonIE_Sodium_Core_Util::substr($message, 32); /** @var string $secretKey */ $secretKey = self::box_secretkey($keypair); /** @var string $publicKey */ $publicKey = self::box_publickey($keypair); /** @var string $nonce */ $nonce = self::generichash( $ephemeralPK . $publicKey, '', 24 ); /** @var string $keypair */ $keypair = self::box_keypair_from_secretkey_and_publickey($secretKey, $ephemeralPK); /** @var string $m */ $m = self::box_open($ciphertext, $nonce, $keypair); try { ParagonIE_Sodium_Compat::memzero($secretKey); ParagonIE_Sodium_Compat::memzero($ephemeralPK); ParagonIE_Sodium_Compat::memzero($nonce); } catch (SodiumException $ex) { $secretKey = null; $ephemeralPK = null; $nonce = null; } return $m; } /** * Used by crypto_box() to get the crypto_secretbox() key. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $sk * @param string $pk * @return string * @throws SodiumException * @throws TypeError */ public static function box_beforenm($sk, $pk) { return ParagonIE_Sodium_Core_HSalsa20::hsalsa20( str_repeat("\x00", 16), self::scalarmult($sk, $pk) ); } /** * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @return string * @throws Exception * @throws SodiumException * @throws TypeError */ public static function box_keypair() { $sKey = random_bytes(32); $pKey = self::scalarmult_base($sKey); return $sKey . $pKey; } /** * @param string $seed * @return string * @throws SodiumException * @throws TypeError */ public static function box_seed_keypair($seed) { $sKey = ParagonIE_Sodium_Core_Util::substr( hash('sha512', $seed, true), 0, 32 ); $pKey = self::scalarmult_base($sKey); return $sKey . $pKey; } /** * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $sKey * @param string $pKey * @return string * @throws TypeError */ public static function box_keypair_from_secretkey_and_publickey($sKey, $pKey) { return ParagonIE_Sodium_Core_Util::substr($sKey, 0, 32) . ParagonIE_Sodium_Core_Util::substr($pKey, 0, 32); } /** * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $keypair * @return string * @throws RangeException * @throws TypeError */ public static function box_secretkey($keypair) { if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== 64) { throw new RangeException( 'Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES bytes long.' ); } return ParagonIE_Sodium_Core_Util::substr($keypair, 0, 32); } /** * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $keypair * @return string * @throws RangeException * @throws TypeError */ public static function box_publickey($keypair) { if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) { throw new RangeException( 'Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES bytes long.' ); } return ParagonIE_Sodium_Core_Util::substr($keypair, 32, 32); } /** * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $sKey * @return string * @throws RangeException * @throws SodiumException * @throws TypeError */ public static function box_publickey_from_secretkey($sKey) { if (ParagonIE_Sodium_Core_Util::strlen($sKey) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES) { throw new RangeException( 'Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES bytes long.' ); } return self::scalarmult_base($sKey); } /** * Decrypt a message encrypted with box(). * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $ciphertext * @param string $nonce * @param string $keypair * @return string * @throws SodiumException * @throws TypeError */ public static function box_open($ciphertext, $nonce, $keypair) { return self::secretbox_open( $ciphertext, $nonce, self::box_beforenm( self::box_secretkey($keypair), self::box_publickey($keypair) ) ); } /** * Calculate a BLAKE2b hash. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string|null $key * @param int $outlen * @return string * @throws RangeException * @throws SodiumException * @throws TypeError */ public static function generichash($message, $key = '', $outlen = 32) { // This ensures that ParagonIE_Sodium_Core_BLAKE2b::$iv is initialized ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor(); $k = null; if (!empty($key)) { /** @var SplFixedArray $k */ $k = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($key); if ($k->count() > ParagonIE_Sodium_Core_BLAKE2b::KEYBYTES) { throw new RangeException('Invalid key size'); } } /** @var SplFixedArray $in */ $in = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($message); /** @var SplFixedArray $ctx */ $ctx = ParagonIE_Sodium_Core_BLAKE2b::init($k, $outlen); ParagonIE_Sodium_Core_BLAKE2b::update($ctx, $in, $in->count()); /** @var SplFixedArray $out */ $out = new SplFixedArray($outlen); $out = ParagonIE_Sodium_Core_BLAKE2b::finish($ctx, $out); /** @var array<int, int> */ $outArray = $out->toArray(); return ParagonIE_Sodium_Core_Util::intArrayToString($outArray); } /** * Finalize a BLAKE2b hashing context, returning the hash. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $ctx * @param int $outlen * @return string * @throws SodiumException * @throws TypeError */ public static function generichash_final($ctx, $outlen = 32) { if (!is_string($ctx)) { throw new TypeError('Context must be a string'); } $out = new SplFixedArray($outlen); /** @var SplFixedArray $context */ $context = ParagonIE_Sodium_Core_BLAKE2b::stringToContext($ctx); /** @var SplFixedArray $out */ $out = ParagonIE_Sodium_Core_BLAKE2b::finish($context, $out); /** @var array<int, int> */ $outArray = $out->toArray(); return ParagonIE_Sodium_Core_Util::intArrayToString($outArray); } /** * Initialize a hashing context for BLAKE2b. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $key * @param int $outputLength * @return string * @throws RangeException * @throws SodiumException * @throws TypeError */ public static function generichash_init($key = '', $outputLength = 32) { // This ensures that ParagonIE_Sodium_Core_BLAKE2b::$iv is initialized ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor(); $k = null; if (!empty($key)) { $k = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($key); if ($k->count() > ParagonIE_Sodium_Core_BLAKE2b::KEYBYTES) { throw new RangeException('Invalid key size'); } } /** @var SplFixedArray $ctx */ $ctx = ParagonIE_Sodium_Core_BLAKE2b::init($k, $outputLength); return ParagonIE_Sodium_Core_BLAKE2b::contextToString($ctx); } /** * Initialize a hashing context for BLAKE2b. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $key * @param int $outputLength * @param string $salt * @param string $personal * @return string * @throws RangeException * @throws SodiumException * @throws TypeError */ public static function generichash_init_salt_personal( $key = '', $outputLength = 32, $salt = '', $personal = '' ) { // This ensures that ParagonIE_Sodium_Core_BLAKE2b::$iv is initialized ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor(); $k = null; if (!empty($key)) { $k = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($key); if ($k->count() > ParagonIE_Sodium_Core_BLAKE2b::KEYBYTES) { throw new RangeException('Invalid key size'); } } if (!empty($salt)) { $s = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($salt); } else { $s = null; } if (!empty($salt)) { $p = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($personal); } else { $p = null; } /** @var SplFixedArray $ctx */ $ctx = ParagonIE_Sodium_Core_BLAKE2b::init($k, $outputLength, $s, $p); return ParagonIE_Sodium_Core_BLAKE2b::contextToString($ctx); } /** * Update a hashing context for BLAKE2b with $message * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $ctx * @param string $message * @return string * @throws SodiumException * @throws TypeError */ public static function generichash_update($ctx, $message) { // This ensures that ParagonIE_Sodium_Core_BLAKE2b::$iv is initialized ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor(); /** @var SplFixedArray $context */ $context = ParagonIE_Sodium_Core_BLAKE2b::stringToContext($ctx); /** @var SplFixedArray $in */ $in = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($message); ParagonIE_Sodium_Core_BLAKE2b::update($context, $in, $in->count()); return ParagonIE_Sodium_Core_BLAKE2b::contextToString($context); } /** * Libsodium's crypto_kx(). * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $my_sk * @param string $their_pk * @param string $client_pk * @param string $server_pk * @return string * @throws SodiumException * @throws TypeError */ public static function keyExchange($my_sk, $their_pk, $client_pk, $server_pk) { return ParagonIE_Sodium_Compat::crypto_generichash( ParagonIE_Sodium_Compat::crypto_scalarmult($my_sk, $their_pk) . $client_pk . $server_pk ); } /** * ECDH over Curve25519 * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $sKey * @param string $pKey * @return string * * @throws SodiumException * @throws TypeError */ public static function scalarmult($sKey, $pKey) { $q = ParagonIE_Sodium_Core_X25519::crypto_scalarmult_curve25519_ref10($sKey, $pKey); self::scalarmult_throw_if_zero($q); return $q; } /** * ECDH over Curve25519, using the basepoint. * Used to get a secret key from a public key. * * @param string $secret * @return string * * @throws SodiumException * @throws TypeError */ public static function scalarmult_base($secret) { $q = ParagonIE_Sodium_Core_X25519::crypto_scalarmult_curve25519_ref10_base($secret); self::scalarmult_throw_if_zero($q); return $q; } /** * This throws an Error if a zero public key was passed to the function. * * @param string $q * @return void * @throws SodiumException * @throws TypeError */ protected static function scalarmult_throw_if_zero($q) { $d = 0; for ($i = 0; $i < self::box_curve25519xsalsa20poly1305_SECRETKEYBYTES; ++$i) { $d |= ParagonIE_Sodium_Core_Util::chrToInt($q[$i]); } /* branch-free variant of === 0 */ if (-(1 & (($d - 1) >> 8))) { throw new SodiumException('Zero public key is not allowed'); } } /** * XSalsa20-Poly1305 authenticated symmetric-key encryption. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $plaintext * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function secretbox($plaintext, $nonce, $key) { /** @var string $subkey */ $subkey = ParagonIE_Sodium_Core_HSalsa20::hsalsa20($nonce, $key); /** @var string $block0 */ $block0 = str_repeat("\x00", 32); /** @var int $mlen - Length of the plaintext message */ $mlen = ParagonIE_Sodium_Core_Util::strlen($plaintext); $mlen0 = $mlen; if ($mlen0 > 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES) { $mlen0 = 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES; } $block0 .= ParagonIE_Sodium_Core_Util::substr($plaintext, 0, $mlen0); /** @var string $block0 */ $block0 = ParagonIE_Sodium_Core_Salsa20::salsa20_xor( $block0, ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8), $subkey ); /** @var string $c */ $c = ParagonIE_Sodium_Core_Util::substr( $block0, self::secretbox_xsalsa20poly1305_ZEROBYTES ); if ($mlen > $mlen0) { $c .= ParagonIE_Sodium_Core_Salsa20::salsa20_xor_ic( ParagonIE_Sodium_Core_Util::substr( $plaintext, self::secretbox_xsalsa20poly1305_ZEROBYTES ), ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8), 1, $subkey ); } $state = new ParagonIE_Sodium_Core_Poly1305_State( ParagonIE_Sodium_Core_Util::substr( $block0, 0, self::onetimeauth_poly1305_KEYBYTES ) ); try { ParagonIE_Sodium_Compat::memzero($block0); ParagonIE_Sodium_Compat::memzero($subkey); } catch (SodiumException $ex) { $block0 = null; $subkey = null; } $state->update($c); /** @var string $c - MAC || ciphertext */ $c = $state->finish() . $c; unset($state); return $c; } /** * Decrypt a ciphertext generated via secretbox(). * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $ciphertext * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function secretbox_open($ciphertext, $nonce, $key) { /** @var string $mac */ $mac = ParagonIE_Sodium_Core_Util::substr( $ciphertext, 0, self::secretbox_xsalsa20poly1305_MACBYTES ); /** @var string $c */ $c = ParagonIE_Sodium_Core_Util::substr( $ciphertext, self::secretbox_xsalsa20poly1305_MACBYTES ); /** @var int $clen */ $clen = ParagonIE_Sodium_Core_Util::strlen($c); /** @var string $subkey */ $subkey = ParagonIE_Sodium_Core_HSalsa20::hsalsa20($nonce, $key); /** @var string $block0 */ $block0 = ParagonIE_Sodium_Core_Salsa20::salsa20( 64, ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8), $subkey ); $verified = ParagonIE_Sodium_Core_Poly1305::onetimeauth_verify( $mac, $c, ParagonIE_Sodium_Core_Util::substr($block0, 0, 32) ); if (!$verified) { try { ParagonIE_Sodium_Compat::memzero($subkey); } catch (SodiumException $ex) { $subkey = null; } throw new SodiumException('Invalid MAC'); } /** @var string $m - Decrypted message */ $m = ParagonIE_Sodium_Core_Util::xorStrings( ParagonIE_Sodium_Core_Util::substr($block0, self::secretbox_xsalsa20poly1305_ZEROBYTES), ParagonIE_Sodium_Core_Util::substr($c, 0, self::secretbox_xsalsa20poly1305_ZEROBYTES) ); if ($clen > self::secretbox_xsalsa20poly1305_ZEROBYTES) { // We had more than 1 block, so let's continue to decrypt the rest. $m .= ParagonIE_Sodium_Core_Salsa20::salsa20_xor_ic( ParagonIE_Sodium_Core_Util::substr( $c, self::secretbox_xsalsa20poly1305_ZEROBYTES ), ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8), 1, (string) $subkey ); } return $m; } /** * XChaCha20-Poly1305 authenticated symmetric-key encryption. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $plaintext * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function secretbox_xchacha20poly1305($plaintext, $nonce, $key) { /** @var string $subkey */ $subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20( ParagonIE_Sodium_Core_Util::substr($nonce, 0, 16), $key ); $nonceLast = ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8); /** @var string $block0 */ $block0 = str_repeat("\x00", 32); /** @var int $mlen - Length of the plaintext message */ $mlen = ParagonIE_Sodium_Core_Util::strlen($plaintext); $mlen0 = $mlen; if ($mlen0 > 64 - self::secretbox_xchacha20poly1305_ZEROBYTES) { $mlen0 = 64 - self::secretbox_xchacha20poly1305_ZEROBYTES; } $block0 .= ParagonIE_Sodium_Core_Util::substr($plaintext, 0, $mlen0); /** @var string $block0 */ $block0 = ParagonIE_Sodium_Core_ChaCha20::streamXorIc( $block0, $nonceLast, $subkey ); /** @var string $c */ $c = ParagonIE_Sodium_Core_Util::substr( $block0, self::secretbox_xchacha20poly1305_ZEROBYTES ); if ($mlen > $mlen0) { $c .= ParagonIE_Sodium_Core_ChaCha20::streamXorIc( ParagonIE_Sodium_Core_Util::substr( $plaintext, self::secretbox_xchacha20poly1305_ZEROBYTES ), $nonceLast, $subkey, ParagonIE_Sodium_Core_Util::store64_le(1) ); } $state = new ParagonIE_Sodium_Core_Poly1305_State( ParagonIE_Sodium_Core_Util::substr( $block0, 0, self::onetimeauth_poly1305_KEYBYTES ) ); try { ParagonIE_Sodium_Compat::memzero($block0); ParagonIE_Sodium_Compat::memzero($subkey); } catch (SodiumException $ex) { $block0 = null; $subkey = null; } $state->update($c); /** @var string $c - MAC || ciphertext */ $c = $state->finish() . $c; unset($state); return $c; } /** * Decrypt a ciphertext generated via secretbox_xchacha20poly1305(). * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $ciphertext * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function secretbox_xchacha20poly1305_open($ciphertext, $nonce, $key) { /** @var string $mac */ $mac = ParagonIE_Sodium_Core_Util::substr( $ciphertext, 0, self::secretbox_xchacha20poly1305_MACBYTES ); /** @var string $c */ $c = ParagonIE_Sodium_Core_Util::substr( $ciphertext, self::secretbox_xchacha20poly1305_MACBYTES ); /** @var int $clen */ $clen = ParagonIE_Sodium_Core_Util::strlen($c); /** @var string $subkey */ $subkey = ParagonIE_Sodium_Core_HChaCha20::hchacha20($nonce, $key); /** @var string $block0 */ $block0 = ParagonIE_Sodium_Core_ChaCha20::stream( 64, ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8), $subkey ); $verified = ParagonIE_Sodium_Core_Poly1305::onetimeauth_verify( $mac, $c, ParagonIE_Sodium_Core_Util::substr($block0, 0, 32) ); if (!$verified) { try { ParagonIE_Sodium_Compat::memzero($subkey); } catch (SodiumException $ex) { $subkey = null; } throw new SodiumException('Invalid MAC'); } /** @var string $m - Decrypted message */ $m = ParagonIE_Sodium_Core_Util::xorStrings( ParagonIE_Sodium_Core_Util::substr($block0, self::secretbox_xchacha20poly1305_ZEROBYTES), ParagonIE_Sodium_Core_Util::substr($c, 0, self::secretbox_xchacha20poly1305_ZEROBYTES) ); if ($clen > self::secretbox_xchacha20poly1305_ZEROBYTES) { // We had more than 1 block, so let's continue to decrypt the rest. $m .= ParagonIE_Sodium_Core_ChaCha20::streamXorIc( ParagonIE_Sodium_Core_Util::substr( $c, self::secretbox_xchacha20poly1305_ZEROBYTES ), ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8), (string) $subkey, ParagonIE_Sodium_Core_Util::store64_le(1) ); } return $m; } /** * @param string $key * @return array<int, string> Returns a state and a header. * @throws Exception * @throws SodiumException */ public static function secretstream_xchacha20poly1305_init_push($key) { # randombytes_buf(out, crypto_secretstream_xchacha20poly1305_HEADERBYTES); $out = random_bytes(24); # crypto_core_hchacha20(state->k, out, k, NULL); $subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20($out, $key); $state = new ParagonIE_Sodium_Core_SecretStream_State( $subkey, ParagonIE_Sodium_Core_Util::substr($out, 16, 8) . str_repeat("\0", 4) ); # _crypto_secretstream_xchacha20poly1305_counter_reset(state); $state->counterReset(); # memcpy(STATE_INONCE(state), out + crypto_core_hchacha20_INPUTBYTES, # crypto_secretstream_xchacha20poly1305_INONCEBYTES); # memset(state->_pad, 0, sizeof state->_pad); return array( $state->toString(), $out ); } /** * @param string $key * @param string $header * @return string Returns a state. * @throws Exception */ public static function secretstream_xchacha20poly1305_init_pull($key, $header) { # crypto_core_hchacha20(state->k, in, k, NULL); $subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20( ParagonIE_Sodium_Core_Util::substr($header, 0, 16), $key ); $state = new ParagonIE_Sodium_Core_SecretStream_State( $subkey, ParagonIE_Sodium_Core_Util::substr($header, 16) ); $state->counterReset(); # memcpy(STATE_INONCE(state), in + crypto_core_hchacha20_INPUTBYTES, # crypto_secretstream_xchacha20poly1305_INONCEBYTES); # memset(state->_pad, 0, sizeof state->_pad); # return 0; return $state->toString(); } /** * @param string $state * @param string $msg * @param string $aad * @param int $tag * @return string * @throws SodiumException */ public static function secretstream_xchacha20poly1305_push(&$state, $msg, $aad = '', $tag = 0) { $st = ParagonIE_Sodium_Core_SecretStream_State::fromString($state); # crypto_onetimeauth_poly1305_state poly1305_state; # unsigned char block[64U]; # unsigned char slen[8U]; # unsigned char *c; # unsigned char *mac; $msglen = ParagonIE_Sodium_Core_Util::strlen($msg); $aadlen = ParagonIE_Sodium_Core_Util::strlen($aad); if ((($msglen + 63) >> 6) > 0xfffffffe) { throw new SodiumException( 'message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes' ); } # if (outlen_p != NULL) { # *outlen_p = 0U; # } # if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) { # sodium_misuse(); # } # crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k); # crypto_onetimeauth_poly1305_init(&poly1305_state, block); # sodium_memzero(block, sizeof block); $auth = new ParagonIE_Sodium_Core_Poly1305_State( ParagonIE_Sodium_Core_ChaCha20::ietfStream(32, $st->getCombinedNonce(), $st->getKey()) ); # crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen); $auth->update($aad); # crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0, # (0x10 - adlen) & 0xf); $auth->update(str_repeat("\0", ((0x10 - $aadlen) & 0xf))); # memset(block, 0, sizeof block); # block[0] = tag; # crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block, # state->nonce, 1U, state->k); $block = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc( ParagonIE_Sodium_Core_Util::intToChr($tag) . str_repeat("\0", 63), $st->getCombinedNonce(), $st->getKey(), ParagonIE_Sodium_Core_Util::store64_le(1) ); # crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block); $auth->update($block); # out[0] = block[0]; $out = $block[0]; # c = out + (sizeof tag); # crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, state->nonce, 2U, state->k); $cipher = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc( $msg, $st->getCombinedNonce(), $st->getKey(), ParagonIE_Sodium_Core_Util::store64_le(2) ); # crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen); $auth->update($cipher); $out .= $cipher; unset($cipher); # crypto_onetimeauth_poly1305_update # (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf); $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen) & 0xf))); # STORE64_LE(slen, (uint64_t) adlen); $slen = ParagonIE_Sodium_Core_Util::store64_le($aadlen); # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); $auth->update($slen); # STORE64_LE(slen, (sizeof block) + mlen); $slen = ParagonIE_Sodium_Core_Util::store64_le(64 + $msglen); # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); $auth->update($slen); # mac = c + mlen; # crypto_onetimeauth_poly1305_final(&poly1305_state, mac); $mac = $auth->finish(); $out .= $mac; # sodium_memzero(&poly1305_state, sizeof poly1305_state); unset($auth); # XOR_BUF(STATE_INONCE(state), mac, # crypto_secretstream_xchacha20poly1305_INONCEBYTES); $st->xorNonce($mac); # sodium_increment(STATE_COUNTER(state), # crypto_secretstream_xchacha20poly1305_COUNTERBYTES); $st->incrementCounter(); // Overwrite by reference: $state = $st->toString(); /** @var bool $rekey */ $rekey = ($tag & ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY) !== 0; # if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 || # sodium_is_zero(STATE_COUNTER(state), # crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) { # crypto_secretstream_xchacha20poly1305_rekey(state); # } if ($rekey || $st->needsRekey()) { // DO REKEY self::secretstream_xchacha20poly1305_rekey($state); } # if (outlen_p != NULL) { # *outlen_p = crypto_secretstream_xchacha20poly1305_ABYTES + mlen; # } return $out; } /** * @param string $state * @param string $cipher * @param string $aad * @return bool|array{0: string, 1: int} * @throws SodiumException */ public static function secretstream_xchacha20poly1305_pull(&$state, $cipher, $aad = '') { $st = ParagonIE_Sodium_Core_SecretStream_State::fromString($state); $cipherlen = ParagonIE_Sodium_Core_Util::strlen($cipher); # mlen = inlen - crypto_secretstream_xchacha20poly1305_ABYTES; $msglen = $cipherlen - ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES; $aadlen = ParagonIE_Sodium_Core_Util::strlen($aad); # if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) { # sodium_misuse(); # } if ((($msglen + 63) >> 6) > 0xfffffffe) { throw new SodiumException( 'message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes' ); } # crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k); # crypto_onetimeauth_poly1305_init(&poly1305_state, block); # sodium_memzero(block, sizeof block); $auth = new ParagonIE_Sodium_Core_Poly1305_State( ParagonIE_Sodium_Core_ChaCha20::ietfStream(32, $st->getCombinedNonce(), $st->getKey()) ); # crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen); $auth->update($aad); # crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0, # (0x10 - adlen) & 0xf); $auth->update(str_repeat("\0", ((0x10 - $aadlen) & 0xf))); # memset(block, 0, sizeof block); # block[0] = in[0]; # crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block, # state->nonce, 1U, state->k); $block = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc( $cipher[0] . str_repeat("\0", 63), $st->getCombinedNonce(), $st->getKey(), ParagonIE_Sodium_Core_Util::store64_le(1) ); # tag = block[0]; # block[0] = in[0]; # crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block); $tag = ParagonIE_Sodium_Core_Util::chrToInt($block[0]); $block[0] = $cipher[0]; $auth->update($block); # c = in + (sizeof tag); # crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen); $auth->update(ParagonIE_Sodium_Core_Util::substr($cipher, 1, $msglen)); # crypto_onetimeauth_poly1305_update # (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf); $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen) & 0xf))); # STORE64_LE(slen, (uint64_t) adlen); # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); $slen = ParagonIE_Sodium_Core_Util::store64_le($aadlen); $auth->update($slen); # STORE64_LE(slen, (sizeof block) + mlen); # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); $slen = ParagonIE_Sodium_Core_Util::store64_le(64 + $msglen); $auth->update($slen); # crypto_onetimeauth_poly1305_final(&poly1305_state, mac); # sodium_memzero(&poly1305_state, sizeof poly1305_state); $mac = $auth->finish(); # stored_mac = c + mlen; # if (sodium_memcmp(mac, stored_mac, sizeof mac) != 0) { # sodium_memzero(mac, sizeof mac); # return -1; # } $stored = ParagonIE_Sodium_Core_Util::substr($cipher, $msglen + 1, 16); if (!ParagonIE_Sodium_Core_Util::hashEquals($mac, $stored)) { return false; } # crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, state->nonce, 2U, state->k); $out = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc( ParagonIE_Sodium_Core_Util::substr($cipher, 1, $msglen), $st->getCombinedNonce(), $st->getKey(), ParagonIE_Sodium_Core_Util::store64_le(2) ); # XOR_BUF(STATE_INONCE(state), mac, # crypto_secretstream_xchacha20poly1305_INONCEBYTES); $st->xorNonce($mac); # sodium_increment(STATE_COUNTER(state), # crypto_secretstream_xchacha20poly1305_COUNTERBYTES); $st->incrementCounter(); # if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 || # sodium_is_zero(STATE_COUNTER(state), # crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) { # crypto_secretstream_xchacha20poly1305_rekey(state); # } // Overwrite by reference: $state = $st->toString(); /** @var bool $rekey */ $rekey = ($tag & ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY) !== 0; if ($rekey || $st->needsRekey()) { // DO REKEY self::secretstream_xchacha20poly1305_rekey($state); } return array($out, $tag); } /** * @param string $state * @return void * @throws SodiumException */ public static function secretstream_xchacha20poly1305_rekey(&$state) { $st = ParagonIE_Sodium_Core_SecretStream_State::fromString($state); # unsigned char new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + # crypto_secretstream_xchacha20poly1305_INONCEBYTES]; # size_t i; # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) { # new_key_and_inonce[i] = state->k[i]; # } $new_key_and_inonce = $st->getKey(); # for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) { # new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i] = # STATE_INONCE(state)[i]; # } $new_key_and_inonce .= ParagonIE_Sodium_Core_Util::substR($st->getNonce(), 0, 8); # crypto_stream_chacha20_ietf_xor(new_key_and_inonce, new_key_and_inonce, # sizeof new_key_and_inonce, # state->nonce, state->k); $st->rekey(ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc( $new_key_and_inonce, $st->getCombinedNonce(), $st->getKey(), ParagonIE_Sodium_Core_Util::store64_le(0) )); # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) { # state->k[i] = new_key_and_inonce[i]; # } # for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) { # STATE_INONCE(state)[i] = # new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i]; # } # _crypto_secretstream_xchacha20poly1305_counter_reset(state); $st->counterReset(); $state = $st->toString(); } /** * Detached Ed25519 signature. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $sk * @return string * @throws SodiumException * @throws TypeError */ public static function sign_detached($message, $sk) { return ParagonIE_Sodium_Core_Ed25519::sign_detached($message, $sk); } /** * Attached Ed25519 signature. (Returns a signed message.) * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $sk * @return string * @throws SodiumException * @throws TypeError */ public static function sign($message, $sk) { return ParagonIE_Sodium_Core_Ed25519::sign($message, $sk); } /** * Opens a signed message. If valid, returns the message. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $signedMessage * @param string $pk * @return string * @throws SodiumException * @throws TypeError */ public static function sign_open($signedMessage, $pk) { return ParagonIE_Sodium_Core_Ed25519::sign_open($signedMessage, $pk); } /** * Verify a detached signature of a given message and public key. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $signature * @param string $message * @param string $pk * @return bool * @throws SodiumException * @throws TypeError */ public static function sign_verify_detached($signature, $message, $pk) { return ParagonIE_Sodium_Core_Ed25519::verify_detached($signature, $message, $pk); } } PK������Z1�� ��Compat.phpnu�W+A��������<?php /** * Libsodium compatibility layer * * This is the only class you should be interfacing with, as a user of * sodium_compat. * * If the PHP extension for libsodium is installed, it will always use that * instead of our implementations. You get better performance and stronger * guarantees against side-channels that way. * * However, if your users don't have the PHP extension installed, we offer a * compatible interface here. It will give you the correct results as if the * PHP extension was installed. It won't be as fast, of course. * * CAUTION * CAUTION * CAUTION * CAUTION * CAUTION * CAUTION * CAUTION * CAUTION * * * * Until audited, this is probably not safe to use! DANGER WILL ROBINSON * * * * CAUTION * CAUTION * CAUTION * CAUTION * CAUTION * CAUTION * CAUTION * CAUTION * */ if (class_exists('ParagonIE_Sodium_Compat', false)) { return; } class ParagonIE_Sodium_Compat { /** * This parameter prevents the use of the PECL extension. * It should only be used for unit testing. * * @var bool */ public static $disableFallbackForUnitTests = false; /** * Use fast multiplication rather than our constant-time multiplication * implementation. Can be enabled at runtime. Only enable this if you * are absolutely certain that there is no timing leak on your platform. * * @var bool */ public static $fastMult = false; const LIBRARY_MAJOR_VERSION = 9; const LIBRARY_MINOR_VERSION = 1; const LIBRARY_VERSION_MAJOR = 9; const LIBRARY_VERSION_MINOR = 1; const VERSION_STRING = 'polyfill-1.0.8'; // From libsodium const BASE64_VARIANT_ORIGINAL = 1; const BASE64_VARIANT_ORIGINAL_NO_PADDING = 3; const BASE64_VARIANT_URLSAFE = 5; const BASE64_VARIANT_URLSAFE_NO_PADDING = 7; const CRYPTO_AEAD_AES256GCM_KEYBYTES = 32; const CRYPTO_AEAD_AES256GCM_NSECBYTES = 0; const CRYPTO_AEAD_AES256GCM_NPUBBYTES = 12; const CRYPTO_AEAD_AES256GCM_ABYTES = 16; const CRYPTO_AEAD_AEGIS128L_KEYBYTES = 16; const CRYPTO_AEAD_AEGIS128L_NSECBYTES = 0; const CRYPTO_AEAD_AEGIS128L_NPUBBYTES = 16; const CRYPTO_AEAD_AEGIS128L_ABYTES = 32; const CRYPTO_AEAD_AEGIS256_KEYBYTES = 32; const CRYPTO_AEAD_AEGIS256_NSECBYTES = 0; const CRYPTO_AEAD_AEGIS256_NPUBBYTES = 32; const CRYPTO_AEAD_AEGIS256_ABYTES = 32; const CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES = 32; const CRYPTO_AEAD_CHACHA20POLY1305_NSECBYTES = 0; const CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES = 8; const CRYPTO_AEAD_CHACHA20POLY1305_ABYTES = 16; const CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES = 32; const CRYPTO_AEAD_CHACHA20POLY1305_IETF_NSECBYTES = 0; const CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES = 12; const CRYPTO_AEAD_CHACHA20POLY1305_IETF_ABYTES = 16; const CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES = 32; const CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NSECBYTES = 0; const CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES = 24; const CRYPTO_AEAD_XCHACHA20POLY1305_IETF_ABYTES = 16; const CRYPTO_AUTH_BYTES = 32; const CRYPTO_AUTH_KEYBYTES = 32; const CRYPTO_BOX_SEALBYTES = 16; const CRYPTO_BOX_SECRETKEYBYTES = 32; const CRYPTO_BOX_PUBLICKEYBYTES = 32; const CRYPTO_BOX_KEYPAIRBYTES = 64; const CRYPTO_BOX_MACBYTES = 16; const CRYPTO_BOX_NONCEBYTES = 24; const CRYPTO_BOX_SEEDBYTES = 32; const CRYPTO_CORE_RISTRETTO255_BYTES = 32; const CRYPTO_CORE_RISTRETTO255_SCALARBYTES = 32; const CRYPTO_CORE_RISTRETTO255_HASHBYTES = 64; const CRYPTO_CORE_RISTRETTO255_NONREDUCEDSCALARBYTES = 64; const CRYPTO_KDF_BYTES_MIN = 16; const CRYPTO_KDF_BYTES_MAX = 64; const CRYPTO_KDF_CONTEXTBYTES = 8; const CRYPTO_KDF_KEYBYTES = 32; const CRYPTO_KX_BYTES = 32; const CRYPTO_KX_PRIMITIVE = 'x25519blake2b'; const CRYPTO_KX_SEEDBYTES = 32; const CRYPTO_KX_KEYPAIRBYTES = 64; const CRYPTO_KX_PUBLICKEYBYTES = 32; const CRYPTO_KX_SECRETKEYBYTES = 32; const CRYPTO_KX_SESSIONKEYBYTES = 32; const CRYPTO_GENERICHASH_BYTES = 32; const CRYPTO_GENERICHASH_BYTES_MIN = 16; const CRYPTO_GENERICHASH_BYTES_MAX = 64; const CRYPTO_GENERICHASH_KEYBYTES = 32; const CRYPTO_GENERICHASH_KEYBYTES_MIN = 16; const CRYPTO_GENERICHASH_KEYBYTES_MAX = 64; const CRYPTO_PWHASH_SALTBYTES = 16; const CRYPTO_PWHASH_STRPREFIX = '$argon2id$'; const CRYPTO_PWHASH_ALG_ARGON2I13 = 1; const CRYPTO_PWHASH_ALG_ARGON2ID13 = 2; const CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE = 33554432; const CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE = 4; const CRYPTO_PWHASH_MEMLIMIT_MODERATE = 134217728; const CRYPTO_PWHASH_OPSLIMIT_MODERATE = 6; const CRYPTO_PWHASH_MEMLIMIT_SENSITIVE = 536870912; const CRYPTO_PWHASH_OPSLIMIT_SENSITIVE = 8; const CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES = 32; const CRYPTO_PWHASH_SCRYPTSALSA208SHA256_STRPREFIX = '$7$'; const CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE = 534288; const CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE = 16777216; const CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_SENSITIVE = 33554432; const CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_SENSITIVE = 1073741824; const CRYPTO_SCALARMULT_BYTES = 32; const CRYPTO_SCALARMULT_SCALARBYTES = 32; const CRYPTO_SCALARMULT_RISTRETTO255_BYTES = 32; const CRYPTO_SCALARMULT_RISTRETTO255_SCALARBYTES = 32; const CRYPTO_SHORTHASH_BYTES = 8; const CRYPTO_SHORTHASH_KEYBYTES = 16; const CRYPTO_SECRETBOX_KEYBYTES = 32; const CRYPTO_SECRETBOX_MACBYTES = 16; const CRYPTO_SECRETBOX_NONCEBYTES = 24; const CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES = 17; const CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES = 24; const CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES = 32; const CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH = 0; const CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PULL = 1; const CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY = 2; const CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL = 3; const CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX = 0x3fffffff80; const CRYPTO_SIGN_BYTES = 64; const CRYPTO_SIGN_SEEDBYTES = 32; const CRYPTO_SIGN_PUBLICKEYBYTES = 32; const CRYPTO_SIGN_SECRETKEYBYTES = 64; const CRYPTO_SIGN_KEYPAIRBYTES = 96; const CRYPTO_STREAM_KEYBYTES = 32; const CRYPTO_STREAM_NONCEBYTES = 24; const CRYPTO_STREAM_XCHACHA20_KEYBYTES = 32; const CRYPTO_STREAM_XCHACHA20_NONCEBYTES = 24; /** * Add two numbers (little-endian unsigned), storing the value in the first * parameter. * * This mutates $val. * * @param string $val * @param string $addv * @return void * @throws SodiumException */ public static function add( #[\SensitiveParameter] &$val, #[\SensitiveParameter] $addv ) { $val_len = ParagonIE_Sodium_Core_Util::strlen($val); $addv_len = ParagonIE_Sodium_Core_Util::strlen($addv); if ($val_len !== $addv_len) { throw new SodiumException('values must have the same length'); } $A = ParagonIE_Sodium_Core_Util::stringToIntArray($val); $B = ParagonIE_Sodium_Core_Util::stringToIntArray($addv); $c = 0; for ($i = 0; $i < $val_len; $i++) { $c += ($A[$i] + $B[$i]); $A[$i] = ($c & 0xff); $c >>= 8; } $val = ParagonIE_Sodium_Core_Util::intArrayToString($A); } /** * @param string $encoded * @param int $variant * @param string $ignore * @return string * @throws SodiumException */ public static function base642bin( #[\SensitiveParameter] $encoded, $variant, $ignore = '' ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($encoded, 'string', 1); /** @var string $encoded */ $encoded = (string) $encoded; if (ParagonIE_Sodium_Core_Util::strlen($encoded) === 0) { return ''; } // Just strip before decoding if (!empty($ignore)) { $encoded = str_replace($ignore, '', $encoded); } try { switch ($variant) { case self::BASE64_VARIANT_ORIGINAL: return ParagonIE_Sodium_Core_Base64_Original::decode($encoded, true); case self::BASE64_VARIANT_ORIGINAL_NO_PADDING: return ParagonIE_Sodium_Core_Base64_Original::decode($encoded, false); case self::BASE64_VARIANT_URLSAFE: return ParagonIE_Sodium_Core_Base64_UrlSafe::decode($encoded, true); case self::BASE64_VARIANT_URLSAFE_NO_PADDING: return ParagonIE_Sodium_Core_Base64_UrlSafe::decode($encoded, false); default: throw new SodiumException('invalid base64 variant identifier'); } } catch (Exception $ex) { if ($ex instanceof SodiumException) { throw $ex; } throw new SodiumException('invalid base64 string'); } } /** * @param string $decoded * @param int $variant * @return string * @throws SodiumException */ public static function bin2base64( #[\SensitiveParameter] $decoded, $variant ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($decoded, 'string', 1); /** @var string $decoded */ $decoded = (string) $decoded; if (ParagonIE_Sodium_Core_Util::strlen($decoded) === 0) { return ''; } switch ($variant) { case self::BASE64_VARIANT_ORIGINAL: return ParagonIE_Sodium_Core_Base64_Original::encode($decoded); case self::BASE64_VARIANT_ORIGINAL_NO_PADDING: return ParagonIE_Sodium_Core_Base64_Original::encodeUnpadded($decoded); case self::BASE64_VARIANT_URLSAFE: return ParagonIE_Sodium_Core_Base64_UrlSafe::encode($decoded); case self::BASE64_VARIANT_URLSAFE_NO_PADDING: return ParagonIE_Sodium_Core_Base64_UrlSafe::encodeUnpadded($decoded); default: throw new SodiumException('invalid base64 variant identifier'); } } /** * Cache-timing-safe implementation of bin2hex(). * * @param string $string A string (probably raw binary) * @return string A hexadecimal-encoded string * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function bin2hex( #[\SensitiveParameter] $string ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($string, 'string', 1); if (self::useNewSodiumAPI()) { return (string) sodium_bin2hex($string); } if (self::use_fallback('bin2hex')) { return (string) call_user_func('\\Sodium\\bin2hex', $string); } return ParagonIE_Sodium_Core_Util::bin2hex($string); } /** * Compare two strings, in constant-time. * Compared to memcmp(), compare() is more useful for sorting. * * @param string $left The left operand; must be a string * @param string $right The right operand; must be a string * @return int If < 0 if the left operand is less than the right * If = 0 if both strings are equal * If > 0 if the right operand is less than the left * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function compare( #[\SensitiveParameter] $left, #[\SensitiveParameter] $right ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($left, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($right, 'string', 2); if (self::useNewSodiumAPI()) { return (int) sodium_compare($left, $right); } if (self::use_fallback('compare')) { return (int) call_user_func('\\Sodium\\compare', $left, $right); } return ParagonIE_Sodium_Core_Util::compare($left, $right); } /** * Authenticated Encryption with Associated Data: Decryption * * Algorithm: * AEGIS-128L * * @param string $ciphertext Encrypted message (with MAC appended) * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 32 bytes * @param string $key Encryption key * * @return string The original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_aead_aegis128l_decrypt( $ciphertext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_AEGIS128L_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_AEGIS_128L_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_AEGIS128L_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_AEGIS128L_KEYBYTES long'); } $ct_length = ParagonIE_Sodium_Core_Util::strlen($ciphertext); if ($ct_length < self::CRYPTO_AEAD_AEGIS128L_ABYTES) { throw new SodiumException('Message must be at least CRYPTO_AEAD_AEGIS128L_ABYTES long'); } $ct = ParagonIE_Sodium_Core_Util::substr( $ciphertext, 0, $ct_length - self::CRYPTO_AEAD_AEGIS128L_ABYTES ); $tag = ParagonIE_Sodium_Core_Util::substr( $ciphertext, $ct_length - self::CRYPTO_AEAD_AEGIS128L_ABYTES, self::CRYPTO_AEAD_AEGIS128L_ABYTES ); return ParagonIE_Sodium_Core_AEGIS128L::decrypt($ct, $tag, $assocData, $key, $nonce); } /** * Authenticated Encryption with Associated Data: Encryption * * Algorithm: * AEGIS-128L * * @param string $plaintext Message to be encrypted * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 32 bytes * @param string $key Encryption key * * @return string Ciphertext with 32-byte authentication tag appended * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_aead_aegis128l_encrypt( #[\SensitiveParameter] $plaintext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_AEGIS128L_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_AEGIS128L_KEYBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_AEGIS128L_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_AEGIS128L_KEYBYTES long'); } list($ct, $tag) = ParagonIE_Sodium_Core_AEGIS128L::encrypt($plaintext, $assocData, $key, $nonce); return $ct . $tag; } /** * Return a secure random key for use with the AEGIS-128L * symmetric AEAD interface. * * @return string * @throws Exception * @throws Error */ public static function crypto_aead_aegis128l_keygen() { return random_bytes(self::CRYPTO_AEAD_AEGIS128L_KEYBYTES); } /** * Authenticated Encryption with Associated Data: Decryption * * Algorithm: * AEGIS-256 * * @param string $ciphertext Encrypted message (with MAC appended) * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 32 bytes * @param string $key Encryption key * * @return string The original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_aead_aegis256_decrypt( $ciphertext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_AEGIS256_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_AEGIS256_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_AEGIS256_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_AEGIS256_KEYBYTES long'); } $ct_length = ParagonIE_Sodium_Core_Util::strlen($ciphertext); if ($ct_length < self::CRYPTO_AEAD_AEGIS256_ABYTES) { throw new SodiumException('Message must be at least CRYPTO_AEAD_AEGIS256_ABYTES long'); } $ct = ParagonIE_Sodium_Core_Util::substr( $ciphertext, 0, $ct_length - self::CRYPTO_AEAD_AEGIS256_ABYTES ); $tag = ParagonIE_Sodium_Core_Util::substr( $ciphertext, $ct_length - self::CRYPTO_AEAD_AEGIS256_ABYTES, self::CRYPTO_AEAD_AEGIS256_ABYTES ); return ParagonIE_Sodium_Core_AEGIS256::decrypt($ct, $tag, $assocData, $key, $nonce); } /** * Authenticated Encryption with Associated Data: Encryption * * Algorithm: * AEGIS-256 * * @param string $plaintext Message to be encrypted * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 32 bytes * @param string $key Encryption key * * @return string Ciphertext with 32-byte authentication tag appended * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_aead_aegis256_encrypt( #[\SensitiveParameter] $plaintext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_AEGIS256_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_AEGIS128L_KEYBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_AEGIS256_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_AEGIS128L_KEYBYTES long'); } list($ct, $tag) = ParagonIE_Sodium_Core_AEGIS256::encrypt($plaintext, $assocData, $key, $nonce); return $ct . $tag; } /** * Return a secure random key for use with the AEGIS-256 * symmetric AEAD interface. * * @return string * @throws Exception * @throws Error */ public static function crypto_aead_aegis256_keygen() { return random_bytes(self::CRYPTO_AEAD_AEGIS256_KEYBYTES); } /** * Is AES-256-GCM even available to use? * * @return bool * @psalm-suppress UndefinedFunction * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_aead_aes256gcm_is_available() { if (self::useNewSodiumAPI()) { return sodium_crypto_aead_aes256gcm_is_available(); } if (self::use_fallback('crypto_aead_aes256gcm_is_available')) { return call_user_func('\\Sodium\\crypto_aead_aes256gcm_is_available'); } if (PHP_VERSION_ID < 70100) { // OpenSSL doesn't support AEAD before 7.1.0 return false; } if (!is_callable('openssl_encrypt') || !is_callable('openssl_decrypt')) { // OpenSSL isn't installed return false; } return (bool) in_array('aes-256-gcm', openssl_get_cipher_methods()); } /** * Authenticated Encryption with Associated Data: Decryption * * Algorithm: * AES-256-GCM * * This mode uses a 64-bit random nonce with a 64-bit counter. * IETF mode uses a 96-bit random nonce with a 32-bit counter. * * @param string $ciphertext Encrypted message (with Poly1305 MAC appended) * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 8 bytes * @param string $key Encryption key * * @return string|bool The original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_aead_aes256gcm_decrypt( $ciphertext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { if (!self::crypto_aead_aes256gcm_is_available()) { throw new SodiumException('AES-256-GCM is not available'); } ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_AES256GCM_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_AES256GCM_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_AES256GCM_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_AES256GCM_KEYBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) < self::CRYPTO_AEAD_AES256GCM_ABYTES) { throw new SodiumException('Message must be at least CRYPTO_AEAD_AES256GCM_ABYTES long'); } if (!is_callable('openssl_decrypt')) { throw new SodiumException('The OpenSSL extension is not installed, or openssl_decrypt() is not available'); } /** @var string $ctext */ $ctext = ParagonIE_Sodium_Core_Util::substr($ciphertext, 0, -self::CRYPTO_AEAD_AES256GCM_ABYTES); /** @var string $authTag */ $authTag = ParagonIE_Sodium_Core_Util::substr($ciphertext, -self::CRYPTO_AEAD_AES256GCM_ABYTES, 16); return openssl_decrypt( $ctext, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $nonce, $authTag, $assocData ); } /** * Authenticated Encryption with Associated Data: Encryption * * Algorithm: * AES-256-GCM * * @param string $plaintext Message to be encrypted * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 8 bytes * @param string $key Encryption key * * @return string Ciphertext with a 16-byte GCM message * authentication code appended * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_aead_aes256gcm_encrypt( #[\SensitiveParameter] $plaintext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { if (!self::crypto_aead_aes256gcm_is_available()) { throw new SodiumException('AES-256-GCM is not available'); } ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_AES256GCM_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_AES256GCM_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_AES256GCM_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_AES256GCM_KEYBYTES long'); } if (!is_callable('openssl_encrypt')) { throw new SodiumException('The OpenSSL extension is not installed, or openssl_encrypt() is not available'); } $authTag = ''; $ciphertext = openssl_encrypt( $plaintext, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $nonce, $authTag, $assocData ); return $ciphertext . $authTag; } /** * Return a secure random key for use with the AES-256-GCM * symmetric AEAD interface. * * @return string * @throws Exception * @throws Error */ public static function crypto_aead_aes256gcm_keygen() { return random_bytes(self::CRYPTO_AEAD_AES256GCM_KEYBYTES); } /** * Authenticated Encryption with Associated Data: Decryption * * Algorithm: * ChaCha20-Poly1305 * * This mode uses a 64-bit random nonce with a 64-bit counter. * IETF mode uses a 96-bit random nonce with a 32-bit counter. * * @param string $ciphertext Encrypted message (with Poly1305 MAC appended) * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 8 bytes * @param string $key Encryption key * * @return string The original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_aead_chacha20poly1305_decrypt( $ciphertext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) < self::CRYPTO_AEAD_CHACHA20POLY1305_ABYTES) { throw new SodiumException('Message must be at least CRYPTO_AEAD_CHACHA20POLY1305_ABYTES long'); } if (self::useNewSodiumAPI()) { /** * @psalm-suppress InvalidReturnStatement * @psalm-suppress FalsableReturnStatement */ return sodium_crypto_aead_chacha20poly1305_decrypt( $ciphertext, $assocData, $nonce, $key ); } if (self::use_fallback('crypto_aead_chacha20poly1305_decrypt')) { return call_user_func( '\\Sodium\\crypto_aead_chacha20poly1305_decrypt', $ciphertext, $assocData, $nonce, $key ); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::aead_chacha20poly1305_decrypt( $ciphertext, $assocData, $nonce, $key ); } return ParagonIE_Sodium_Crypto::aead_chacha20poly1305_decrypt( $ciphertext, $assocData, $nonce, $key ); } /** * Authenticated Encryption with Associated Data * * Algorithm: * ChaCha20-Poly1305 * * This mode uses a 64-bit random nonce with a 64-bit counter. * IETF mode uses a 96-bit random nonce with a 32-bit counter. * * @param string $plaintext Message to be encrypted * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 8 bytes * @param string $key Encryption key * * @return string Ciphertext with a 16-byte Poly1305 message * authentication code appended * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_aead_chacha20poly1305_encrypt( #[\SensitiveParameter] $plaintext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES long'); } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_aead_chacha20poly1305_encrypt( $plaintext, $assocData, $nonce, $key ); } if (self::use_fallback('crypto_aead_chacha20poly1305_encrypt')) { return (string) call_user_func( '\\Sodium\\crypto_aead_chacha20poly1305_encrypt', $plaintext, $assocData, $nonce, $key ); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::aead_chacha20poly1305_encrypt( $plaintext, $assocData, $nonce, $key ); } return ParagonIE_Sodium_Crypto::aead_chacha20poly1305_encrypt( $plaintext, $assocData, $nonce, $key ); } /** * Authenticated Encryption with Associated Data: Decryption * * Algorithm: * ChaCha20-Poly1305 * * IETF mode uses a 96-bit random nonce with a 32-bit counter. * Regular mode uses a 64-bit random nonce with a 64-bit counter. * * @param string $ciphertext Encrypted message (with Poly1305 MAC appended) * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 12 bytes * @param string $key Encryption key * * @return string The original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_aead_chacha20poly1305_ietf_decrypt( $ciphertext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) < self::CRYPTO_AEAD_CHACHA20POLY1305_ABYTES) { throw new SodiumException('Message must be at least CRYPTO_AEAD_CHACHA20POLY1305_ABYTES long'); } if (self::useNewSodiumAPI()) { /** * @psalm-suppress InvalidReturnStatement * @psalm-suppress FalsableReturnStatement */ return sodium_crypto_aead_chacha20poly1305_ietf_decrypt( $ciphertext, $assocData, $nonce, $key ); } if (self::use_fallback('crypto_aead_chacha20poly1305_ietf_decrypt')) { return call_user_func( '\\Sodium\\crypto_aead_chacha20poly1305_ietf_decrypt', $ciphertext, $assocData, $nonce, $key ); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::aead_chacha20poly1305_ietf_decrypt( $ciphertext, $assocData, $nonce, $key ); } return ParagonIE_Sodium_Crypto::aead_chacha20poly1305_ietf_decrypt( $ciphertext, $assocData, $nonce, $key ); } /** * Return a secure random key for use with the ChaCha20-Poly1305 * symmetric AEAD interface. * * @return string * @throws Exception * @throws Error */ public static function crypto_aead_chacha20poly1305_keygen() { return random_bytes(self::CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES); } /** * Authenticated Encryption with Associated Data * * Algorithm: * ChaCha20-Poly1305 * * IETF mode uses a 96-bit random nonce with a 32-bit counter. * Regular mode uses a 64-bit random nonce with a 64-bit counter. * * @param string $plaintext Message to be encrypted * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 8 bytes * @param string $key Encryption key * * @return string Ciphertext with a 16-byte Poly1305 message * authentication code appended * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_aead_chacha20poly1305_ietf_encrypt( #[\SensitiveParameter] $plaintext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '' ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); if (!is_null($assocData)) { ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); } ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES long'); } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_aead_chacha20poly1305_ietf_encrypt( $plaintext, $assocData, $nonce, $key ); } if (self::use_fallback('crypto_aead_chacha20poly1305_ietf_encrypt')) { return (string) call_user_func( '\\Sodium\\crypto_aead_chacha20poly1305_ietf_encrypt', $plaintext, $assocData, $nonce, $key ); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::aead_chacha20poly1305_ietf_encrypt( $plaintext, $assocData, $nonce, $key ); } return ParagonIE_Sodium_Crypto::aead_chacha20poly1305_ietf_encrypt( $plaintext, $assocData, $nonce, $key ); } /** * Return a secure random key for use with the ChaCha20-Poly1305 * symmetric AEAD interface. (IETF version) * * @return string * @throws Exception * @throws Error */ public static function crypto_aead_chacha20poly1305_ietf_keygen() { return random_bytes(self::CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES); } /** * Authenticated Encryption with Associated Data: Decryption * * Algorithm: * XChaCha20-Poly1305 * * This mode uses a 64-bit random nonce with a 64-bit counter. * IETF mode uses a 96-bit random nonce with a 32-bit counter. * * @param string $ciphertext Encrypted message (with Poly1305 MAC appended) * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 8 bytes * @param string $key Encryption key * @param bool $dontFallback Don't fallback to ext/sodium * * @return string|bool The original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_aead_xchacha20poly1305_ietf_decrypt( $ciphertext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '', $dontFallback = false ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); if (!is_null($assocData)) { ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); } else { $assocData = ''; } ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) < self::CRYPTO_AEAD_XCHACHA20POLY1305_IETF_ABYTES) { throw new SodiumException('Message must be at least CRYPTO_AEAD_XCHACHA20POLY1305_IETF_ABYTES long'); } if (self::useNewSodiumAPI() && !$dontFallback) { if (is_callable('sodium_crypto_aead_xchacha20poly1305_ietf_decrypt')) { return sodium_crypto_aead_xchacha20poly1305_ietf_decrypt( $ciphertext, $assocData, $nonce, $key ); } } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::aead_xchacha20poly1305_ietf_decrypt( $ciphertext, $assocData, $nonce, $key ); } return ParagonIE_Sodium_Crypto::aead_xchacha20poly1305_ietf_decrypt( $ciphertext, $assocData, $nonce, $key ); } /** * Authenticated Encryption with Associated Data * * Algorithm: * XChaCha20-Poly1305 * * This mode uses a 64-bit random nonce with a 64-bit counter. * IETF mode uses a 96-bit random nonce with a 32-bit counter. * * @param string $plaintext Message to be encrypted * @param string $assocData Authenticated Associated Data (unencrypted) * @param string $nonce Number to be used only Once; must be 8 bytes * @param string $key Encryption key * @param bool $dontFallback Don't fallback to ext/sodium * * @return string Ciphertext with a 16-byte Poly1305 message * authentication code appended * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_aead_xchacha20poly1305_ietf_encrypt( #[\SensitiveParameter] $plaintext = '', $assocData = '', $nonce = '', #[\SensitiveParameter] $key = '', $dontFallback = false ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); if (!is_null($assocData)) { ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); } else { $assocData = ''; } ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES) { throw new SodiumException('Nonce must be CRYPTO_AEAD_XCHACHA20POLY1305_NPUBBYTES long'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES) { throw new SodiumException('Key must be CRYPTO_AEAD_XCHACHA20POLY1305_KEYBYTES long'); } if (self::useNewSodiumAPI() && !$dontFallback) { if (is_callable('sodium_crypto_aead_xchacha20poly1305_ietf_encrypt')) { return sodium_crypto_aead_xchacha20poly1305_ietf_encrypt( $plaintext, $assocData, $nonce, $key ); } } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::aead_xchacha20poly1305_ietf_encrypt( $plaintext, $assocData, $nonce, $key ); } return ParagonIE_Sodium_Crypto::aead_xchacha20poly1305_ietf_encrypt( $plaintext, $assocData, $nonce, $key ); } /** * Return a secure random key for use with the XChaCha20-Poly1305 * symmetric AEAD interface. * * @return string * @throws Exception * @throws Error */ public static function crypto_aead_xchacha20poly1305_ietf_keygen() { return random_bytes(self::CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES); } /** * Authenticate a message. Uses symmetric-key cryptography. * * Algorithm: * HMAC-SHA512-256. Which is HMAC-SHA-512 truncated to 256 bits. * Not to be confused with HMAC-SHA-512/256 which would use the * SHA-512/256 hash function (uses different initial parameters * but still truncates to 256 bits to sidestep length-extension * attacks). * * @param string $message Message to be authenticated * @param string $key Symmetric authentication key * @return string Message authentication code * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_auth( $message, #[\SensitiveParameter] $key ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 2); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AUTH_KEYBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_AUTH_KEYBYTES long.'); } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_auth($message, $key); } if (self::use_fallback('crypto_auth')) { return (string) call_user_func('\\Sodium\\crypto_auth', $message, $key); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::auth($message, $key); } return ParagonIE_Sodium_Crypto::auth($message, $key); } /** * @return string * @throws Exception * @throws Error */ public static function crypto_auth_keygen() { return random_bytes(self::CRYPTO_AUTH_KEYBYTES); } /** * Verify the MAC of a message previously authenticated with crypto_auth. * * @param string $mac Message authentication code * @param string $message Message whose authenticity you are attempting to * verify (with a given MAC and key) * @param string $key Symmetric authentication key * @return bool TRUE if authenticated, FALSE otherwise * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_auth_verify( $mac, $message, #[\SensitiveParameter] $key ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($mac, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($mac) !== self::CRYPTO_AUTH_BYTES) { throw new SodiumException('Argument 1 must be CRYPTO_AUTH_BYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AUTH_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_AUTH_KEYBYTES long.'); } if (self::useNewSodiumAPI()) { return (bool) sodium_crypto_auth_verify($mac, $message, $key); } if (self::use_fallback('crypto_auth_verify')) { return (bool) call_user_func('\\Sodium\\crypto_auth_verify', $mac, $message, $key); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::auth_verify($mac, $message, $key); } return ParagonIE_Sodium_Crypto::auth_verify($mac, $message, $key); } /** * Authenticated asymmetric-key encryption. Both the sender and recipient * may decrypt messages. * * Algorithm: X25519-XSalsa20-Poly1305. * X25519: Elliptic-Curve Diffie Hellman over Curve25519. * XSalsa20: Extended-nonce variant of salsa20. * Poyl1305: Polynomial MAC for one-time message authentication. * * @param string $plaintext The message to be encrypted * @param string $nonce A Number to only be used Once; must be 24 bytes * @param string $keypair Your secret key and your recipient's public key * @return string Ciphertext with 16-byte Poly1305 MAC * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_box( $plaintext, $nonce, #[\SensitiveParameter] $keypair ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_BOX_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_BOX_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_BOX_KEYPAIRBYTES long.'); } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_box($plaintext, $nonce, $keypair); } if (self::use_fallback('crypto_box')) { return (string) call_user_func('\\Sodium\\crypto_box', $plaintext, $nonce, $keypair); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box($plaintext, $nonce, $keypair); } return ParagonIE_Sodium_Crypto::box($plaintext, $nonce, $keypair); } /** * Anonymous public-key encryption. Only the recipient may decrypt messages. * * Algorithm: X25519-XSalsa20-Poly1305, as with crypto_box. * The sender's X25519 keypair is ephemeral. * Nonce is generated from the BLAKE2b hash of both public keys. * * This provides ciphertext integrity. * * @param string $plaintext Message to be sealed * @param string $publicKey Your recipient's public key * @return string Sealed message that only your recipient can * decrypt * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_box_seal( #[\SensitiveParameter] $plaintext, $publicKey ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($publicKey, 'string', 2); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !== self::CRYPTO_BOX_PUBLICKEYBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_BOX_PUBLICKEYBYTES long.'); } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_box_seal($plaintext, $publicKey); } if (self::use_fallback('crypto_box_seal')) { return (string) call_user_func('\\Sodium\\crypto_box_seal', $plaintext, $publicKey); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box_seal($plaintext, $publicKey); } return ParagonIE_Sodium_Crypto::box_seal($plaintext, $publicKey); } /** * Opens a message encrypted with crypto_box_seal(). Requires * the recipient's keypair (sk || pk) to decrypt successfully. * * This validates ciphertext integrity. * * @param string $ciphertext Sealed message to be opened * @param string $keypair Your crypto_box keypair * @return string The original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_box_seal_open( $ciphertext, #[\SensitiveParameter] $keypair ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 2); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_BOX_KEYPAIRBYTES long.'); } if (self::useNewSodiumAPI()) { /** * @psalm-suppress InvalidReturnStatement * @psalm-suppress FalsableReturnStatement */ return sodium_crypto_box_seal_open($ciphertext, $keypair); } if (self::use_fallback('crypto_box_seal_open')) { return call_user_func('\\Sodium\\crypto_box_seal_open', $ciphertext, $keypair); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box_seal_open($ciphertext, $keypair); } return ParagonIE_Sodium_Crypto::box_seal_open($ciphertext, $keypair); } /** * Generate a new random X25519 keypair. * * @return string A 64-byte string; the first 32 are your secret key, while * the last 32 are your public key. crypto_box_secretkey() * and crypto_box_publickey() exist to separate them so you * don't accidentally get them mixed up! * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_box_keypair() { if (self::useNewSodiumAPI()) { return (string) sodium_crypto_box_keypair(); } if (self::use_fallback('crypto_box_keypair')) { return (string) call_user_func('\\Sodium\\crypto_box_keypair'); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box_keypair(); } return ParagonIE_Sodium_Crypto::box_keypair(); } /** * Combine two keys into a keypair for use in library methods that expect * a keypair. This doesn't necessarily have to be the same person's keys. * * @param string $secretKey Secret key * @param string $publicKey Public key * @return string Keypair * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_box_keypair_from_secretkey_and_publickey( #[\SensitiveParameter] $secretKey, $publicKey ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($secretKey, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($publicKey, 'string', 2); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !== self::CRYPTO_BOX_SECRETKEYBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_BOX_SECRETKEYBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !== self::CRYPTO_BOX_PUBLICKEYBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_BOX_PUBLICKEYBYTES long.'); } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_box_keypair_from_secretkey_and_publickey($secretKey, $publicKey); } if (self::use_fallback('crypto_box_keypair_from_secretkey_and_publickey')) { return (string) call_user_func('\\Sodium\\crypto_box_keypair_from_secretkey_and_publickey', $secretKey, $publicKey); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box_keypair_from_secretkey_and_publickey($secretKey, $publicKey); } return ParagonIE_Sodium_Crypto::box_keypair_from_secretkey_and_publickey($secretKey, $publicKey); } /** * Decrypt a message previously encrypted with crypto_box(). * * @param string $ciphertext Encrypted message * @param string $nonce Number to only be used Once; must be 24 bytes * @param string $keypair Your secret key and the sender's public key * @return string The original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_box_open( $ciphertext, $nonce, #[\SensitiveParameter] $keypair ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) < self::CRYPTO_BOX_MACBYTES) { throw new SodiumException('Argument 1 must be at least CRYPTO_BOX_MACBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_BOX_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_BOX_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_BOX_KEYPAIRBYTES long.'); } if (self::useNewSodiumAPI()) { /** * @psalm-suppress InvalidReturnStatement * @psalm-suppress FalsableReturnStatement */ return sodium_crypto_box_open($ciphertext, $nonce, $keypair); } if (self::use_fallback('crypto_box_open')) { return call_user_func('\\Sodium\\crypto_box_open', $ciphertext, $nonce, $keypair); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box_open($ciphertext, $nonce, $keypair); } return ParagonIE_Sodium_Crypto::box_open($ciphertext, $nonce, $keypair); } /** * Extract the public key from a crypto_box keypair. * * @param string $keypair Keypair containing secret and public key * @return string Your crypto_box public key * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_box_publickey( #[\SensitiveParameter] $keypair ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 1); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_BOX_KEYPAIRBYTES long.'); } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_box_publickey($keypair); } if (self::use_fallback('crypto_box_publickey')) { return (string) call_user_func('\\Sodium\\crypto_box_publickey', $keypair); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box_publickey($keypair); } return ParagonIE_Sodium_Crypto::box_publickey($keypair); } /** * Calculate the X25519 public key from a given X25519 secret key. * * @param string $secretKey Any X25519 secret key * @return string The corresponding X25519 public key * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_box_publickey_from_secretkey( #[\SensitiveParameter] $secretKey ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($secretKey, 'string', 1); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !== self::CRYPTO_BOX_SECRETKEYBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_BOX_SECRETKEYBYTES long.'); } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_box_publickey_from_secretkey($secretKey); } if (self::use_fallback('crypto_box_publickey_from_secretkey')) { return (string) call_user_func('\\Sodium\\crypto_box_publickey_from_secretkey', $secretKey); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box_publickey_from_secretkey($secretKey); } return ParagonIE_Sodium_Crypto::box_publickey_from_secretkey($secretKey); } /** * Extract the secret key from a crypto_box keypair. * * @param string $keypair * @return string Your crypto_box secret key * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_box_secretkey( #[\SensitiveParameter] $keypair ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 1); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_BOX_KEYPAIRBYTES long.'); } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_box_secretkey($keypair); } if (self::use_fallback('crypto_box_secretkey')) { return (string) call_user_func('\\Sodium\\crypto_box_secretkey', $keypair); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box_secretkey($keypair); } return ParagonIE_Sodium_Crypto::box_secretkey($keypair); } /** * Generate an X25519 keypair from a seed. * * @param string $seed * @return string * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress UndefinedFunction */ public static function crypto_box_seed_keypair( #[\SensitiveParameter] $seed ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($seed, 'string', 1); if (self::useNewSodiumAPI()) { return (string) sodium_crypto_box_seed_keypair($seed); } if (self::use_fallback('crypto_box_seed_keypair')) { return (string) call_user_func('\\Sodium\\crypto_box_seed_keypair', $seed); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::box_seed_keypair($seed); } return ParagonIE_Sodium_Crypto::box_seed_keypair($seed); } /** * Calculates a BLAKE2b hash, with an optional key. * * @param string $message The message to be hashed * @param string|null $key If specified, must be a string between 16 * and 64 bytes long * @param int $length Output length in bytes; must be between 16 * and 64 (default = 32) * @return string Raw binary * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_generichash( $message, #[\SensitiveParameter] $key = '', $length = self::CRYPTO_GENERICHASH_BYTES ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1); if (is_null($key)) { $key = ''; } ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($length, 'int', 3); /* Input validation: */ if (!empty($key)) { if (ParagonIE_Sodium_Core_Util::strlen($key) < self::CRYPTO_GENERICHASH_KEYBYTES_MIN) { throw new SodiumException('Unsupported key size. Must be at least CRYPTO_GENERICHASH_KEYBYTES_MIN bytes long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) > self::CRYPTO_GENERICHASH_KEYBYTES_MAX) { throw new SodiumException('Unsupported key size. Must be at most CRYPTO_GENERICHASH_KEYBYTES_MAX bytes long.'); } } if (self::useNewSodiumAPI()) { return (string) sodium_crypto_generichash($message, $key, $length); } if (self::use_fallback('crypto_generichash')) { return (string) call_user_func('\\Sodium\\crypto_generichash', $message, $key, $length); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::generichash($message, $key, $length); } return ParagonIE_Sodium_Crypto::generichash($message, $key, $length); } /** * Get the final BLAKE2b hash output for a given context. * * @param string $ctx BLAKE2 hashing context. Generated by crypto_generichash_init(). * @param int $length Hash output size. * @return string Final BLAKE2b hash. * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress ReferenceConstraintViolation * @psalm-suppress ConflictingReferenceConstraint */ public static function crypto_generichash_final( #[\SensitiveParameter] &$ctx, $length = self::CRYPTO_GENERICHASH_BYTES ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($ctx, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($length, 'int', 2); if (self::useNewSodiumAPI()) { return sodium_crypto_generichash_final($ctx, $length); } if (self::use_fallback('crypto_generichash_final')) { $func = '\\Sodium\\crypto_generichash_final'; return (string) $func($ctx, $length); } if ($length < 1) { try { self::memzero($ctx); } catch (SodiumException $ex) { unset($ctx); } return ''; } if (PHP_INT_SIZE === 4) { $result = ParagonIE_Sodium_Crypto32::generichash_final($ctx, $length); } else { $result = ParagonIE_Sodium_Crypto::generichash_final($ctx, $length); } try { self::memzero($ctx); } catch (SodiumException $ex) { unset($ctx); } return $result; } /** * Initialize a BLAKE2b hashing context, for use in a streaming interface. * * @param string|null $key If specified must be a string between 16 and 64 bytes * @param int $length The size of the desired hash output * @return string A BLAKE2 hashing context, encoded as a string * (To be 100% compatible with ext/libsodium) * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_generichash_init( #[\SensitiveParameter] $key = '', $length = self::CRYPTO_GENERICHASH_BYTES ) { /* Type checks: */ if (is_null($key)) { $key = ''; } ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($length, 'int', 2); /* Input validation: */ if (!empty($key)) { if (ParagonIE_Sodium_Core_Util::strlen($key) < self::CRYPTO_GENERICHASH_KEYBYTES_MIN) { throw new SodiumException('Unsupported key size. Must be at least CRYPTO_GENERICHASH_KEYBYTES_MIN bytes long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) > self::CRYPTO_GENERICHASH_KEYBYTES_MAX) { throw new SodiumException('Unsupported key size. Must be at most CRYPTO_GENERICHASH_KEYBYTES_MAX bytes long.'); } } if (self::useNewSodiumAPI()) { return sodium_crypto_generichash_init($key, $length); } if (self::use_fallback('crypto_generichash_init')) { return (string) call_user_func('\\Sodium\\crypto_generichash_init', $key, $length); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::generichash_init($key, $length); } return ParagonIE_Sodium_Crypto::generichash_init($key, $length); } /** * Initialize a BLAKE2b hashing context, for use in a streaming interface. * * @param string|null $key If specified must be a string between 16 and 64 bytes * @param int $length The size of the desired hash output * @param string $salt Salt (up to 16 bytes) * @param string $personal Personalization string (up to 16 bytes) * @return string A BLAKE2 hashing context, encoded as a string * (To be 100% compatible with ext/libsodium) * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_generichash_init_salt_personal( #[\SensitiveParameter] $key = '', $length = self::CRYPTO_GENERICHASH_BYTES, $salt = '', $personal = '' ) { /* Type checks: */ if (is_null($key)) { $key = ''; } ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($length, 'int', 2); ParagonIE_Sodium_Core_Util::declareScalarType($salt, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($personal, 'string', 4); $salt = str_pad($salt, 16, "\0", STR_PAD_RIGHT); $personal = str_pad($personal, 16, "\0", STR_PAD_RIGHT); /* Input validation: */ if (!empty($key)) { /* if (ParagonIE_Sodium_Core_Util::strlen($key) < self::CRYPTO_GENERICHASH_KEYBYTES_MIN) { throw new SodiumException('Unsupported key size. Must be at least CRYPTO_GENERICHASH_KEYBYTES_MIN bytes long.'); } */ if (ParagonIE_Sodium_Core_Util::strlen($key) > self::CRYPTO_GENERICHASH_KEYBYTES_MAX) { throw new SodiumException('Unsupported key size. Must be at most CRYPTO_GENERICHASH_KEYBYTES_MAX bytes long.'); } } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::generichash_init_salt_personal($key, $length, $salt, $personal); } return ParagonIE_Sodium_Crypto::generichash_init_salt_personal($key, $length, $salt, $personal); } /** * Update a BLAKE2b hashing context with additional data. * * @param string $ctx BLAKE2 hashing context. Generated by crypto_generichash_init(). * $ctx is passed by reference and gets updated in-place. * @param-out string $ctx * @param string $message The message to append to the existing hash state. * @return void * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress ReferenceConstraintViolation */ public static function crypto_generichash_update( #[\SensitiveParameter] &$ctx, $message ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($ctx, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 2); if (self::useNewSodiumAPI()) { sodium_crypto_generichash_update($ctx, $message); return; } if (self::use_fallback('crypto_generichash_update')) { $func = '\\Sodium\\crypto_generichash_update'; $func($ctx, $message); return; } if (PHP_INT_SIZE === 4) { $ctx = ParagonIE_Sodium_Crypto32::generichash_update($ctx, $message); } else { $ctx = ParagonIE_Sodium_Crypto::generichash_update($ctx, $message); } } /** * @return string * @throws Exception * @throws Error */ public static function crypto_generichash_keygen() { return random_bytes(self::CRYPTO_GENERICHASH_KEYBYTES); } /** * @param int $subkey_len * @param int $subkey_id * @param string $context * @param string $key * @return string * @throws SodiumException */ public static function crypto_kdf_derive_from_key( $subkey_len, $subkey_id, $context, #[\SensitiveParameter] $key ) { ParagonIE_Sodium_Core_Util::declareScalarType($subkey_len, 'int', 1); ParagonIE_Sodium_Core_Util::declareScalarType($subkey_id, 'int', 2); ParagonIE_Sodium_Core_Util::declareScalarType($context, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); $subkey_id = (int) $subkey_id; $subkey_len = (int) $subkey_len; $context = (string) $context; $key = (string) $key; if ($subkey_len < self::CRYPTO_KDF_BYTES_MIN) { throw new SodiumException('subkey cannot be smaller than SODIUM_CRYPTO_KDF_BYTES_MIN'); } if ($subkey_len > self::CRYPTO_KDF_BYTES_MAX) { throw new SodiumException('subkey cannot be larger than SODIUM_CRYPTO_KDF_BYTES_MAX'); } if ($subkey_id < 0) { throw new SodiumException('subkey_id cannot be negative'); } if (ParagonIE_Sodium_Core_Util::strlen($context) !== self::CRYPTO_KDF_CONTEXTBYTES) { throw new SodiumException('context should be SODIUM_CRYPTO_KDF_CONTEXTBYTES bytes'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_KDF_KEYBYTES) { throw new SodiumException('key should be SODIUM_CRYPTO_KDF_KEYBYTES bytes'); } $salt = ParagonIE_Sodium_Core_Util::store64_le($subkey_id); $state = self::crypto_generichash_init_salt_personal( $key, $subkey_len, $salt, $context ); return self::crypto_generichash_final($state, $subkey_len); } /** * @return string * @throws Exception * @throws Error */ public static function crypto_kdf_keygen() { return random_bytes(self::CRYPTO_KDF_KEYBYTES); } /** * Perform a key exchange, between a designated client and a server. * * Typically, you would designate one machine to be the client and the * other to be the server. The first two keys are what you'd expect for * scalarmult() below, but the latter two public keys don't swap places. * * | ALICE | BOB | * | Client | Server | * |--------------------------------|-------------------------------------| * | shared = crypto_kx( | shared = crypto_kx( | * | alice_sk, | bob_sk, | <- contextual * | bob_pk, | alice_pk, | <- contextual * | alice_pk, | alice_pk, | <----- static * | bob_pk | bob_pk | <----- static * | ) | ) | * * They are used along with the scalarmult product to generate a 256-bit * BLAKE2b hash unique to the client and server keys. * * @param string $my_secret * @param string $their_public * @param string $client_public * @param string $server_public * @param bool $dontFallback * @return string * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_kx( #[\SensitiveParameter] $my_secret, $their_public, $client_public, $server_public, $dontFallback = false ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($my_secret, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($their_public, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($client_public, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($server_public, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($my_secret) !== self::CRYPTO_BOX_SECRETKEYBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_BOX_SECRETKEYBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($their_public) !== self::CRYPTO_BOX_PUBLICKEYBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_BOX_PUBLICKEYBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($client_public) !== self::CRYPTO_BOX_PUBLICKEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_BOX_PUBLICKEYBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($server_public) !== self::CRYPTO_BOX_PUBLICKEYBYTES) { throw new SodiumException('Argument 4 must be CRYPTO_BOX_PUBLICKEYBYTES long.'); } if (self::useNewSodiumAPI() && !$dontFallback) { if (is_callable('sodium_crypto_kx')) { return (string) sodium_crypto_kx( $my_secret, $their_public, $client_public, $server_public ); } } if (self::use_fallback('crypto_kx')) { return (string) call_user_func( '\\Sodium\\crypto_kx', $my_secret, $their_public, $client_public, $server_public ); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::keyExchange( $my_secret, $their_public, $client_public, $server_public ); } return ParagonIE_Sodium_Crypto::keyExchange( $my_secret, $their_public, $client_public, $server_public ); } /** * @param string $seed * @return string * @throws SodiumException */ public static function crypto_kx_seed_keypair( #[\SensitiveParameter] $seed ) { ParagonIE_Sodium_Core_Util::declareScalarType($seed, 'string', 1); $seed = (string) $seed; if (ParagonIE_Sodium_Core_Util::strlen($seed) !== self::CRYPTO_KX_SEEDBYTES) { throw new SodiumException('seed must be SODIUM_CRYPTO_KX_SEEDBYTES bytes'); } $sk = self::crypto_generichash($seed, '', self::CRYPTO_KX_SECRETKEYBYTES); $pk = self::crypto_scalarmult_base($sk); return $sk . $pk; } /** * @return string * @throws Exception */ public static function crypto_kx_keypair() { $sk = self::randombytes_buf(self::CRYPTO_KX_SECRETKEYBYTES); $pk = self::crypto_scalarmult_base($sk); return $sk . $pk; } /** * @param string $keypair * @param string $serverPublicKey * @return array{0: string, 1: string} * @throws SodiumException */ public static function crypto_kx_client_session_keys( #[\SensitiveParameter] $keypair, $serverPublicKey ) { ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($serverPublicKey, 'string', 2); $keypair = (string) $keypair; $serverPublicKey = (string) $serverPublicKey; if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_KX_KEYPAIRBYTES) { throw new SodiumException('keypair should be SODIUM_CRYPTO_KX_KEYPAIRBYTES bytes'); } if (ParagonIE_Sodium_Core_Util::strlen($serverPublicKey) !== self::CRYPTO_KX_PUBLICKEYBYTES) { throw new SodiumException('public keys must be SODIUM_CRYPTO_KX_PUBLICKEYBYTES bytes'); } $sk = self::crypto_kx_secretkey($keypair); $pk = self::crypto_kx_publickey($keypair); $h = self::crypto_generichash_init(null, self::CRYPTO_KX_SESSIONKEYBYTES * 2); self::crypto_generichash_update($h, self::crypto_scalarmult($sk, $serverPublicKey)); self::crypto_generichash_update($h, $pk); self::crypto_generichash_update($h, $serverPublicKey); $sessionKeys = self::crypto_generichash_final($h, self::CRYPTO_KX_SESSIONKEYBYTES * 2); return array( ParagonIE_Sodium_Core_Util::substr( $sessionKeys, 0, self::CRYPTO_KX_SESSIONKEYBYTES ), ParagonIE_Sodium_Core_Util::substr( $sessionKeys, self::CRYPTO_KX_SESSIONKEYBYTES, self::CRYPTO_KX_SESSIONKEYBYTES ) ); } /** * @param string $keypair * @param string $clientPublicKey * @return array{0: string, 1: string} * @throws SodiumException */ public static function crypto_kx_server_session_keys( #[\SensitiveParameter] $keypair, $clientPublicKey ) { ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($clientPublicKey, 'string', 2); $keypair = (string) $keypair; $clientPublicKey = (string) $clientPublicKey; if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_KX_KEYPAIRBYTES) { throw new SodiumException('keypair should be SODIUM_CRYPTO_KX_KEYPAIRBYTES bytes'); } if (ParagonIE_Sodium_Core_Util::strlen($clientPublicKey) !== self::CRYPTO_KX_PUBLICKEYBYTES) { throw new SodiumException('public keys must be SODIUM_CRYPTO_KX_PUBLICKEYBYTES bytes'); } $sk = self::crypto_kx_secretkey($keypair); $pk = self::crypto_kx_publickey($keypair); $h = self::crypto_generichash_init(null, self::CRYPTO_KX_SESSIONKEYBYTES * 2); self::crypto_generichash_update($h, self::crypto_scalarmult($sk, $clientPublicKey)); self::crypto_generichash_update($h, $clientPublicKey); self::crypto_generichash_update($h, $pk); $sessionKeys = self::crypto_generichash_final($h, self::CRYPTO_KX_SESSIONKEYBYTES * 2); return array( ParagonIE_Sodium_Core_Util::substr( $sessionKeys, self::CRYPTO_KX_SESSIONKEYBYTES, self::CRYPTO_KX_SESSIONKEYBYTES ), ParagonIE_Sodium_Core_Util::substr( $sessionKeys, 0, self::CRYPTO_KX_SESSIONKEYBYTES ) ); } /** * @param string $kp * @return string * @throws SodiumException */ public static function crypto_kx_secretkey( #[\SensitiveParameter] $kp ) { return ParagonIE_Sodium_Core_Util::substr( $kp, 0, self::CRYPTO_KX_SECRETKEYBYTES ); } /** * @param string $kp * @return string * @throws SodiumException */ public static function crypto_kx_publickey($kp) { return ParagonIE_Sodium_Core_Util::substr( $kp, self::CRYPTO_KX_SECRETKEYBYTES, self::CRYPTO_KX_PUBLICKEYBYTES ); } /** * @param int $outlen * @param string $passwd * @param string $salt * @param int $opslimit * @param int $memlimit * @param int|null $alg * @return string * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_pwhash( $outlen, #[\SensitiveParameter] $passwd, $salt, $opslimit, $memlimit, $alg = null ) { ParagonIE_Sodium_Core_Util::declareScalarType($outlen, 'int', 1); ParagonIE_Sodium_Core_Util::declareScalarType($passwd, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($salt, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($opslimit, 'int', 4); ParagonIE_Sodium_Core_Util::declareScalarType($memlimit, 'int', 5); if (self::useNewSodiumAPI()) { if (!is_null($alg)) { ParagonIE_Sodium_Core_Util::declareScalarType($alg, 'int', 6); return sodium_crypto_pwhash($outlen, $passwd, $salt, $opslimit, $memlimit, $alg); } return sodium_crypto_pwhash($outlen, $passwd, $salt, $opslimit, $memlimit); } if (self::use_fallback('crypto_pwhash')) { return (string) call_user_func('\\Sodium\\crypto_pwhash', $outlen, $passwd, $salt, $opslimit, $memlimit); } // This is the best we can do. throw new SodiumException( 'This is not implemented, as it is not possible to implement Argon2i with acceptable performance in pure-PHP' ); } /** * !Exclusive to sodium_compat! * * This returns TRUE if the native crypto_pwhash API is available by libsodium. * This returns FALSE if only sodium_compat is available. * * @return bool */ public static function crypto_pwhash_is_available() { if (self::useNewSodiumAPI()) { return true; } if (self::use_fallback('crypto_pwhash')) { return true; } return false; } /** * @param string $passwd * @param int $opslimit * @param int $memlimit * @return string * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_pwhash_str( #[\SensitiveParameter] $passwd, $opslimit, $memlimit ) { ParagonIE_Sodium_Core_Util::declareScalarType($passwd, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($opslimit, 'int', 2); ParagonIE_Sodium_Core_Util::declareScalarType($memlimit, 'int', 3); if (self::useNewSodiumAPI()) { return sodium_crypto_pwhash_str($passwd, $opslimit, $memlimit); } if (self::use_fallback('crypto_pwhash_str')) { return (string) call_user_func('\\Sodium\\crypto_pwhash_str', $passwd, $opslimit, $memlimit); } // This is the best we can do. throw new SodiumException( 'This is not implemented, as it is not possible to implement Argon2i with acceptable performance in pure-PHP' ); } /** * Do we need to rehash this password? * * @param string $hash * @param int $opslimit * @param int $memlimit * @return bool * @throws SodiumException */ public static function crypto_pwhash_str_needs_rehash( #[\SensitiveParameter] $hash, $opslimit, $memlimit ) { ParagonIE_Sodium_Core_Util::declareScalarType($hash, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($opslimit, 'int', 2); ParagonIE_Sodium_Core_Util::declareScalarType($memlimit, 'int', 3); // Just grab the first 4 pieces. $pieces = explode('$', (string) $hash); $prefix = implode('$', array_slice($pieces, 0, 4)); // Rebuild the expected header. /** @var int $ops */ $ops = (int) $opslimit; /** @var int $mem */ $mem = (int) $memlimit >> 10; $encoded = self::CRYPTO_PWHASH_STRPREFIX . 'v=19$m=' . $mem . ',t=' . $ops . ',p=1'; // Do they match? If so, we don't need to rehash, so return false. return !ParagonIE_Sodium_Core_Util::hashEquals($encoded, $prefix); } /** * @param string $passwd * @param string $hash * @return bool * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_pwhash_str_verify( #[\SensitiveParameter] $passwd, #[\SensitiveParameter] $hash ) { ParagonIE_Sodium_Core_Util::declareScalarType($passwd, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($hash, 'string', 2); if (self::useNewSodiumAPI()) { return (bool) sodium_crypto_pwhash_str_verify($passwd, $hash); } if (self::use_fallback('crypto_pwhash_str_verify')) { return (bool) call_user_func('\\Sodium\\crypto_pwhash_str_verify', $passwd, $hash); } // This is the best we can do. throw new SodiumException( 'This is not implemented, as it is not possible to implement Argon2i with acceptable performance in pure-PHP' ); } /** * @param int $outlen * @param string $passwd * @param string $salt * @param int $opslimit * @param int $memlimit * @return string * @throws SodiumException * @throws TypeError */ public static function crypto_pwhash_scryptsalsa208sha256( $outlen, #[\SensitiveParameter] $passwd, $salt, $opslimit, $memlimit ) { ParagonIE_Sodium_Core_Util::declareScalarType($outlen, 'int', 1); ParagonIE_Sodium_Core_Util::declareScalarType($passwd, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($salt, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($opslimit, 'int', 4); ParagonIE_Sodium_Core_Util::declareScalarType($memlimit, 'int', 5); if (self::useNewSodiumAPI()) { return (string) sodium_crypto_pwhash_scryptsalsa208sha256( (int) $outlen, (string) $passwd, (string) $salt, (int) $opslimit, (int) $memlimit ); } if (self::use_fallback('crypto_pwhash_scryptsalsa208sha256')) { return (string) call_user_func( '\\Sodium\\crypto_pwhash_scryptsalsa208sha256', (int) $outlen, (string) $passwd, (string) $salt, (int) $opslimit, (int) $memlimit ); } // This is the best we can do. throw new SodiumException( 'This is not implemented, as it is not possible to implement Scrypt with acceptable performance in pure-PHP' ); } /** * !Exclusive to sodium_compat! * * This returns TRUE if the native crypto_pwhash API is available by libsodium. * This returns FALSE if only sodium_compat is available. * * @return bool */ public static function crypto_pwhash_scryptsalsa208sha256_is_available() { if (self::useNewSodiumAPI()) { return true; } if (self::use_fallback('crypto_pwhash_scryptsalsa208sha256')) { return true; } return false; } /** * @param string $passwd * @param int $opslimit * @param int $memlimit * @return string * @throws SodiumException * @throws TypeError */ public static function crypto_pwhash_scryptsalsa208sha256_str( #[\SensitiveParameter] $passwd, $opslimit, $memlimit ) { ParagonIE_Sodium_Core_Util::declareScalarType($passwd, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($opslimit, 'int', 2); ParagonIE_Sodium_Core_Util::declareScalarType($memlimit, 'int', 3); if (self::useNewSodiumAPI()) { return (string) sodium_crypto_pwhash_scryptsalsa208sha256_str( (string) $passwd, (int) $opslimit, (int) $memlimit ); } if (self::use_fallback('crypto_pwhash_scryptsalsa208sha256_str')) { return (string) call_user_func( '\\Sodium\\crypto_pwhash_scryptsalsa208sha256_str', (string) $passwd, (int) $opslimit, (int) $memlimit ); } // This is the best we can do. throw new SodiumException( 'This is not implemented, as it is not possible to implement Scrypt with acceptable performance in pure-PHP' ); } /** * @param string $passwd * @param string $hash * @return bool * @throws SodiumException * @throws TypeError */ public static function crypto_pwhash_scryptsalsa208sha256_str_verify( #[\SensitiveParameter] $passwd, #[\SensitiveParameter] $hash ) { ParagonIE_Sodium_Core_Util::declareScalarType($passwd, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($hash, 'string', 2); if (self::useNewSodiumAPI()) { return (bool) sodium_crypto_pwhash_scryptsalsa208sha256_str_verify( (string) $passwd, (string) $hash ); } if (self::use_fallback('crypto_pwhash_scryptsalsa208sha256_str_verify')) { return (bool) call_user_func( '\\Sodium\\crypto_pwhash_scryptsalsa208sha256_str_verify', (string) $passwd, (string) $hash ); } // This is the best we can do. throw new SodiumException( 'This is not implemented, as it is not possible to implement Scrypt with acceptable performance in pure-PHP' ); } /** * Calculate the shared secret between your secret key and your * recipient's public key. * * Algorithm: X25519 (ECDH over Curve25519) * * @param string $secretKey * @param string $publicKey * @return string * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_scalarmult( #[\SensitiveParameter] $secretKey, $publicKey ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($secretKey, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($publicKey, 'string', 2); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !== self::CRYPTO_BOX_SECRETKEYBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_BOX_SECRETKEYBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !== self::CRYPTO_BOX_PUBLICKEYBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_BOX_PUBLICKEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_scalarmult($secretKey, $publicKey); } if (self::use_fallback('crypto_scalarmult')) { return (string) call_user_func('\\Sodium\\crypto_scalarmult', $secretKey, $publicKey); } /* Output validation: Forbid all-zero keys */ if (ParagonIE_Sodium_Core_Util::hashEquals($secretKey, str_repeat("\0", self::CRYPTO_BOX_SECRETKEYBYTES))) { throw new SodiumException('Zero secret key is not allowed'); } if (ParagonIE_Sodium_Core_Util::hashEquals($publicKey, str_repeat("\0", self::CRYPTO_BOX_PUBLICKEYBYTES))) { throw new SodiumException('Zero public key is not allowed'); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::scalarmult($secretKey, $publicKey); } return ParagonIE_Sodium_Crypto::scalarmult($secretKey, $publicKey); } /** * Calculate an X25519 public key from an X25519 secret key. * * @param string $secretKey * @return string * @throws SodiumException * @throws TypeError * @psalm-suppress TooFewArguments * @psalm-suppress MixedArgument */ public static function crypto_scalarmult_base( #[\SensitiveParameter] $secretKey ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($secretKey, 'string', 1); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !== self::CRYPTO_BOX_SECRETKEYBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_BOX_SECRETKEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_scalarmult_base($secretKey); } if (self::use_fallback('crypto_scalarmult_base')) { return (string) call_user_func('\\Sodium\\crypto_scalarmult_base', $secretKey); } if (ParagonIE_Sodium_Core_Util::hashEquals($secretKey, str_repeat("\0", self::CRYPTO_BOX_SECRETKEYBYTES))) { throw new SodiumException('Zero secret key is not allowed'); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::scalarmult_base($secretKey); } return ParagonIE_Sodium_Crypto::scalarmult_base($secretKey); } /** * Authenticated symmetric-key encryption. * * Algorithm: XSalsa20-Poly1305 * * @param string $plaintext The message you're encrypting * @param string $nonce A Number to be used Once; must be 24 bytes * @param string $key Symmetric encryption key * @return string Ciphertext with Poly1305 MAC * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_secretbox( #[\SensitiveParameter] $plaintext, $nonce, #[\SensitiveParameter] $key ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_SECRETBOX_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_SECRETBOX_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_KEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_secretbox($plaintext, $nonce, $key); } if (self::use_fallback('crypto_secretbox')) { return (string) call_user_func('\\Sodium\\crypto_secretbox', $plaintext, $nonce, $key); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::secretbox($plaintext, $nonce, $key); } return ParagonIE_Sodium_Crypto::secretbox($plaintext, $nonce, $key); } /** * Decrypts a message previously encrypted with crypto_secretbox(). * * @param string $ciphertext Ciphertext with Poly1305 MAC * @param string $nonce A Number to be used Once; must be 24 bytes * @param string $key Symmetric encryption key * @return string Original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_secretbox_open( $ciphertext, $nonce, #[\SensitiveParameter] $key ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_SECRETBOX_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_SECRETBOX_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_KEYBYTES long.'); } if (self::useNewSodiumAPI()) { /** * @psalm-suppress InvalidReturnStatement * @psalm-suppress FalsableReturnStatement */ return sodium_crypto_secretbox_open($ciphertext, $nonce, $key); } if (self::use_fallback('crypto_secretbox_open')) { return call_user_func('\\Sodium\\crypto_secretbox_open', $ciphertext, $nonce, $key); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::secretbox_open($ciphertext, $nonce, $key); } return ParagonIE_Sodium_Crypto::secretbox_open($ciphertext, $nonce, $key); } /** * Return a secure random key for use with crypto_secretbox * * @return string * @throws Exception * @throws Error */ public static function crypto_secretbox_keygen() { return random_bytes(self::CRYPTO_SECRETBOX_KEYBYTES); } /** * Authenticated symmetric-key encryption. * * Algorithm: XChaCha20-Poly1305 * * @param string $plaintext The message you're encrypting * @param string $nonce A Number to be used Once; must be 24 bytes * @param string $key Symmetric encryption key * @return string Ciphertext with Poly1305 MAC * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_secretbox_xchacha20poly1305($plaintext, $nonce, $key) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_SECRETBOX_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_SECRETBOX_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_KEYBYTES long.'); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::secretbox_xchacha20poly1305($plaintext, $nonce, $key); } return ParagonIE_Sodium_Crypto::secretbox_xchacha20poly1305($plaintext, $nonce, $key); } /** * Decrypts a message previously encrypted with crypto_secretbox_xchacha20poly1305(). * * @param string $ciphertext Ciphertext with Poly1305 MAC * @param string $nonce A Number to be used Once; must be 24 bytes * @param string $key Symmetric encryption key * @return string Original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_secretbox_xchacha20poly1305_open( $ciphertext, $nonce, #[\SensitiveParameter] $key ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_SECRETBOX_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_SECRETBOX_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_KEYBYTES long.'); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::secretbox_xchacha20poly1305_open($ciphertext, $nonce, $key); } return ParagonIE_Sodium_Crypto::secretbox_xchacha20poly1305_open($ciphertext, $nonce, $key); } /** * @param string $key * @return array<int, string> Returns a state and a header. * @throws Exception * @throws SodiumException */ public static function crypto_secretstream_xchacha20poly1305_init_push( #[\SensitiveParameter] $key ) { if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_init_push($key); } return ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_init_push($key); } /** * @param string $header * @param string $key * @return string Returns a state. * @throws Exception */ public static function crypto_secretstream_xchacha20poly1305_init_pull( $header, #[\SensitiveParameter] $key ) { if (ParagonIE_Sodium_Core_Util::strlen($header) < self::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES) { throw new SodiumException( 'header size should be SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES bytes' ); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_init_pull($key, $header); } return ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_init_pull($key, $header); } /** * @param string $state * @param string $msg * @param string $aad * @param int $tag * @return string * @throws SodiumException */ public static function crypto_secretstream_xchacha20poly1305_push( #[\SensitiveParameter] &$state, #[\SensitiveParameter] $msg, $aad = '', $tag = 0 ) { if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_push( $state, $msg, $aad, $tag ); } return ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_push( $state, $msg, $aad, $tag ); } /** * @param string $state * @param string $msg * @param string $aad * @return bool|array{0: string, 1: int} * @throws SodiumException */ public static function crypto_secretstream_xchacha20poly1305_pull( #[\SensitiveParameter] &$state, $msg, $aad = '' ) { if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_pull( $state, $msg, $aad ); } return ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_pull( $state, $msg, $aad ); } /** * @return string * @throws Exception */ public static function crypto_secretstream_xchacha20poly1305_keygen() { return random_bytes(self::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES); } /** * @param string $state * @return void * @throws SodiumException */ public static function crypto_secretstream_xchacha20poly1305_rekey( #[\SensitiveParameter] &$state ) { if (PHP_INT_SIZE === 4) { ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_rekey($state); } else { ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_rekey($state); } } /** * Calculates a SipHash-2-4 hash of a message for a given key. * * @param string $message Input message * @param string $key SipHash-2-4 key * @return string Hash * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_shorthash( $message, #[\SensitiveParameter] $key ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 2); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_SHORTHASH_KEYBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SHORTHASH_KEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_shorthash($message, $key); } if (self::use_fallback('crypto_shorthash')) { return (string) call_user_func('\\Sodium\\crypto_shorthash', $message, $key); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_SipHash::sipHash24($message, $key); } return ParagonIE_Sodium_Core_SipHash::sipHash24($message, $key); } /** * Return a secure random key for use with crypto_shorthash * * @return string * @throws Exception * @throws Error */ public static function crypto_shorthash_keygen() { return random_bytes(self::CRYPTO_SHORTHASH_KEYBYTES); } /** * Returns a signed message. You probably want crypto_sign_detached() * instead, which only returns the signature. * * Algorithm: Ed25519 (EdDSA over Curve25519) * * @param string $message Message to be signed. * @param string $secretKey Secret signing key. * @return string Signed message (signature is prefixed). * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_sign( $message, #[\SensitiveParameter] $secretKey ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($secretKey, 'string', 2); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !== self::CRYPTO_SIGN_SECRETKEYBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SIGN_SECRETKEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_sign($message, $secretKey); } if (self::use_fallback('crypto_sign')) { return (string) call_user_func('\\Sodium\\crypto_sign', $message, $secretKey); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::sign($message, $secretKey); } return ParagonIE_Sodium_Crypto::sign($message, $secretKey); } /** * Validates a signed message then returns the message. * * @param string $signedMessage A signed message * @param string $publicKey A public key * @return string The original message (if the signature is * valid for this public key) * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public static function crypto_sign_open( $signedMessage, $publicKey ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($signedMessage, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($publicKey, 'string', 2); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($signedMessage) < self::CRYPTO_SIGN_BYTES) { throw new SodiumException('Argument 1 must be at least CRYPTO_SIGN_BYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !== self::CRYPTO_SIGN_PUBLICKEYBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SIGN_PUBLICKEYBYTES long.'); } if (self::useNewSodiumAPI()) { /** * @psalm-suppress InvalidReturnStatement * @psalm-suppress FalsableReturnStatement */ return sodium_crypto_sign_open($signedMessage, $publicKey); } if (self::use_fallback('crypto_sign_open')) { return call_user_func('\\Sodium\\crypto_sign_open', $signedMessage, $publicKey); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::sign_open($signedMessage, $publicKey); } return ParagonIE_Sodium_Crypto::sign_open($signedMessage, $publicKey); } /** * Generate a new random Ed25519 keypair. * * @return string * @throws SodiumException * @throws TypeError */ public static function crypto_sign_keypair() { if (self::useNewSodiumAPI()) { return sodium_crypto_sign_keypair(); } if (self::use_fallback('crypto_sign_keypair')) { return (string) call_user_func('\\Sodium\\crypto_sign_keypair'); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_Ed25519::keypair(); } return ParagonIE_Sodium_Core_Ed25519::keypair(); } /** * @param string $sk * @param string $pk * @return string * @throws SodiumException */ public static function crypto_sign_keypair_from_secretkey_and_publickey( #[\SensitiveParameter] $sk, $pk ) { ParagonIE_Sodium_Core_Util::declareScalarType($sk, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($pk, 'string', 1); $sk = (string) $sk; $pk = (string) $pk; if (ParagonIE_Sodium_Core_Util::strlen($sk) !== self::CRYPTO_SIGN_SECRETKEYBYTES) { throw new SodiumException('secretkey should be SODIUM_CRYPTO_SIGN_SECRETKEYBYTES bytes'); } if (ParagonIE_Sodium_Core_Util::strlen($pk) !== self::CRYPTO_SIGN_PUBLICKEYBYTES) { throw new SodiumException('publickey should be SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES bytes'); } if (self::useNewSodiumAPI()) { return sodium_crypto_sign_keypair_from_secretkey_and_publickey($sk, $pk); } return $sk . $pk; } /** * Generate an Ed25519 keypair from a seed. * * @param string $seed Input seed * @return string Keypair * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_sign_seed_keypair( #[\SensitiveParameter] $seed ) { ParagonIE_Sodium_Core_Util::declareScalarType($seed, 'string', 1); if (self::useNewSodiumAPI()) { return sodium_crypto_sign_seed_keypair($seed); } if (self::use_fallback('crypto_sign_keypair')) { return (string) call_user_func('\\Sodium\\crypto_sign_seed_keypair', $seed); } $publicKey = ''; $secretKey = ''; if (PHP_INT_SIZE === 4) { ParagonIE_Sodium_Core32_Ed25519::seed_keypair($publicKey, $secretKey, $seed); } else { ParagonIE_Sodium_Core_Ed25519::seed_keypair($publicKey, $secretKey, $seed); } return $secretKey . $publicKey; } /** * Extract an Ed25519 public key from an Ed25519 keypair. * * @param string $keypair Keypair * @return string Public key * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_sign_publickey( #[\SensitiveParameter] $keypair ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 1); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_SIGN_KEYPAIRBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_SIGN_KEYPAIRBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_sign_publickey($keypair); } if (self::use_fallback('crypto_sign_publickey')) { return (string) call_user_func('\\Sodium\\crypto_sign_publickey', $keypair); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_Ed25519::publickey($keypair); } return ParagonIE_Sodium_Core_Ed25519::publickey($keypair); } /** * Calculate an Ed25519 public key from an Ed25519 secret key. * * @param string $secretKey Your Ed25519 secret key * @return string The corresponding Ed25519 public key * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_sign_publickey_from_secretkey( #[\SensitiveParameter] $secretKey ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($secretKey, 'string', 1); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !== self::CRYPTO_SIGN_SECRETKEYBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_SIGN_SECRETKEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_sign_publickey_from_secretkey($secretKey); } if (self::use_fallback('crypto_sign_publickey_from_secretkey')) { return (string) call_user_func('\\Sodium\\crypto_sign_publickey_from_secretkey', $secretKey); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_Ed25519::publickey_from_secretkey($secretKey); } return ParagonIE_Sodium_Core_Ed25519::publickey_from_secretkey($secretKey); } /** * Extract an Ed25519 secret key from an Ed25519 keypair. * * @param string $keypair Keypair * @return string Secret key * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_sign_secretkey( #[\SensitiveParameter] $keypair ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 1); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_SIGN_KEYPAIRBYTES) { throw new SodiumException('Argument 1 must be CRYPTO_SIGN_KEYPAIRBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_sign_secretkey($keypair); } if (self::use_fallback('crypto_sign_secretkey')) { return (string) call_user_func('\\Sodium\\crypto_sign_secretkey', $keypair); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_Ed25519::secretkey($keypair); } return ParagonIE_Sodium_Core_Ed25519::secretkey($keypair); } /** * Calculate the Ed25519 signature of a message and return ONLY the signature. * * Algorithm: Ed25519 (EdDSA over Curve25519) * * @param string $message Message to be signed * @param string $secretKey Secret signing key * @return string Digital signature * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_sign_detached( $message, #[\SensitiveParameter] $secretKey ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($secretKey, 'string', 2); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !== self::CRYPTO_SIGN_SECRETKEYBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SIGN_SECRETKEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_sign_detached($message, $secretKey); } if (self::use_fallback('crypto_sign_detached')) { return (string) call_user_func('\\Sodium\\crypto_sign_detached', $message, $secretKey); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::sign_detached($message, $secretKey); } return ParagonIE_Sodium_Crypto::sign_detached($message, $secretKey); } /** * Verify the Ed25519 signature of a message. * * @param string $signature Digital sginature * @param string $message Message to be verified * @param string $publicKey Public key * @return bool TRUE if this signature is good for this public key; * FALSE otherwise * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_sign_verify_detached($signature, $message, $publicKey) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($signature, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($publicKey, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($signature) !== self::CRYPTO_SIGN_BYTES) { throw new SodiumException('Argument 1 must be CRYPTO_SIGN_BYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !== self::CRYPTO_SIGN_PUBLICKEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_SIGN_PUBLICKEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_sign_verify_detached($signature, $message, $publicKey); } if (self::use_fallback('crypto_sign_verify_detached')) { return (bool) call_user_func( '\\Sodium\\crypto_sign_verify_detached', $signature, $message, $publicKey ); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Crypto32::sign_verify_detached($signature, $message, $publicKey); } return ParagonIE_Sodium_Crypto::sign_verify_detached($signature, $message, $publicKey); } /** * Convert an Ed25519 public key to a Curve25519 public key * * @param string $pk * @return string * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_sign_ed25519_pk_to_curve25519($pk) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($pk, 'string', 1); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($pk) < self::CRYPTO_SIGN_PUBLICKEYBYTES) { throw new SodiumException('Argument 1 must be at least CRYPTO_SIGN_PUBLICKEYBYTES long.'); } if (self::useNewSodiumAPI()) { if (is_callable('crypto_sign_ed25519_pk_to_curve25519')) { return (string) sodium_crypto_sign_ed25519_pk_to_curve25519($pk); } } if (self::use_fallback('crypto_sign_ed25519_pk_to_curve25519')) { return (string) call_user_func('\\Sodium\\crypto_sign_ed25519_pk_to_curve25519', $pk); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_Ed25519::pk_to_curve25519($pk); } return ParagonIE_Sodium_Core_Ed25519::pk_to_curve25519($pk); } /** * Convert an Ed25519 secret key to a Curve25519 secret key * * @param string $sk * @return string * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_sign_ed25519_sk_to_curve25519( #[\SensitiveParameter] $sk ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($sk, 'string', 1); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($sk) < self::CRYPTO_SIGN_SEEDBYTES) { throw new SodiumException('Argument 1 must be at least CRYPTO_SIGN_SEEDBYTES long.'); } if (self::useNewSodiumAPI()) { if (is_callable('crypto_sign_ed25519_sk_to_curve25519')) { return sodium_crypto_sign_ed25519_sk_to_curve25519($sk); } } if (self::use_fallback('crypto_sign_ed25519_sk_to_curve25519')) { return (string) call_user_func('\\Sodium\\crypto_sign_ed25519_sk_to_curve25519', $sk); } $h = hash('sha512', ParagonIE_Sodium_Core_Util::substr($sk, 0, 32), true); $h[0] = ParagonIE_Sodium_Core_Util::intToChr( ParagonIE_Sodium_Core_Util::chrToInt($h[0]) & 248 ); $h[31] = ParagonIE_Sodium_Core_Util::intToChr( (ParagonIE_Sodium_Core_Util::chrToInt($h[31]) & 127) | 64 ); return ParagonIE_Sodium_Core_Util::substr($h, 0, 32); } /** * Expand a key and nonce into a keystream of pseudorandom bytes. * * @param int $len Number of bytes desired * @param string $nonce Number to be used Once; must be 24 bytes * @param string $key XSalsa20 key * @return string Pseudorandom stream that can be XORed with messages * to provide encryption (but not authentication; see * Poly1305 or crypto_auth() for that, which is not * optional for security) * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_stream( $len, $nonce, #[\SensitiveParameter] $key ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($len, 'int', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_STREAM_KEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_stream($len, $nonce, $key); } if (self::use_fallback('crypto_stream')) { return (string) call_user_func('\\Sodium\\crypto_stream', $len, $nonce, $key); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_XSalsa20::xsalsa20($len, $nonce, $key); } return ParagonIE_Sodium_Core_XSalsa20::xsalsa20($len, $nonce, $key); } /** * DANGER! UNAUTHENTICATED ENCRYPTION! * * Unless you are following expert advice, do not use this feature. * * Algorithm: XSalsa20 * * This DOES NOT provide ciphertext integrity. * * @param string $message Plaintext message * @param string $nonce Number to be used Once; must be 24 bytes * @param string $key Encryption key * @return string Encrypted text which is vulnerable to chosen- * ciphertext attacks unless you implement some * other mitigation to the ciphertext (i.e. * Encrypt then MAC) * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_stream_xor( #[\SensitiveParameter] $message, $nonce, #[\SensitiveParameter] $key ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_KEYBYTES long.'); } if (self::useNewSodiumAPI()) { return sodium_crypto_stream_xor($message, $nonce, $key); } if (self::use_fallback('crypto_stream_xor')) { return (string) call_user_func('\\Sodium\\crypto_stream_xor', $message, $nonce, $key); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_XSalsa20::xsalsa20_xor($message, $nonce, $key); } return ParagonIE_Sodium_Core_XSalsa20::xsalsa20_xor($message, $nonce, $key); } /** * Return a secure random key for use with crypto_stream * * @return string * @throws Exception * @throws Error */ public static function crypto_stream_keygen() { return random_bytes(self::CRYPTO_STREAM_KEYBYTES); } /** * Expand a key and nonce into a keystream of pseudorandom bytes. * * @param int $len Number of bytes desired * @param string $nonce Number to be used Once; must be 24 bytes * @param string $key XChaCha20 key * @param bool $dontFallback * @return string Pseudorandom stream that can be XORed with messages * to provide encryption (but not authentication; see * Poly1305 or crypto_auth() for that, which is not * optional for security) * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_stream_xchacha20( $len, $nonce, #[\SensitiveParameter] $key, $dontFallback = false ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($len, 'int', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_XCHACHA20_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_XCHACHA20_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_XCHACHA20_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_STREAM_XCHACHA20_KEYBYTES long.'); } if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_stream_xchacha20($len, $nonce, $key); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_XChaCha20::stream($len, $nonce, $key); } return ParagonIE_Sodium_Core_XChaCha20::stream($len, $nonce, $key); } /** * DANGER! UNAUTHENTICATED ENCRYPTION! * * Unless you are following expert advice, do not use this feature. * * Algorithm: XChaCha20 * * This DOES NOT provide ciphertext integrity. * * @param string $message Plaintext message * @param string $nonce Number to be used Once; must be 24 bytes * @param string $key Encryption key * @return string Encrypted text which is vulnerable to chosen- * ciphertext attacks unless you implement some * other mitigation to the ciphertext (i.e. * Encrypt then MAC) * @param bool $dontFallback * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_stream_xchacha20_xor( #[\SensitiveParameter] $message, $nonce, #[\SensitiveParameter] $key, $dontFallback = false ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_XCHACHA20_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_XCHACHA20_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_XCHACHA20_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_XCHACHA20_KEYBYTES long.'); } if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_stream_xchacha20_xor($message, $nonce, $key); } if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_XChaCha20::streamXorIc($message, $nonce, $key); } return ParagonIE_Sodium_Core_XChaCha20::streamXorIc($message, $nonce, $key); } /** * DANGER! UNAUTHENTICATED ENCRYPTION! * * Unless you are following expert advice, do not use this feature. * * Algorithm: XChaCha20 * * This DOES NOT provide ciphertext integrity. * * @param string $message Plaintext message * @param string $nonce Number to be used Once; must be 24 bytes * @param int $counter * @param string $key Encryption key * @return string Encrypted text which is vulnerable to chosen- * ciphertext attacks unless you implement some * other mitigation to the ciphertext (i.e. * Encrypt then MAC) * @param bool $dontFallback * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function crypto_stream_xchacha20_xor_ic( #[\SensitiveParameter] $message, $nonce, $counter, #[\SensitiveParameter] $key, $dontFallback = false ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); ParagonIE_Sodium_Core_Util::declareScalarType($counter, 'int', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); /* Input validation: */ if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_XCHACHA20_NONCEBYTES) { throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_XCHACHA20_NONCEBYTES long.'); } if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_XCHACHA20_KEYBYTES) { throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_XCHACHA20_KEYBYTES long.'); } if (is_callable('sodium_crypto_stream_xchacha20_xor_ic') && !$dontFallback) { return sodium_crypto_stream_xchacha20_xor_ic($message, $nonce, $counter, $key); } $ic = ParagonIE_Sodium_Core_Util::store64_le($counter); if (PHP_INT_SIZE === 4) { return ParagonIE_Sodium_Core32_XChaCha20::streamXorIc($message, $nonce, $key, $ic); } return ParagonIE_Sodium_Core_XChaCha20::streamXorIc($message, $nonce, $key, $ic); } /** * Return a secure random key for use with crypto_stream_xchacha20 * * @return string * @throws Exception * @throws Error */ public static function crypto_stream_xchacha20_keygen() { return random_bytes(self::CRYPTO_STREAM_XCHACHA20_KEYBYTES); } /** * Cache-timing-safe implementation of hex2bin(). * * @param string $string Hexadecimal string * @param string $ignore List of characters to ignore; useful for whitespace * @return string Raw binary string * @throws SodiumException * @throws TypeError * @psalm-suppress TooFewArguments * @psalm-suppress MixedArgument */ public static function hex2bin( #[\SensitiveParameter] $string, $ignore = '' ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($string, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($ignore, 'string', 2); if (self::useNewSodiumAPI()) { if (is_callable('sodium_hex2bin')) { return (string) sodium_hex2bin($string, $ignore); } } if (self::use_fallback('hex2bin')) { return (string) call_user_func('\\Sodium\\hex2bin', $string, $ignore); } return ParagonIE_Sodium_Core_Util::hex2bin($string, $ignore); } /** * Increase a string (little endian) * * @param string $var * * @return void * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function increment( #[\SensitiveParameter] &$var ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($var, 'string', 1); if (self::useNewSodiumAPI()) { sodium_increment($var); return; } if (self::use_fallback('increment')) { $func = '\\Sodium\\increment'; $func($var); return; } $len = ParagonIE_Sodium_Core_Util::strlen($var); $c = 1; $copy = ''; for ($i = 0; $i < $len; ++$i) { $c += ParagonIE_Sodium_Core_Util::chrToInt( ParagonIE_Sodium_Core_Util::substr($var, $i, 1) ); $copy .= ParagonIE_Sodium_Core_Util::intToChr($c); $c >>= 8; } $var = $copy; } /** * @param string $str * @return bool * * @throws SodiumException */ public static function is_zero( #[\SensitiveParameter] $str ) { $d = 0; for ($i = 0; $i < 32; ++$i) { $d |= ParagonIE_Sodium_Core_Util::chrToInt($str[$i]); } return ((($d - 1) >> 31) & 1) === 1; } /** * The equivalent to the libsodium minor version we aim to be compatible * with (sans pwhash and memzero). * * @return int */ public static function library_version_major() { if (self::useNewSodiumAPI() && defined('SODIUM_LIBRARY_MAJOR_VERSION')) { return SODIUM_LIBRARY_MAJOR_VERSION; } if (self::use_fallback('library_version_major')) { /** @psalm-suppress UndefinedFunction */ return (int) call_user_func('\\Sodium\\library_version_major'); } return self::LIBRARY_VERSION_MAJOR; } /** * The equivalent to the libsodium minor version we aim to be compatible * with (sans pwhash and memzero). * * @return int */ public static function library_version_minor() { if (self::useNewSodiumAPI() && defined('SODIUM_LIBRARY_MINOR_VERSION')) { return SODIUM_LIBRARY_MINOR_VERSION; } if (self::use_fallback('library_version_minor')) { /** @psalm-suppress UndefinedFunction */ return (int) call_user_func('\\Sodium\\library_version_minor'); } return self::LIBRARY_VERSION_MINOR; } /** * Compare two strings. * * @param string $left * @param string $right * @return int * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ public static function memcmp( #[\SensitiveParameter] $left, #[\SensitiveParameter] $right ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($left, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($right, 'string', 2); if (self::useNewSodiumAPI()) { return sodium_memcmp($left, $right); } if (self::use_fallback('memcmp')) { return (int) call_user_func('\\Sodium\\memcmp', $left, $right); } /** @var string $left */ /** @var string $right */ return ParagonIE_Sodium_Core_Util::memcmp($left, $right); } /** * It's actually not possible to zero memory buffers in PHP. You need the * native library for that. * * @param string|null $var * @param-out string|null $var * * @return void * @throws SodiumException (Unless libsodium is installed) * @throws TypeError * @psalm-suppress TooFewArguments */ public static function memzero( #[\SensitiveParameter] &$var ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($var, 'string', 1); if (self::useNewSodiumAPI()) { /** @psalm-suppress MixedArgument */ sodium_memzero($var); return; } if (self::use_fallback('memzero')) { $func = '\\Sodium\\memzero'; $func($var); if ($var === null) { return; } } // This is the best we can do. throw new SodiumException( 'This is not implemented in sodium_compat, as it is not possible to securely wipe memory from PHP. ' . 'To fix this error, make sure libsodium is installed and the PHP extension is enabled.' ); } /** * @param string $unpadded * @param int $blockSize * @param bool $dontFallback * @return string * @throws SodiumException */ public static function pad( #[\SensitiveParameter] $unpadded, $blockSize, $dontFallback = false ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($unpadded, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($blockSize, 'int', 2); $unpadded = (string) $unpadded; $blockSize = (int) $blockSize; if (self::useNewSodiumAPI() && !$dontFallback) { return (string) sodium_pad($unpadded, $blockSize); } if ($blockSize <= 0) { throw new SodiumException( 'block size cannot be less than 1' ); } $unpadded_len = ParagonIE_Sodium_Core_Util::strlen($unpadded); $xpadlen = ($blockSize - 1); if (($blockSize & ($blockSize - 1)) === 0) { $xpadlen -= $unpadded_len & ($blockSize - 1); } else { $xpadlen -= $unpadded_len % $blockSize; } $xpadded_len = $unpadded_len + $xpadlen; $padded = str_repeat("\0", $xpadded_len - 1); if ($unpadded_len > 0) { $st = 1; $i = 0; $k = $unpadded_len; for ($j = 0; $j <= $xpadded_len; ++$j) { $i = (int) $i; $k = (int) $k; $st = (int) $st; if ($j >= $unpadded_len) { $padded[$j] = "\0"; } else { $padded[$j] = $unpadded[$j]; } /** @var int $k */ $k -= $st; $st = (int) (~( ( ( ($k >> 48) | ($k >> 32) | ($k >> 16) | $k ) - 1 ) >> 16 ) ) & 1; $i += $st; } } $mask = 0; $tail = $xpadded_len; for ($i = 0; $i < $blockSize; ++$i) { # barrier_mask = (unsigned char) # (((i ^ xpadlen) - 1U) >> ((sizeof(size_t) - 1U) * CHAR_BIT)); $barrier_mask = (($i ^ $xpadlen) -1) >> ((PHP_INT_SIZE << 3) - 1); # tail[-i] = (tail[-i] & mask) | (0x80 & barrier_mask); $padded[$tail - $i] = ParagonIE_Sodium_Core_Util::intToChr( (ParagonIE_Sodium_Core_Util::chrToInt($padded[$tail - $i]) & $mask) | (0x80 & $barrier_mask) ); # mask |= barrier_mask; $mask |= $barrier_mask; } return $padded; } /** * @param string $padded * @param int $blockSize * @param bool $dontFallback * @return string * @throws SodiumException */ public static function unpad( #[\SensitiveParameter] $padded, $blockSize, $dontFallback = false ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($padded, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($blockSize, 'int', 2); $padded = (string) $padded; $blockSize = (int) $blockSize; if (self::useNewSodiumAPI() && !$dontFallback) { return (string) sodium_unpad($padded, $blockSize); } if ($blockSize <= 0) { throw new SodiumException('block size cannot be less than 1'); } $padded_len = ParagonIE_Sodium_Core_Util::strlen($padded); if ($padded_len < $blockSize) { throw new SodiumException('invalid padding'); } # tail = &padded[padded_len - 1U]; $tail = $padded_len - 1; $acc = 0; $valid = 0; $pad_len = 0; $found = 0; for ($i = 0; $i < $blockSize; ++$i) { # c = tail[-i]; $c = ParagonIE_Sodium_Core_Util::chrToInt($padded[$tail - $i]); # is_barrier = # (( (acc - 1U) & (pad_len - 1U) & ((c ^ 0x80) - 1U) ) >> 8) & 1U; $is_barrier = ( ( ($acc - 1) & ($pad_len - 1) & (($c ^ 80) - 1) ) >> 7 ) & 1; $is_barrier &= ~$found; $found |= $is_barrier; # acc |= c; $acc |= $c; # pad_len |= i & (1U + ~is_barrier); $pad_len |= $i & (1 + ~$is_barrier); # valid |= (unsigned char) is_barrier; $valid |= ($is_barrier & 0xff); } # unpadded_len = padded_len - 1U - pad_len; $unpadded_len = $padded_len - 1 - $pad_len; if ($valid !== 1) { throw new SodiumException('invalid padding'); } return ParagonIE_Sodium_Core_Util::substr($padded, 0, $unpadded_len); } /** * Will sodium_compat run fast on the current hardware and PHP configuration? * * @return bool */ public static function polyfill_is_fast() { if (extension_loaded('sodium')) { return true; } if (extension_loaded('libsodium')) { return true; } return PHP_INT_SIZE === 8; } /** * Generate a string of bytes from the kernel's CSPRNG. * Proudly uses /dev/urandom (if getrandom(2) is not available). * * @param int $numBytes * @return string * @throws Exception * @throws TypeError */ public static function randombytes_buf($numBytes) { /* Type checks: */ if (!is_int($numBytes)) { if (is_numeric($numBytes)) { $numBytes = (int) $numBytes; } else { throw new TypeError( 'Argument 1 must be an integer, ' . gettype($numBytes) . ' given.' ); } } /** @var positive-int $numBytes */ if (self::use_fallback('randombytes_buf')) { return (string) call_user_func('\\Sodium\\randombytes_buf', $numBytes); } if ($numBytes < 0) { throw new SodiumException("Number of bytes must be a positive integer"); } return random_bytes($numBytes); } /** * Generate an integer between 0 and $range (non-inclusive). * * @param int $range * @return int * @throws Exception * @throws Error * @throws TypeError */ public static function randombytes_uniform($range) { /* Type checks: */ if (!is_int($range)) { if (is_numeric($range)) { $range = (int) $range; } else { throw new TypeError( 'Argument 1 must be an integer, ' . gettype($range) . ' given.' ); } } if (self::use_fallback('randombytes_uniform')) { return (int) call_user_func('\\Sodium\\randombytes_uniform', $range); } return random_int(0, $range - 1); } /** * Generate a random 16-bit integer. * * @return int * @throws Exception * @throws Error * @throws TypeError */ public static function randombytes_random16() { if (self::use_fallback('randombytes_random16')) { return (int) call_user_func('\\Sodium\\randombytes_random16'); } return random_int(0, 65535); } /** * @param string $p * @param bool $dontFallback * @return bool * @throws SodiumException */ public static function ristretto255_is_valid_point( #[\SensitiveParameter] $p, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_is_valid_point($p); } try { $r = ParagonIE_Sodium_Core_Ristretto255::ristretto255_frombytes($p); return $r['res'] === 0 && ParagonIE_Sodium_Core_Ristretto255::ristretto255_point_is_canonical($p) === 1; } catch (SodiumException $ex) { if ($ex->getMessage() === 'S is not canonical') { return false; } throw $ex; } } /** * @param string $p * @param string $q * @param bool $dontFallback * @return string * @throws SodiumException */ public static function ristretto255_add( #[\SensitiveParameter] $p, #[\SensitiveParameter] $q, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_add($p, $q); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_add($p, $q); } /** * @param string $p * @param string $q * @param bool $dontFallback * @return string * @throws SodiumException */ public static function ristretto255_sub( #[\SensitiveParameter] $p, #[\SensitiveParameter] $q, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_sub($p, $q); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_sub($p, $q); } /** * @param string $r * @param bool $dontFallback * @return string * * @throws SodiumException */ public static function ristretto255_from_hash( #[\SensitiveParameter] $r, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_from_hash($r); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_from_hash($r); } /** * @param bool $dontFallback * @return string * * @throws SodiumException */ public static function ristretto255_random($dontFallback = false) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_random(); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_random(); } /** * @param bool $dontFallback * @return string * * @throws SodiumException */ public static function ristretto255_scalar_random($dontFallback = false) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_scalar_random(); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_random(); } /** * @param string $s * @param bool $dontFallback * @return string * @throws SodiumException */ public static function ristretto255_scalar_invert( #[\SensitiveParameter] $s, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_scalar_invert($s); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_invert($s); } /** * @param string $s * @param bool $dontFallback * @return string * @throws SodiumException */ public static function ristretto255_scalar_negate( #[\SensitiveParameter] $s, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_scalar_negate($s); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_negate($s); } /** * @param string $s * @param bool $dontFallback * @return string * @throws SodiumException */ public static function ristretto255_scalar_complement( #[\SensitiveParameter] $s, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_scalar_complement($s); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_complement($s); } /** * @param string $x * @param string $y * @param bool $dontFallback * @return string * @throws SodiumException */ public static function ristretto255_scalar_add( #[\SensitiveParameter] $x, #[\SensitiveParameter] $y, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_scalar_add($x, $y); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_add($x, $y); } /** * @param string $x * @param string $y * @param bool $dontFallback * @return string * @throws SodiumException */ public static function ristretto255_scalar_sub( #[\SensitiveParameter] $x, #[\SensitiveParameter] $y, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_scalar_sub($x, $y); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_sub($x, $y); } /** * @param string $x * @param string $y * @param bool $dontFallback * @return string * @throws SodiumException */ public static function ristretto255_scalar_mul( #[\SensitiveParameter] $x, #[\SensitiveParameter] $y, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_scalar_mul($x, $y); } return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_mul($x, $y); } /** * @param string $n * @param string $p * @param bool $dontFallback * @return string * @throws SodiumException */ public static function scalarmult_ristretto255( #[\SensitiveParameter] $n, #[\SensitiveParameter] $p, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_scalarmult_ristretto255($n, $p); } return ParagonIE_Sodium_Core_Ristretto255::scalarmult_ristretto255($n, $p); } /** * @param string $n * @param string $p * @param bool $dontFallback * @return string * @throws SodiumException */ public static function scalarmult_ristretto255_base( #[\SensitiveParameter] $n, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_scalarmult_ristretto255_base($n); } return ParagonIE_Sodium_Core_Ristretto255::scalarmult_ristretto255_base($n); } /** * @param string $s * @param bool $dontFallback * @return string * @throws SodiumException */ public static function ristretto255_scalar_reduce( #[\SensitiveParameter] $s, $dontFallback = false ) { if (self::useNewSodiumAPI() && !$dontFallback) { return sodium_crypto_core_ristretto255_scalar_reduce($s); } return ParagonIE_Sodium_Core_Ristretto255::sc_reduce($s); } /** * Runtime testing method for 32-bit platforms. * * Usage: If runtime_speed_test() returns FALSE, then our 32-bit * implementation is to slow to use safely without risking timeouts. * If this happens, install sodium from PECL to get acceptable * performance. * * @param int $iterations Number of multiplications to attempt * @param int $maxTimeout Milliseconds * @return bool TRUE if we're fast enough, FALSE is not * @throws SodiumException */ public static function runtime_speed_test($iterations, $maxTimeout) { if (self::polyfill_is_fast()) { return true; } /** @var float $end */ $end = 0.0; /** @var float $start */ $start = microtime(true); /** @var ParagonIE_Sodium_Core32_Int64 $a */ $a = ParagonIE_Sodium_Core32_Int64::fromInt(random_int(3, 1 << 16)); for ($i = 0; $i < $iterations; ++$i) { /** @var ParagonIE_Sodium_Core32_Int64 $b */ $b = ParagonIE_Sodium_Core32_Int64::fromInt(random_int(3, 1 << 16)); $a->mulInt64($b); } /** @var float $end */ $end = microtime(true); /** @var int $diff */ $diff = (int) ceil(($end - $start) * 1000); return $diff < $maxTimeout; } /** * Add two numbers (little-endian unsigned), storing the value in the first * parameter. * * This mutates $val. * * @param string $val * @param string $addv * @return void * @throws SodiumException */ public static function sub( #[\SensitiveParameter] &$val, #[\SensitiveParameter] $addv ) { $val_len = ParagonIE_Sodium_Core_Util::strlen($val); $addv_len = ParagonIE_Sodium_Core_Util::strlen($addv); if ($val_len !== $addv_len) { throw new SodiumException('values must have the same length'); } $A = ParagonIE_Sodium_Core_Util::stringToIntArray($val); $B = ParagonIE_Sodium_Core_Util::stringToIntArray($addv); $c = 0; for ($i = 0; $i < $val_len; $i++) { $c = ($A[$i] - $B[$i] - $c); $A[$i] = ($c & 0xff); $c = ($c >> 8) & 1; } $val = ParagonIE_Sodium_Core_Util::intArrayToString($A); } /** * This emulates libsodium's version_string() function, except ours is * prefixed with 'polyfill-'. * * @return string * @psalm-suppress MixedInferredReturnType * @psalm-suppress UndefinedFunction */ public static function version_string() { if (self::useNewSodiumAPI()) { return (string) sodium_version_string(); } if (self::use_fallback('version_string')) { return (string) call_user_func('\\Sodium\\version_string'); } return (string) self::VERSION_STRING; } /** * Should we use the libsodium core function instead? * This is always a good idea, if it's available. (Unless we're in the * middle of running our unit test suite.) * * If ext/libsodium is available, use it. Return TRUE. * Otherwise, we have to use the code provided herein. Return FALSE. * * @param string $sodium_func_name * * @return bool */ protected static function use_fallback($sodium_func_name = '') { static $res = null; if ($res === null) { $res = extension_loaded('libsodium') && PHP_VERSION_ID >= 50300; } if ($res === false) { // No libsodium installed return false; } if (self::$disableFallbackForUnitTests) { // Don't fallback. Use the PHP implementation. return false; } if (!empty($sodium_func_name)) { return is_callable('\\Sodium\\' . $sodium_func_name); } return true; } /** * Libsodium as implemented in PHP 7.2 * and/or ext/sodium (via PECL) * * @ref https://wiki.php.net/rfc/libsodium * @return bool */ protected static function useNewSodiumAPI() { static $res = null; if ($res === null) { $res = PHP_VERSION_ID >= 70000 && extension_loaded('sodium'); } if (self::$disableFallbackForUnitTests) { // Don't fallback. Use the PHP implementation. return false; } return (bool) $res; } } PK������Z8ĤY��Y����Core/AES/KeySchedule.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_AES_KeySchedule', false)) { return; } /** * @internal This should only be used by sodium_compat */ class ParagonIE_Sodium_Core_AES_KeySchedule { /** @var array<int, int> $skey -- has size 120 */ protected $skey; /** @var bool $expanded */ protected $expanded = false; /** @var int $numRounds */ private $numRounds; /** * @param array $skey * @param int $numRounds */ public function __construct(array $skey, $numRounds = 10) { $this->skey = $skey; $this->numRounds = $numRounds; } /** * Get a value at an arbitrary index. Mostly used for unit testing. * * @param int $i * @return int */ public function get($i) { return $this->skey[$i]; } /** * @return int */ public function getNumRounds() { return $this->numRounds; } /** * @param int $offset * @return ParagonIE_Sodium_Core_AES_Block */ public function getRoundKey($offset) { return ParagonIE_Sodium_Core_AES_Block::fromArray( array_slice($this->skey, $offset, 8) ); } /** * Return an expanded key schedule * * @return ParagonIE_Sodium_Core_AES_Expanded */ public function expand() { $exp = new ParagonIE_Sodium_Core_AES_Expanded( array_fill(0, 120, 0), $this->numRounds ); $n = ($exp->numRounds + 1) << 2; for ($u = 0, $v = 0; $u < $n; ++$u, $v += 2) { $x = $y = $this->skey[$u]; $x &= 0x55555555; $exp->skey[$v] = ($x | ($x << 1)) & ParagonIE_Sodium_Core_Util::U32_MAX; $y &= 0xAAAAAAAA; $exp->skey[$v + 1] = ($y | ($y >> 1)) & ParagonIE_Sodium_Core_Util::U32_MAX; } return $exp; } } PK������ZrS(��(����Core/AES/Block.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_AES_Block', false)) { return; } /** * @internal This should only be used by sodium_compat */ class ParagonIE_Sodium_Core_AES_Block extends SplFixedArray { /** * @var array<int, int> */ protected $values = array(); /** * @var int */ protected $size; /** * @param int $size */ public function __construct($size = 8) { parent::__construct($size); $this->size = $size; $this->values = array_fill(0, $size, 0); } /** * @return self */ public static function init() { return new self(8); } /** * @internal You should not use this directly from another application * * @param array<int, int> $array * @param bool $save_indexes * @return self * * @psalm-suppress MethodSignatureMismatch */ #[ReturnTypeWillChange] public static function fromArray($array, $save_indexes = null) { $count = count($array); if ($save_indexes) { $keys = array_keys($array); } else { $keys = range(0, $count - 1); } $array = array_values($array); /** @var array<int, int> $keys */ $obj = new ParagonIE_Sodium_Core_AES_Block(); if ($save_indexes) { for ($i = 0; $i < $count; ++$i) { $obj->offsetSet($keys[$i], $array[$i]); } } else { for ($i = 0; $i < $count; ++$i) { $obj->offsetSet($i, $array[$i]); } } return $obj; } /** * @internal You should not use this directly from another application * * @param int|null $offset * @param int $value * @return void * * @psalm-suppress MethodSignatureMismatch * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetSet($offset, $value) { if (!is_int($value)) { throw new InvalidArgumentException('Expected an integer'); } if (is_null($offset)) { $this->values[] = $value; } else { $this->values[$offset] = $value; } } /** * @internal You should not use this directly from another application * * @param int $offset * @return bool * * @psalm-suppress MethodSignatureMismatch * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->values[$offset]); } /** * @internal You should not use this directly from another application * * @param int $offset * @return void * * @psalm-suppress MethodSignatureMismatch * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->values[$offset]); } /** * @internal You should not use this directly from another application * * @param int $offset * @return int * * @psalm-suppress MethodSignatureMismatch * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetGet($offset) { if (!isset($this->values[$offset])) { $this->values[$offset] = 0; } return (int) ($this->values[$offset]); } /** * @internal You should not use this directly from another application * * @return array */ public function __debugInfo() { $out = array(); foreach ($this->values as $v) { $out[] = str_pad(dechex($v), 8, '0', STR_PAD_LEFT); } return array(implode(', ', $out)); /* return array(implode(', ', $this->values)); */ } /** * @param int $cl low bit mask * @param int $ch high bit mask * @param int $s shift * @param int $x index 1 * @param int $y index 2 * @return self */ public function swapN($cl, $ch, $s, $x, $y) { static $u32mask = ParagonIE_Sodium_Core_Util::U32_MAX; $a = $this->values[$x] & $u32mask; $b = $this->values[$y] & $u32mask; // (x) = (a & cl) | ((b & cl) << (s)); $this->values[$x] = ($a & $cl) | ((($b & $cl) << $s) & $u32mask); // (y) = ((a & ch) >> (s)) | (b & ch); $this->values[$y] = ((($a & $ch) & $u32mask) >> $s) | ($b & $ch); return $this; } /** * @param int $x index 1 * @param int $y index 2 * @return self */ public function swap2($x, $y) { return $this->swapN(0x55555555, 0xAAAAAAAA, 1, $x, $y); } /** * @param int $x index 1 * @param int $y index 2 * @return self */ public function swap4($x, $y) { return $this->swapN(0x33333333, 0xCCCCCCCC, 2, $x, $y); } /** * @param int $x index 1 * @param int $y index 2 * @return self */ public function swap8($x, $y) { return $this->swapN(0x0F0F0F0F, 0xF0F0F0F0, 4, $x, $y); } /** * @return self */ public function orthogonalize() { return $this ->swap2(0, 1) ->swap2(2, 3) ->swap2(4, 5) ->swap2(6, 7) ->swap4(0, 2) ->swap4(1, 3) ->swap4(4, 6) ->swap4(5, 7) ->swap8(0, 4) ->swap8(1, 5) ->swap8(2, 6) ->swap8(3, 7); } /** * @return self */ public function shiftRows() { for ($i = 0; $i < 8; ++$i) { $x = $this->values[$i] & ParagonIE_Sodium_Core_Util::U32_MAX; $this->values[$i] = ( ($x & 0x000000FF) | (($x & 0x0000FC00) >> 2) | (($x & 0x00000300) << 6) | (($x & 0x00F00000) >> 4) | (($x & 0x000F0000) << 4) | (($x & 0xC0000000) >> 6) | (($x & 0x3F000000) << 2) ) & ParagonIE_Sodium_Core_Util::U32_MAX; } return $this; } /** * @param int $x * @return int */ public static function rotr16($x) { return (($x << 16) & ParagonIE_Sodium_Core_Util::U32_MAX) | ($x >> 16); } /** * @return self */ public function mixColumns() { $q0 = $this->values[0]; $q1 = $this->values[1]; $q2 = $this->values[2]; $q3 = $this->values[3]; $q4 = $this->values[4]; $q5 = $this->values[5]; $q6 = $this->values[6]; $q7 = $this->values[7]; $r0 = (($q0 >> 8) | ($q0 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r1 = (($q1 >> 8) | ($q1 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r2 = (($q2 >> 8) | ($q2 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r3 = (($q3 >> 8) | ($q3 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r4 = (($q4 >> 8) | ($q4 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r5 = (($q5 >> 8) | ($q5 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r6 = (($q6 >> 8) | ($q6 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r7 = (($q7 >> 8) | ($q7 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $this->values[0] = $q7 ^ $r7 ^ $r0 ^ self::rotr16($q0 ^ $r0); $this->values[1] = $q0 ^ $r0 ^ $q7 ^ $r7 ^ $r1 ^ self::rotr16($q1 ^ $r1); $this->values[2] = $q1 ^ $r1 ^ $r2 ^ self::rotr16($q2 ^ $r2); $this->values[3] = $q2 ^ $r2 ^ $q7 ^ $r7 ^ $r3 ^ self::rotr16($q3 ^ $r3); $this->values[4] = $q3 ^ $r3 ^ $q7 ^ $r7 ^ $r4 ^ self::rotr16($q4 ^ $r4); $this->values[5] = $q4 ^ $r4 ^ $r5 ^ self::rotr16($q5 ^ $r5); $this->values[6] = $q5 ^ $r5 ^ $r6 ^ self::rotr16($q6 ^ $r6); $this->values[7] = $q6 ^ $r6 ^ $r7 ^ self::rotr16($q7 ^ $r7); return $this; } /** * @return self */ public function inverseMixColumns() { $q0 = $this->values[0]; $q1 = $this->values[1]; $q2 = $this->values[2]; $q3 = $this->values[3]; $q4 = $this->values[4]; $q5 = $this->values[5]; $q6 = $this->values[6]; $q7 = $this->values[7]; $r0 = (($q0 >> 8) | ($q0 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r1 = (($q1 >> 8) | ($q1 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r2 = (($q2 >> 8) | ($q2 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r3 = (($q3 >> 8) | ($q3 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r4 = (($q4 >> 8) | ($q4 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r5 = (($q5 >> 8) | ($q5 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r6 = (($q6 >> 8) | ($q6 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $r7 = (($q7 >> 8) | ($q7 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX; $this->values[0] = $q5 ^ $q6 ^ $q7 ^ $r0 ^ $r5 ^ $r7 ^ self::rotr16($q0 ^ $q5 ^ $q6 ^ $r0 ^ $r5); $this->values[1] = $q0 ^ $q5 ^ $r0 ^ $r1 ^ $r5 ^ $r6 ^ $r7 ^ self::rotr16($q1 ^ $q5 ^ $q7 ^ $r1 ^ $r5 ^ $r6); $this->values[2] = $q0 ^ $q1 ^ $q6 ^ $r1 ^ $r2 ^ $r6 ^ $r7 ^ self::rotr16($q0 ^ $q2 ^ $q6 ^ $r2 ^ $r6 ^ $r7); $this->values[3] = $q0 ^ $q1 ^ $q2 ^ $q5 ^ $q6 ^ $r0 ^ $r2 ^ $r3 ^ $r5 ^ self::rotr16($q0 ^ $q1 ^ $q3 ^ $q5 ^ $q6 ^ $q7 ^ $r0 ^ $r3 ^ $r5 ^ $r7); $this->values[4] = $q1 ^ $q2 ^ $q3 ^ $q5 ^ $r1 ^ $r3 ^ $r4 ^ $r5 ^ $r6 ^ $r7 ^ self::rotr16($q1 ^ $q2 ^ $q4 ^ $q5 ^ $q7 ^ $r1 ^ $r4 ^ $r5 ^ $r6); $this->values[5] = $q2 ^ $q3 ^ $q4 ^ $q6 ^ $r2 ^ $r4 ^ $r5 ^ $r6 ^ $r7 ^ self::rotr16($q2 ^ $q3 ^ $q5 ^ $q6 ^ $r2 ^ $r5 ^ $r6 ^ $r7); $this->values[6] = $q3 ^ $q4 ^ $q5 ^ $q7 ^ $r3 ^ $r5 ^ $r6 ^ $r7 ^ self::rotr16($q3 ^ $q4 ^ $q6 ^ $q7 ^ $r3 ^ $r6 ^ $r7); $this->values[7] = $q4 ^ $q5 ^ $q6 ^ $r4 ^ $r6 ^ $r7 ^ self::rotr16($q4 ^ $q5 ^ $q7 ^ $r4 ^ $r7); return $this; } /** * @return self */ public function inverseShiftRows() { for ($i = 0; $i < 8; ++$i) { $x = $this->values[$i]; $this->values[$i] = ParagonIE_Sodium_Core_Util::U32_MAX & ( ($x & 0x000000FF) | (($x & 0x00003F00) << 2) | (($x & 0x0000C000) >> 6) | (($x & 0x000F0000) << 4) | (($x & 0x00F00000) >> 4) | (($x & 0x03000000) << 6) | (($x & 0xFC000000) >> 2) ); } return $this; } } PK������Z0��0����Core/AES/Expanded.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_AES_Expanded', false)) { return; } /** * @internal This should only be used by sodium_compat */ class ParagonIE_Sodium_Core_AES_Expanded extends ParagonIE_Sodium_Core_AES_KeySchedule { /** @var bool $expanded */ protected $expanded = true; } PK������Zf( >�� >�� ��Core/AES.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_AES', false)) { return; } /** * Bitsliced implementation of the AES block cipher. * * Based on the implementation provided by BearSSL. * * @internal This should only be used by sodium_compat */ class ParagonIE_Sodium_Core_AES extends ParagonIE_Sodium_Core_Util { /** * @var int[] AES round constants */ private static $Rcon = array( 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 ); /** * Mutates the values of $q! * * @param ParagonIE_Sodium_Core_AES_Block $q * @return void */ public static function sbox(ParagonIE_Sodium_Core_AES_Block $q) { /** * @var int $x0 * @var int $x1 * @var int $x2 * @var int $x3 * @var int $x4 * @var int $x5 * @var int $x6 * @var int $x7 */ $x0 = $q[7] & self::U32_MAX; $x1 = $q[6] & self::U32_MAX; $x2 = $q[5] & self::U32_MAX; $x3 = $q[4] & self::U32_MAX; $x4 = $q[3] & self::U32_MAX; $x5 = $q[2] & self::U32_MAX; $x6 = $q[1] & self::U32_MAX; $x7 = $q[0] & self::U32_MAX; $y14 = $x3 ^ $x5; $y13 = $x0 ^ $x6; $y9 = $x0 ^ $x3; $y8 = $x0 ^ $x5; $t0 = $x1 ^ $x2; $y1 = $t0 ^ $x7; $y4 = $y1 ^ $x3; $y12 = $y13 ^ $y14; $y2 = $y1 ^ $x0; $y5 = $y1 ^ $x6; $y3 = $y5 ^ $y8; $t1 = $x4 ^ $y12; $y15 = $t1 ^ $x5; $y20 = $t1 ^ $x1; $y6 = $y15 ^ $x7; $y10 = $y15 ^ $t0; $y11 = $y20 ^ $y9; $y7 = $x7 ^ $y11; $y17 = $y10 ^ $y11; $y19 = $y10 ^ $y8; $y16 = $t0 ^ $y11; $y21 = $y13 ^ $y16; $y18 = $x0 ^ $y16; /* * Non-linear section. */ $t2 = $y12 & $y15; $t3 = $y3 & $y6; $t4 = $t3 ^ $t2; $t5 = $y4 & $x7; $t6 = $t5 ^ $t2; $t7 = $y13 & $y16; $t8 = $y5 & $y1; $t9 = $t8 ^ $t7; $t10 = $y2 & $y7; $t11 = $t10 ^ $t7; $t12 = $y9 & $y11; $t13 = $y14 & $y17; $t14 = $t13 ^ $t12; $t15 = $y8 & $y10; $t16 = $t15 ^ $t12; $t17 = $t4 ^ $t14; $t18 = $t6 ^ $t16; $t19 = $t9 ^ $t14; $t20 = $t11 ^ $t16; $t21 = $t17 ^ $y20; $t22 = $t18 ^ $y19; $t23 = $t19 ^ $y21; $t24 = $t20 ^ $y18; $t25 = $t21 ^ $t22; $t26 = $t21 & $t23; $t27 = $t24 ^ $t26; $t28 = $t25 & $t27; $t29 = $t28 ^ $t22; $t30 = $t23 ^ $t24; $t31 = $t22 ^ $t26; $t32 = $t31 & $t30; $t33 = $t32 ^ $t24; $t34 = $t23 ^ $t33; $t35 = $t27 ^ $t33; $t36 = $t24 & $t35; $t37 = $t36 ^ $t34; $t38 = $t27 ^ $t36; $t39 = $t29 & $t38; $t40 = $t25 ^ $t39; $t41 = $t40 ^ $t37; $t42 = $t29 ^ $t33; $t43 = $t29 ^ $t40; $t44 = $t33 ^ $t37; $t45 = $t42 ^ $t41; $z0 = $t44 & $y15; $z1 = $t37 & $y6; $z2 = $t33 & $x7; $z3 = $t43 & $y16; $z4 = $t40 & $y1; $z5 = $t29 & $y7; $z6 = $t42 & $y11; $z7 = $t45 & $y17; $z8 = $t41 & $y10; $z9 = $t44 & $y12; $z10 = $t37 & $y3; $z11 = $t33 & $y4; $z12 = $t43 & $y13; $z13 = $t40 & $y5; $z14 = $t29 & $y2; $z15 = $t42 & $y9; $z16 = $t45 & $y14; $z17 = $t41 & $y8; /* * Bottom linear transformation. */ $t46 = $z15 ^ $z16; $t47 = $z10 ^ $z11; $t48 = $z5 ^ $z13; $t49 = $z9 ^ $z10; $t50 = $z2 ^ $z12; $t51 = $z2 ^ $z5; $t52 = $z7 ^ $z8; $t53 = $z0 ^ $z3; $t54 = $z6 ^ $z7; $t55 = $z16 ^ $z17; $t56 = $z12 ^ $t48; $t57 = $t50 ^ $t53; $t58 = $z4 ^ $t46; $t59 = $z3 ^ $t54; $t60 = $t46 ^ $t57; $t61 = $z14 ^ $t57; $t62 = $t52 ^ $t58; $t63 = $t49 ^ $t58; $t64 = $z4 ^ $t59; $t65 = $t61 ^ $t62; $t66 = $z1 ^ $t63; $s0 = $t59 ^ $t63; $s6 = $t56 ^ ~$t62; $s7 = $t48 ^ ~$t60; $t67 = $t64 ^ $t65; $s3 = $t53 ^ $t66; $s4 = $t51 ^ $t66; $s5 = $t47 ^ $t65; $s1 = $t64 ^ ~$s3; $s2 = $t55 ^ ~$t67; $q[7] = $s0 & self::U32_MAX; $q[6] = $s1 & self::U32_MAX; $q[5] = $s2 & self::U32_MAX; $q[4] = $s3 & self::U32_MAX; $q[3] = $s4 & self::U32_MAX; $q[2] = $s5 & self::U32_MAX; $q[1] = $s6 & self::U32_MAX; $q[0] = $s7 & self::U32_MAX; } /** * Mutates the values of $q! * * @param ParagonIE_Sodium_Core_AES_Block $q * @return void */ public static function invSbox(ParagonIE_Sodium_Core_AES_Block $q) { self::processInversion($q); self::sbox($q); self::processInversion($q); } /** * This is some boilerplate code needed to invert an S-box. Rather than repeat the code * twice, I moved it to a protected method. * * Mutates $q * * @param ParagonIE_Sodium_Core_AES_Block $q * @return void */ protected static function processInversion(ParagonIE_Sodium_Core_AES_Block $q) { $q0 = (~$q[0]) & self::U32_MAX; $q1 = (~$q[1]) & self::U32_MAX; $q2 = $q[2] & self::U32_MAX; $q3 = $q[3] & self::U32_MAX; $q4 = $q[4] & self::U32_MAX; $q5 = (~$q[5]) & self::U32_MAX; $q6 = (~$q[6]) & self::U32_MAX; $q7 = $q[7] & self::U32_MAX; $q[7] = ($q1 ^ $q4 ^ $q6) & self::U32_MAX; $q[6] = ($q0 ^ $q3 ^ $q5) & self::U32_MAX; $q[5] = ($q7 ^ $q2 ^ $q4) & self::U32_MAX; $q[4] = ($q6 ^ $q1 ^ $q3) & self::U32_MAX; $q[3] = ($q5 ^ $q0 ^ $q2) & self::U32_MAX; $q[2] = ($q4 ^ $q7 ^ $q1) & self::U32_MAX; $q[1] = ($q3 ^ $q6 ^ $q0) & self::U32_MAX; $q[0] = ($q2 ^ $q5 ^ $q7) & self::U32_MAX; } /** * @param int $x * @return int */ public static function subWord($x) { $q = ParagonIE_Sodium_Core_AES_Block::fromArray( array($x, $x, $x, $x, $x, $x, $x, $x) ); $q->orthogonalize(); self::sbox($q); $q->orthogonalize(); return $q[0] & self::U32_MAX; } /** * Calculate the key schedule from a given random key * * @param string $key * @return ParagonIE_Sodium_Core_AES_KeySchedule * @throws SodiumException */ public static function keySchedule($key) { $key_len = self::strlen($key); switch ($key_len) { case 16: $num_rounds = 10; break; case 24: $num_rounds = 12; break; case 32: $num_rounds = 14; break; default: throw new SodiumException('Invalid key length: ' . $key_len); } $skey = array(); $comp_skey = array(); $nk = $key_len >> 2; $nkf = ($num_rounds + 1) << 2; $tmp = 0; for ($i = 0; $i < $nk; ++$i) { $tmp = self::load_4(self::substr($key, $i << 2, 4)); $skey[($i << 1)] = $tmp; $skey[($i << 1) + 1] = $tmp; } for ($i = $nk, $j = 0, $k = 0; $i < $nkf; ++$i) { if ($j === 0) { $tmp = (($tmp & 0xff) << 24) | ($tmp >> 8); $tmp = (self::subWord($tmp) ^ self::$Rcon[$k]) & self::U32_MAX; } elseif ($nk > 6 && $j === 4) { $tmp = self::subWord($tmp); } $tmp ^= $skey[($i - $nk) << 1]; $skey[($i << 1)] = $tmp & self::U32_MAX; $skey[($i << 1) + 1] = $tmp & self::U32_MAX; if (++$j === $nk) { /** @psalm-suppress LoopInvalidation */ $j = 0; ++$k; } } for ($i = 0; $i < $nkf; $i += 4) { $q = ParagonIE_Sodium_Core_AES_Block::fromArray( array_slice($skey, $i << 1, 8) ); $q->orthogonalize(); // We have to overwrite $skey since we're not using C pointers like BearSSL did for ($j = 0; $j < 8; ++$j) { $skey[($i << 1) + $j] = $q[$j]; } } for ($i = 0, $j = 0; $i < $nkf; ++$i, $j += 2) { $comp_skey[$i] = ($skey[$j] & 0x55555555) | ($skey[$j + 1] & 0xAAAAAAAA); } return new ParagonIE_Sodium_Core_AES_KeySchedule($comp_skey, $num_rounds); } /** * Mutates $q * * @param ParagonIE_Sodium_Core_AES_KeySchedule $skey * @param ParagonIE_Sodium_Core_AES_Block $q * @param int $offset * @return void */ public static function addRoundKey( ParagonIE_Sodium_Core_AES_Block $q, ParagonIE_Sodium_Core_AES_KeySchedule $skey, $offset = 0 ) { $block = $skey->getRoundKey($offset); for ($j = 0; $j < 8; ++$j) { $q[$j] = ($q[$j] ^ $block[$j]) & ParagonIE_Sodium_Core_Util::U32_MAX; } } /** * This mainly exists for testing, as we need the round key features for AEGIS. * * @param string $message * @param string $key * @return string * @throws SodiumException */ public static function decryptBlockECB($message, $key) { if (self::strlen($message) !== 16) { throw new SodiumException('decryptBlockECB() expects a 16 byte message'); } $skey = self::keySchedule($key)->expand(); $q = ParagonIE_Sodium_Core_AES_Block::init(); $q[0] = self::load_4(self::substr($message, 0, 4)); $q[2] = self::load_4(self::substr($message, 4, 4)); $q[4] = self::load_4(self::substr($message, 8, 4)); $q[6] = self::load_4(self::substr($message, 12, 4)); $q->orthogonalize(); self::bitsliceDecryptBlock($skey, $q); $q->orthogonalize(); return self::store32_le($q[0]) . self::store32_le($q[2]) . self::store32_le($q[4]) . self::store32_le($q[6]); } /** * This mainly exists for testing, as we need the round key features for AEGIS. * * @param string $message * @param string $key * @return string * @throws SodiumException */ public static function encryptBlockECB($message, $key) { if (self::strlen($message) !== 16) { throw new SodiumException('encryptBlockECB() expects a 16 byte message'); } $comp_skey = self::keySchedule($key); $skey = $comp_skey->expand(); $q = ParagonIE_Sodium_Core_AES_Block::init(); $q[0] = self::load_4(self::substr($message, 0, 4)); $q[2] = self::load_4(self::substr($message, 4, 4)); $q[4] = self::load_4(self::substr($message, 8, 4)); $q[6] = self::load_4(self::substr($message, 12, 4)); $q->orthogonalize(); self::bitsliceEncryptBlock($skey, $q); $q->orthogonalize(); return self::store32_le($q[0]) . self::store32_le($q[2]) . self::store32_le($q[4]) . self::store32_le($q[6]); } /** * Mutates $q * * @param ParagonIE_Sodium_Core_AES_Expanded $skey * @param ParagonIE_Sodium_Core_AES_Block $q * @return void */ public static function bitsliceEncryptBlock( ParagonIE_Sodium_Core_AES_Expanded $skey, ParagonIE_Sodium_Core_AES_Block $q ) { self::addRoundKey($q, $skey); for ($u = 1; $u < $skey->getNumRounds(); ++$u) { self::sbox($q); $q->shiftRows(); $q->mixColumns(); self::addRoundKey($q, $skey, ($u << 3)); } self::sbox($q); $q->shiftRows(); self::addRoundKey($q, $skey, ($skey->getNumRounds() << 3)); } /** * @param string $x * @param string $y * @return string */ public static function aesRound($x, $y) { $q = ParagonIE_Sodium_Core_AES_Block::init(); $q[0] = self::load_4(self::substr($x, 0, 4)); $q[2] = self::load_4(self::substr($x, 4, 4)); $q[4] = self::load_4(self::substr($x, 8, 4)); $q[6] = self::load_4(self::substr($x, 12, 4)); $rk = ParagonIE_Sodium_Core_AES_Block::init(); $rk[0] = $rk[1] = self::load_4(self::substr($y, 0, 4)); $rk[2] = $rk[3] = self::load_4(self::substr($y, 4, 4)); $rk[4] = $rk[5] = self::load_4(self::substr($y, 8, 4)); $rk[6] = $rk[7] = self::load_4(self::substr($y, 12, 4)); $q->orthogonalize(); self::sbox($q); $q->shiftRows(); $q->mixColumns(); $q->orthogonalize(); // add round key without key schedule: for ($i = 0; $i < 8; ++$i) { $q[$i] ^= $rk[$i]; } return self::store32_le($q[0]) . self::store32_le($q[2]) . self::store32_le($q[4]) . self::store32_le($q[6]); } /** * Process two AES blocks in one shot. * * @param string $b0 First AES block * @param string $rk0 First round key * @param string $b1 Second AES block * @param string $rk1 Second round key * @return string[] */ public static function doubleRound($b0, $rk0, $b1, $rk1) { $q = ParagonIE_Sodium_Core_AES_Block::init(); // First block $q[0] = self::load_4(self::substr($b0, 0, 4)); $q[2] = self::load_4(self::substr($b0, 4, 4)); $q[4] = self::load_4(self::substr($b0, 8, 4)); $q[6] = self::load_4(self::substr($b0, 12, 4)); // Second block $q[1] = self::load_4(self::substr($b1, 0, 4)); $q[3] = self::load_4(self::substr($b1, 4, 4)); $q[5] = self::load_4(self::substr($b1, 8, 4)); $q[7] = self::load_4(self::substr($b1, 12, 4));; $rk = ParagonIE_Sodium_Core_AES_Block::init(); // First round key $rk[0] = self::load_4(self::substr($rk0, 0, 4)); $rk[2] = self::load_4(self::substr($rk0, 4, 4)); $rk[4] = self::load_4(self::substr($rk0, 8, 4)); $rk[6] = self::load_4(self::substr($rk0, 12, 4)); // Second round key $rk[1] = self::load_4(self::substr($rk1, 0, 4)); $rk[3] = self::load_4(self::substr($rk1, 4, 4)); $rk[5] = self::load_4(self::substr($rk1, 8, 4)); $rk[7] = self::load_4(self::substr($rk1, 12, 4)); $q->orthogonalize(); self::sbox($q); $q->shiftRows(); $q->mixColumns(); $q->orthogonalize(); // add round key without key schedule: for ($i = 0; $i < 8; ++$i) { $q[$i] ^= $rk[$i]; } return array( self::store32_le($q[0]) . self::store32_le($q[2]) . self::store32_le($q[4]) . self::store32_le($q[6]), self::store32_le($q[1]) . self::store32_le($q[3]) . self::store32_le($q[5]) . self::store32_le($q[7]), ); } /** * @param ParagonIE_Sodium_Core_AES_Expanded $skey * @param ParagonIE_Sodium_Core_AES_Block $q * @return void */ public static function bitsliceDecryptBlock( ParagonIE_Sodium_Core_AES_Expanded $skey, ParagonIE_Sodium_Core_AES_Block $q ) { self::addRoundKey($q, $skey, ($skey->getNumRounds() << 3)); for ($u = $skey->getNumRounds() - 1; $u > 0; --$u) { $q->inverseShiftRows(); self::invSbox($q); self::addRoundKey($q, $skey, ($u << 3)); $q->inverseMixColumns(); } $q->inverseShiftRows(); self::invSbox($q); self::addRoundKey($q, $skey, ($u << 3)); } } PK������Z{[��[����Core/XSalsa20.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_XSalsa20', false)) { return; } /** * Class ParagonIE_Sodium_Core_XSalsa20 */ abstract class ParagonIE_Sodium_Core_XSalsa20 extends ParagonIE_Sodium_Core_HSalsa20 { /** * Expand a key and nonce into an xsalsa20 keystream. * * @internal You should not use this directly from another application * * @param int $len * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function xsalsa20($len, $nonce, $key) { $ret = self::salsa20( $len, self::substr($nonce, 16, 8), self::hsalsa20($nonce, $key) ); return $ret; } /** * Encrypt a string with XSalsa20. Doesn't provide integrity. * * @internal You should not use this directly from another application * * @param string $message * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function xsalsa20_xor($message, $nonce, $key) { return self::xorStrings( $message, self::xsalsa20( self::strlen($message), $nonce, $key ) ); } } PK������Z &-�&-���Core/Curve25519.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_Curve25519', false)) { return; } /** * Class ParagonIE_Sodium_Core_Curve25519 * * Implements Curve25519 core functions * * Based on the ref10 curve25519 code provided by libsodium * * @ref https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c */ abstract class ParagonIE_Sodium_Core_Curve25519 extends ParagonIE_Sodium_Core_Curve25519_H { /** * Get a field element of size 10 with a value of 0 * * @internal You should not use this directly from another application * * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function fe_0() { return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray( array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0) ); } /** * Get a field element of size 10 with a value of 1 * * @internal You should not use this directly from another application * * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function fe_1() { return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray( array(1, 0, 0, 0, 0, 0, 0, 0, 0, 0) ); } /** * Add two field elements. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @param ParagonIE_Sodium_Core_Curve25519_Fe $g * @return ParagonIE_Sodium_Core_Curve25519_Fe * @psalm-suppress MixedAssignment * @psalm-suppress MixedOperand */ public static function fe_add( ParagonIE_Sodium_Core_Curve25519_Fe $f, ParagonIE_Sodium_Core_Curve25519_Fe $g ) { /** @var array<int, int> $arr */ $arr = array(); for ($i = 0; $i < 10; ++$i) { $arr[$i] = (int) ($f[$i] + $g[$i]); } return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($arr); } /** * Constant-time conditional move. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @param ParagonIE_Sodium_Core_Curve25519_Fe $g * @param int $b * @return ParagonIE_Sodium_Core_Curve25519_Fe * @psalm-suppress MixedAssignment */ public static function fe_cmov( ParagonIE_Sodium_Core_Curve25519_Fe $f, ParagonIE_Sodium_Core_Curve25519_Fe $g, $b = 0 ) { /** @var array<int, int> $h */ $h = array(); $b *= -1; for ($i = 0; $i < 10; ++$i) { $x = (($f[$i] ^ $g[$i]) & $b); $h[$i] = ($f[$i]) ^ $x; } return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($h); } /** * Create a copy of a field element. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function fe_copy(ParagonIE_Sodium_Core_Curve25519_Fe $f) { $h = clone $f; return $h; } /** * Give: 32-byte string. * Receive: A field element object to use for internal calculations. * * @internal You should not use this directly from another application * * @param string $s * @return ParagonIE_Sodium_Core_Curve25519_Fe * @throws RangeException * @throws TypeError */ public static function fe_frombytes($s) { if (self::strlen($s) !== 32) { throw new RangeException('Expected a 32-byte string.'); } $h0 = self::load_4($s); $h1 = self::load_3(self::substr($s, 4, 3)) << 6; $h2 = self::load_3(self::substr($s, 7, 3)) << 5; $h3 = self::load_3(self::substr($s, 10, 3)) << 3; $h4 = self::load_3(self::substr($s, 13, 3)) << 2; $h5 = self::load_4(self::substr($s, 16, 4)); $h6 = self::load_3(self::substr($s, 20, 3)) << 7; $h7 = self::load_3(self::substr($s, 23, 3)) << 5; $h8 = self::load_3(self::substr($s, 26, 3)) << 4; $h9 = (self::load_3(self::substr($s, 29, 3)) & 8388607) << 2; $carry9 = ($h9 + (1 << 24)) >> 25; $h0 += self::mul($carry9, 19, 5); $h9 -= $carry9 << 25; $carry1 = ($h1 + (1 << 24)) >> 25; $h2 += $carry1; $h1 -= $carry1 << 25; $carry3 = ($h3 + (1 << 24)) >> 25; $h4 += $carry3; $h3 -= $carry3 << 25; $carry5 = ($h5 + (1 << 24)) >> 25; $h6 += $carry5; $h5 -= $carry5 << 25; $carry7 = ($h7 + (1 << 24)) >> 25; $h8 += $carry7; $h7 -= $carry7 << 25; $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; $carry2 = ($h2 + (1 << 25)) >> 26; $h3 += $carry2; $h2 -= $carry2 << 26; $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; $carry6 = ($h6 + (1 << 25)) >> 26; $h7 += $carry6; $h6 -= $carry6 << 26; $carry8 = ($h8 + (1 << 25)) >> 26; $h9 += $carry8; $h8 -= $carry8 << 26; return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray( array( (int) $h0, (int) $h1, (int) $h2, (int) $h3, (int) $h4, (int) $h5, (int) $h6, (int) $h7, (int) $h8, (int) $h9 ) ); } /** * Convert a field element to a byte string. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $h * @return string */ public static function fe_tobytes(ParagonIE_Sodium_Core_Curve25519_Fe $h) { $h0 = (int) $h[0]; $h1 = (int) $h[1]; $h2 = (int) $h[2]; $h3 = (int) $h[3]; $h4 = (int) $h[4]; $h5 = (int) $h[5]; $h6 = (int) $h[6]; $h7 = (int) $h[7]; $h8 = (int) $h[8]; $h9 = (int) $h[9]; $q = (self::mul($h9, 19, 5) + (1 << 24)) >> 25; $q = ($h0 + $q) >> 26; $q = ($h1 + $q) >> 25; $q = ($h2 + $q) >> 26; $q = ($h3 + $q) >> 25; $q = ($h4 + $q) >> 26; $q = ($h5 + $q) >> 25; $q = ($h6 + $q) >> 26; $q = ($h7 + $q) >> 25; $q = ($h8 + $q) >> 26; $q = ($h9 + $q) >> 25; $h0 += self::mul($q, 19, 5); $carry0 = $h0 >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; $carry1 = $h1 >> 25; $h2 += $carry1; $h1 -= $carry1 << 25; $carry2 = $h2 >> 26; $h3 += $carry2; $h2 -= $carry2 << 26; $carry3 = $h3 >> 25; $h4 += $carry3; $h3 -= $carry3 << 25; $carry4 = $h4 >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; $carry5 = $h5 >> 25; $h6 += $carry5; $h5 -= $carry5 << 25; $carry6 = $h6 >> 26; $h7 += $carry6; $h6 -= $carry6 << 26; $carry7 = $h7 >> 25; $h8 += $carry7; $h7 -= $carry7 << 25; $carry8 = $h8 >> 26; $h9 += $carry8; $h8 -= $carry8 << 26; $carry9 = $h9 >> 25; $h9 -= $carry9 << 25; /** * @var array<int, int> */ $s = array( (int) (($h0 >> 0) & 0xff), (int) (($h0 >> 8) & 0xff), (int) (($h0 >> 16) & 0xff), (int) ((($h0 >> 24) | ($h1 << 2)) & 0xff), (int) (($h1 >> 6) & 0xff), (int) (($h1 >> 14) & 0xff), (int) ((($h1 >> 22) | ($h2 << 3)) & 0xff), (int) (($h2 >> 5) & 0xff), (int) (($h2 >> 13) & 0xff), (int) ((($h2 >> 21) | ($h3 << 5)) & 0xff), (int) (($h3 >> 3) & 0xff), (int) (($h3 >> 11) & 0xff), (int) ((($h3 >> 19) | ($h4 << 6)) & 0xff), (int) (($h4 >> 2) & 0xff), (int) (($h4 >> 10) & 0xff), (int) (($h4 >> 18) & 0xff), (int) (($h5 >> 0) & 0xff), (int) (($h5 >> 8) & 0xff), (int) (($h5 >> 16) & 0xff), (int) ((($h5 >> 24) | ($h6 << 1)) & 0xff), (int) (($h6 >> 7) & 0xff), (int) (($h6 >> 15) & 0xff), (int) ((($h6 >> 23) | ($h7 << 3)) & 0xff), (int) (($h7 >> 5) & 0xff), (int) (($h7 >> 13) & 0xff), (int) ((($h7 >> 21) | ($h8 << 4)) & 0xff), (int) (($h8 >> 4) & 0xff), (int) (($h8 >> 12) & 0xff), (int) ((($h8 >> 20) | ($h9 << 6)) & 0xff), (int) (($h9 >> 2) & 0xff), (int) (($h9 >> 10) & 0xff), (int) (($h9 >> 18) & 0xff) ); return self::intArrayToString($s); } /** * Is a field element negative? (1 = yes, 0 = no. Used in calculations.) * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @return int * @throws SodiumException * @throws TypeError */ public static function fe_isnegative(ParagonIE_Sodium_Core_Curve25519_Fe $f) { $str = self::fe_tobytes($f); return (int) (self::chrToInt($str[0]) & 1); } /** * Returns 0 if this field element results in all NUL bytes. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @return bool * @throws SodiumException * @throws TypeError */ public static function fe_isnonzero(ParagonIE_Sodium_Core_Curve25519_Fe $f) { static $zero; if ($zero === null) { $zero = str_repeat("\x00", 32); } /** @var string $zero */ /** @var string $str */ $str = self::fe_tobytes($f); return !self::verify_32($str, (string) $zero); } /** * Multiply two field elements * * h = f * g * * @internal You should not use this directly from another application * * @security Is multiplication a source of timing leaks? If so, can we do * anything to prevent that from happening? * * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @param ParagonIE_Sodium_Core_Curve25519_Fe $g * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function fe_mul( ParagonIE_Sodium_Core_Curve25519_Fe $f, ParagonIE_Sodium_Core_Curve25519_Fe $g ) { // Ensure limbs aren't oversized. $f = self::fe_normalize($f); $g = self::fe_normalize($g); $f0 = $f[0]; $f1 = $f[1]; $f2 = $f[2]; $f3 = $f[3]; $f4 = $f[4]; $f5 = $f[5]; $f6 = $f[6]; $f7 = $f[7]; $f8 = $f[8]; $f9 = $f[9]; $g0 = $g[0]; $g1 = $g[1]; $g2 = $g[2]; $g3 = $g[3]; $g4 = $g[4]; $g5 = $g[5]; $g6 = $g[6]; $g7 = $g[7]; $g8 = $g[8]; $g9 = $g[9]; $g1_19 = self::mul($g1, 19, 5); $g2_19 = self::mul($g2, 19, 5); $g3_19 = self::mul($g3, 19, 5); $g4_19 = self::mul($g4, 19, 5); $g5_19 = self::mul($g5, 19, 5); $g6_19 = self::mul($g6, 19, 5); $g7_19 = self::mul($g7, 19, 5); $g8_19 = self::mul($g8, 19, 5); $g9_19 = self::mul($g9, 19, 5); $f1_2 = $f1 << 1; $f3_2 = $f3 << 1; $f5_2 = $f5 << 1; $f7_2 = $f7 << 1; $f9_2 = $f9 << 1; $f0g0 = self::mul($f0, $g0, 26); $f0g1 = self::mul($f0, $g1, 25); $f0g2 = self::mul($f0, $g2, 26); $f0g3 = self::mul($f0, $g3, 25); $f0g4 = self::mul($f0, $g4, 26); $f0g5 = self::mul($f0, $g5, 25); $f0g6 = self::mul($f0, $g6, 26); $f0g7 = self::mul($f0, $g7, 25); $f0g8 = self::mul($f0, $g8, 26); $f0g9 = self::mul($f0, $g9, 26); $f1g0 = self::mul($f1, $g0, 26); $f1g1_2 = self::mul($f1_2, $g1, 25); $f1g2 = self::mul($f1, $g2, 26); $f1g3_2 = self::mul($f1_2, $g3, 25); $f1g4 = self::mul($f1, $g4, 26); $f1g5_2 = self::mul($f1_2, $g5, 25); $f1g6 = self::mul($f1, $g6, 26); $f1g7_2 = self::mul($f1_2, $g7, 25); $f1g8 = self::mul($f1, $g8, 26); $f1g9_38 = self::mul($g9_19, $f1_2, 26); $f2g0 = self::mul($f2, $g0, 26); $f2g1 = self::mul($f2, $g1, 25); $f2g2 = self::mul($f2, $g2, 26); $f2g3 = self::mul($f2, $g3, 25); $f2g4 = self::mul($f2, $g4, 26); $f2g5 = self::mul($f2, $g5, 25); $f2g6 = self::mul($f2, $g6, 26); $f2g7 = self::mul($f2, $g7, 25); $f2g8_19 = self::mul($g8_19, $f2, 26); $f2g9_19 = self::mul($g9_19, $f2, 26); $f3g0 = self::mul($f3, $g0, 26); $f3g1_2 = self::mul($f3_2, $g1, 25); $f3g2 = self::mul($f3, $g2, 26); $f3g3_2 = self::mul($f3_2, $g3, 25); $f3g4 = self::mul($f3, $g4, 26); $f3g5_2 = self::mul($f3_2, $g5, 25); $f3g6 = self::mul($f3, $g6, 26); $f3g7_38 = self::mul($g7_19, $f3_2, 26); $f3g8_19 = self::mul($g8_19, $f3, 25); $f3g9_38 = self::mul($g9_19, $f3_2, 26); $f4g0 = self::mul($f4, $g0, 26); $f4g1 = self::mul($f4, $g1, 25); $f4g2 = self::mul($f4, $g2, 26); $f4g3 = self::mul($f4, $g3, 25); $f4g4 = self::mul($f4, $g4, 26); $f4g5 = self::mul($f4, $g5, 25); $f4g6_19 = self::mul($g6_19, $f4, 26); $f4g7_19 = self::mul($g7_19, $f4, 26); $f4g8_19 = self::mul($g8_19, $f4, 26); $f4g9_19 = self::mul($g9_19, $f4, 26); $f5g0 = self::mul($f5, $g0, 26); $f5g1_2 = self::mul($f5_2, $g1, 25); $f5g2 = self::mul($f5, $g2, 26); $f5g3_2 = self::mul($f5_2, $g3, 25); $f5g4 = self::mul($f5, $g4, 26); $f5g5_38 = self::mul($g5_19, $f5_2, 26); $f5g6_19 = self::mul($g6_19, $f5, 25); $f5g7_38 = self::mul($g7_19, $f5_2, 26); $f5g8_19 = self::mul($g8_19, $f5, 25); $f5g9_38 = self::mul($g9_19, $f5_2, 26); $f6g0 = self::mul($f6, $g0, 26); $f6g1 = self::mul($f6, $g1, 25); $f6g2 = self::mul($f6, $g2, 26); $f6g3 = self::mul($f6, $g3, 25); $f6g4_19 = self::mul($g4_19, $f6, 26); $f6g5_19 = self::mul($g5_19, $f6, 26); $f6g6_19 = self::mul($g6_19, $f6, 26); $f6g7_19 = self::mul($g7_19, $f6, 26); $f6g8_19 = self::mul($g8_19, $f6, 26); $f6g9_19 = self::mul($g9_19, $f6, 26); $f7g0 = self::mul($f7, $g0, 26); $f7g1_2 = self::mul($f7_2, $g1, 25); $f7g2 = self::mul($f7, $g2, 26); $f7g3_38 = self::mul($g3_19, $f7_2, 26); $f7g4_19 = self::mul($g4_19, $f7, 26); $f7g5_38 = self::mul($g5_19, $f7_2, 26); $f7g6_19 = self::mul($g6_19, $f7, 25); $f7g7_38 = self::mul($g7_19, $f7_2, 26); $f7g8_19 = self::mul($g8_19, $f7, 25); $f7g9_38 = self::mul($g9_19,$f7_2, 26); $f8g0 = self::mul($f8, $g0, 26); $f8g1 = self::mul($f8, $g1, 25); $f8g2_19 = self::mul($g2_19, $f8, 26); $f8g3_19 = self::mul($g3_19, $f8, 26); $f8g4_19 = self::mul($g4_19, $f8, 26); $f8g5_19 = self::mul($g5_19, $f8, 26); $f8g6_19 = self::mul($g6_19, $f8, 26); $f8g7_19 = self::mul($g7_19, $f8, 26); $f8g8_19 = self::mul($g8_19, $f8, 26); $f8g9_19 = self::mul($g9_19, $f8, 26); $f9g0 = self::mul($f9, $g0, 26); $f9g1_38 = self::mul($g1_19, $f9_2, 26); $f9g2_19 = self::mul($g2_19, $f9, 25); $f9g3_38 = self::mul($g3_19, $f9_2, 26); $f9g4_19 = self::mul($g4_19, $f9, 25); $f9g5_38 = self::mul($g5_19, $f9_2, 26); $f9g6_19 = self::mul($g6_19, $f9, 25); $f9g7_38 = self::mul($g7_19, $f9_2, 26); $f9g8_19 = self::mul($g8_19, $f9, 25); $f9g9_38 = self::mul($g9_19, $f9_2, 26); $h0 = $f0g0 + $f1g9_38 + $f2g8_19 + $f3g7_38 + $f4g6_19 + $f5g5_38 + $f6g4_19 + $f7g3_38 + $f8g2_19 + $f9g1_38; $h1 = $f0g1 + $f1g0 + $f2g9_19 + $f3g8_19 + $f4g7_19 + $f5g6_19 + $f6g5_19 + $f7g4_19 + $f8g3_19 + $f9g2_19; $h2 = $f0g2 + $f1g1_2 + $f2g0 + $f3g9_38 + $f4g8_19 + $f5g7_38 + $f6g6_19 + $f7g5_38 + $f8g4_19 + $f9g3_38; $h3 = $f0g3 + $f1g2 + $f2g1 + $f3g0 + $f4g9_19 + $f5g8_19 + $f6g7_19 + $f7g6_19 + $f8g5_19 + $f9g4_19; $h4 = $f0g4 + $f1g3_2 + $f2g2 + $f3g1_2 + $f4g0 + $f5g9_38 + $f6g8_19 + $f7g7_38 + $f8g6_19 + $f9g5_38; $h5 = $f0g5 + $f1g4 + $f2g3 + $f3g2 + $f4g1 + $f5g0 + $f6g9_19 + $f7g8_19 + $f8g7_19 + $f9g6_19; $h6 = $f0g6 + $f1g5_2 + $f2g4 + $f3g3_2 + $f4g2 + $f5g1_2 + $f6g0 + $f7g9_38 + $f8g8_19 + $f9g7_38; $h7 = $f0g7 + $f1g6 + $f2g5 + $f3g4 + $f4g3 + $f5g2 + $f6g1 + $f7g0 + $f8g9_19 + $f9g8_19; $h8 = $f0g8 + $f1g7_2 + $f2g6 + $f3g5_2 + $f4g4 + $f5g3_2 + $f6g2 + $f7g1_2 + $f8g0 + $f9g9_38; $h9 = $f0g9 + $f1g8 + $f2g7 + $f3g6 + $f4g5 + $f5g4 + $f6g3 + $f7g2 + $f8g1 + $f9g0 ; $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; $carry1 = ($h1 + (1 << 24)) >> 25; $h2 += $carry1; $h1 -= $carry1 << 25; $carry5 = ($h5 + (1 << 24)) >> 25; $h6 += $carry5; $h5 -= $carry5 << 25; $carry2 = ($h2 + (1 << 25)) >> 26; $h3 += $carry2; $h2 -= $carry2 << 26; $carry6 = ($h6 + (1 << 25)) >> 26; $h7 += $carry6; $h6 -= $carry6 << 26; $carry3 = ($h3 + (1 << 24)) >> 25; $h4 += $carry3; $h3 -= $carry3 << 25; $carry7 = ($h7 + (1 << 24)) >> 25; $h8 += $carry7; $h7 -= $carry7 << 25; $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; $carry8 = ($h8 + (1 << 25)) >> 26; $h9 += $carry8; $h8 -= $carry8 << 26; $carry9 = ($h9 + (1 << 24)) >> 25; $h0 += self::mul($carry9, 19, 5); $h9 -= $carry9 << 25; $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; return self::fe_normalize( ParagonIE_Sodium_Core_Curve25519_Fe::fromArray( array( (int) $h0, (int) $h1, (int) $h2, (int) $h3, (int) $h4, (int) $h5, (int) $h6, (int) $h7, (int) $h8, (int) $h9 ) ) ); } /** * Get the negative values for each piece of the field element. * * h = -f * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @return ParagonIE_Sodium_Core_Curve25519_Fe * @psalm-suppress MixedAssignment */ public static function fe_neg(ParagonIE_Sodium_Core_Curve25519_Fe $f) { $h = new ParagonIE_Sodium_Core_Curve25519_Fe(); for ($i = 0; $i < 10; ++$i) { $h[$i] = -$f[$i]; } return self::fe_normalize($h); } /** * Square a field element * * h = f * f * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function fe_sq(ParagonIE_Sodium_Core_Curve25519_Fe $f) { $f = self::fe_normalize($f); $f0 = (int) $f[0]; $f1 = (int) $f[1]; $f2 = (int) $f[2]; $f3 = (int) $f[3]; $f4 = (int) $f[4]; $f5 = (int) $f[5]; $f6 = (int) $f[6]; $f7 = (int) $f[7]; $f8 = (int) $f[8]; $f9 = (int) $f[9]; $f0_2 = $f0 << 1; $f1_2 = $f1 << 1; $f2_2 = $f2 << 1; $f3_2 = $f3 << 1; $f4_2 = $f4 << 1; $f5_2 = $f5 << 1; $f6_2 = $f6 << 1; $f7_2 = $f7 << 1; $f5_38 = self::mul($f5, 38, 6); $f6_19 = self::mul($f6, 19, 5); $f7_38 = self::mul($f7, 38, 6); $f8_19 = self::mul($f8, 19, 5); $f9_38 = self::mul($f9, 38, 6); $f0f0 = self::mul($f0, $f0, 26); $f0f1_2 = self::mul($f0_2, $f1, 26); $f0f2_2 = self::mul($f0_2, $f2, 26); $f0f3_2 = self::mul($f0_2, $f3, 26); $f0f4_2 = self::mul($f0_2, $f4, 26); $f0f5_2 = self::mul($f0_2, $f5, 26); $f0f6_2 = self::mul($f0_2, $f6, 26); $f0f7_2 = self::mul($f0_2, $f7, 26); $f0f8_2 = self::mul($f0_2, $f8, 26); $f0f9_2 = self::mul($f0_2, $f9, 26); $f1f1_2 = self::mul($f1_2, $f1, 26); $f1f2_2 = self::mul($f1_2, $f2, 26); $f1f3_4 = self::mul($f1_2, $f3_2, 26); $f1f4_2 = self::mul($f1_2, $f4, 26); $f1f5_4 = self::mul($f1_2, $f5_2, 26); $f1f6_2 = self::mul($f1_2, $f6, 26); $f1f7_4 = self::mul($f1_2, $f7_2, 26); $f1f8_2 = self::mul($f1_2, $f8, 26); $f1f9_76 = self::mul($f9_38, $f1_2, 27); $f2f2 = self::mul($f2, $f2, 27); $f2f3_2 = self::mul($f2_2, $f3, 27); $f2f4_2 = self::mul($f2_2, $f4, 27); $f2f5_2 = self::mul($f2_2, $f5, 27); $f2f6_2 = self::mul($f2_2, $f6, 27); $f2f7_2 = self::mul($f2_2, $f7, 27); $f2f8_38 = self::mul($f8_19, $f2_2, 27); $f2f9_38 = self::mul($f9_38, $f2, 26); $f3f3_2 = self::mul($f3_2, $f3, 26); $f3f4_2 = self::mul($f3_2, $f4, 26); $f3f5_4 = self::mul($f3_2, $f5_2, 26); $f3f6_2 = self::mul($f3_2, $f6, 26); $f3f7_76 = self::mul($f7_38, $f3_2, 26); $f3f8_38 = self::mul($f8_19, $f3_2, 26); $f3f9_76 = self::mul($f9_38, $f3_2, 26); $f4f4 = self::mul($f4, $f4, 26); $f4f5_2 = self::mul($f4_2, $f5, 26); $f4f6_38 = self::mul($f6_19, $f4_2, 27); $f4f7_38 = self::mul($f7_38, $f4, 26); $f4f8_38 = self::mul($f8_19, $f4_2, 27); $f4f9_38 = self::mul($f9_38, $f4, 26); $f5f5_38 = self::mul($f5_38, $f5, 26); $f5f6_38 = self::mul($f6_19, $f5_2, 26); $f5f7_76 = self::mul($f7_38, $f5_2, 26); $f5f8_38 = self::mul($f8_19, $f5_2, 26); $f5f9_76 = self::mul($f9_38, $f5_2, 26); $f6f6_19 = self::mul($f6_19, $f6, 26); $f6f7_38 = self::mul($f7_38, $f6, 26); $f6f8_38 = self::mul($f8_19, $f6_2, 27); $f6f9_38 = self::mul($f9_38, $f6, 26); $f7f7_38 = self::mul($f7_38, $f7, 26); $f7f8_38 = self::mul($f8_19, $f7_2, 26); $f7f9_76 = self::mul($f9_38, $f7_2, 26); $f8f8_19 = self::mul($f8_19, $f8, 26); $f8f9_38 = self::mul($f9_38, $f8, 26); $f9f9_38 = self::mul($f9_38, $f9, 26); $h0 = $f0f0 + $f1f9_76 + $f2f8_38 + $f3f7_76 + $f4f6_38 + $f5f5_38; $h1 = $f0f1_2 + $f2f9_38 + $f3f8_38 + $f4f7_38 + $f5f6_38; $h2 = $f0f2_2 + $f1f1_2 + $f3f9_76 + $f4f8_38 + $f5f7_76 + $f6f6_19; $h3 = $f0f3_2 + $f1f2_2 + $f4f9_38 + $f5f8_38 + $f6f7_38; $h4 = $f0f4_2 + $f1f3_4 + $f2f2 + $f5f9_76 + $f6f8_38 + $f7f7_38; $h5 = $f0f5_2 + $f1f4_2 + $f2f3_2 + $f6f9_38 + $f7f8_38; $h6 = $f0f6_2 + $f1f5_4 + $f2f4_2 + $f3f3_2 + $f7f9_76 + $f8f8_19; $h7 = $f0f7_2 + $f1f6_2 + $f2f5_2 + $f3f4_2 + $f8f9_38; $h8 = $f0f8_2 + $f1f7_4 + $f2f6_2 + $f3f5_4 + $f4f4 + $f9f9_38; $h9 = $f0f9_2 + $f1f8_2 + $f2f7_2 + $f3f6_2 + $f4f5_2; $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; $carry1 = ($h1 + (1 << 24)) >> 25; $h2 += $carry1; $h1 -= $carry1 << 25; $carry5 = ($h5 + (1 << 24)) >> 25; $h6 += $carry5; $h5 -= $carry5 << 25; $carry2 = ($h2 + (1 << 25)) >> 26; $h3 += $carry2; $h2 -= $carry2 << 26; $carry6 = ($h6 + (1 << 25)) >> 26; $h7 += $carry6; $h6 -= $carry6 << 26; $carry3 = ($h3 + (1 << 24)) >> 25; $h4 += $carry3; $h3 -= $carry3 << 25; $carry7 = ($h7 + (1 << 24)) >> 25; $h8 += $carry7; $h7 -= $carry7 << 25; $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; $carry8 = ($h8 + (1 << 25)) >> 26; $h9 += $carry8; $h8 -= $carry8 << 26; $carry9 = ($h9 + (1 << 24)) >> 25; $h0 += self::mul($carry9, 19, 5); $h9 -= $carry9 << 25; $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; return self::fe_normalize( ParagonIE_Sodium_Core_Curve25519_Fe::fromArray( array( (int) $h0, (int) $h1, (int) $h2, (int) $h3, (int) $h4, (int) $h5, (int) $h6, (int) $h7, (int) $h8, (int) $h9 ) ) ); } /** * Square and double a field element * * h = 2 * f * f * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function fe_sq2(ParagonIE_Sodium_Core_Curve25519_Fe $f) { $f = self::fe_normalize($f); $f0 = (int) $f[0]; $f1 = (int) $f[1]; $f2 = (int) $f[2]; $f3 = (int) $f[3]; $f4 = (int) $f[4]; $f5 = (int) $f[5]; $f6 = (int) $f[6]; $f7 = (int) $f[7]; $f8 = (int) $f[8]; $f9 = (int) $f[9]; $f0_2 = $f0 << 1; $f1_2 = $f1 << 1; $f2_2 = $f2 << 1; $f3_2 = $f3 << 1; $f4_2 = $f4 << 1; $f5_2 = $f5 << 1; $f6_2 = $f6 << 1; $f7_2 = $f7 << 1; $f5_38 = self::mul($f5, 38, 6); /* 1.959375*2^30 */ $f6_19 = self::mul($f6, 19, 5); /* 1.959375*2^30 */ $f7_38 = self::mul($f7, 38, 6); /* 1.959375*2^30 */ $f8_19 = self::mul($f8, 19, 5); /* 1.959375*2^30 */ $f9_38 = self::mul($f9, 38, 6); /* 1.959375*2^30 */ $f0f0 = self::mul($f0, $f0, 24); $f0f1_2 = self::mul($f0_2, $f1, 24); $f0f2_2 = self::mul($f0_2, $f2, 24); $f0f3_2 = self::mul($f0_2, $f3, 24); $f0f4_2 = self::mul($f0_2, $f4, 24); $f0f5_2 = self::mul($f0_2, $f5, 24); $f0f6_2 = self::mul($f0_2, $f6, 24); $f0f7_2 = self::mul($f0_2, $f7, 24); $f0f8_2 = self::mul($f0_2, $f8, 24); $f0f9_2 = self::mul($f0_2, $f9, 24); $f1f1_2 = self::mul($f1_2, $f1, 24); $f1f2_2 = self::mul($f1_2, $f2, 24); $f1f3_4 = self::mul($f1_2, $f3_2, 24); $f1f4_2 = self::mul($f1_2, $f4, 24); $f1f5_4 = self::mul($f1_2, $f5_2, 24); $f1f6_2 = self::mul($f1_2, $f6, 24); $f1f7_4 = self::mul($f1_2, $f7_2, 24); $f1f8_2 = self::mul($f1_2, $f8, 24); $f1f9_76 = self::mul($f9_38, $f1_2, 24); $f2f2 = self::mul($f2, $f2, 24); $f2f3_2 = self::mul($f2_2, $f3, 24); $f2f4_2 = self::mul($f2_2, $f4, 24); $f2f5_2 = self::mul($f2_2, $f5, 24); $f2f6_2 = self::mul($f2_2, $f6, 24); $f2f7_2 = self::mul($f2_2, $f7, 24); $f2f8_38 = self::mul($f8_19, $f2_2, 25); $f2f9_38 = self::mul($f9_38, $f2, 24); $f3f3_2 = self::mul($f3_2, $f3, 24); $f3f4_2 = self::mul($f3_2, $f4, 24); $f3f5_4 = self::mul($f3_2, $f5_2, 24); $f3f6_2 = self::mul($f3_2, $f6, 24); $f3f7_76 = self::mul($f7_38, $f3_2, 24); $f3f8_38 = self::mul($f8_19, $f3_2, 24); $f3f9_76 = self::mul($f9_38, $f3_2, 24); $f4f4 = self::mul($f4, $f4, 24); $f4f5_2 = self::mul($f4_2, $f5, 24); $f4f6_38 = self::mul($f6_19, $f4_2, 25); $f4f7_38 = self::mul($f7_38, $f4, 24); $f4f8_38 = self::mul($f8_19, $f4_2, 25); $f4f9_38 = self::mul($f9_38, $f4, 24); $f5f5_38 = self::mul($f5_38, $f5, 24); $f5f6_38 = self::mul($f6_19, $f5_2, 24); $f5f7_76 = self::mul($f7_38, $f5_2, 24); $f5f8_38 = self::mul($f8_19, $f5_2, 24); $f5f9_76 = self::mul($f9_38, $f5_2, 24); $f6f6_19 = self::mul($f6_19, $f6, 24); $f6f7_38 = self::mul($f7_38, $f6, 24); $f6f8_38 = self::mul($f8_19, $f6_2, 25); $f6f9_38 = self::mul($f9_38, $f6, 24); $f7f7_38 = self::mul($f7_38, $f7, 24); $f7f8_38 = self::mul($f8_19, $f7_2, 24); $f7f9_76 = self::mul($f9_38, $f7_2, 24); $f8f8_19 = self::mul($f8_19, $f8, 24); $f8f9_38 = self::mul($f9_38, $f8, 24); $f9f9_38 = self::mul($f9_38, $f9, 24); $h0 = (int) ($f0f0 + $f1f9_76 + $f2f8_38 + $f3f7_76 + $f4f6_38 + $f5f5_38) << 1; $h1 = (int) ($f0f1_2 + $f2f9_38 + $f3f8_38 + $f4f7_38 + $f5f6_38) << 1; $h2 = (int) ($f0f2_2 + $f1f1_2 + $f3f9_76 + $f4f8_38 + $f5f7_76 + $f6f6_19) << 1; $h3 = (int) ($f0f3_2 + $f1f2_2 + $f4f9_38 + $f5f8_38 + $f6f7_38) << 1; $h4 = (int) ($f0f4_2 + $f1f3_4 + $f2f2 + $f5f9_76 + $f6f8_38 + $f7f7_38) << 1; $h5 = (int) ($f0f5_2 + $f1f4_2 + $f2f3_2 + $f6f9_38 + $f7f8_38) << 1; $h6 = (int) ($f0f6_2 + $f1f5_4 + $f2f4_2 + $f3f3_2 + $f7f9_76 + $f8f8_19) << 1; $h7 = (int) ($f0f7_2 + $f1f6_2 + $f2f5_2 + $f3f4_2 + $f8f9_38) << 1; $h8 = (int) ($f0f8_2 + $f1f7_4 + $f2f6_2 + $f3f5_4 + $f4f4 + $f9f9_38) << 1; $h9 = (int) ($f0f9_2 + $f1f8_2 + $f2f7_2 + $f3f6_2 + $f4f5_2) << 1; $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; $carry1 = ($h1 + (1 << 24)) >> 25; $h2 += $carry1; $h1 -= $carry1 << 25; $carry5 = ($h5 + (1 << 24)) >> 25; $h6 += $carry5; $h5 -= $carry5 << 25; $carry2 = ($h2 + (1 << 25)) >> 26; $h3 += $carry2; $h2 -= $carry2 << 26; $carry6 = ($h6 + (1 << 25)) >> 26; $h7 += $carry6; $h6 -= $carry6 << 26; $carry3 = ($h3 + (1 << 24)) >> 25; $h4 += $carry3; $h3 -= $carry3 << 25; $carry7 = ($h7 + (1 << 24)) >> 25; $h8 += $carry7; $h7 -= $carry7 << 25; $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; $carry8 = ($h8 + (1 << 25)) >> 26; $h9 += $carry8; $h8 -= $carry8 << 26; $carry9 = ($h9 + (1 << 24)) >> 25; $h0 += self::mul($carry9, 19, 5); $h9 -= $carry9 << 25; $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; return self::fe_normalize( ParagonIE_Sodium_Core_Curve25519_Fe::fromArray( array( (int) $h0, (int) $h1, (int) $h2, (int) $h3, (int) $h4, (int) $h5, (int) $h6, (int) $h7, (int) $h8, (int) $h9 ) ) ); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $Z * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function fe_invert(ParagonIE_Sodium_Core_Curve25519_Fe $Z) { $z = clone $Z; $t0 = self::fe_sq($z); $t1 = self::fe_sq($t0); $t1 = self::fe_sq($t1); $t1 = self::fe_mul($z, $t1); $t0 = self::fe_mul($t0, $t1); $t2 = self::fe_sq($t0); $t1 = self::fe_mul($t1, $t2); $t2 = self::fe_sq($t1); for ($i = 1; $i < 5; ++$i) { $t2 = self::fe_sq($t2); } $t1 = self::fe_mul($t2, $t1); $t2 = self::fe_sq($t1); for ($i = 1; $i < 10; ++$i) { $t2 = self::fe_sq($t2); } $t2 = self::fe_mul($t2, $t1); $t3 = self::fe_sq($t2); for ($i = 1; $i < 20; ++$i) { $t3 = self::fe_sq($t3); } $t2 = self::fe_mul($t3, $t2); $t2 = self::fe_sq($t2); for ($i = 1; $i < 10; ++$i) { $t2 = self::fe_sq($t2); } $t1 = self::fe_mul($t2, $t1); $t2 = self::fe_sq($t1); for ($i = 1; $i < 50; ++$i) { $t2 = self::fe_sq($t2); } $t2 = self::fe_mul($t2, $t1); $t3 = self::fe_sq($t2); for ($i = 1; $i < 100; ++$i) { $t3 = self::fe_sq($t3); } $t2 = self::fe_mul($t3, $t2); $t2 = self::fe_sq($t2); for ($i = 1; $i < 50; ++$i) { $t2 = self::fe_sq($t2); } $t1 = self::fe_mul($t2, $t1); $t1 = self::fe_sq($t1); for ($i = 1; $i < 5; ++$i) { $t1 = self::fe_sq($t1); } return self::fe_mul($t1, $t0); } /** * @internal You should not use this directly from another application * * @ref https://github.com/jedisct1/libsodium/blob/68564326e1e9dc57ef03746f85734232d20ca6fb/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1054-L1106 * * @param ParagonIE_Sodium_Core_Curve25519_Fe $z * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function fe_pow22523(ParagonIE_Sodium_Core_Curve25519_Fe $z) { $z = self::fe_normalize($z); # fe_sq(t0, z); # fe_sq(t1, t0); # fe_sq(t1, t1); # fe_mul(t1, z, t1); # fe_mul(t0, t0, t1); # fe_sq(t0, t0); # fe_mul(t0, t1, t0); # fe_sq(t1, t0); $t0 = self::fe_sq($z); $t1 = self::fe_sq($t0); $t1 = self::fe_sq($t1); $t1 = self::fe_mul($z, $t1); $t0 = self::fe_mul($t0, $t1); $t0 = self::fe_sq($t0); $t0 = self::fe_mul($t1, $t0); $t1 = self::fe_sq($t0); # for (i = 1; i < 5; ++i) { # fe_sq(t1, t1); # } for ($i = 1; $i < 5; ++$i) { $t1 = self::fe_sq($t1); } # fe_mul(t0, t1, t0); # fe_sq(t1, t0); $t0 = self::fe_mul($t1, $t0); $t1 = self::fe_sq($t0); # for (i = 1; i < 10; ++i) { # fe_sq(t1, t1); # } for ($i = 1; $i < 10; ++$i) { $t1 = self::fe_sq($t1); } # fe_mul(t1, t1, t0); # fe_sq(t2, t1); $t1 = self::fe_mul($t1, $t0); $t2 = self::fe_sq($t1); # for (i = 1; i < 20; ++i) { # fe_sq(t2, t2); # } for ($i = 1; $i < 20; ++$i) { $t2 = self::fe_sq($t2); } # fe_mul(t1, t2, t1); # fe_sq(t1, t1); $t1 = self::fe_mul($t2, $t1); $t1 = self::fe_sq($t1); # for (i = 1; i < 10; ++i) { # fe_sq(t1, t1); # } for ($i = 1; $i < 10; ++$i) { $t1 = self::fe_sq($t1); } # fe_mul(t0, t1, t0); # fe_sq(t1, t0); $t0 = self::fe_mul($t1, $t0); $t1 = self::fe_sq($t0); # for (i = 1; i < 50; ++i) { # fe_sq(t1, t1); # } for ($i = 1; $i < 50; ++$i) { $t1 = self::fe_sq($t1); } # fe_mul(t1, t1, t0); # fe_sq(t2, t1); $t1 = self::fe_mul($t1, $t0); $t2 = self::fe_sq($t1); # for (i = 1; i < 100; ++i) { # fe_sq(t2, t2); # } for ($i = 1; $i < 100; ++$i) { $t2 = self::fe_sq($t2); } # fe_mul(t1, t2, t1); # fe_sq(t1, t1); $t1 = self::fe_mul($t2, $t1); $t1 = self::fe_sq($t1); # for (i = 1; i < 50; ++i) { # fe_sq(t1, t1); # } for ($i = 1; $i < 50; ++$i) { $t1 = self::fe_sq($t1); } # fe_mul(t0, t1, t0); # fe_sq(t0, t0); # fe_sq(t0, t0); # fe_mul(out, t0, z); $t0 = self::fe_mul($t1, $t0); $t0 = self::fe_sq($t0); $t0 = self::fe_sq($t0); return self::fe_mul($t0, $z); } /** * Subtract two field elements. * * h = f - g * * Preconditions: * |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. * |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. * * Postconditions: * |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @param ParagonIE_Sodium_Core_Curve25519_Fe $g * @return ParagonIE_Sodium_Core_Curve25519_Fe * @psalm-suppress MixedOperand */ public static function fe_sub(ParagonIE_Sodium_Core_Curve25519_Fe $f, ParagonIE_Sodium_Core_Curve25519_Fe $g) { return self::fe_normalize( ParagonIE_Sodium_Core_Curve25519_Fe::fromArray( array( (int) ($f[0] - $g[0]), (int) ($f[1] - $g[1]), (int) ($f[2] - $g[2]), (int) ($f[3] - $g[3]), (int) ($f[4] - $g[4]), (int) ($f[5] - $g[5]), (int) ($f[6] - $g[6]), (int) ($f[7] - $g[7]), (int) ($f[8] - $g[8]), (int) ($f[9] - $g[9]) ) ) ); } /** * Add two group elements. * * r = p + q * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 */ public static function ge_add( ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p, ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q ) { $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1(); $r->X = self::fe_add($p->Y, $p->X); $r->Y = self::fe_sub($p->Y, $p->X); $r->Z = self::fe_mul($r->X, $q->YplusX); $r->Y = self::fe_mul($r->Y, $q->YminusX); $r->T = self::fe_mul($q->T2d, $p->T); $r->X = self::fe_mul($p->Z, $q->Z); $t0 = self::fe_add($r->X, $r->X); $r->X = self::fe_sub($r->Z, $r->Y); $r->Y = self::fe_add($r->Z, $r->Y); $r->Z = self::fe_add($t0, $r->T); $r->T = self::fe_sub($t0, $r->T); return $r; } /** * @internal You should not use this directly from another application * * @ref https://github.com/jedisct1/libsodium/blob/157c4a80c13b117608aeae12178b2d38825f9f8f/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1185-L1215 * @param string $a * @return array<int, mixed> * @throws SodiumException * @throws TypeError */ public static function slide($a) { if (self::strlen($a) < 256) { if (self::strlen($a) < 16) { $a = str_pad($a, 256, '0', STR_PAD_RIGHT); } } /** @var array<int, int> $r */ $r = array(); /** @var int $i */ for ($i = 0; $i < 256; ++$i) { $r[$i] = (int) ( 1 & ( self::chrToInt($a[(int) ($i >> 3)]) >> ($i & 7) ) ); } for ($i = 0;$i < 256;++$i) { if ($r[$i]) { for ($b = 1;$b <= 6 && $i + $b < 256;++$b) { if ($r[$i + $b]) { if ($r[$i] + ($r[$i + $b] << $b) <= 15) { $r[$i] += $r[$i + $b] << $b; $r[$i + $b] = 0; } elseif ($r[$i] - ($r[$i + $b] << $b) >= -15) { $r[$i] -= $r[$i + $b] << $b; for ($k = $i + $b; $k < 256; ++$k) { if (!$r[$k]) { $r[$k] = 1; break; } $r[$k] = 0; } } else { break; } } } } } return $r; } /** * @internal You should not use this directly from another application * * @param string $s * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 * @throws SodiumException * @throws TypeError */ public static function ge_frombytes_negate_vartime($s) { static $d = null; if (!$d) { $d = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d); } # fe_frombytes(h->Y,s); # fe_1(h->Z); $h = new ParagonIE_Sodium_Core_Curve25519_Ge_P3( self::fe_0(), self::fe_frombytes($s), self::fe_1() ); # fe_sq(u,h->Y); # fe_mul(v,u,d); # fe_sub(u,u,h->Z); /* u = y^2-1 */ # fe_add(v,v,h->Z); /* v = dy^2+1 */ $u = self::fe_sq($h->Y); /** @var ParagonIE_Sodium_Core_Curve25519_Fe $d */ $v = self::fe_mul($u, $d); $u = self::fe_sub($u, $h->Z); /* u = y^2 - 1 */ $v = self::fe_add($v, $h->Z); /* v = dy^2 + 1 */ # fe_sq(v3,v); # fe_mul(v3,v3,v); /* v3 = v^3 */ # fe_sq(h->X,v3); # fe_mul(h->X,h->X,v); # fe_mul(h->X,h->X,u); /* x = uv^7 */ $v3 = self::fe_sq($v); $v3 = self::fe_mul($v3, $v); /* v3 = v^3 */ $h->X = self::fe_sq($v3); $h->X = self::fe_mul($h->X, $v); $h->X = self::fe_mul($h->X, $u); /* x = uv^7 */ # fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */ # fe_mul(h->X,h->X,v3); # fe_mul(h->X,h->X,u); /* x = uv^3(uv^7)^((q-5)/8) */ $h->X = self::fe_pow22523($h->X); /* x = (uv^7)^((q-5)/8) */ $h->X = self::fe_mul($h->X, $v3); $h->X = self::fe_mul($h->X, $u); /* x = uv^3(uv^7)^((q-5)/8) */ # fe_sq(vxx,h->X); # fe_mul(vxx,vxx,v); # fe_sub(check,vxx,u); /* vx^2-u */ $vxx = self::fe_sq($h->X); $vxx = self::fe_mul($vxx, $v); $check = self::fe_sub($vxx, $u); /* vx^2 - u */ # if (fe_isnonzero(check)) { # fe_add(check,vxx,u); /* vx^2+u */ # if (fe_isnonzero(check)) { # return -1; # } # fe_mul(h->X,h->X,sqrtm1); # } if (self::fe_isnonzero($check)) { $check = self::fe_add($vxx, $u); /* vx^2 + u */ if (self::fe_isnonzero($check)) { throw new RangeException('Internal check failed.'); } $h->X = self::fe_mul( $h->X, ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1) ); } # if (fe_isnegative(h->X) == (s[31] >> 7)) { # fe_neg(h->X,h->X); # } $i = self::chrToInt($s[31]); if (self::fe_isnegative($h->X) === ($i >> 7)) { $h->X = self::fe_neg($h->X); } # fe_mul(h->T,h->X,h->Y); $h->T = self::fe_mul($h->X, $h->Y); return $h; } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 */ public static function ge_madd( ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R, ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p, ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q ) { $r = clone $R; $r->X = self::fe_add($p->Y, $p->X); $r->Y = self::fe_sub($p->Y, $p->X); $r->Z = self::fe_mul($r->X, $q->yplusx); $r->Y = self::fe_mul($r->Y, $q->yminusx); $r->T = self::fe_mul($q->xy2d, $p->T); $t0 = self::fe_add(clone $p->Z, clone $p->Z); $r->X = self::fe_sub($r->Z, $r->Y); $r->Y = self::fe_add($r->Z, $r->Y); $r->Z = self::fe_add($t0, $r->T); $r->T = self::fe_sub($t0, $r->T); return $r; } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 */ public static function ge_msub( ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R, ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p, ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q ) { $r = clone $R; $r->X = self::fe_add($p->Y, $p->X); $r->Y = self::fe_sub($p->Y, $p->X); $r->Z = self::fe_mul($r->X, $q->yminusx); $r->Y = self::fe_mul($r->Y, $q->yplusx); $r->T = self::fe_mul($q->xy2d, $p->T); $t0 = self::fe_add($p->Z, $p->Z); $r->X = self::fe_sub($r->Z, $r->Y); $r->Y = self::fe_add($r->Z, $r->Y); $r->Z = self::fe_sub($t0, $r->T); $r->T = self::fe_add($t0, $r->T); return $r; } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p * @return ParagonIE_Sodium_Core_Curve25519_Ge_P2 */ public static function ge_p1p1_to_p2(ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p) { $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P2(); $r->X = self::fe_mul($p->X, $p->T); $r->Y = self::fe_mul($p->Y, $p->Z); $r->Z = self::fe_mul($p->Z, $p->T); return $r; } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 */ public static function ge_p1p1_to_p3(ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p) { $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P3(); $r->X = self::fe_mul($p->X, $p->T); $r->Y = self::fe_mul($p->Y, $p->Z); $r->Z = self::fe_mul($p->Z, $p->T); $r->T = self::fe_mul($p->X, $p->Y); return $r; } /** * @internal You should not use this directly from another application * * @return ParagonIE_Sodium_Core_Curve25519_Ge_P2 */ public static function ge_p2_0() { return new ParagonIE_Sodium_Core_Curve25519_Ge_P2( self::fe_0(), self::fe_1(), self::fe_1() ); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Ge_P2 $p * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 */ public static function ge_p2_dbl(ParagonIE_Sodium_Core_Curve25519_Ge_P2 $p) { $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1(); $r->X = self::fe_sq($p->X); $r->Z = self::fe_sq($p->Y); $r->T = self::fe_sq2($p->Z); $r->Y = self::fe_add($p->X, $p->Y); $t0 = self::fe_sq($r->Y); $r->Y = self::fe_add($r->Z, $r->X); $r->Z = self::fe_sub($r->Z, $r->X); $r->X = self::fe_sub($t0, $r->Y); $r->T = self::fe_sub($r->T, $r->Z); return $r; } /** * @internal You should not use this directly from another application * * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 */ public static function ge_p3_0() { return new ParagonIE_Sodium_Core_Curve25519_Ge_P3( self::fe_0(), self::fe_1(), self::fe_1(), self::fe_0() ); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p * @return ParagonIE_Sodium_Core_Curve25519_Ge_Cached */ public static function ge_p3_to_cached(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p) { static $d2 = null; if ($d2 === null) { $d2 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d2); } /** @var ParagonIE_Sodium_Core_Curve25519_Fe $d2 */ $r = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached(); $r->YplusX = self::fe_add($p->Y, $p->X); $r->YminusX = self::fe_sub($p->Y, $p->X); $r->Z = self::fe_copy($p->Z); $r->T2d = self::fe_mul($p->T, $d2); return $r; } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p * @return ParagonIE_Sodium_Core_Curve25519_Ge_P2 */ public static function ge_p3_to_p2(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p) { return new ParagonIE_Sodium_Core_Curve25519_Ge_P2( self::fe_copy($p->X), self::fe_copy($p->Y), self::fe_copy($p->Z) ); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h * @return string * @throws SodiumException * @throws TypeError */ public static function ge_p3_tobytes(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h) { $recip = self::fe_invert($h->Z); $x = self::fe_mul($h->X, $recip); $y = self::fe_mul($h->Y, $recip); $s = self::fe_tobytes($y); $s[31] = self::intToChr( self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7) ); return $s; } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 */ public static function ge_p3_dbl(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p) { $q = self::ge_p3_to_p2($p); return self::ge_p2_dbl($q); } /** * @return ParagonIE_Sodium_Core_Curve25519_Ge_Precomp */ public static function ge_precomp_0() { return new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp( self::fe_1(), self::fe_1(), self::fe_0() ); } /** * @internal You should not use this directly from another application * * @param int $b * @param int $c * @return int */ public static function equal($b, $c) { return (int) ((($b ^ $c) - 1) >> 31) & 1; } /** * @internal You should not use this directly from another application * * @param int|string $char * @return int (1 = yes, 0 = no) * @throws SodiumException * @throws TypeError */ public static function negative($char) { if (is_int($char)) { return ($char >> 63) & 1; } $x = self::chrToInt(self::substr($char, 0, 1)); return (int) ($x >> 63); } /** * Conditional move * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $t * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $u * @param int $b * @return ParagonIE_Sodium_Core_Curve25519_Ge_Precomp */ public static function cmov( ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $t, ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $u, $b ) { if (!is_int($b)) { throw new InvalidArgumentException('Expected an integer.'); } return new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp( self::fe_cmov($t->yplusx, $u->yplusx, $b), self::fe_cmov($t->yminusx, $u->yminusx, $b), self::fe_cmov($t->xy2d, $u->xy2d, $b) ); } /** * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $t * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $u * @param int $b * @return ParagonIE_Sodium_Core_Curve25519_Ge_Cached */ public static function ge_cmov_cached( ParagonIE_Sodium_Core_Curve25519_Ge_Cached $t, ParagonIE_Sodium_Core_Curve25519_Ge_Cached $u, $b ) { $b &= 1; $ret = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached(); $ret->YplusX = self::fe_cmov($t->YplusX, $u->YplusX, $b); $ret->YminusX = self::fe_cmov($t->YminusX, $u->YminusX, $b); $ret->Z = self::fe_cmov($t->Z, $u->Z, $b); $ret->T2d = self::fe_cmov($t->T2d, $u->T2d, $b); return $ret; } /** * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached[] $cached * @param int $b * @return ParagonIE_Sodium_Core_Curve25519_Ge_Cached * @throws SodiumException */ public static function ge_cmov8_cached(array $cached, $b) { // const unsigned char bnegative = negative(b); // const unsigned char babs = b - (((-bnegative) & b) * ((signed char) 1 << 1)); $bnegative = self::negative($b); $babs = $b - (((-$bnegative) & $b) << 1); // ge25519_cached_0(t); $t = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached( self::fe_1(), self::fe_1(), self::fe_1(), self::fe_0() ); // ge25519_cmov_cached(t, &cached[0], equal(babs, 1)); // ge25519_cmov_cached(t, &cached[1], equal(babs, 2)); // ge25519_cmov_cached(t, &cached[2], equal(babs, 3)); // ge25519_cmov_cached(t, &cached[3], equal(babs, 4)); // ge25519_cmov_cached(t, &cached[4], equal(babs, 5)); // ge25519_cmov_cached(t, &cached[5], equal(babs, 6)); // ge25519_cmov_cached(t, &cached[6], equal(babs, 7)); // ge25519_cmov_cached(t, &cached[7], equal(babs, 8)); for ($x = 0; $x < 8; ++$x) { $t = self::ge_cmov_cached($t, $cached[$x], self::equal($babs, $x + 1)); } // fe25519_copy(minust.YplusX, t->YminusX); // fe25519_copy(minust.YminusX, t->YplusX); // fe25519_copy(minust.Z, t->Z); // fe25519_neg(minust.T2d, t->T2d); $minust = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached( self::fe_copy($t->YminusX), self::fe_copy($t->YplusX), self::fe_copy($t->Z), self::fe_neg($t->T2d) ); return self::ge_cmov_cached($t, $minust, $bnegative); } /** * @internal You should not use this directly from another application * * @param int $pos * @param int $b * @return ParagonIE_Sodium_Core_Curve25519_Ge_Precomp * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayOffset */ public static function ge_select($pos = 0, $b = 0) { static $base = null; if ($base === null) { $base = array(); /** @var int $i */ foreach (self::$base as $i => $bas) { for ($j = 0; $j < 8; ++$j) { $base[$i][$j] = new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp( ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($bas[$j][0]), ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($bas[$j][1]), ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($bas[$j][2]) ); } } } /** @var array<int, array<int, ParagonIE_Sodium_Core_Curve25519_Ge_Precomp>> $base */ if (!is_int($pos)) { throw new InvalidArgumentException('Position must be an integer'); } if ($pos < 0 || $pos > 31) { throw new RangeException('Position is out of range [0, 31]'); } $bnegative = self::negative($b); $babs = $b - (((-$bnegative) & $b) << 1); $t = self::ge_precomp_0(); for ($i = 0; $i < 8; ++$i) { $t = self::cmov( $t, $base[$pos][$i], self::equal($babs, $i + 1) ); } $minusT = new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp( self::fe_copy($t->yminusx), self::fe_copy($t->yplusx), self::fe_neg($t->xy2d) ); return self::cmov($t, $minusT, $bnegative); } /** * Subtract two group elements. * * r = p - q * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 */ public static function ge_sub( ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p, ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q ) { $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1(); $r->X = self::fe_add($p->Y, $p->X); $r->Y = self::fe_sub($p->Y, $p->X); $r->Z = self::fe_mul($r->X, $q->YminusX); $r->Y = self::fe_mul($r->Y, $q->YplusX); $r->T = self::fe_mul($q->T2d, $p->T); $r->X = self::fe_mul($p->Z, $q->Z); $t0 = self::fe_add($r->X, $r->X); $r->X = self::fe_sub($r->Z, $r->Y); $r->Y = self::fe_add($r->Z, $r->Y); $r->Z = self::fe_sub($t0, $r->T); $r->T = self::fe_add($t0, $r->T); return $r; } /** * Convert a group element to a byte string. * * @param ParagonIE_Sodium_Core_Curve25519_Ge_P2 $h * @return string * @throws SodiumException * @throws TypeError */ public static function ge_tobytes(ParagonIE_Sodium_Core_Curve25519_Ge_P2 $h) { $recip = self::fe_invert($h->Z); $x = self::fe_mul($h->X, $recip); $y = self::fe_mul($h->Y, $recip); $s = self::fe_tobytes($y); $s[31] = self::intToChr( self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7) ); return $s; } /** * @internal You should not use this directly from another application * * @param string $a * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A * @param string $b * @return ParagonIE_Sodium_Core_Curve25519_Ge_P2 * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedArrayAccess */ public static function ge_double_scalarmult_vartime( $a, ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A, $b ) { /** @var array<int, ParagonIE_Sodium_Core_Curve25519_Ge_Cached> $Ai */ $Ai = array(); /** @var array<int, ParagonIE_Sodium_Core_Curve25519_Ge_Precomp> $Bi */ static $Bi = array(); if (!$Bi) { for ($i = 0; $i < 8; ++$i) { $Bi[$i] = new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp( ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$base2[$i][0]), ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$base2[$i][1]), ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$base2[$i][2]) ); } } for ($i = 0; $i < 8; ++$i) { $Ai[$i] = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached( self::fe_0(), self::fe_0(), self::fe_0(), self::fe_0() ); } # slide(aslide,a); # slide(bslide,b); /** @var array<int, int> $aslide */ $aslide = self::slide($a); /** @var array<int, int> $bslide */ $bslide = self::slide($b); # ge_p3_to_cached(&Ai[0],A); # ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t); $Ai[0] = self::ge_p3_to_cached($A); $t = self::ge_p3_dbl($A); $A2 = self::ge_p1p1_to_p3($t); # ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[1],&u); # ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[2],&u); # ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[3],&u); # ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[4],&u); # ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[5],&u); # ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[6],&u); # ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[7],&u); for ($i = 0; $i < 7; ++$i) { $t = self::ge_add($A2, $Ai[$i]); $u = self::ge_p1p1_to_p3($t); $Ai[$i + 1] = self::ge_p3_to_cached($u); } # ge_p2_0(r); $r = self::ge_p2_0(); # for (i = 255;i >= 0;--i) { # if (aslide[i] || bslide[i]) break; # } $i = 255; for (; $i >= 0; --$i) { if ($aslide[$i] || $bslide[$i]) { break; } } # for (;i >= 0;--i) { for (; $i >= 0; --$i) { # ge_p2_dbl(&t,r); $t = self::ge_p2_dbl($r); # if (aslide[i] > 0) { if ($aslide[$i] > 0) { # ge_p1p1_to_p3(&u,&t); # ge_add(&t,&u,&Ai[aslide[i]/2]); $u = self::ge_p1p1_to_p3($t); $t = self::ge_add( $u, $Ai[(int) floor($aslide[$i] / 2)] ); # } else if (aslide[i] < 0) { } elseif ($aslide[$i] < 0) { # ge_p1p1_to_p3(&u,&t); # ge_sub(&t,&u,&Ai[(-aslide[i])/2]); $u = self::ge_p1p1_to_p3($t); $t = self::ge_sub( $u, $Ai[(int) floor(-$aslide[$i] / 2)] ); } # if (bslide[i] > 0) { if ($bslide[$i] > 0) { /** @var int $index */ $index = (int) floor($bslide[$i] / 2); # ge_p1p1_to_p3(&u,&t); # ge_madd(&t,&u,&Bi[bslide[i]/2]); $u = self::ge_p1p1_to_p3($t); $t = self::ge_madd($t, $u, $Bi[$index]); # } else if (bslide[i] < 0) { } elseif ($bslide[$i] < 0) { /** @var int $index */ $index = (int) floor(-$bslide[$i] / 2); # ge_p1p1_to_p3(&u,&t); # ge_msub(&t,&u,&Bi[(-bslide[i])/2]); $u = self::ge_p1p1_to_p3($t); $t = self::ge_msub($t, $u, $Bi[$index]); } # ge_p1p1_to_p2(r,&t); $r = self::ge_p1p1_to_p2($t); } return $r; } /** * @internal You should not use this directly from another application * * @param string $a * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 * @throws SodiumException * @throws TypeError * @psalm-suppress MixedAssignment * @psalm-suppress MixedOperand */ public static function ge_scalarmult($a, $p) { $e = array_fill(0, 64, 0); /** @var ParagonIE_Sodium_Core_Curve25519_Ge_Cached[] $pi */ $pi = array(); // ge25519_p3_to_cached(&pi[1 - 1], p); /* p */ $pi[0] = self::ge_p3_to_cached($p); // ge25519_p3_dbl(&t2, p); // ge25519_p1p1_to_p3(&p2, &t2); // ge25519_p3_to_cached(&pi[2 - 1], &p2); /* 2p = 2*p */ $t2 = self::ge_p3_dbl($p); $p2 = self::ge_p1p1_to_p3($t2); $pi[1] = self::ge_p3_to_cached($p2); // ge25519_add_cached(&t3, p, &pi[2 - 1]); // ge25519_p1p1_to_p3(&p3, &t3); // ge25519_p3_to_cached(&pi[3 - 1], &p3); /* 3p = 2p+p */ $t3 = self::ge_add($p, $pi[1]); $p3 = self::ge_p1p1_to_p3($t3); $pi[2] = self::ge_p3_to_cached($p3); // ge25519_p3_dbl(&t4, &p2); // ge25519_p1p1_to_p3(&p4, &t4); // ge25519_p3_to_cached(&pi[4 - 1], &p4); /* 4p = 2*2p */ $t4 = self::ge_p3_dbl($p2); $p4 = self::ge_p1p1_to_p3($t4); $pi[3] = self::ge_p3_to_cached($p4); // ge25519_add_cached(&t5, p, &pi[4 - 1]); // ge25519_p1p1_to_p3(&p5, &t5); // ge25519_p3_to_cached(&pi[5 - 1], &p5); /* 5p = 4p+p */ $t5 = self::ge_add($p, $pi[3]); $p5 = self::ge_p1p1_to_p3($t5); $pi[4] = self::ge_p3_to_cached($p5); // ge25519_p3_dbl(&t6, &p3); // ge25519_p1p1_to_p3(&p6, &t6); // ge25519_p3_to_cached(&pi[6 - 1], &p6); /* 6p = 2*3p */ $t6 = self::ge_p3_dbl($p3); $p6 = self::ge_p1p1_to_p3($t6); $pi[5] = self::ge_p3_to_cached($p6); // ge25519_add_cached(&t7, p, &pi[6 - 1]); // ge25519_p1p1_to_p3(&p7, &t7); // ge25519_p3_to_cached(&pi[7 - 1], &p7); /* 7p = 6p+p */ $t7 = self::ge_add($p, $pi[5]); $p7 = self::ge_p1p1_to_p3($t7); $pi[6] = self::ge_p3_to_cached($p7); // ge25519_p3_dbl(&t8, &p4); // ge25519_p1p1_to_p3(&p8, &t8); // ge25519_p3_to_cached(&pi[8 - 1], &p8); /* 8p = 2*4p */ $t8 = self::ge_p3_dbl($p4); $p8 = self::ge_p1p1_to_p3($t8); $pi[7] = self::ge_p3_to_cached($p8); // for (i = 0; i < 32; ++i) { // e[2 * i + 0] = (a[i] >> 0) & 15; // e[2 * i + 1] = (a[i] >> 4) & 15; // } for ($i = 0; $i < 32; ++$i) { $e[($i << 1) ] = self::chrToInt($a[$i]) & 15; $e[($i << 1) + 1] = (self::chrToInt($a[$i]) >> 4) & 15; } // /* each e[i] is between 0 and 15 */ // /* e[63] is between 0 and 7 */ // carry = 0; // for (i = 0; i < 63; ++i) { // e[i] += carry; // carry = e[i] + 8; // carry >>= 4; // e[i] -= carry * ((signed char) 1 << 4); // } $carry = 0; for ($i = 0; $i < 63; ++$i) { $e[$i] += $carry; $carry = $e[$i] + 8; $carry >>= 4; $e[$i] -= $carry << 4; } // e[63] += carry; // /* each e[i] is between -8 and 8 */ $e[63] += $carry; // ge25519_p3_0(h); $h = self::ge_p3_0(); // for (i = 63; i != 0; i--) { for ($i = 63; $i != 0; --$i) { // ge25519_cmov8_cached(&t, pi, e[i]); $t = self::ge_cmov8_cached($pi, $e[$i]); // ge25519_add_cached(&r, h, &t); $r = self::ge_add($h, $t); // ge25519_p1p1_to_p2(&s, &r); // ge25519_p2_dbl(&r, &s); // ge25519_p1p1_to_p2(&s, &r); // ge25519_p2_dbl(&r, &s); // ge25519_p1p1_to_p2(&s, &r); // ge25519_p2_dbl(&r, &s); // ge25519_p1p1_to_p2(&s, &r); // ge25519_p2_dbl(&r, &s); $s = self::ge_p1p1_to_p2($r); $r = self::ge_p2_dbl($s); $s = self::ge_p1p1_to_p2($r); $r = self::ge_p2_dbl($s); $s = self::ge_p1p1_to_p2($r); $r = self::ge_p2_dbl($s); $s = self::ge_p1p1_to_p2($r); $r = self::ge_p2_dbl($s); // ge25519_p1p1_to_p3(h, &r); /* *16 */ $h = self::ge_p1p1_to_p3($r); /* *16 */ } // ge25519_cmov8_cached(&t, pi, e[i]); // ge25519_add_cached(&r, h, &t); // ge25519_p1p1_to_p3(h, &r); $t = self::ge_cmov8_cached($pi, $e[0]); $r = self::ge_add($h, $t); return self::ge_p1p1_to_p3($r); } /** * @internal You should not use this directly from another application * * @param string $a * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 * @throws SodiumException * @throws TypeError * @psalm-suppress MixedAssignment * @psalm-suppress MixedOperand */ public static function ge_scalarmult_base($a) { /** @var array<int, int> $e */ $e = array(); $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1(); for ($i = 0; $i < 32; ++$i) { $dbl = (int) $i << 1; $e[$dbl] = (int) self::chrToInt($a[$i]) & 15; $e[$dbl + 1] = (int) (self::chrToInt($a[$i]) >> 4) & 15; } $carry = 0; for ($i = 0; $i < 63; ++$i) { $e[$i] += $carry; $carry = $e[$i] + 8; $carry >>= 4; $e[$i] -= $carry << 4; } $e[63] += (int) $carry; $h = self::ge_p3_0(); for ($i = 1; $i < 64; $i += 2) { $t = self::ge_select((int) floor($i / 2), (int) $e[$i]); $r = self::ge_madd($r, $h, $t); $h = self::ge_p1p1_to_p3($r); } $r = self::ge_p3_dbl($h); $s = self::ge_p1p1_to_p2($r); $r = self::ge_p2_dbl($s); $s = self::ge_p1p1_to_p2($r); $r = self::ge_p2_dbl($s); $s = self::ge_p1p1_to_p2($r); $r = self::ge_p2_dbl($s); $h = self::ge_p1p1_to_p3($r); for ($i = 0; $i < 64; $i += 2) { $t = self::ge_select($i >> 1, (int) $e[$i]); $r = self::ge_madd($r, $h, $t); $h = self::ge_p1p1_to_p3($r); } return $h; } /** * Calculates (ab + c) mod l * where l = 2^252 + 27742317777372353535851937790883648493 * * @internal You should not use this directly from another application * * @param string $a * @param string $b * @param string $c * @return string * @throws TypeError */ public static function sc_muladd($a, $b, $c) { $a0 = 2097151 & self::load_3(self::substr($a, 0, 3)); $a1 = 2097151 & (self::load_4(self::substr($a, 2, 4)) >> 5); $a2 = 2097151 & (self::load_3(self::substr($a, 5, 3)) >> 2); $a3 = 2097151 & (self::load_4(self::substr($a, 7, 4)) >> 7); $a4 = 2097151 & (self::load_4(self::substr($a, 10, 4)) >> 4); $a5 = 2097151 & (self::load_3(self::substr($a, 13, 3)) >> 1); $a6 = 2097151 & (self::load_4(self::substr($a, 15, 4)) >> 6); $a7 = 2097151 & (self::load_3(self::substr($a, 18, 3)) >> 3); $a8 = 2097151 & self::load_3(self::substr($a, 21, 3)); $a9 = 2097151 & (self::load_4(self::substr($a, 23, 4)) >> 5); $a10 = 2097151 & (self::load_3(self::substr($a, 26, 3)) >> 2); $a11 = (self::load_4(self::substr($a, 28, 4)) >> 7); $b0 = 2097151 & self::load_3(self::substr($b, 0, 3)); $b1 = 2097151 & (self::load_4(self::substr($b, 2, 4)) >> 5); $b2 = 2097151 & (self::load_3(self::substr($b, 5, 3)) >> 2); $b3 = 2097151 & (self::load_4(self::substr($b, 7, 4)) >> 7); $b4 = 2097151 & (self::load_4(self::substr($b, 10, 4)) >> 4); $b5 = 2097151 & (self::load_3(self::substr($b, 13, 3)) >> 1); $b6 = 2097151 & (self::load_4(self::substr($b, 15, 4)) >> 6); $b7 = 2097151 & (self::load_3(self::substr($b, 18, 3)) >> 3); $b8 = 2097151 & self::load_3(self::substr($b, 21, 3)); $b9 = 2097151 & (self::load_4(self::substr($b, 23, 4)) >> 5); $b10 = 2097151 & (self::load_3(self::substr($b, 26, 3)) >> 2); $b11 = (self::load_4(self::substr($b, 28, 4)) >> 7); $c0 = 2097151 & self::load_3(self::substr($c, 0, 3)); $c1 = 2097151 & (self::load_4(self::substr($c, 2, 4)) >> 5); $c2 = 2097151 & (self::load_3(self::substr($c, 5, 3)) >> 2); $c3 = 2097151 & (self::load_4(self::substr($c, 7, 4)) >> 7); $c4 = 2097151 & (self::load_4(self::substr($c, 10, 4)) >> 4); $c5 = 2097151 & (self::load_3(self::substr($c, 13, 3)) >> 1); $c6 = 2097151 & (self::load_4(self::substr($c, 15, 4)) >> 6); $c7 = 2097151 & (self::load_3(self::substr($c, 18, 3)) >> 3); $c8 = 2097151 & self::load_3(self::substr($c, 21, 3)); $c9 = 2097151 & (self::load_4(self::substr($c, 23, 4)) >> 5); $c10 = 2097151 & (self::load_3(self::substr($c, 26, 3)) >> 2); $c11 = (self::load_4(self::substr($c, 28, 4)) >> 7); /* Can't really avoid the pyramid here: */ $s0 = $c0 + self::mul($a0, $b0, 24); $s1 = $c1 + self::mul($a0, $b1, 24) + self::mul($a1, $b0, 24); $s2 = $c2 + self::mul($a0, $b2, 24) + self::mul($a1, $b1, 24) + self::mul($a2, $b0, 24); $s3 = $c3 + self::mul($a0, $b3, 24) + self::mul($a1, $b2, 24) + self::mul($a2, $b1, 24) + self::mul($a3, $b0, 24); $s4 = $c4 + self::mul($a0, $b4, 24) + self::mul($a1, $b3, 24) + self::mul($a2, $b2, 24) + self::mul($a3, $b1, 24) + self::mul($a4, $b0, 24); $s5 = $c5 + self::mul($a0, $b5, 24) + self::mul($a1, $b4, 24) + self::mul($a2, $b3, 24) + self::mul($a3, $b2, 24) + self::mul($a4, $b1, 24) + self::mul($a5, $b0, 24); $s6 = $c6 + self::mul($a0, $b6, 24) + self::mul($a1, $b5, 24) + self::mul($a2, $b4, 24) + self::mul($a3, $b3, 24) + self::mul($a4, $b2, 24) + self::mul($a5, $b1, 24) + self::mul($a6, $b0, 24); $s7 = $c7 + self::mul($a0, $b7, 24) + self::mul($a1, $b6, 24) + self::mul($a2, $b5, 24) + self::mul($a3, $b4, 24) + self::mul($a4, $b3, 24) + self::mul($a5, $b2, 24) + self::mul($a6, $b1, 24) + self::mul($a7, $b0, 24); $s8 = $c8 + self::mul($a0, $b8, 24) + self::mul($a1, $b7, 24) + self::mul($a2, $b6, 24) + self::mul($a3, $b5, 24) + self::mul($a4, $b4, 24) + self::mul($a5, $b3, 24) + self::mul($a6, $b2, 24) + self::mul($a7, $b1, 24) + self::mul($a8, $b0, 24); $s9 = $c9 + self::mul($a0, $b9, 24) + self::mul($a1, $b8, 24) + self::mul($a2, $b7, 24) + self::mul($a3, $b6, 24) + self::mul($a4, $b5, 24) + self::mul($a5, $b4, 24) + self::mul($a6, $b3, 24) + self::mul($a7, $b2, 24) + self::mul($a8, $b1, 24) + self::mul($a9, $b0, 24); $s10 = $c10 + self::mul($a0, $b10, 24) + self::mul($a1, $b9, 24) + self::mul($a2, $b8, 24) + self::mul($a3, $b7, 24) + self::mul($a4, $b6, 24) + self::mul($a5, $b5, 24) + self::mul($a6, $b4, 24) + self::mul($a7, $b3, 24) + self::mul($a8, $b2, 24) + self::mul($a9, $b1, 24) + self::mul($a10, $b0, 24); $s11 = $c11 + self::mul($a0, $b11, 24) + self::mul($a1, $b10, 24) + self::mul($a2, $b9, 24) + self::mul($a3, $b8, 24) + self::mul($a4, $b7, 24) + self::mul($a5, $b6, 24) + self::mul($a6, $b5, 24) + self::mul($a7, $b4, 24) + self::mul($a8, $b3, 24) + self::mul($a9, $b2, 24) + self::mul($a10, $b1, 24) + self::mul($a11, $b0, 24); $s12 = self::mul($a1, $b11, 24) + self::mul($a2, $b10, 24) + self::mul($a3, $b9, 24) + self::mul($a4, $b8, 24) + self::mul($a5, $b7, 24) + self::mul($a6, $b6, 24) + self::mul($a7, $b5, 24) + self::mul($a8, $b4, 24) + self::mul($a9, $b3, 24) + self::mul($a10, $b2, 24) + self::mul($a11, $b1, 24); $s13 = self::mul($a2, $b11, 24) + self::mul($a3, $b10, 24) + self::mul($a4, $b9, 24) + self::mul($a5, $b8, 24) + self::mul($a6, $b7, 24) + self::mul($a7, $b6, 24) + self::mul($a8, $b5, 24) + self::mul($a9, $b4, 24) + self::mul($a10, $b3, 24) + self::mul($a11, $b2, 24); $s14 = self::mul($a3, $b11, 24) + self::mul($a4, $b10, 24) + self::mul($a5, $b9, 24) + self::mul($a6, $b8, 24) + self::mul($a7, $b7, 24) + self::mul($a8, $b6, 24) + self::mul($a9, $b5, 24) + self::mul($a10, $b4, 24) + self::mul($a11, $b3, 24); $s15 = self::mul($a4, $b11, 24) + self::mul($a5, $b10, 24) + self::mul($a6, $b9, 24) + self::mul($a7, $b8, 24) + self::mul($a8, $b7, 24) + self::mul($a9, $b6, 24) + self::mul($a10, $b5, 24) + self::mul($a11, $b4, 24); $s16 = self::mul($a5, $b11, 24) + self::mul($a6, $b10, 24) + self::mul($a7, $b9, 24) + self::mul($a8, $b8, 24) + self::mul($a9, $b7, 24) + self::mul($a10, $b6, 24) + self::mul($a11, $b5, 24); $s17 = self::mul($a6, $b11, 24) + self::mul($a7, $b10, 24) + self::mul($a8, $b9, 24) + self::mul($a9, $b8, 24) + self::mul($a10, $b7, 24) + self::mul($a11, $b6, 24); $s18 = self::mul($a7, $b11, 24) + self::mul($a8, $b10, 24) + self::mul($a9, $b9, 24) + self::mul($a10, $b8, 24) + self::mul($a11, $b7, 24); $s19 = self::mul($a8, $b11, 24) + self::mul($a9, $b10, 24) + self::mul($a10, $b9, 24) + self::mul($a11, $b8, 24); $s20 = self::mul($a9, $b11, 24) + self::mul($a10, $b10, 24) + self::mul($a11, $b9, 24); $s21 = self::mul($a10, $b11, 24) + self::mul($a11, $b10, 24); $s22 = self::mul($a11, $b11, 24); $s23 = 0; $carry0 = ($s0 + (1 << 20)) >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; $carry2 = ($s2 + (1 << 20)) >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; $carry4 = ($s4 + (1 << 20)) >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; $carry12 = ($s12 + (1 << 20)) >> 21; $s13 += $carry12; $s12 -= $carry12 << 21; $carry14 = ($s14 + (1 << 20)) >> 21; $s15 += $carry14; $s14 -= $carry14 << 21; $carry16 = ($s16 + (1 << 20)) >> 21; $s17 += $carry16; $s16 -= $carry16 << 21; $carry18 = ($s18 + (1 << 20)) >> 21; $s19 += $carry18; $s18 -= $carry18 << 21; $carry20 = ($s20 + (1 << 20)) >> 21; $s21 += $carry20; $s20 -= $carry20 << 21; $carry22 = ($s22 + (1 << 20)) >> 21; $s23 += $carry22; $s22 -= $carry22 << 21; $carry1 = ($s1 + (1 << 20)) >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; $carry3 = ($s3 + (1 << 20)) >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; $carry5 = ($s5 + (1 << 20)) >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; $carry13 = ($s13 + (1 << 20)) >> 21; $s14 += $carry13; $s13 -= $carry13 << 21; $carry15 = ($s15 + (1 << 20)) >> 21; $s16 += $carry15; $s15 -= $carry15 << 21; $carry17 = ($s17 + (1 << 20)) >> 21; $s18 += $carry17; $s17 -= $carry17 << 21; $carry19 = ($s19 + (1 << 20)) >> 21; $s20 += $carry19; $s19 -= $carry19 << 21; $carry21 = ($s21 + (1 << 20)) >> 21; $s22 += $carry21; $s21 -= $carry21 << 21; $s11 += self::mul($s23, 666643, 20); $s12 += self::mul($s23, 470296, 19); $s13 += self::mul($s23, 654183, 20); $s14 -= self::mul($s23, 997805, 20); $s15 += self::mul($s23, 136657, 18); $s16 -= self::mul($s23, 683901, 20); $s10 += self::mul($s22, 666643, 20); $s11 += self::mul($s22, 470296, 19); $s12 += self::mul($s22, 654183, 20); $s13 -= self::mul($s22, 997805, 20); $s14 += self::mul($s22, 136657, 18); $s15 -= self::mul($s22, 683901, 20); $s9 += self::mul($s21, 666643, 20); $s10 += self::mul($s21, 470296, 19); $s11 += self::mul($s21, 654183, 20); $s12 -= self::mul($s21, 997805, 20); $s13 += self::mul($s21, 136657, 18); $s14 -= self::mul($s21, 683901, 20); $s8 += self::mul($s20, 666643, 20); $s9 += self::mul($s20, 470296, 19); $s10 += self::mul($s20, 654183, 20); $s11 -= self::mul($s20, 997805, 20); $s12 += self::mul($s20, 136657, 18); $s13 -= self::mul($s20, 683901, 20); $s7 += self::mul($s19, 666643, 20); $s8 += self::mul($s19, 470296, 19); $s9 += self::mul($s19, 654183, 20); $s10 -= self::mul($s19, 997805, 20); $s11 += self::mul($s19, 136657, 18); $s12 -= self::mul($s19, 683901, 20); $s6 += self::mul($s18, 666643, 20); $s7 += self::mul($s18, 470296, 19); $s8 += self::mul($s18, 654183, 20); $s9 -= self::mul($s18, 997805, 20); $s10 += self::mul($s18, 136657, 18); $s11 -= self::mul($s18, 683901, 20); $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; $carry12 = ($s12 + (1 << 20)) >> 21; $s13 += $carry12; $s12 -= $carry12 << 21; $carry14 = ($s14 + (1 << 20)) >> 21; $s15 += $carry14; $s14 -= $carry14 << 21; $carry16 = ($s16 + (1 << 20)) >> 21; $s17 += $carry16; $s16 -= $carry16 << 21; $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; $carry13 = ($s13 + (1 << 20)) >> 21; $s14 += $carry13; $s13 -= $carry13 << 21; $carry15 = ($s15 + (1 << 20)) >> 21; $s16 += $carry15; $s15 -= $carry15 << 21; $s5 += self::mul($s17, 666643, 20); $s6 += self::mul($s17, 470296, 19); $s7 += self::mul($s17, 654183, 20); $s8 -= self::mul($s17, 997805, 20); $s9 += self::mul($s17, 136657, 18); $s10 -= self::mul($s17, 683901, 20); $s4 += self::mul($s16, 666643, 20); $s5 += self::mul($s16, 470296, 19); $s6 += self::mul($s16, 654183, 20); $s7 -= self::mul($s16, 997805, 20); $s8 += self::mul($s16, 136657, 18); $s9 -= self::mul($s16, 683901, 20); $s3 += self::mul($s15, 666643, 20); $s4 += self::mul($s15, 470296, 19); $s5 += self::mul($s15, 654183, 20); $s6 -= self::mul($s15, 997805, 20); $s7 += self::mul($s15, 136657, 18); $s8 -= self::mul($s15, 683901, 20); $s2 += self::mul($s14, 666643, 20); $s3 += self::mul($s14, 470296, 19); $s4 += self::mul($s14, 654183, 20); $s5 -= self::mul($s14, 997805, 20); $s6 += self::mul($s14, 136657, 18); $s7 -= self::mul($s14, 683901, 20); $s1 += self::mul($s13, 666643, 20); $s2 += self::mul($s13, 470296, 19); $s3 += self::mul($s13, 654183, 20); $s4 -= self::mul($s13, 997805, 20); $s5 += self::mul($s13, 136657, 18); $s6 -= self::mul($s13, 683901, 20); $s0 += self::mul($s12, 666643, 20); $s1 += self::mul($s12, 470296, 19); $s2 += self::mul($s12, 654183, 20); $s3 -= self::mul($s12, 997805, 20); $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); $s12 = 0; $carry0 = ($s0 + (1 << 20)) >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; $carry2 = ($s2 + (1 << 20)) >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; $carry4 = ($s4 + (1 << 20)) >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; $carry1 = ($s1 + (1 << 20)) >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; $carry3 = ($s3 + (1 << 20)) >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; $carry5 = ($s5 + (1 << 20)) >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; $s0 += self::mul($s12, 666643, 20); $s1 += self::mul($s12, 470296, 19); $s2 += self::mul($s12, 654183, 20); $s3 -= self::mul($s12, 997805, 20); $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); $s12 = 0; $carry0 = $s0 >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; $carry1 = $s1 >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; $carry2 = $s2 >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; $carry3 = $s3 >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; $carry4 = $s4 >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; $carry5 = $s5 >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; $carry6 = $s6 >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; $carry7 = $s7 >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; $carry8 = $s8 >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; $carry9 = $s9 >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; $carry10 = $s10 >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; $carry11 = $s11 >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; $s0 += self::mul($s12, 666643, 20); $s1 += self::mul($s12, 470296, 19); $s2 += self::mul($s12, 654183, 20); $s3 -= self::mul($s12, 997805, 20); $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); $carry0 = $s0 >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; $carry1 = $s1 >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; $carry2 = $s2 >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; $carry3 = $s3 >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; $carry4 = $s4 >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; $carry5 = $s5 >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; $carry6 = $s6 >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; $carry7 = $s7 >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; $carry8 = $s8 >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; $carry9 = $s9 >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; $carry10 = $s10 >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; /** * @var array<int, int> */ $arr = array( (int) (0xff & ($s0 >> 0)), (int) (0xff & ($s0 >> 8)), (int) (0xff & (($s0 >> 16) | $s1 << 5)), (int) (0xff & ($s1 >> 3)), (int) (0xff & ($s1 >> 11)), (int) (0xff & (($s1 >> 19) | $s2 << 2)), (int) (0xff & ($s2 >> 6)), (int) (0xff & (($s2 >> 14) | $s3 << 7)), (int) (0xff & ($s3 >> 1)), (int) (0xff & ($s3 >> 9)), (int) (0xff & (($s3 >> 17) | $s4 << 4)), (int) (0xff & ($s4 >> 4)), (int) (0xff & ($s4 >> 12)), (int) (0xff & (($s4 >> 20) | $s5 << 1)), (int) (0xff & ($s5 >> 7)), (int) (0xff & (($s5 >> 15) | $s6 << 6)), (int) (0xff & ($s6 >> 2)), (int) (0xff & ($s6 >> 10)), (int) (0xff & (($s6 >> 18) | $s7 << 3)), (int) (0xff & ($s7 >> 5)), (int) (0xff & ($s7 >> 13)), (int) (0xff & ($s8 >> 0)), (int) (0xff & ($s8 >> 8)), (int) (0xff & (($s8 >> 16) | $s9 << 5)), (int) (0xff & ($s9 >> 3)), (int) (0xff & ($s9 >> 11)), (int) (0xff & (($s9 >> 19) | $s10 << 2)), (int) (0xff & ($s10 >> 6)), (int) (0xff & (($s10 >> 14) | $s11 << 7)), (int) (0xff & ($s11 >> 1)), (int) (0xff & ($s11 >> 9)), 0xff & ($s11 >> 17) ); return self::intArrayToString($arr); } /** * @internal You should not use this directly from another application * * @param string $s * @return string * @throws TypeError */ public static function sc_reduce($s) { $s0 = 2097151 & self::load_3(self::substr($s, 0, 3)); $s1 = 2097151 & (self::load_4(self::substr($s, 2, 4)) >> 5); $s2 = 2097151 & (self::load_3(self::substr($s, 5, 3)) >> 2); $s3 = 2097151 & (self::load_4(self::substr($s, 7, 4)) >> 7); $s4 = 2097151 & (self::load_4(self::substr($s, 10, 4)) >> 4); $s5 = 2097151 & (self::load_3(self::substr($s, 13, 3)) >> 1); $s6 = 2097151 & (self::load_4(self::substr($s, 15, 4)) >> 6); $s7 = 2097151 & (self::load_3(self::substr($s, 18, 4)) >> 3); $s8 = 2097151 & self::load_3(self::substr($s, 21, 3)); $s9 = 2097151 & (self::load_4(self::substr($s, 23, 4)) >> 5); $s10 = 2097151 & (self::load_3(self::substr($s, 26, 3)) >> 2); $s11 = 2097151 & (self::load_4(self::substr($s, 28, 4)) >> 7); $s12 = 2097151 & (self::load_4(self::substr($s, 31, 4)) >> 4); $s13 = 2097151 & (self::load_3(self::substr($s, 34, 3)) >> 1); $s14 = 2097151 & (self::load_4(self::substr($s, 36, 4)) >> 6); $s15 = 2097151 & (self::load_3(self::substr($s, 39, 4)) >> 3); $s16 = 2097151 & self::load_3(self::substr($s, 42, 3)); $s17 = 2097151 & (self::load_4(self::substr($s, 44, 4)) >> 5); $s18 = 2097151 & (self::load_3(self::substr($s, 47, 3)) >> 2); $s19 = 2097151 & (self::load_4(self::substr($s, 49, 4)) >> 7); $s20 = 2097151 & (self::load_4(self::substr($s, 52, 4)) >> 4); $s21 = 2097151 & (self::load_3(self::substr($s, 55, 3)) >> 1); $s22 = 2097151 & (self::load_4(self::substr($s, 57, 4)) >> 6); $s23 = 0x1fffffff & (self::load_4(self::substr($s, 60, 4)) >> 3); $s11 += self::mul($s23, 666643, 20); $s12 += self::mul($s23, 470296, 19); $s13 += self::mul($s23, 654183, 20); $s14 -= self::mul($s23, 997805, 20); $s15 += self::mul($s23, 136657, 18); $s16 -= self::mul($s23, 683901, 20); $s10 += self::mul($s22, 666643, 20); $s11 += self::mul($s22, 470296, 19); $s12 += self::mul($s22, 654183, 20); $s13 -= self::mul($s22, 997805, 20); $s14 += self::mul($s22, 136657, 18); $s15 -= self::mul($s22, 683901, 20); $s9 += self::mul($s21, 666643, 20); $s10 += self::mul($s21, 470296, 19); $s11 += self::mul($s21, 654183, 20); $s12 -= self::mul($s21, 997805, 20); $s13 += self::mul($s21, 136657, 18); $s14 -= self::mul($s21, 683901, 20); $s8 += self::mul($s20, 666643, 20); $s9 += self::mul($s20, 470296, 19); $s10 += self::mul($s20, 654183, 20); $s11 -= self::mul($s20, 997805, 20); $s12 += self::mul($s20, 136657, 18); $s13 -= self::mul($s20, 683901, 20); $s7 += self::mul($s19, 666643, 20); $s8 += self::mul($s19, 470296, 19); $s9 += self::mul($s19, 654183, 20); $s10 -= self::mul($s19, 997805, 20); $s11 += self::mul($s19, 136657, 18); $s12 -= self::mul($s19, 683901, 20); $s6 += self::mul($s18, 666643, 20); $s7 += self::mul($s18, 470296, 19); $s8 += self::mul($s18, 654183, 20); $s9 -= self::mul($s18, 997805, 20); $s10 += self::mul($s18, 136657, 18); $s11 -= self::mul($s18, 683901, 20); $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; $carry12 = ($s12 + (1 << 20)) >> 21; $s13 += $carry12; $s12 -= $carry12 << 21; $carry14 = ($s14 + (1 << 20)) >> 21; $s15 += $carry14; $s14 -= $carry14 << 21; $carry16 = ($s16 + (1 << 20)) >> 21; $s17 += $carry16; $s16 -= $carry16 << 21; $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; $carry13 = ($s13 + (1 << 20)) >> 21; $s14 += $carry13; $s13 -= $carry13 << 21; $carry15 = ($s15 + (1 << 20)) >> 21; $s16 += $carry15; $s15 -= $carry15 << 21; $s5 += self::mul($s17, 666643, 20); $s6 += self::mul($s17, 470296, 19); $s7 += self::mul($s17, 654183, 20); $s8 -= self::mul($s17, 997805, 20); $s9 += self::mul($s17, 136657, 18); $s10 -= self::mul($s17, 683901, 20); $s4 += self::mul($s16, 666643, 20); $s5 += self::mul($s16, 470296, 19); $s6 += self::mul($s16, 654183, 20); $s7 -= self::mul($s16, 997805, 20); $s8 += self::mul($s16, 136657, 18); $s9 -= self::mul($s16, 683901, 20); $s3 += self::mul($s15, 666643, 20); $s4 += self::mul($s15, 470296, 19); $s5 += self::mul($s15, 654183, 20); $s6 -= self::mul($s15, 997805, 20); $s7 += self::mul($s15, 136657, 18); $s8 -= self::mul($s15, 683901, 20); $s2 += self::mul($s14, 666643, 20); $s3 += self::mul($s14, 470296, 19); $s4 += self::mul($s14, 654183, 20); $s5 -= self::mul($s14, 997805, 20); $s6 += self::mul($s14, 136657, 18); $s7 -= self::mul($s14, 683901, 20); $s1 += self::mul($s13, 666643, 20); $s2 += self::mul($s13, 470296, 19); $s3 += self::mul($s13, 654183, 20); $s4 -= self::mul($s13, 997805, 20); $s5 += self::mul($s13, 136657, 18); $s6 -= self::mul($s13, 683901, 20); $s0 += self::mul($s12, 666643, 20); $s1 += self::mul($s12, 470296, 19); $s2 += self::mul($s12, 654183, 20); $s3 -= self::mul($s12, 997805, 20); $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); $s12 = 0; $carry0 = ($s0 + (1 << 20)) >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; $carry2 = ($s2 + (1 << 20)) >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; $carry4 = ($s4 + (1 << 20)) >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; $carry1 = ($s1 + (1 << 20)) >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; $carry3 = ($s3 + (1 << 20)) >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; $carry5 = ($s5 + (1 << 20)) >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; $s0 += self::mul($s12, 666643, 20); $s1 += self::mul($s12, 470296, 19); $s2 += self::mul($s12, 654183, 20); $s3 -= self::mul($s12, 997805, 20); $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); $s12 = 0; $carry0 = $s0 >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; $carry1 = $s1 >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; $carry2 = $s2 >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; $carry3 = $s3 >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; $carry4 = $s4 >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; $carry5 = $s5 >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; $carry6 = $s6 >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; $carry7 = $s7 >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; $carry8 = $s8 >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; $carry9 = $s9 >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; $carry10 = $s10 >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; $carry11 = $s11 >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; $s0 += self::mul($s12, 666643, 20); $s1 += self::mul($s12, 470296, 19); $s2 += self::mul($s12, 654183, 20); $s3 -= self::mul($s12, 997805, 20); $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); $carry0 = $s0 >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; $carry1 = $s1 >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; $carry2 = $s2 >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; $carry3 = $s3 >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; $carry4 = $s4 >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; $carry5 = $s5 >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; $carry6 = $s6 >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; $carry7 = $s7 >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; $carry8 = $s8 >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; $carry9 = $s9 >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; $carry10 = $s10 >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; /** * @var array<int, int> */ $arr = array( (int) ($s0 >> 0), (int) ($s0 >> 8), (int) (($s0 >> 16) | $s1 << 5), (int) ($s1 >> 3), (int) ($s1 >> 11), (int) (($s1 >> 19) | $s2 << 2), (int) ($s2 >> 6), (int) (($s2 >> 14) | $s3 << 7), (int) ($s3 >> 1), (int) ($s3 >> 9), (int) (($s3 >> 17) | $s4 << 4), (int) ($s4 >> 4), (int) ($s4 >> 12), (int) (($s4 >> 20) | $s5 << 1), (int) ($s5 >> 7), (int) (($s5 >> 15) | $s6 << 6), (int) ($s6 >> 2), (int) ($s6 >> 10), (int) (($s6 >> 18) | $s7 << 3), (int) ($s7 >> 5), (int) ($s7 >> 13), (int) ($s8 >> 0), (int) ($s8 >> 8), (int) (($s8 >> 16) | $s9 << 5), (int) ($s9 >> 3), (int) ($s9 >> 11), (int) (($s9 >> 19) | $s10 << 2), (int) ($s10 >> 6), (int) (($s10 >> 14) | $s11 << 7), (int) ($s11 >> 1), (int) ($s11 >> 9), (int) $s11 >> 17 ); return self::intArrayToString($arr); } /** * multiply by the order of the main subgroup l = 2^252+27742317777372353535851937790883648493 * * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 */ public static function ge_mul_l(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A) { $aslide = array( 13, 0, 0, 0, 0, -1, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, -5, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, -13, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, -13, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, -13, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 3, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ); /** @var array<int, ParagonIE_Sodium_Core_Curve25519_Ge_Cached> $Ai size 8 */ $Ai = array(); # ge_p3_to_cached(&Ai[0], A); $Ai[0] = self::ge_p3_to_cached($A); # ge_p3_dbl(&t, A); $t = self::ge_p3_dbl($A); # ge_p1p1_to_p3(&A2, &t); $A2 = self::ge_p1p1_to_p3($t); for ($i = 1; $i < 8; ++$i) { # ge_add(&t, &A2, &Ai[0]); $t = self::ge_add($A2, $Ai[$i - 1]); # ge_p1p1_to_p3(&u, &t); $u = self::ge_p1p1_to_p3($t); # ge_p3_to_cached(&Ai[i], &u); $Ai[$i] = self::ge_p3_to_cached($u); } $r = self::ge_p3_0(); for ($i = 252; $i >= 0; --$i) { $t = self::ge_p3_dbl($r); if ($aslide[$i] > 0) { # ge_p1p1_to_p3(&u, &t); $u = self::ge_p1p1_to_p3($t); # ge_add(&t, &u, &Ai[aslide[i] / 2]); $t = self::ge_add($u, $Ai[(int)($aslide[$i] / 2)]); } elseif ($aslide[$i] < 0) { # ge_p1p1_to_p3(&u, &t); $u = self::ge_p1p1_to_p3($t); # ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]); $t = self::ge_sub($u, $Ai[(int)(-$aslide[$i] / 2)]); } } # ge_p1p1_to_p3(r, &t); return self::ge_p1p1_to_p3($t); } /** * @param string $a * @param string $b * @return string */ public static function sc25519_mul($a, $b) { // int64_t a0 = 2097151 & load_3(a); // int64_t a1 = 2097151 & (load_4(a + 2) >> 5); // int64_t a2 = 2097151 & (load_3(a + 5) >> 2); // int64_t a3 = 2097151 & (load_4(a + 7) >> 7); // int64_t a4 = 2097151 & (load_4(a + 10) >> 4); // int64_t a5 = 2097151 & (load_3(a + 13) >> 1); // int64_t a6 = 2097151 & (load_4(a + 15) >> 6); // int64_t a7 = 2097151 & (load_3(a + 18) >> 3); // int64_t a8 = 2097151 & load_3(a + 21); // int64_t a9 = 2097151 & (load_4(a + 23) >> 5); // int64_t a10 = 2097151 & (load_3(a + 26) >> 2); // int64_t a11 = (load_4(a + 28) >> 7); $a0 = 2097151 & self::load_3(self::substr($a, 0, 3)); $a1 = 2097151 & (self::load_4(self::substr($a, 2, 4)) >> 5); $a2 = 2097151 & (self::load_3(self::substr($a, 5, 3)) >> 2); $a3 = 2097151 & (self::load_4(self::substr($a, 7, 4)) >> 7); $a4 = 2097151 & (self::load_4(self::substr($a, 10, 4)) >> 4); $a5 = 2097151 & (self::load_3(self::substr($a, 13, 3)) >> 1); $a6 = 2097151 & (self::load_4(self::substr($a, 15, 4)) >> 6); $a7 = 2097151 & (self::load_3(self::substr($a, 18, 3)) >> 3); $a8 = 2097151 & self::load_3(self::substr($a, 21, 3)); $a9 = 2097151 & (self::load_4(self::substr($a, 23, 4)) >> 5); $a10 = 2097151 & (self::load_3(self::substr($a, 26, 3)) >> 2); $a11 = (self::load_4(self::substr($a, 28, 4)) >> 7); // int64_t b0 = 2097151 & load_3(b); // int64_t b1 = 2097151 & (load_4(b + 2) >> 5); // int64_t b2 = 2097151 & (load_3(b + 5) >> 2); // int64_t b3 = 2097151 & (load_4(b + 7) >> 7); // int64_t b4 = 2097151 & (load_4(b + 10) >> 4); // int64_t b5 = 2097151 & (load_3(b + 13) >> 1); // int64_t b6 = 2097151 & (load_4(b + 15) >> 6); // int64_t b7 = 2097151 & (load_3(b + 18) >> 3); // int64_t b8 = 2097151 & load_3(b + 21); // int64_t b9 = 2097151 & (load_4(b + 23) >> 5); // int64_t b10 = 2097151 & (load_3(b + 26) >> 2); // int64_t b11 = (load_4(b + 28) >> 7); $b0 = 2097151 & self::load_3(self::substr($b, 0, 3)); $b1 = 2097151 & (self::load_4(self::substr($b, 2, 4)) >> 5); $b2 = 2097151 & (self::load_3(self::substr($b, 5, 3)) >> 2); $b3 = 2097151 & (self::load_4(self::substr($b, 7, 4)) >> 7); $b4 = 2097151 & (self::load_4(self::substr($b, 10, 4)) >> 4); $b5 = 2097151 & (self::load_3(self::substr($b, 13, 3)) >> 1); $b6 = 2097151 & (self::load_4(self::substr($b, 15, 4)) >> 6); $b7 = 2097151 & (self::load_3(self::substr($b, 18, 3)) >> 3); $b8 = 2097151 & self::load_3(self::substr($b, 21, 3)); $b9 = 2097151 & (self::load_4(self::substr($b, 23, 4)) >> 5); $b10 = 2097151 & (self::load_3(self::substr($b, 26, 3)) >> 2); $b11 = (self::load_4(self::substr($b, 28, 4)) >> 7); // s0 = a0 * b0; // s1 = a0 * b1 + a1 * b0; // s2 = a0 * b2 + a1 * b1 + a2 * b0; // s3 = a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; // s4 = a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0; // s5 = a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0; // s6 = a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0; // s7 = a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + // a6 * b1 + a7 * b0; // s8 = a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + // a6 * b2 + a7 * b1 + a8 * b0; // s9 = a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + // a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0; // s10 = a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + // a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0; // s11 = a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + // a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0; // s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + // a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1; // s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + // a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2; // s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + // a9 * b5 + a10 * b4 + a11 * b3; // s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + // a10 * b5 + a11 * b4; // s16 = // a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5; // s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6; // s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7; // s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8; // s20 = a9 * b11 + a10 * b10 + a11 * b9; // s21 = a10 * b11 + a11 * b10; // s22 = a11 * b11; // s23 = 0; $s0 = self::mul($a0, $b0, 22); $s1 = self::mul($a0, $b1, 22) + self::mul($a1, $b0, 22); $s2 = self::mul($a0, $b2, 22) + self::mul($a1, $b1, 22) + self::mul($a2, $b0, 22); $s3 = self::mul($a0, $b3, 22) + self::mul($a1, $b2, 22) + self::mul($a2, $b1, 22) + self::mul($a3, $b0, 22); $s4 = self::mul($a0, $b4, 22) + self::mul($a1, $b3, 22) + self::mul($a2, $b2, 22) + self::mul($a3, $b1, 22) + self::mul($a4, $b0, 22); $s5 = self::mul($a0, $b5, 22) + self::mul($a1, $b4, 22) + self::mul($a2, $b3, 22) + self::mul($a3, $b2, 22) + self::mul($a4, $b1, 22) + self::mul($a5, $b0, 22); $s6 = self::mul($a0, $b6, 22) + self::mul($a1, $b5, 22) + self::mul($a2, $b4, 22) + self::mul($a3, $b3, 22) + self::mul($a4, $b2, 22) + self::mul($a5, $b1, 22) + self::mul($a6, $b0, 22); $s7 = self::mul($a0, $b7, 22) + self::mul($a1, $b6, 22) + self::mul($a2, $b5, 22) + self::mul($a3, $b4, 22) + self::mul($a4, $b3, 22) + self::mul($a5, $b2, 22) + self::mul($a6, $b1, 22) + self::mul($a7, $b0, 22); $s8 = self::mul($a0, $b8, 22) + self::mul($a1, $b7, 22) + self::mul($a2, $b6, 22) + self::mul($a3, $b5, 22) + self::mul($a4, $b4, 22) + self::mul($a5, $b3, 22) + self::mul($a6, $b2, 22) + self::mul($a7, $b1, 22) + self::mul($a8, $b0, 22); $s9 = self::mul($a0, $b9, 22) + self::mul($a1, $b8, 22) + self::mul($a2, $b7, 22) + self::mul($a3, $b6, 22) + self::mul($a4, $b5, 22) + self::mul($a5, $b4, 22) + self::mul($a6, $b3, 22) + self::mul($a7, $b2, 22) + self::mul($a8, $b1, 22) + self::mul($a9, $b0, 22); $s10 = self::mul($a0, $b10, 22) + self::mul($a1, $b9, 22) + self::mul($a2, $b8, 22) + self::mul($a3, $b7, 22) + self::mul($a4, $b6, 22) + self::mul($a5, $b5, 22) + self::mul($a6, $b4, 22) + self::mul($a7, $b3, 22) + self::mul($a8, $b2, 22) + self::mul($a9, $b1, 22) + self::mul($a10, $b0, 22); $s11 = self::mul($a0, $b11, 22) + self::mul($a1, $b10, 22) + self::mul($a2, $b9, 22) + self::mul($a3, $b8, 22) + self::mul($a4, $b7, 22) + self::mul($a5, $b6, 22) + self::mul($a6, $b5, 22) + self::mul($a7, $b4, 22) + self::mul($a8, $b3, 22) + self::mul($a9, $b2, 22) + self::mul($a10, $b1, 22) + self::mul($a11, $b0, 22); $s12 = self::mul($a1, $b11, 22) + self::mul($a2, $b10, 22) + self::mul($a3, $b9, 22) + self::mul($a4, $b8, 22) + self::mul($a5, $b7, 22) + self::mul($a6, $b6, 22) + self::mul($a7, $b5, 22) + self::mul($a8, $b4, 22) + self::mul($a9, $b3, 22) + self::mul($a10, $b2, 22) + self::mul($a11, $b1, 22); $s13 = self::mul($a2, $b11, 22) + self::mul($a3, $b10, 22) + self::mul($a4, $b9, 22) + self::mul($a5, $b8, 22) + self::mul($a6, $b7, 22) + self::mul($a7, $b6, 22) + self::mul($a8, $b5, 22) + self::mul($a9, $b4, 22) + self::mul($a10, $b3, 22) + self::mul($a11, $b2, 22); $s14 = self::mul($a3, $b11, 22) + self::mul($a4, $b10, 22) + self::mul($a5, $b9, 22) + self::mul($a6, $b8, 22) + self::mul($a7, $b7, 22) + self::mul($a8, $b6, 22) + self::mul($a9, $b5, 22) + self::mul($a10, $b4, 22) + self::mul($a11, $b3, 22); $s15 = self::mul($a4, $b11, 22) + self::mul($a5, $b10, 22) + self::mul($a6, $b9, 22) + self::mul($a7, $b8, 22) + self::mul($a8, $b7, 22) + self::mul($a9, $b6, 22) + self::mul($a10, $b5, 22) + self::mul($a11, $b4, 22); $s16 = self::mul($a5, $b11, 22) + self::mul($a6, $b10, 22) + self::mul($a7, $b9, 22) + self::mul($a8, $b8, 22) + self::mul($a9, $b7, 22) + self::mul($a10, $b6, 22) + self::mul($a11, $b5, 22); $s17 = self::mul($a6, $b11, 22) + self::mul($a7, $b10, 22) + self::mul($a8, $b9, 22) + self::mul($a9, $b8, 22) + self::mul($a10, $b7, 22) + self::mul($a11, $b6, 22); $s18 = self::mul($a7, $b11, 22) + self::mul($a8, $b10, 22) + self::mul($a9, $b9, 22) + self::mul($a10, $b8, 22) + self::mul($a11, $b7, 22); $s19 = self::mul($a8, $b11, 22) + self::mul($a9, $b10, 22) + self::mul($a10, $b9, 22) + self::mul($a11, $b8, 22); $s20 = self::mul($a9, $b11, 22) + self::mul($a10, $b10, 22) + self::mul($a11, $b9, 22); $s21 = self::mul($a10, $b11, 22) + self::mul($a11, $b10, 22); $s22 = self::mul($a11, $b11, 22); $s23 = 0; // carry0 = (s0 + (int64_t) (1L << 20)) >> 21; // s1 += carry0; // s0 -= carry0 * ((uint64_t) 1L << 21); $carry0 = ($s0 + (1 << 20)) >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; // carry2 = (s2 + (int64_t) (1L << 20)) >> 21; // s3 += carry2; // s2 -= carry2 * ((uint64_t) 1L << 21); $carry2 = ($s2 + (1 << 20)) >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; // carry4 = (s4 + (int64_t) (1L << 20)) >> 21; // s5 += carry4; // s4 -= carry4 * ((uint64_t) 1L << 21); $carry4 = ($s4 + (1 << 20)) >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; // carry6 = (s6 + (int64_t) (1L << 20)) >> 21; // s7 += carry6; // s6 -= carry6 * ((uint64_t) 1L << 21); $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; // carry8 = (s8 + (int64_t) (1L << 20)) >> 21; // s9 += carry8; // s8 -= carry8 * ((uint64_t) 1L << 21); $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; // carry10 = (s10 + (int64_t) (1L << 20)) >> 21; // s11 += carry10; // s10 -= carry10 * ((uint64_t) 1L << 21); $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; // carry12 = (s12 + (int64_t) (1L << 20)) >> 21; // s13 += carry12; // s12 -= carry12 * ((uint64_t) 1L << 21); $carry12 = ($s12 + (1 << 20)) >> 21; $s13 += $carry12; $s12 -= $carry12 << 21; // carry14 = (s14 + (int64_t) (1L << 20)) >> 21; // s15 += carry14; // s14 -= carry14 * ((uint64_t) 1L << 21); $carry14 = ($s14 + (1 << 20)) >> 21; $s15 += $carry14; $s14 -= $carry14 << 21; // carry16 = (s16 + (int64_t) (1L << 20)) >> 21; // s17 += carry16; // s16 -= carry16 * ((uint64_t) 1L << 21); $carry16 = ($s16 + (1 << 20)) >> 21; $s17 += $carry16; $s16 -= $carry16 << 21; // carry18 = (s18 + (int64_t) (1L << 20)) >> 21; // s19 += carry18; // s18 -= carry18 * ((uint64_t) 1L << 21); $carry18 = ($s18 + (1 << 20)) >> 21; $s19 += $carry18; $s18 -= $carry18 << 21; // carry20 = (s20 + (int64_t) (1L << 20)) >> 21; // s21 += carry20; // s20 -= carry20 * ((uint64_t) 1L << 21); $carry20 = ($s20 + (1 << 20)) >> 21; $s21 += $carry20; $s20 -= $carry20 << 21; // carry22 = (s22 + (int64_t) (1L << 20)) >> 21; // s23 += carry22; // s22 -= carry22 * ((uint64_t) 1L << 21); $carry22 = ($s22 + (1 << 20)) >> 21; $s23 += $carry22; $s22 -= $carry22 << 21; // carry1 = (s1 + (int64_t) (1L << 20)) >> 21; // s2 += carry1; // s1 -= carry1 * ((uint64_t) 1L << 21); $carry1 = ($s1 + (1 << 20)) >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; // carry3 = (s3 + (int64_t) (1L << 20)) >> 21; // s4 += carry3; // s3 -= carry3 * ((uint64_t) 1L << 21); $carry3 = ($s3 + (1 << 20)) >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; // carry5 = (s5 + (int64_t) (1L << 20)) >> 21; // s6 += carry5; // s5 -= carry5 * ((uint64_t) 1L << 21); $carry5 = ($s5 + (1 << 20)) >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; // carry7 = (s7 + (int64_t) (1L << 20)) >> 21; // s8 += carry7; // s7 -= carry7 * ((uint64_t) 1L << 21); $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; // carry9 = (s9 + (int64_t) (1L << 20)) >> 21; // s10 += carry9; // s9 -= carry9 * ((uint64_t) 1L << 21); $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; // carry11 = (s11 + (int64_t) (1L << 20)) >> 21; // s12 += carry11; // s11 -= carry11 * ((uint64_t) 1L << 21); $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; // carry13 = (s13 + (int64_t) (1L << 20)) >> 21; // s14 += carry13; // s13 -= carry13 * ((uint64_t) 1L << 21); $carry13 = ($s13 + (1 << 20)) >> 21; $s14 += $carry13; $s13 -= $carry13 << 21; // carry15 = (s15 + (int64_t) (1L << 20)) >> 21; // s16 += carry15; // s15 -= carry15 * ((uint64_t) 1L << 21); $carry15 = ($s15 + (1 << 20)) >> 21; $s16 += $carry15; $s15 -= $carry15 << 21; // carry17 = (s17 + (int64_t) (1L << 20)) >> 21; // s18 += carry17; // s17 -= carry17 * ((uint64_t) 1L << 21); $carry17 = ($s17 + (1 << 20)) >> 21; $s18 += $carry17; $s17 -= $carry17 << 21; // carry19 = (s19 + (int64_t) (1L << 20)) >> 21; // s20 += carry19; // s19 -= carry19 * ((uint64_t) 1L << 21); $carry19 = ($s19 + (1 << 20)) >> 21; $s20 += $carry19; $s19 -= $carry19 << 21; // carry21 = (s21 + (int64_t) (1L << 20)) >> 21; // s22 += carry21; // s21 -= carry21 * ((uint64_t) 1L << 21); $carry21 = ($s21 + (1 << 20)) >> 21; $s22 += $carry21; $s21 -= $carry21 << 21; // s11 += s23 * 666643; // s12 += s23 * 470296; // s13 += s23 * 654183; // s14 -= s23 * 997805; // s15 += s23 * 136657; // s16 -= s23 * 683901; $s11 += self::mul($s23, 666643, 20); $s12 += self::mul($s23, 470296, 19); $s13 += self::mul($s23, 654183, 20); $s14 -= self::mul($s23, 997805, 20); $s15 += self::mul($s23, 136657, 18); $s16 -= self::mul($s23, 683901, 20); // s10 += s22 * 666643; // s11 += s22 * 470296; // s12 += s22 * 654183; // s13 -= s22 * 997805; // s14 += s22 * 136657; // s15 -= s22 * 683901; $s10 += self::mul($s22, 666643, 20); $s11 += self::mul($s22, 470296, 19); $s12 += self::mul($s22, 654183, 20); $s13 -= self::mul($s22, 997805, 20); $s14 += self::mul($s22, 136657, 18); $s15 -= self::mul($s22, 683901, 20); // s9 += s21 * 666643; // s10 += s21 * 470296; // s11 += s21 * 654183; // s12 -= s21 * 997805; // s13 += s21 * 136657; // s14 -= s21 * 683901; $s9 += self::mul($s21, 666643, 20); $s10 += self::mul($s21, 470296, 19); $s11 += self::mul($s21, 654183, 20); $s12 -= self::mul($s21, 997805, 20); $s13 += self::mul($s21, 136657, 18); $s14 -= self::mul($s21, 683901, 20); // s8 += s20 * 666643; // s9 += s20 * 470296; // s10 += s20 * 654183; // s11 -= s20 * 997805; // s12 += s20 * 136657; // s13 -= s20 * 683901; $s8 += self::mul($s20, 666643, 20); $s9 += self::mul($s20, 470296, 19); $s10 += self::mul($s20, 654183, 20); $s11 -= self::mul($s20, 997805, 20); $s12 += self::mul($s20, 136657, 18); $s13 -= self::mul($s20, 683901, 20); // s7 += s19 * 666643; // s8 += s19 * 470296; // s9 += s19 * 654183; // s10 -= s19 * 997805; // s11 += s19 * 136657; // s12 -= s19 * 683901; $s7 += self::mul($s19, 666643, 20); $s8 += self::mul($s19, 470296, 19); $s9 += self::mul($s19, 654183, 20); $s10 -= self::mul($s19, 997805, 20); $s11 += self::mul($s19, 136657, 18); $s12 -= self::mul($s19, 683901, 20); // s6 += s18 * 666643; // s7 += s18 * 470296; // s8 += s18 * 654183; // s9 -= s18 * 997805; // s10 += s18 * 136657; // s11 -= s18 * 683901; $s6 += self::mul($s18, 666643, 20); $s7 += self::mul($s18, 470296, 19); $s8 += self::mul($s18, 654183, 20); $s9 -= self::mul($s18, 997805, 20); $s10 += self::mul($s18, 136657, 18); $s11 -= self::mul($s18, 683901, 20); // carry6 = (s6 + (int64_t) (1L << 20)) >> 21; // s7 += carry6; // s6 -= carry6 * ((uint64_t) 1L << 21); $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; // carry8 = (s8 + (int64_t) (1L << 20)) >> 21; // s9 += carry8; // s8 -= carry8 * ((uint64_t) 1L << 21); $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; // carry10 = (s10 + (int64_t) (1L << 20)) >> 21; // s11 += carry10; // s10 -= carry10 * ((uint64_t) 1L << 21); $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; // carry12 = (s12 + (int64_t) (1L << 20)) >> 21; // s13 += carry12; // s12 -= carry12 * ((uint64_t) 1L << 21); $carry12 = ($s12 + (1 << 20)) >> 21; $s13 += $carry12; $s12 -= $carry12 << 21; // carry14 = (s14 + (int64_t) (1L << 20)) >> 21; // s15 += carry14; // s14 -= carry14 * ((uint64_t) 1L << 21); $carry14 = ($s14 + (1 << 20)) >> 21; $s15 += $carry14; $s14 -= $carry14 << 21; // carry16 = (s16 + (int64_t) (1L << 20)) >> 21; // s17 += carry16; // s16 -= carry16 * ((uint64_t) 1L << 21); $carry16 = ($s16 + (1 << 20)) >> 21; $s17 += $carry16; $s16 -= $carry16 << 21; // carry7 = (s7 + (int64_t) (1L << 20)) >> 21; // s8 += carry7; // s7 -= carry7 * ((uint64_t) 1L << 21); $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; // carry9 = (s9 + (int64_t) (1L << 20)) >> 21; // s10 += carry9; // s9 -= carry9 * ((uint64_t) 1L << 21); $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; // carry11 = (s11 + (int64_t) (1L << 20)) >> 21; // s12 += carry11; // s11 -= carry11 * ((uint64_t) 1L << 21); $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; // carry13 = (s13 + (int64_t) (1L << 20)) >> 21; // s14 += carry13; // s13 -= carry13 * ((uint64_t) 1L << 21); $carry13 = ($s13 + (1 << 20)) >> 21; $s14 += $carry13; $s13 -= $carry13 << 21; // carry15 = (s15 + (int64_t) (1L << 20)) >> 21; // s16 += carry15; // s15 -= carry15 * ((uint64_t) 1L << 21); $carry15 = ($s15 + (1 << 20)) >> 21; $s16 += $carry15; $s15 -= $carry15 << 21; // s5 += s17 * 666643; // s6 += s17 * 470296; // s7 += s17 * 654183; // s8 -= s17 * 997805; // s9 += s17 * 136657; // s10 -= s17 * 683901; $s5 += self::mul($s17, 666643, 20); $s6 += self::mul($s17, 470296, 19); $s7 += self::mul($s17, 654183, 20); $s8 -= self::mul($s17, 997805, 20); $s9 += self::mul($s17, 136657, 18); $s10 -= self::mul($s17, 683901, 20); // s4 += s16 * 666643; // s5 += s16 * 470296; // s6 += s16 * 654183; // s7 -= s16 * 997805; // s8 += s16 * 136657; // s9 -= s16 * 683901; $s4 += self::mul($s16, 666643, 20); $s5 += self::mul($s16, 470296, 19); $s6 += self::mul($s16, 654183, 20); $s7 -= self::mul($s16, 997805, 20); $s8 += self::mul($s16, 136657, 18); $s9 -= self::mul($s16, 683901, 20); // s3 += s15 * 666643; // s4 += s15 * 470296; // s5 += s15 * 654183; // s6 -= s15 * 997805; // s7 += s15 * 136657; // s8 -= s15 * 683901; $s3 += self::mul($s15, 666643, 20); $s4 += self::mul($s15, 470296, 19); $s5 += self::mul($s15, 654183, 20); $s6 -= self::mul($s15, 997805, 20); $s7 += self::mul($s15, 136657, 18); $s8 -= self::mul($s15, 683901, 20); // s2 += s14 * 666643; // s3 += s14 * 470296; // s4 += s14 * 654183; // s5 -= s14 * 997805; // s6 += s14 * 136657; // s7 -= s14 * 683901; $s2 += self::mul($s14, 666643, 20); $s3 += self::mul($s14, 470296, 19); $s4 += self::mul($s14, 654183, 20); $s5 -= self::mul($s14, 997805, 20); $s6 += self::mul($s14, 136657, 18); $s7 -= self::mul($s14, 683901, 20); // s1 += s13 * 666643; // s2 += s13 * 470296; // s3 += s13 * 654183; // s4 -= s13 * 997805; // s5 += s13 * 136657; // s6 -= s13 * 683901; $s1 += self::mul($s13, 666643, 20); $s2 += self::mul($s13, 470296, 19); $s3 += self::mul($s13, 654183, 20); $s4 -= self::mul($s13, 997805, 20); $s5 += self::mul($s13, 136657, 18); $s6 -= self::mul($s13, 683901, 20); // s0 += s12 * 666643; // s1 += s12 * 470296; // s2 += s12 * 654183; // s3 -= s12 * 997805; // s4 += s12 * 136657; // s5 -= s12 * 683901; // s12 = 0; $s0 += self::mul($s12, 666643, 20); $s1 += self::mul($s12, 470296, 19); $s2 += self::mul($s12, 654183, 20); $s3 -= self::mul($s12, 997805, 20); $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); $s12 = 0; // carry0 = (s0 + (int64_t) (1L << 20)) >> 21; // s1 += carry0; // s0 -= carry0 * ((uint64_t) 1L << 21); $carry0 = ($s0 + (1 << 20)) >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; // carry2 = (s2 + (int64_t) (1L << 20)) >> 21; // s3 += carry2; // s2 -= carry2 * ((uint64_t) 1L << 21); $carry2 = ($s2 + (1 << 20)) >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; // carry4 = (s4 + (int64_t) (1L << 20)) >> 21; // s5 += carry4; // s4 -= carry4 * ((uint64_t) 1L << 21); $carry4 = ($s4 + (1 << 20)) >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; // carry6 = (s6 + (int64_t) (1L << 20)) >> 21; // s7 += carry6; // s6 -= carry6 * ((uint64_t) 1L << 21); $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; // carry8 = (s8 + (int64_t) (1L << 20)) >> 21; // s9 += carry8; // s8 -= carry8 * ((uint64_t) 1L << 21); $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; // carry10 = (s10 + (int64_t) (1L << 20)) >> 21; // s11 += carry10; // s10 -= carry10 * ((uint64_t) 1L << 21); $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; // carry1 = (s1 + (int64_t) (1L << 20)) >> 21; // s2 += carry1; // s1 -= carry1 * ((uint64_t) 1L << 21); $carry1 = ($s1 + (1 << 20)) >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; // carry3 = (s3 + (int64_t) (1L << 20)) >> 21; // s4 += carry3; // s3 -= carry3 * ((uint64_t) 1L << 21); $carry3 = ($s3 + (1 << 20)) >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; // carry5 = (s5 + (int64_t) (1L << 20)) >> 21; // s6 += carry5; // s5 -= carry5 * ((uint64_t) 1L << 21); $carry5 = ($s5 + (1 << 20)) >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; // carry7 = (s7 + (int64_t) (1L << 20)) >> 21; // s8 += carry7; // s7 -= carry7 * ((uint64_t) 1L << 21); $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; // carry9 = (s9 + (int64_t) (1L << 20)) >> 21; // s10 += carry9; // s9 -= carry9 * ((uint64_t) 1L << 21); $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; // carry11 = (s11 + (int64_t) (1L << 20)) >> 21; // s12 += carry11; // s11 -= carry11 * ((uint64_t) 1L << 21); $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; // s0 += s12 * 666643; // s1 += s12 * 470296; // s2 += s12 * 654183; // s3 -= s12 * 997805; // s4 += s12 * 136657; // s5 -= s12 * 683901; // s12 = 0; $s0 += self::mul($s12, 666643, 20); $s1 += self::mul($s12, 470296, 19); $s2 += self::mul($s12, 654183, 20); $s3 -= self::mul($s12, 997805, 20); $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); $s12 = 0; // carry0 = s0 >> 21; // s1 += carry0; // s0 -= carry0 * ((uint64_t) 1L << 21); $carry0 = $s0 >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; // carry1 = s1 >> 21; // s2 += carry1; // s1 -= carry1 * ((uint64_t) 1L << 21); $carry1 = $s1 >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; // carry2 = s2 >> 21; // s3 += carry2; // s2 -= carry2 * ((uint64_t) 1L << 21); $carry2 = $s2 >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; // carry3 = s3 >> 21; // s4 += carry3; // s3 -= carry3 * ((uint64_t) 1L << 21); $carry3 = $s3 >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; // carry4 = s4 >> 21; // s5 += carry4; // s4 -= carry4 * ((uint64_t) 1L << 21); $carry4 = $s4 >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; // carry5 = s5 >> 21; // s6 += carry5; // s5 -= carry5 * ((uint64_t) 1L << 21); $carry5 = $s5 >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; // carry6 = s6 >> 21; // s7 += carry6; // s6 -= carry6 * ((uint64_t) 1L << 21); $carry6 = $s6 >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; // carry7 = s7 >> 21; // s8 += carry7; // s7 -= carry7 * ((uint64_t) 1L << 21); $carry7 = $s7 >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; // carry8 = s8 >> 21; // s9 += carry8; // s8 -= carry8 * ((uint64_t) 1L << 21); $carry8 = $s8 >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; // carry9 = s9 >> 21; // s10 += carry9; // s9 -= carry9 * ((uint64_t) 1L << 21); $carry9 = $s9 >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; // carry10 = s10 >> 21; // s11 += carry10; // s10 -= carry10 * ((uint64_t) 1L << 21); $carry10 = $s10 >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; // carry11 = s11 >> 21; // s12 += carry11; // s11 -= carry11 * ((uint64_t) 1L << 21); $carry11 = $s11 >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; // s0 += s12 * 666643; // s1 += s12 * 470296; // s2 += s12 * 654183; // s3 -= s12 * 997805; // s4 += s12 * 136657; // s5 -= s12 * 683901; $s0 += self::mul($s12, 666643, 20); $s1 += self::mul($s12, 470296, 19); $s2 += self::mul($s12, 654183, 20); $s3 -= self::mul($s12, 997805, 20); $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); // carry0 = s0 >> 21; // s1 += carry0; // s0 -= carry0 * ((uint64_t) 1L << 21); $carry0 = $s0 >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; // carry1 = s1 >> 21; // s2 += carry1; // s1 -= carry1 * ((uint64_t) 1L << 21); $carry1 = $s1 >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; // carry2 = s2 >> 21; // s3 += carry2; // s2 -= carry2 * ((uint64_t) 1L << 21); $carry2 = $s2 >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; // carry3 = s3 >> 21; // s4 += carry3; // s3 -= carry3 * ((uint64_t) 1L << 21); $carry3 = $s3 >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; // carry4 = s4 >> 21; // s5 += carry4; // s4 -= carry4 * ((uint64_t) 1L << 21); $carry4 = $s4 >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; // carry5 = s5 >> 21; // s6 += carry5; // s5 -= carry5 * ((uint64_t) 1L << 21); $carry5 = $s5 >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; // carry6 = s6 >> 21; // s7 += carry6; // s6 -= carry6 * ((uint64_t) 1L << 21); $carry6 = $s6 >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; // carry7 = s7 >> 21; // s8 += carry7; // s7 -= carry7 * ((uint64_t) 1L << 21); $carry7 = $s7 >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; // carry8 = s8 >> 21; // s9 += carry8; // s8 -= carry8 * ((uint64_t) 1L << 21); $carry8 = $s8 >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; // carry9 = s9 >> 21; // s10 += carry9; // s9 -= carry9 * ((uint64_t) 1L << 21); $carry9 = $s9 >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; // carry10 = s10 >> 21; // s11 += carry10; // s10 -= carry10 * ((uint64_t) 1L << 21); $carry10 = $s10 >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; $s = array_fill(0, 32, 0); // s[0] = s0 >> 0; $s[0] = $s0 >> 0; // s[1] = s0 >> 8; $s[1] = $s0 >> 8; // s[2] = (s0 >> 16) | (s1 * ((uint64_t) 1 << 5)); $s[2] = ($s0 >> 16) | ($s1 << 5); // s[3] = s1 >> 3; $s[3] = $s1 >> 3; // s[4] = s1 >> 11; $s[4] = $s1 >> 11; // s[5] = (s1 >> 19) | (s2 * ((uint64_t) 1 << 2)); $s[5] = ($s1 >> 19) | ($s2 << 2); // s[6] = s2 >> 6; $s[6] = $s2 >> 6; // s[7] = (s2 >> 14) | (s3 * ((uint64_t) 1 << 7)); $s[7] = ($s2 >> 14) | ($s3 << 7); // s[8] = s3 >> 1; $s[8] = $s3 >> 1; // s[9] = s3 >> 9; $s[9] = $s3 >> 9; // s[10] = (s3 >> 17) | (s4 * ((uint64_t) 1 << 4)); $s[10] = ($s3 >> 17) | ($s4 << 4); // s[11] = s4 >> 4; $s[11] = $s4 >> 4; // s[12] = s4 >> 12; $s[12] = $s4 >> 12; // s[13] = (s4 >> 20) | (s5 * ((uint64_t) 1 << 1)); $s[13] = ($s4 >> 20) | ($s5 << 1); // s[14] = s5 >> 7; $s[14] = $s5 >> 7; // s[15] = (s5 >> 15) | (s6 * ((uint64_t) 1 << 6)); $s[15] = ($s5 >> 15) | ($s6 << 6); // s[16] = s6 >> 2; $s[16] = $s6 >> 2; // s[17] = s6 >> 10; $s[17] = $s6 >> 10; // s[18] = (s6 >> 18) | (s7 * ((uint64_t) 1 << 3)); $s[18] = ($s6 >> 18) | ($s7 << 3); // s[19] = s7 >> 5; $s[19] = $s7 >> 5; // s[20] = s7 >> 13; $s[20] = $s7 >> 13; // s[21] = s8 >> 0; $s[21] = $s8 >> 0; // s[22] = s8 >> 8; $s[22] = $s8 >> 8; // s[23] = (s8 >> 16) | (s9 * ((uint64_t) 1 << 5)); $s[23] = ($s8 >> 16) | ($s9 << 5); // s[24] = s9 >> 3; $s[24] = $s9 >> 3; // s[25] = s9 >> 11; $s[25] = $s9 >> 11; // s[26] = (s9 >> 19) | (s10 * ((uint64_t) 1 << 2)); $s[26] = ($s9 >> 19) | ($s10 << 2); // s[27] = s10 >> 6; $s[27] = $s10 >> 6; // s[28] = (s10 >> 14) | (s11 * ((uint64_t) 1 << 7)); $s[28] = ($s10 >> 14) | ($s11 << 7); // s[29] = s11 >> 1; $s[29] = $s11 >> 1; // s[30] = s11 >> 9; $s[30] = $s11 >> 9; // s[31] = s11 >> 17; $s[31] = $s11 >> 17; return self::intArrayToString($s); } /** * @param string $s * @return string */ public static function sc25519_sq($s) { return self::sc25519_mul($s, $s); } /** * @param string $s * @param int $n * @param string $a * @return string */ public static function sc25519_sqmul($s, $n, $a) { for ($i = 0; $i < $n; ++$i) { $s = self::sc25519_sq($s); } return self::sc25519_mul($s, $a); } /** * @param string $s * @return string */ public static function sc25519_invert($s) { $_10 = self::sc25519_sq($s); $_11 = self::sc25519_mul($s, $_10); $_100 = self::sc25519_mul($s, $_11); $_1000 = self::sc25519_sq($_100); $_1010 = self::sc25519_mul($_10, $_1000); $_1011 = self::sc25519_mul($s, $_1010); $_10000 = self::sc25519_sq($_1000); $_10110 = self::sc25519_sq($_1011); $_100000 = self::sc25519_mul($_1010, $_10110); $_100110 = self::sc25519_mul($_10000, $_10110); $_1000000 = self::sc25519_sq($_100000); $_1010000 = self::sc25519_mul($_10000, $_1000000); $_1010011 = self::sc25519_mul($_11, $_1010000); $_1100011 = self::sc25519_mul($_10000, $_1010011); $_1100111 = self::sc25519_mul($_100, $_1100011); $_1101011 = self::sc25519_mul($_100, $_1100111); $_10010011 = self::sc25519_mul($_1000000, $_1010011); $_10010111 = self::sc25519_mul($_100, $_10010011); $_10111101 = self::sc25519_mul($_100110, $_10010111); $_11010011 = self::sc25519_mul($_10110, $_10111101); $_11100111 = self::sc25519_mul($_1010000, $_10010111); $_11101011 = self::sc25519_mul($_100, $_11100111); $_11110101 = self::sc25519_mul($_1010, $_11101011); $recip = self::sc25519_mul($_1011, $_11110101); $recip = self::sc25519_sqmul($recip, 126, $_1010011); $recip = self::sc25519_sqmul($recip, 9, $_10); $recip = self::sc25519_mul($recip, $_11110101); $recip = self::sc25519_sqmul($recip, 7, $_1100111); $recip = self::sc25519_sqmul($recip, 9, $_11110101); $recip = self::sc25519_sqmul($recip, 11, $_10111101); $recip = self::sc25519_sqmul($recip, 8, $_11100111); $recip = self::sc25519_sqmul($recip, 9, $_1101011); $recip = self::sc25519_sqmul($recip, 6, $_1011); $recip = self::sc25519_sqmul($recip, 14, $_10010011); $recip = self::sc25519_sqmul($recip, 10, $_1100011); $recip = self::sc25519_sqmul($recip, 9, $_10010111); $recip = self::sc25519_sqmul($recip, 10, $_11110101); $recip = self::sc25519_sqmul($recip, 8, $_11010011); return self::sc25519_sqmul($recip, 8, $_11101011); } /** * @param string $s * @return string */ public static function clamp($s) { $s_ = self::stringToIntArray($s); $s_[0] &= 248; $s_[31] |= 64; $s_[31] &= 128; return self::intArrayToString($s_); } /** * Ensure limbs are less than 28 bits long to prevent float promotion. * * This uses a constant-time conditional swap under the hood. * * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function fe_normalize(ParagonIE_Sodium_Core_Curve25519_Fe $f) { $x = (PHP_INT_SIZE << 3) - 1; // 31 or 63 $g = self::fe_copy($f); for ($i = 0; $i < 10; ++$i) { $mask = -(($g[$i] >> $x) & 1); /* * Get two candidate normalized values for $g[$i], depending on the sign of $g[$i]: */ $a = $g[$i] & 0x7ffffff; $b = -((-$g[$i]) & 0x7ffffff); /* * Return the appropriate candidate value, based on the sign of the original input: * * The following is equivalent to this ternary: * * $g[$i] = (($g[$i] >> $x) & 1) ? $a : $b; * * Except what's written doesn't contain timing leaks. */ $g[$i] = ($a ^ (($a ^ $b) & $mask)); } return $g; } } PK������ZI2��2����Core/ChaCha20.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_ChaCha20', false)) { return; } /** * Class ParagonIE_Sodium_Core_ChaCha20 */ class ParagonIE_Sodium_Core_ChaCha20 extends ParagonIE_Sodium_Core_Util { /** * Bitwise left rotation * * @internal You should not use this directly from another application * * @param int $v * @param int $n * @return int */ public static function rotate($v, $n) { $v &= 0xffffffff; $n &= 31; return (int) ( 0xffffffff & ( ($v << $n) | ($v >> (32 - $n)) ) ); } /** * The ChaCha20 quarter round function. Works on four 32-bit integers. * * @internal You should not use this directly from another application * * @param int $a * @param int $b * @param int $c * @param int $d * @return array<int, int> */ protected static function quarterRound($a, $b, $c, $d) { # a = PLUS(a,b); d = ROTATE(XOR(d,a),16); /** @var int $a */ $a = ($a + $b) & 0xffffffff; $d = self::rotate($d ^ $a, 16); # c = PLUS(c,d); b = ROTATE(XOR(b,c),12); /** @var int $c */ $c = ($c + $d) & 0xffffffff; $b = self::rotate($b ^ $c, 12); # a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); /** @var int $a */ $a = ($a + $b) & 0xffffffff; $d = self::rotate($d ^ $a, 8); # c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); /** @var int $c */ $c = ($c + $d) & 0xffffffff; $b = self::rotate($b ^ $c, 7); return array((int) $a, (int) $b, (int) $c, (int) $d); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_ChaCha20_Ctx $ctx * @param string $message * * @return string * @throws TypeError * @throws SodiumException */ public static function encryptBytes( ParagonIE_Sodium_Core_ChaCha20_Ctx $ctx, $message = '' ) { $bytes = self::strlen($message); /* j0 = ctx->input[0]; j1 = ctx->input[1]; j2 = ctx->input[2]; j3 = ctx->input[3]; j4 = ctx->input[4]; j5 = ctx->input[5]; j6 = ctx->input[6]; j7 = ctx->input[7]; j8 = ctx->input[8]; j9 = ctx->input[9]; j10 = ctx->input[10]; j11 = ctx->input[11]; j12 = ctx->input[12]; j13 = ctx->input[13]; j14 = ctx->input[14]; j15 = ctx->input[15]; */ $j0 = (int) $ctx[0]; $j1 = (int) $ctx[1]; $j2 = (int) $ctx[2]; $j3 = (int) $ctx[3]; $j4 = (int) $ctx[4]; $j5 = (int) $ctx[5]; $j6 = (int) $ctx[6]; $j7 = (int) $ctx[7]; $j8 = (int) $ctx[8]; $j9 = (int) $ctx[9]; $j10 = (int) $ctx[10]; $j11 = (int) $ctx[11]; $j12 = (int) $ctx[12]; $j13 = (int) $ctx[13]; $j14 = (int) $ctx[14]; $j15 = (int) $ctx[15]; $c = ''; for (;;) { if ($bytes < 64) { $message .= str_repeat("\x00", 64 - $bytes); } $x0 = (int) $j0; $x1 = (int) $j1; $x2 = (int) $j2; $x3 = (int) $j3; $x4 = (int) $j4; $x5 = (int) $j5; $x6 = (int) $j6; $x7 = (int) $j7; $x8 = (int) $j8; $x9 = (int) $j9; $x10 = (int) $j10; $x11 = (int) $j11; $x12 = (int) $j12; $x13 = (int) $j13; $x14 = (int) $j14; $x15 = (int) $j15; # for (i = 20; i > 0; i -= 2) { for ($i = 20; $i > 0; $i -= 2) { # QUARTERROUND( x0, x4, x8, x12) list($x0, $x4, $x8, $x12) = self::quarterRound($x0, $x4, $x8, $x12); # QUARTERROUND( x1, x5, x9, x13) list($x1, $x5, $x9, $x13) = self::quarterRound($x1, $x5, $x9, $x13); # QUARTERROUND( x2, x6, x10, x14) list($x2, $x6, $x10, $x14) = self::quarterRound($x2, $x6, $x10, $x14); # QUARTERROUND( x3, x7, x11, x15) list($x3, $x7, $x11, $x15) = self::quarterRound($x3, $x7, $x11, $x15); # QUARTERROUND( x0, x5, x10, x15) list($x0, $x5, $x10, $x15) = self::quarterRound($x0, $x5, $x10, $x15); # QUARTERROUND( x1, x6, x11, x12) list($x1, $x6, $x11, $x12) = self::quarterRound($x1, $x6, $x11, $x12); # QUARTERROUND( x2, x7, x8, x13) list($x2, $x7, $x8, $x13) = self::quarterRound($x2, $x7, $x8, $x13); # QUARTERROUND( x3, x4, x9, x14) list($x3, $x4, $x9, $x14) = self::quarterRound($x3, $x4, $x9, $x14); } /* x0 = PLUS(x0, j0); x1 = PLUS(x1, j1); x2 = PLUS(x2, j2); x3 = PLUS(x3, j3); x4 = PLUS(x4, j4); x5 = PLUS(x5, j5); x6 = PLUS(x6, j6); x7 = PLUS(x7, j7); x8 = PLUS(x8, j8); x9 = PLUS(x9, j9); x10 = PLUS(x10, j10); x11 = PLUS(x11, j11); x12 = PLUS(x12, j12); x13 = PLUS(x13, j13); x14 = PLUS(x14, j14); x15 = PLUS(x15, j15); */ /** @var int $x0 */ $x0 = ($x0 & 0xffffffff) + $j0; /** @var int $x1 */ $x1 = ($x1 & 0xffffffff) + $j1; /** @var int $x2 */ $x2 = ($x2 & 0xffffffff) + $j2; /** @var int $x3 */ $x3 = ($x3 & 0xffffffff) + $j3; /** @var int $x4 */ $x4 = ($x4 & 0xffffffff) + $j4; /** @var int $x5 */ $x5 = ($x5 & 0xffffffff) + $j5; /** @var int $x6 */ $x6 = ($x6 & 0xffffffff) + $j6; /** @var int $x7 */ $x7 = ($x7 & 0xffffffff) + $j7; /** @var int $x8 */ $x8 = ($x8 & 0xffffffff) + $j8; /** @var int $x9 */ $x9 = ($x9 & 0xffffffff) + $j9; /** @var int $x10 */ $x10 = ($x10 & 0xffffffff) + $j10; /** @var int $x11 */ $x11 = ($x11 & 0xffffffff) + $j11; /** @var int $x12 */ $x12 = ($x12 & 0xffffffff) + $j12; /** @var int $x13 */ $x13 = ($x13 & 0xffffffff) + $j13; /** @var int $x14 */ $x14 = ($x14 & 0xffffffff) + $j14; /** @var int $x15 */ $x15 = ($x15 & 0xffffffff) + $j15; /* x0 = XOR(x0, LOAD32_LE(m + 0)); x1 = XOR(x1, LOAD32_LE(m + 4)); x2 = XOR(x2, LOAD32_LE(m + 8)); x3 = XOR(x3, LOAD32_LE(m + 12)); x4 = XOR(x4, LOAD32_LE(m + 16)); x5 = XOR(x5, LOAD32_LE(m + 20)); x6 = XOR(x6, LOAD32_LE(m + 24)); x7 = XOR(x7, LOAD32_LE(m + 28)); x8 = XOR(x8, LOAD32_LE(m + 32)); x9 = XOR(x9, LOAD32_LE(m + 36)); x10 = XOR(x10, LOAD32_LE(m + 40)); x11 = XOR(x11, LOAD32_LE(m + 44)); x12 = XOR(x12, LOAD32_LE(m + 48)); x13 = XOR(x13, LOAD32_LE(m + 52)); x14 = XOR(x14, LOAD32_LE(m + 56)); x15 = XOR(x15, LOAD32_LE(m + 60)); */ $x0 ^= self::load_4(self::substr($message, 0, 4)); $x1 ^= self::load_4(self::substr($message, 4, 4)); $x2 ^= self::load_4(self::substr($message, 8, 4)); $x3 ^= self::load_4(self::substr($message, 12, 4)); $x4 ^= self::load_4(self::substr($message, 16, 4)); $x5 ^= self::load_4(self::substr($message, 20, 4)); $x6 ^= self::load_4(self::substr($message, 24, 4)); $x7 ^= self::load_4(self::substr($message, 28, 4)); $x8 ^= self::load_4(self::substr($message, 32, 4)); $x9 ^= self::load_4(self::substr($message, 36, 4)); $x10 ^= self::load_4(self::substr($message, 40, 4)); $x11 ^= self::load_4(self::substr($message, 44, 4)); $x12 ^= self::load_4(self::substr($message, 48, 4)); $x13 ^= self::load_4(self::substr($message, 52, 4)); $x14 ^= self::load_4(self::substr($message, 56, 4)); $x15 ^= self::load_4(self::substr($message, 60, 4)); /* j12 = PLUSONE(j12); if (!j12) { j13 = PLUSONE(j13); } */ ++$j12; if ($j12 & 0xf0000000) { throw new SodiumException('Overflow'); } /* STORE32_LE(c + 0, x0); STORE32_LE(c + 4, x1); STORE32_LE(c + 8, x2); STORE32_LE(c + 12, x3); STORE32_LE(c + 16, x4); STORE32_LE(c + 20, x5); STORE32_LE(c + 24, x6); STORE32_LE(c + 28, x7); STORE32_LE(c + 32, x8); STORE32_LE(c + 36, x9); STORE32_LE(c + 40, x10); STORE32_LE(c + 44, x11); STORE32_LE(c + 48, x12); STORE32_LE(c + 52, x13); STORE32_LE(c + 56, x14); STORE32_LE(c + 60, x15); */ $block = self::store32_le((int) ($x0 & 0xffffffff)) . self::store32_le((int) ($x1 & 0xffffffff)) . self::store32_le((int) ($x2 & 0xffffffff)) . self::store32_le((int) ($x3 & 0xffffffff)) . self::store32_le((int) ($x4 & 0xffffffff)) . self::store32_le((int) ($x5 & 0xffffffff)) . self::store32_le((int) ($x6 & 0xffffffff)) . self::store32_le((int) ($x7 & 0xffffffff)) . self::store32_le((int) ($x8 & 0xffffffff)) . self::store32_le((int) ($x9 & 0xffffffff)) . self::store32_le((int) ($x10 & 0xffffffff)) . self::store32_le((int) ($x11 & 0xffffffff)) . self::store32_le((int) ($x12 & 0xffffffff)) . self::store32_le((int) ($x13 & 0xffffffff)) . self::store32_le((int) ($x14 & 0xffffffff)) . self::store32_le((int) ($x15 & 0xffffffff)); /* Partial block */ if ($bytes < 64) { $c .= self::substr($block, 0, $bytes); break; } /* Full block */ $c .= $block; $bytes -= 64; if ($bytes <= 0) { break; } $message = self::substr($message, 64); } /* end for(;;) loop */ $ctx[12] = $j12; $ctx[13] = $j13; return $c; } /** * @internal You should not use this directly from another application * * @param int $len * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function stream($len = 64, $nonce = '', $key = '') { return self::encryptBytes( new ParagonIE_Sodium_Core_ChaCha20_Ctx($key, $nonce), str_repeat("\x00", $len) ); } /** * @internal You should not use this directly from another application * * @param int $len * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function ietfStream($len, $nonce = '', $key = '') { return self::encryptBytes( new ParagonIE_Sodium_Core_ChaCha20_IetfCtx($key, $nonce), str_repeat("\x00", $len) ); } /** * @internal You should not use this directly from another application * * @param string $message * @param string $nonce * @param string $key * @param string $ic * @return string * @throws SodiumException * @throws TypeError */ public static function ietfStreamXorIc($message, $nonce = '', $key = '', $ic = '') { return self::encryptBytes( new ParagonIE_Sodium_Core_ChaCha20_IetfCtx($key, $nonce, $ic), $message ); } /** * @internal You should not use this directly from another application * * @param string $message * @param string $nonce * @param string $key * @param string $ic * @return string * @throws SodiumException * @throws TypeError */ public static function streamXorIc($message, $nonce = '', $key = '', $ic = '') { return self::encryptBytes( new ParagonIE_Sodium_Core_ChaCha20_Ctx($key, $nonce, $ic), $message ); } } PK������Z0) ��) ����Core/Salsa20.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_Salsa20', false)) { return; } /** * Class ParagonIE_Sodium_Core_Salsa20 */ abstract class ParagonIE_Sodium_Core_Salsa20 extends ParagonIE_Sodium_Core_Util { const ROUNDS = 20; /** * Calculate an salsa20 hash of a single block * * @internal You should not use this directly from another application * * @param string $in * @param string $k * @param string|null $c * @return string * @throws TypeError */ public static function core_salsa20($in, $k, $c = null) { if (self::strlen($k) < 32) { throw new RangeException('Key must be 32 bytes long'); } if ($c === null) { $j0 = $x0 = 0x61707865; $j5 = $x5 = 0x3320646e; $j10 = $x10 = 0x79622d32; $j15 = $x15 = 0x6b206574; } else { $j0 = $x0 = self::load_4(self::substr($c, 0, 4)); $j5 = $x5 = self::load_4(self::substr($c, 4, 4)); $j10 = $x10 = self::load_4(self::substr($c, 8, 4)); $j15 = $x15 = self::load_4(self::substr($c, 12, 4)); } $j1 = $x1 = self::load_4(self::substr($k, 0, 4)); $j2 = $x2 = self::load_4(self::substr($k, 4, 4)); $j3 = $x3 = self::load_4(self::substr($k, 8, 4)); $j4 = $x4 = self::load_4(self::substr($k, 12, 4)); $j6 = $x6 = self::load_4(self::substr($in, 0, 4)); $j7 = $x7 = self::load_4(self::substr($in, 4, 4)); $j8 = $x8 = self::load_4(self::substr($in, 8, 4)); $j9 = $x9 = self::load_4(self::substr($in, 12, 4)); $j11 = $x11 = self::load_4(self::substr($k, 16, 4)); $j12 = $x12 = self::load_4(self::substr($k, 20, 4)); $j13 = $x13 = self::load_4(self::substr($k, 24, 4)); $j14 = $x14 = self::load_4(self::substr($k, 28, 4)); for ($i = self::ROUNDS; $i > 0; $i -= 2) { $x4 ^= self::rotate($x0 + $x12, 7); $x8 ^= self::rotate($x4 + $x0, 9); $x12 ^= self::rotate($x8 + $x4, 13); $x0 ^= self::rotate($x12 + $x8, 18); $x9 ^= self::rotate($x5 + $x1, 7); $x13 ^= self::rotate($x9 + $x5, 9); $x1 ^= self::rotate($x13 + $x9, 13); $x5 ^= self::rotate($x1 + $x13, 18); $x14 ^= self::rotate($x10 + $x6, 7); $x2 ^= self::rotate($x14 + $x10, 9); $x6 ^= self::rotate($x2 + $x14, 13); $x10 ^= self::rotate($x6 + $x2, 18); $x3 ^= self::rotate($x15 + $x11, 7); $x7 ^= self::rotate($x3 + $x15, 9); $x11 ^= self::rotate($x7 + $x3, 13); $x15 ^= self::rotate($x11 + $x7, 18); $x1 ^= self::rotate($x0 + $x3, 7); $x2 ^= self::rotate($x1 + $x0, 9); $x3 ^= self::rotate($x2 + $x1, 13); $x0 ^= self::rotate($x3 + $x2, 18); $x6 ^= self::rotate($x5 + $x4, 7); $x7 ^= self::rotate($x6 + $x5, 9); $x4 ^= self::rotate($x7 + $x6, 13); $x5 ^= self::rotate($x4 + $x7, 18); $x11 ^= self::rotate($x10 + $x9, 7); $x8 ^= self::rotate($x11 + $x10, 9); $x9 ^= self::rotate($x8 + $x11, 13); $x10 ^= self::rotate($x9 + $x8, 18); $x12 ^= self::rotate($x15 + $x14, 7); $x13 ^= self::rotate($x12 + $x15, 9); $x14 ^= self::rotate($x13 + $x12, 13); $x15 ^= self::rotate($x14 + $x13, 18); } $x0 += $j0; $x1 += $j1; $x2 += $j2; $x3 += $j3; $x4 += $j4; $x5 += $j5; $x6 += $j6; $x7 += $j7; $x8 += $j8; $x9 += $j9; $x10 += $j10; $x11 += $j11; $x12 += $j12; $x13 += $j13; $x14 += $j14; $x15 += $j15; return self::store32_le($x0) . self::store32_le($x1) . self::store32_le($x2) . self::store32_le($x3) . self::store32_le($x4) . self::store32_le($x5) . self::store32_le($x6) . self::store32_le($x7) . self::store32_le($x8) . self::store32_le($x9) . self::store32_le($x10) . self::store32_le($x11) . self::store32_le($x12) . self::store32_le($x13) . self::store32_le($x14) . self::store32_le($x15); } /** * @internal You should not use this directly from another application * * @param int $len * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function salsa20($len, $nonce, $key) { if (self::strlen($key) !== 32) { throw new RangeException('Key must be 32 bytes long'); } $kcopy = '' . $key; $in = self::substr($nonce, 0, 8) . str_repeat("\0", 8); $c = ''; while ($len >= 64) { $c .= self::core_salsa20($in, $kcopy, null); $u = 1; // Internal counter. for ($i = 8; $i < 16; ++$i) { $u += self::chrToInt($in[$i]); $in[$i] = self::intToChr($u & 0xff); $u >>= 8; } $len -= 64; } if ($len > 0) { $c .= self::substr( self::core_salsa20($in, $kcopy, null), 0, $len ); } try { ParagonIE_Sodium_Compat::memzero($kcopy); } catch (SodiumException $ex) { $kcopy = null; } return $c; } /** * @internal You should not use this directly from another application * * @param string $m * @param string $n * @param int $ic * @param string $k * @return string * @throws SodiumException * @throws TypeError */ public static function salsa20_xor_ic($m, $n, $ic, $k) { $mlen = self::strlen($m); if ($mlen < 1) { return ''; } $kcopy = self::substr($k, 0, 32); $in = self::substr($n, 0, 8); // Initialize the counter $in .= ParagonIE_Sodium_Core_Util::store64_le($ic); $c = ''; while ($mlen >= 64) { $block = self::core_salsa20($in, $kcopy, null); $c .= self::xorStrings( self::substr($m, 0, 64), self::substr($block, 0, 64) ); $u = 1; for ($i = 8; $i < 16; ++$i) { $u += self::chrToInt($in[$i]); $in[$i] = self::intToChr($u & 0xff); $u >>= 8; } $mlen -= 64; $m = self::substr($m, 64); } if ($mlen) { $block = self::core_salsa20($in, $kcopy, null); $c .= self::xorStrings( self::substr($m, 0, $mlen), self::substr($block, 0, $mlen) ); } try { ParagonIE_Sodium_Compat::memzero($block); ParagonIE_Sodium_Compat::memzero($kcopy); } catch (SodiumException $ex) { $block = null; $kcopy = null; } return $c; } /** * @internal You should not use this directly from another application * * @param string $message * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function salsa20_xor($message, $nonce, $key) { return self::xorStrings( $message, self::salsa20( self::strlen($message), $nonce, $key ) ); } /** * @internal You should not use this directly from another application * * @param int $u * @param int $c * @return int */ public static function rotate($u, $c) { $u &= 0xffffffff; $c %= 32; return (int) (0xffffffff & ( ($u << $c) | ($u >> (32 - $c)) ) ); } } PK������Z"(��(����Core/SecretStream/State.phpnu�W+A��������<?php /** * Class ParagonIE_Sodium_Core_SecretStream_State */ class ParagonIE_Sodium_Core_SecretStream_State { /** @var string $key */ protected $key; /** @var int $counter */ protected $counter; /** @var string $nonce */ protected $nonce; /** @var string $_pad */ protected $_pad; /** * ParagonIE_Sodium_Core_SecretStream_State constructor. * @param string $key * @param string|null $nonce */ public function __construct($key, $nonce = null) { $this->key = $key; $this->counter = 1; if (is_null($nonce)) { $nonce = str_repeat("\0", 12); } $this->nonce = str_pad($nonce, 12, "\0", STR_PAD_RIGHT);; $this->_pad = str_repeat("\0", 4); } /** * @return self */ public function counterReset() { $this->counter = 1; $this->_pad = str_repeat("\0", 4); return $this; } /** * @return string */ public function getKey() { return $this->key; } /** * @return string */ public function getCounter() { return ParagonIE_Sodium_Core_Util::store32_le($this->counter); } /** * @return string */ public function getNonce() { if (!is_string($this->nonce)) { $this->nonce = str_repeat("\0", 12); } if (ParagonIE_Sodium_Core_Util::strlen($this->nonce) !== 12) { $this->nonce = str_pad($this->nonce, 12, "\0", STR_PAD_RIGHT); } return $this->nonce; } /** * @return string */ public function getCombinedNonce() { return $this->getCounter() . ParagonIE_Sodium_Core_Util::substr($this->getNonce(), 0, 8); } /** * @return self */ public function incrementCounter() { ++$this->counter; return $this; } /** * @return bool */ public function needsRekey() { return ($this->counter & 0xffff) === 0; } /** * @param string $newKeyAndNonce * @return self */ public function rekey($newKeyAndNonce) { $this->key = ParagonIE_Sodium_Core_Util::substr($newKeyAndNonce, 0, 32); $this->nonce = str_pad( ParagonIE_Sodium_Core_Util::substr($newKeyAndNonce, 32), 12, "\0", STR_PAD_RIGHT ); return $this; } /** * @param string $str * @return self */ public function xorNonce($str) { $this->nonce = ParagonIE_Sodium_Core_Util::xorStrings( $this->getNonce(), str_pad( ParagonIE_Sodium_Core_Util::substr($str, 0, 8), 12, "\0", STR_PAD_RIGHT ) ); return $this; } /** * @param string $string * @return self */ public static function fromString($string) { $state = new ParagonIE_Sodium_Core_SecretStream_State( ParagonIE_Sodium_Core_Util::substr($string, 0, 32) ); $state->counter = ParagonIE_Sodium_Core_Util::load_4( ParagonIE_Sodium_Core_Util::substr($string, 32, 4) ); $state->nonce = ParagonIE_Sodium_Core_Util::substr($string, 36, 12); $state->_pad = ParagonIE_Sodium_Core_Util::substr($string, 48, 8); return $state; } /** * @return string */ public function toString() { return $this->key . $this->getCounter() . $this->nonce . $this->_pad; } } PK������ZCDf��f����Core/ChaCha20/Ctx.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_ChaCha20_Ctx', false)) { return; } /** * Class ParagonIE_Sodium_Core_ChaCha20_Ctx */ class ParagonIE_Sodium_Core_ChaCha20_Ctx extends ParagonIE_Sodium_Core_Util implements ArrayAccess { /** * @var SplFixedArray internally, <int, int> */ protected $container; /** * ParagonIE_Sodium_Core_ChaCha20_Ctx constructor. * * @internal You should not use this directly from another application * * @param string $key ChaCha20 key. * @param string $iv Initialization Vector (a.k.a. nonce). * @param string $counter The initial counter value. * Defaults to 8 0x00 bytes. * @throws InvalidArgumentException * @throws TypeError */ public function __construct($key = '', $iv = '', $counter = '') { if (self::strlen($key) !== 32) { throw new InvalidArgumentException('ChaCha20 expects a 256-bit key.'); } if (self::strlen($iv) !== 8) { throw new InvalidArgumentException('ChaCha20 expects a 64-bit nonce.'); } $this->container = new SplFixedArray(16); /* "expand 32-byte k" as per ChaCha20 spec */ $this->container[0] = 0x61707865; $this->container[1] = 0x3320646e; $this->container[2] = 0x79622d32; $this->container[3] = 0x6b206574; $this->container[4] = self::load_4(self::substr($key, 0, 4)); $this->container[5] = self::load_4(self::substr($key, 4, 4)); $this->container[6] = self::load_4(self::substr($key, 8, 4)); $this->container[7] = self::load_4(self::substr($key, 12, 4)); $this->container[8] = self::load_4(self::substr($key, 16, 4)); $this->container[9] = self::load_4(self::substr($key, 20, 4)); $this->container[10] = self::load_4(self::substr($key, 24, 4)); $this->container[11] = self::load_4(self::substr($key, 28, 4)); if (empty($counter)) { $this->container[12] = 0; $this->container[13] = 0; } else { $this->container[12] = self::load_4(self::substr($counter, 0, 4)); $this->container[13] = self::load_4(self::substr($counter, 4, 4)); } $this->container[14] = self::load_4(self::substr($iv, 0, 4)); $this->container[15] = self::load_4(self::substr($iv, 4, 4)); } /** * @internal You should not use this directly from another application * * @param int $offset * @param int $value * @return void * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetSet($offset, $value) { if (!is_int($offset)) { throw new InvalidArgumentException('Expected an integer'); } if (!is_int($value)) { throw new InvalidArgumentException('Expected an integer'); } $this->container[$offset] = $value; } /** * @internal You should not use this directly from another application * * @param int $offset * @return bool */ #[ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->container[$offset]); } /** * @internal You should not use this directly from another application * * @param int $offset * @return void * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->container[$offset]); } /** * @internal You should not use this directly from another application * * @param int $offset * @return mixed|null * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetGet($offset) { return isset($this->container[$offset]) ? $this->container[$offset] : null; } } PK������ZӘ*��*����Core/ChaCha20/IetfCtx.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_ChaCha20_IetfCtx', false)) { return; } /** * Class ParagonIE_Sodium_Core_ChaCha20_IetfCtx */ class ParagonIE_Sodium_Core_ChaCha20_IetfCtx extends ParagonIE_Sodium_Core_ChaCha20_Ctx { /** * ParagonIE_Sodium_Core_ChaCha20_IetfCtx constructor. * * @internal You should not use this directly from another application * * @param string $key ChaCha20 key. * @param string $iv Initialization Vector (a.k.a. nonce). * @param string $counter The initial counter value. * Defaults to 4 0x00 bytes. * @throws InvalidArgumentException * @throws TypeError */ public function __construct($key = '', $iv = '', $counter = '') { if (self::strlen($iv) !== 12) { throw new InvalidArgumentException('ChaCha20 expects a 96-bit nonce in IETF mode.'); } parent::__construct($key, self::substr($iv, 0, 8), $counter); if (!empty($counter)) { $this->container[12] = self::load_4(self::substr($counter, 0, 4)); } $this->container[13] = self::load_4(self::substr($iv, 0, 4)); $this->container[14] = self::load_4(self::substr($iv, 4, 4)); $this->container[15] = self::load_4(self::substr($iv, 8, 4)); } } PK������Z.}��}����Core/AEGIS/State256.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_AEGIS_State256', false)) { return; } if (!defined('SODIUM_COMPAT_AEGIS_C0')) { define('SODIUM_COMPAT_AEGIS_C0', "\x00\x01\x01\x02\x03\x05\x08\x0d\x15\x22\x37\x59\x90\xe9\x79\x62"); } if (!defined('SODIUM_COMPAT_AEGIS_C1')) { define('SODIUM_COMPAT_AEGIS_C1', "\xdb\x3d\x18\x55\x6d\xc2\x2f\xf1\x20\x11\x31\x42\x73\xb5\x28\xdd"); } class ParagonIE_Sodium_Core_AEGIS_State256 { /** @var array<int, string> $state */ protected $state; public function __construct() { $this->state = array_fill(0, 6, ''); } /** * @internal Only use this for unit tests! * @return string[] */ public function getState() { return array_values($this->state); } /** * @param array $input * @return self * @throws SodiumException * * @internal Only for unit tests */ public static function initForUnitTests(array $input) { if (count($input) < 6) { throw new SodiumException('invalid input'); } $state = new self(); for ($i = 0; $i < 6; ++$i) { $state->state[$i] = $input[$i]; } return $state; } /** * @param string $key * @param string $nonce * @return self */ public static function init($key, $nonce) { $state = new self(); $k0 = ParagonIE_Sodium_Core_Util::substr($key, 0, 16); $k1 = ParagonIE_Sodium_Core_Util::substr($key, 16, 16); $n0 = ParagonIE_Sodium_Core_Util::substr($nonce, 0, 16); $n1 = ParagonIE_Sodium_Core_Util::substr($nonce, 16, 16); // S0 = k0 ^ n0 // S1 = k1 ^ n1 // S2 = C1 // S3 = C0 // S4 = k0 ^ C0 // S5 = k1 ^ C1 $k0_n0 = $k0 ^ $n0; $k1_n1 = $k1 ^ $n1; $state->state[0] = $k0_n0; $state->state[1] = $k1_n1; $state->state[2] = SODIUM_COMPAT_AEGIS_C1; $state->state[3] = SODIUM_COMPAT_AEGIS_C0; $state->state[4] = $k0 ^ SODIUM_COMPAT_AEGIS_C0; $state->state[5] = $k1 ^ SODIUM_COMPAT_AEGIS_C1; // Repeat(4, // Update(k0) // Update(k1) // Update(k0 ^ n0) // Update(k1 ^ n1) // ) for ($i = 0; $i < 4; ++$i) { $state->update($k0); $state->update($k1); $state->update($k0 ^ $n0); $state->update($k1 ^ $n1); } return $state; } /** * @param string $ai * @return self * @throws SodiumException */ public function absorb($ai) { if (ParagonIE_Sodium_Core_Util::strlen($ai) !== 16) { throw new SodiumException('Input must be an AES block in size'); } return $this->update($ai); } /** * @param string $ci * @return string * @throws SodiumException */ public function dec($ci) { if (ParagonIE_Sodium_Core_Util::strlen($ci) !== 16) { throw new SodiumException('Input must be an AES block in size'); } // z = S1 ^ S4 ^ S5 ^ (S2 & S3) $z = $this->state[1] ^ $this->state[4] ^ $this->state[5] ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[2], $this->state[3]); $xi = $ci ^ $z; $this->update($xi); return $xi; } /** * @param string $cn * @return string */ public function decPartial($cn) { $len = ParagonIE_Sodium_Core_Util::strlen($cn); // z = S1 ^ S4 ^ S5 ^ (S2 & S3) $z = $this->state[1] ^ $this->state[4] ^ $this->state[5] ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[2], $this->state[3]); // t = ZeroPad(cn, 128) $t = str_pad($cn, 16, "\0", STR_PAD_RIGHT); // out = t ^ z $out = $t ^ $z; // xn = Truncate(out, |cn|) $xn = ParagonIE_Sodium_Core_Util::substr($out, 0, $len); // v = ZeroPad(xn, 128) $v = str_pad($xn, 16, "\0", STR_PAD_RIGHT); // Update(v) $this->update($v); // return xn return $xn; } /** * @param string $xi * @return string * @throws SodiumException */ public function enc($xi) { if (ParagonIE_Sodium_Core_Util::strlen($xi) !== 16) { throw new SodiumException('Input must be an AES block in size'); } // z = S1 ^ S4 ^ S5 ^ (S2 & S3) $z = $this->state[1] ^ $this->state[4] ^ $this->state[5] ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[2], $this->state[3]); $this->update($xi); return $xi ^ $z; } /** * @param int $ad_len_bits * @param int $msg_len_bits * @return string */ public function finalize($ad_len_bits, $msg_len_bits) { $encoded = ParagonIE_Sodium_Core_Util::store64_le($ad_len_bits) . ParagonIE_Sodium_Core_Util::store64_le($msg_len_bits); $t = $this->state[3] ^ $encoded; for ($i = 0; $i < 7; ++$i) { $this->update($t); } return ($this->state[0] ^ $this->state[1] ^ $this->state[2]) . ($this->state[3] ^ $this->state[4] ^ $this->state[5]); } /** * @param string $m * @return self */ public function update($m) { /* S'0 = AESRound(S5, S0 ^ M) S'1 = AESRound(S0, S1) S'2 = AESRound(S1, S2) S'3 = AESRound(S2, S3) S'4 = AESRound(S3, S4) S'5 = AESRound(S4, S5) */ list($s_0, $s_1) = ParagonIE_Sodium_Core_AES::doubleRound( $this->state[5],$this->state[0] ^ $m, $this->state[0], $this->state[1] ); list($s_2, $s_3) = ParagonIE_Sodium_Core_AES::doubleRound( $this->state[1], $this->state[2], $this->state[2], $this->state[3] ); list($s_4, $s_5) = ParagonIE_Sodium_Core_AES::doubleRound( $this->state[3], $this->state[4], $this->state[4], $this->state[5] ); /* S0 = S'0 S1 = S'1 S2 = S'2 S3 = S'3 S4 = S'4 S5 = S'5 */ $this->state[0] = $s_0; $this->state[1] = $s_1; $this->state[2] = $s_2; $this->state[3] = $s_3; $this->state[4] = $s_4; $this->state[5] = $s_5; return $this; } } PK������Z.]L* ��* ����Core/AEGIS/State128L.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_AEGIS_State128L', false)) { return; } if (!defined('SODIUM_COMPAT_AEGIS_C0')) { define('SODIUM_COMPAT_AEGIS_C0', "\x00\x01\x01\x02\x03\x05\x08\x0d\x15\x22\x37\x59\x90\xe9\x79\x62"); } if (!defined('SODIUM_COMPAT_AEGIS_C1')) { define('SODIUM_COMPAT_AEGIS_C1', "\xdb\x3d\x18\x55\x6d\xc2\x2f\xf1\x20\x11\x31\x42\x73\xb5\x28\xdd"); } class ParagonIE_Sodium_Core_AEGIS_State128L { /** @var array<int, string> $state */ protected $state; public function __construct() { $this->state = array_fill(0, 8, ''); } /** * @internal Only use this for unit tests! * @return string[] */ public function getState() { return array_values($this->state); } /** * @param array $input * @return self * @throws SodiumException * * @internal Only for unit tests */ public static function initForUnitTests(array $input) { if (count($input) < 8) { throw new SodiumException('invalid input'); } $state = new self(); for ($i = 0; $i < 8; ++$i) { $state->state[$i] = $input[$i]; } return $state; } /** * @param string $key * @param string $nonce * @return self */ public static function init($key, $nonce) { $state = new self(); // S0 = key ^ nonce $state->state[0] = $key ^ $nonce; // S1 = C1 $state->state[1] = SODIUM_COMPAT_AEGIS_C1; // S2 = C0 $state->state[2] = SODIUM_COMPAT_AEGIS_C0; // S3 = C1 $state->state[3] = SODIUM_COMPAT_AEGIS_C1; // S4 = key ^ nonce $state->state[4] = $key ^ $nonce; // S5 = key ^ C0 $state->state[5] = $key ^ SODIUM_COMPAT_AEGIS_C0; // S6 = key ^ C1 $state->state[6] = $key ^ SODIUM_COMPAT_AEGIS_C1; // S7 = key ^ C0 $state->state[7] = $key ^ SODIUM_COMPAT_AEGIS_C0; // Repeat(10, Update(nonce, key)) for ($i = 0; $i < 10; ++$i) { $state->update($nonce, $key); } return $state; } /** * @param string $ai * @return self */ public function absorb($ai) { if (ParagonIE_Sodium_Core_Util::strlen($ai) !== 32) { throw new SodiumException('Input must be two AES blocks in size'); } $t0 = ParagonIE_Sodium_Core_Util::substr($ai, 0, 16); $t1 = ParagonIE_Sodium_Core_Util::substr($ai, 16, 16); return $this->update($t0, $t1); } /** * @param string $ci * @return string * @throws SodiumException */ public function dec($ci) { if (ParagonIE_Sodium_Core_Util::strlen($ci) !== 32) { throw new SodiumException('Input must be two AES blocks in size'); } // z0 = S6 ^ S1 ^ (S2 & S3) $z0 = $this->state[6] ^ $this->state[1] ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[2], $this->state[3]); // z1 = S2 ^ S5 ^ (S6 & S7) $z1 = $this->state[2] ^ $this->state[5] ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[6], $this->state[7]); // t0, t1 = Split(xi, 128) $t0 = ParagonIE_Sodium_Core_Util::substr($ci, 0, 16); $t1 = ParagonIE_Sodium_Core_Util::substr($ci, 16, 16); // out0 = t0 ^ z0 // out1 = t1 ^ z1 $out0 = $t0 ^ $z0; $out1 = $t1 ^ $z1; // Update(out0, out1) // xi = out0 || out1 $this->update($out0, $out1); return $out0 . $out1; } /** * @param string $cn * @return string */ public function decPartial($cn) { $len = ParagonIE_Sodium_Core_Util::strlen($cn); // z0 = S6 ^ S1 ^ (S2 & S3) $z0 = $this->state[6] ^ $this->state[1] ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[2], $this->state[3]); // z1 = S2 ^ S5 ^ (S6 & S7) $z1 = $this->state[2] ^ $this->state[5] ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[6], $this->state[7]); // t0, t1 = Split(ZeroPad(cn, 256), 128) $cn = str_pad($cn, 32, "\0", STR_PAD_RIGHT); $t0 = ParagonIE_Sodium_Core_Util::substr($cn, 0, 16); $t1 = ParagonIE_Sodium_Core_Util::substr($cn, 16, 16); // out0 = t0 ^ z0 // out1 = t1 ^ z1 $out0 = $t0 ^ $z0; $out1 = $t1 ^ $z1; // xn = Truncate(out0 || out1, |cn|) $xn = ParagonIE_Sodium_Core_Util::substr($out0 . $out1, 0, $len); // v0, v1 = Split(ZeroPad(xn, 256), 128) $padded = str_pad($xn, 32, "\0", STR_PAD_RIGHT); $v0 = ParagonIE_Sodium_Core_Util::substr($padded, 0, 16); $v1 = ParagonIE_Sodium_Core_Util::substr($padded, 16, 16); // Update(v0, v1) $this->update($v0, $v1); // return xn return $xn; } /** * @param string $xi * @return string * @throws SodiumException */ public function enc($xi) { if (ParagonIE_Sodium_Core_Util::strlen($xi) !== 32) { throw new SodiumException('Input must be two AES blocks in size'); } // z0 = S6 ^ S1 ^ (S2 & S3) $z0 = $this->state[6] ^ $this->state[1] ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[2], $this->state[3]); // z1 = S2 ^ S5 ^ (S6 & S7) $z1 = $this->state[2] ^ $this->state[5] ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[6], $this->state[7]); // t0, t1 = Split(xi, 128) $t0 = ParagonIE_Sodium_Core_Util::substr($xi, 0, 16); $t1 = ParagonIE_Sodium_Core_Util::substr($xi, 16, 16); // out0 = t0 ^ z0 // out1 = t1 ^ z1 $out0 = $t0 ^ $z0; $out1 = $t1 ^ $z1; // Update(t0, t1) // ci = out0 || out1 $this->update($t0, $t1); // return ci return $out0 . $out1; } /** * @param int $ad_len_bits * @param int $msg_len_bits * @return string */ public function finalize($ad_len_bits, $msg_len_bits) { $encoded = ParagonIE_Sodium_Core_Util::store64_le($ad_len_bits) . ParagonIE_Sodium_Core_Util::store64_le($msg_len_bits); $t = $this->state[2] ^ $encoded; for ($i = 0; $i < 7; ++$i) { $this->update($t, $t); } return ($this->state[0] ^ $this->state[1] ^ $this->state[2] ^ $this->state[3]) . ($this->state[4] ^ $this->state[5] ^ $this->state[6] ^ $this->state[7]); } /** * @param string $m0 * @param string $m1 * @return self */ public function update($m0, $m1) { /* S'0 = AESRound(S7, S0 ^ M0) S'1 = AESRound(S0, S1) S'2 = AESRound(S1, S2) S'3 = AESRound(S2, S3) S'4 = AESRound(S3, S4 ^ M1) S'5 = AESRound(S4, S5) S'6 = AESRound(S5, S6) S'7 = AESRound(S6, S7) */ list($s_0, $s_1) = ParagonIE_Sodium_Core_AES::doubleRound( $this->state[7], $this->state[0] ^ $m0, $this->state[0], $this->state[1] ); list($s_2, $s_3) = ParagonIE_Sodium_Core_AES::doubleRound( $this->state[1], $this->state[2], $this->state[2], $this->state[3] ); list($s_4, $s_5) = ParagonIE_Sodium_Core_AES::doubleRound( $this->state[3], $this->state[4] ^ $m1, $this->state[4], $this->state[5] ); list($s_6, $s_7) = ParagonIE_Sodium_Core_AES::doubleRound( $this->state[5], $this->state[6], $this->state[6], $this->state[7] ); /* S0 = S'0 S1 = S'1 S2 = S'2 S3 = S'3 S4 = S'4 S5 = S'5 S6 = S'6 S7 = S'7 */ $this->state[0] = $s_0; $this->state[1] = $s_1; $this->state[2] = $s_2; $this->state[3] = $s_3; $this->state[4] = $s_4; $this->state[5] = $s_5; $this->state[6] = $s_6; $this->state[7] = $s_7; return $this; } }PK������Zk &p2��p2����Core/Poly1305/State.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_Poly1305_State', false)) { return; } /** * Class ParagonIE_Sodium_Core_Poly1305_State */ class ParagonIE_Sodium_Core_Poly1305_State extends ParagonIE_Sodium_Core_Util { /** * @var array<int, int> */ protected $buffer = array(); /** * @var bool */ protected $final = false; /** * @var array<int, int> */ public $h; /** * @var int */ protected $leftover = 0; /** * @var int[] */ public $r; /** * @var int[] */ public $pad; /** * ParagonIE_Sodium_Core_Poly1305_State constructor. * * @internal You should not use this directly from another application * * @param string $key * @throws InvalidArgumentException * @throws TypeError */ public function __construct($key = '') { if (self::strlen($key) < 32) { throw new InvalidArgumentException( 'Poly1305 requires a 32-byte key' ); } /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ $this->r = array( (int) ((self::load_4(self::substr($key, 0, 4))) & 0x3ffffff), (int) ((self::load_4(self::substr($key, 3, 4)) >> 2) & 0x3ffff03), (int) ((self::load_4(self::substr($key, 6, 4)) >> 4) & 0x3ffc0ff), (int) ((self::load_4(self::substr($key, 9, 4)) >> 6) & 0x3f03fff), (int) ((self::load_4(self::substr($key, 12, 4)) >> 8) & 0x00fffff) ); /* h = 0 */ $this->h = array(0, 0, 0, 0, 0); /* save pad for later */ $this->pad = array( self::load_4(self::substr($key, 16, 4)), self::load_4(self::substr($key, 20, 4)), self::load_4(self::substr($key, 24, 4)), self::load_4(self::substr($key, 28, 4)), ); $this->leftover = 0; $this->final = false; } /** * Zero internal buffer upon destruction */ public function __destruct() { $this->r[0] ^= $this->r[0]; $this->r[1] ^= $this->r[1]; $this->r[2] ^= $this->r[2]; $this->r[3] ^= $this->r[3]; $this->r[4] ^= $this->r[4]; $this->h[0] ^= $this->h[0]; $this->h[1] ^= $this->h[1]; $this->h[2] ^= $this->h[2]; $this->h[3] ^= $this->h[3]; $this->h[4] ^= $this->h[4]; $this->pad[0] ^= $this->pad[0]; $this->pad[1] ^= $this->pad[1]; $this->pad[2] ^= $this->pad[2]; $this->pad[3] ^= $this->pad[3]; $this->leftover = 0; $this->final = true; } /** * @internal You should not use this directly from another application * * @param string $message * @return self * @throws SodiumException * @throws TypeError */ public function update($message = '') { $bytes = self::strlen($message); if ($bytes < 1) { return $this; } /* handle leftover */ if ($this->leftover) { $want = ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE - $this->leftover; if ($want > $bytes) { $want = $bytes; } for ($i = 0; $i < $want; ++$i) { $mi = self::chrToInt($message[$i]); $this->buffer[$this->leftover + $i] = $mi; } // We snip off the leftmost bytes. $message = self::substr($message, $want); $bytes = self::strlen($message); $this->leftover += $want; if ($this->leftover < ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) { // We still don't have enough to run $this->blocks() return $this; } $this->blocks( self::intArrayToString($this->buffer), ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE ); $this->leftover = 0; } /* process full blocks */ if ($bytes >= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) { /** @var int $want */ $want = $bytes & ~(ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE - 1); if ($want >= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) { $block = self::substr($message, 0, $want); if (self::strlen($block) >= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) { $this->blocks($block, $want); $message = self::substr($message, $want); $bytes = self::strlen($message); } } } /* store leftover */ if ($bytes) { for ($i = 0; $i < $bytes; ++$i) { $mi = self::chrToInt($message[$i]); $this->buffer[$this->leftover + $i] = $mi; } $this->leftover = (int) $this->leftover + $bytes; } return $this; } /** * @internal You should not use this directly from another application * * @param string $message * @param int $bytes * @return self * @throws TypeError */ public function blocks($message, $bytes) { if (self::strlen($message) < 16) { $message = str_pad($message, 16, "\x00", STR_PAD_RIGHT); } /** @var int $hibit */ $hibit = $this->final ? 0 : 1 << 24; /* 1 << 128 */ $r0 = (int) $this->r[0]; $r1 = (int) $this->r[1]; $r2 = (int) $this->r[2]; $r3 = (int) $this->r[3]; $r4 = (int) $this->r[4]; $s1 = self::mul($r1, 5, 3); $s2 = self::mul($r2, 5, 3); $s3 = self::mul($r3, 5, 3); $s4 = self::mul($r4, 5, 3); $h0 = $this->h[0]; $h1 = $this->h[1]; $h2 = $this->h[2]; $h3 = $this->h[3]; $h4 = $this->h[4]; while ($bytes >= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) { /* h += m[i] */ $h0 += self::load_4(self::substr($message, 0, 4)) & 0x3ffffff; $h1 += (self::load_4(self::substr($message, 3, 4)) >> 2) & 0x3ffffff; $h2 += (self::load_4(self::substr($message, 6, 4)) >> 4) & 0x3ffffff; $h3 += (self::load_4(self::substr($message, 9, 4)) >> 6) & 0x3ffffff; $h4 += (self::load_4(self::substr($message, 12, 4)) >> 8) | $hibit; /* h *= r */ $d0 = ( self::mul($h0, $r0, 27) + self::mul($s4, $h1, 27) + self::mul($s3, $h2, 27) + self::mul($s2, $h3, 27) + self::mul($s1, $h4, 27) ); $d1 = ( self::mul($h0, $r1, 27) + self::mul($h1, $r0, 27) + self::mul($s4, $h2, 27) + self::mul($s3, $h3, 27) + self::mul($s2, $h4, 27) ); $d2 = ( self::mul($h0, $r2, 27) + self::mul($h1, $r1, 27) + self::mul($h2, $r0, 27) + self::mul($s4, $h3, 27) + self::mul($s3, $h4, 27) ); $d3 = ( self::mul($h0, $r3, 27) + self::mul($h1, $r2, 27) + self::mul($h2, $r1, 27) + self::mul($h3, $r0, 27) + self::mul($s4, $h4, 27) ); $d4 = ( self::mul($h0, $r4, 27) + self::mul($h1, $r3, 27) + self::mul($h2, $r2, 27) + self::mul($h3, $r1, 27) + self::mul($h4, $r0, 27) ); /* (partial) h %= p */ /** @var int $c */ $c = $d0 >> 26; /** @var int $h0 */ $h0 = $d0 & 0x3ffffff; $d1 += $c; /** @var int $c */ $c = $d1 >> 26; /** @var int $h1 */ $h1 = $d1 & 0x3ffffff; $d2 += $c; /** @var int $c */ $c = $d2 >> 26; /** @var int $h2 */ $h2 = $d2 & 0x3ffffff; $d3 += $c; /** @var int $c */ $c = $d3 >> 26; /** @var int $h3 */ $h3 = $d3 & 0x3ffffff; $d4 += $c; /** @var int $c */ $c = $d4 >> 26; /** @var int $h4 */ $h4 = $d4 & 0x3ffffff; $h0 += (int) self::mul($c, 5, 3); /** @var int $c */ $c = $h0 >> 26; /** @var int $h0 */ $h0 &= 0x3ffffff; $h1 += $c; // Chop off the left 32 bytes. $message = self::substr( $message, ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE ); $bytes -= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE; } $this->h = array( (int) ($h0 & 0xffffffff), (int) ($h1 & 0xffffffff), (int) ($h2 & 0xffffffff), (int) ($h3 & 0xffffffff), (int) ($h4 & 0xffffffff) ); return $this; } /** * @internal You should not use this directly from another application * * @return string * @throws TypeError */ public function finish() { /* process the remaining block */ if ($this->leftover) { $i = $this->leftover; $this->buffer[$i++] = 1; for (; $i < ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE; ++$i) { $this->buffer[$i] = 0; } $this->final = true; $this->blocks( self::substr( self::intArrayToString($this->buffer), 0, ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE ), ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE ); } $h0 = (int) $this->h[0]; $h1 = (int) $this->h[1]; $h2 = (int) $this->h[2]; $h3 = (int) $this->h[3]; $h4 = (int) $this->h[4]; /** @var int $c */ $c = $h1 >> 26; /** @var int $h1 */ $h1 &= 0x3ffffff; /** @var int $h2 */ $h2 += $c; /** @var int $c */ $c = $h2 >> 26; /** @var int $h2 */ $h2 &= 0x3ffffff; $h3 += $c; /** @var int $c */ $c = $h3 >> 26; $h3 &= 0x3ffffff; $h4 += $c; /** @var int $c */ $c = $h4 >> 26; $h4 &= 0x3ffffff; /** @var int $h0 */ $h0 += self::mul($c, 5, 3); /** @var int $c */ $c = $h0 >> 26; /** @var int $h0 */ $h0 &= 0x3ffffff; /** @var int $h1 */ $h1 += $c; /* compute h + -p */ /** @var int $g0 */ $g0 = $h0 + 5; /** @var int $c */ $c = $g0 >> 26; /** @var int $g0 */ $g0 &= 0x3ffffff; /** @var int $g1 */ $g1 = $h1 + $c; /** @var int $c */ $c = $g1 >> 26; $g1 &= 0x3ffffff; /** @var int $g2 */ $g2 = $h2 + $c; /** @var int $c */ $c = $g2 >> 26; /** @var int $g2 */ $g2 &= 0x3ffffff; /** @var int $g3 */ $g3 = $h3 + $c; /** @var int $c */ $c = $g3 >> 26; /** @var int $g3 */ $g3 &= 0x3ffffff; /** @var int $g4 */ $g4 = ($h4 + $c - (1 << 26)) & 0xffffffff; /* select h if h < p, or h + -p if h >= p */ /** @var int $mask */ $mask = ($g4 >> 31) - 1; $g0 &= $mask; $g1 &= $mask; $g2 &= $mask; $g3 &= $mask; $g4 &= $mask; /** @var int $mask */ $mask = ~$mask & 0xffffffff; /** @var int $h0 */ $h0 = ($h0 & $mask) | $g0; /** @var int $h1 */ $h1 = ($h1 & $mask) | $g1; /** @var int $h2 */ $h2 = ($h2 & $mask) | $g2; /** @var int $h3 */ $h3 = ($h3 & $mask) | $g3; /** @var int $h4 */ $h4 = ($h4 & $mask) | $g4; /* h = h % (2^128) */ /** @var int $h0 */ $h0 = (($h0) | ($h1 << 26)) & 0xffffffff; /** @var int $h1 */ $h1 = (($h1 >> 6) | ($h2 << 20)) & 0xffffffff; /** @var int $h2 */ $h2 = (($h2 >> 12) | ($h3 << 14)) & 0xffffffff; /** @var int $h3 */ $h3 = (($h3 >> 18) | ($h4 << 8)) & 0xffffffff; /* mac = (h + pad) % (2^128) */ $f = (int) ($h0 + $this->pad[0]); $h0 = (int) $f; $f = (int) ($h1 + $this->pad[1] + ($f >> 32)); $h1 = (int) $f; $f = (int) ($h2 + $this->pad[2] + ($f >> 32)); $h2 = (int) $f; $f = (int) ($h3 + $this->pad[3] + ($f >> 32)); $h3 = (int) $f; return self::store32_le($h0 & 0xffffffff) . self::store32_le($h1 & 0xffffffff) . self::store32_le($h2 & 0xffffffff) . self::store32_le($h3 & 0xffffffff); } } PK������Z]iu) ��) ����Core/SipHash.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_SipHash', false)) { return; } /** * Class ParagonIE_SodiumCompat_Core_SipHash * * Only uses 32-bit arithmetic, while the original SipHash used 64-bit integers */ class ParagonIE_Sodium_Core_SipHash extends ParagonIE_Sodium_Core_Util { /** * @internal You should not use this directly from another application * * @param int[] $v * @return int[] * */ public static function sipRound(array $v) { # v0 += v1; list($v[0], $v[1]) = self::add( array($v[0], $v[1]), array($v[2], $v[3]) ); # v1=ROTL(v1,13); list($v[2], $v[3]) = self::rotl_64((int) $v[2], (int) $v[3], 13); # v1 ^= v0; $v[2] = (int) $v[2] ^ (int) $v[0]; $v[3] = (int) $v[3] ^ (int) $v[1]; # v0=ROTL(v0,32); list($v[0], $v[1]) = self::rotl_64((int) $v[0], (int) $v[1], 32); # v2 += v3; list($v[4], $v[5]) = self::add( array((int) $v[4], (int) $v[5]), array((int) $v[6], (int) $v[7]) ); # v3=ROTL(v3,16); list($v[6], $v[7]) = self::rotl_64((int) $v[6], (int) $v[7], 16); # v3 ^= v2; $v[6] = (int) $v[6] ^ (int) $v[4]; $v[7] = (int) $v[7] ^ (int) $v[5]; # v0 += v3; list($v[0], $v[1]) = self::add( array((int) $v[0], (int) $v[1]), array((int) $v[6], (int) $v[7]) ); # v3=ROTL(v3,21); list($v[6], $v[7]) = self::rotl_64((int) $v[6], (int) $v[7], 21); # v3 ^= v0; $v[6] = (int) $v[6] ^ (int) $v[0]; $v[7] = (int) $v[7] ^ (int) $v[1]; # v2 += v1; list($v[4], $v[5]) = self::add( array((int) $v[4], (int) $v[5]), array((int) $v[2], (int) $v[3]) ); # v1=ROTL(v1,17); list($v[2], $v[3]) = self::rotl_64((int) $v[2], (int) $v[3], 17); # v1 ^= v2;; $v[2] = (int) $v[2] ^ (int) $v[4]; $v[3] = (int) $v[3] ^ (int) $v[5]; # v2=ROTL(v2,32) list($v[4], $v[5]) = self::rotl_64((int) $v[4], (int) $v[5], 32); return $v; } /** * Add two 32 bit integers representing a 64-bit integer. * * @internal You should not use this directly from another application * * @param int[] $a * @param int[] $b * @return array<int, mixed> */ public static function add(array $a, array $b) { /** @var int $x1 */ $x1 = $a[1] + $b[1]; /** @var int $c */ $c = $x1 >> 32; // Carry if ($a + $b) > 0xffffffff /** @var int $x0 */ $x0 = $a[0] + $b[0] + $c; return array( $x0 & 0xffffffff, $x1 & 0xffffffff ); } /** * @internal You should not use this directly from another application * * @param int $int0 * @param int $int1 * @param int $c * @return array<int, mixed> */ public static function rotl_64($int0, $int1, $c) { $int0 &= 0xffffffff; $int1 &= 0xffffffff; $c &= 63; if ($c === 32) { return array($int1, $int0); } if ($c > 31) { $tmp = $int1; $int1 = $int0; $int0 = $tmp; $c &= 31; } if ($c === 0) { return array($int0, $int1); } return array( 0xffffffff & ( ($int0 << $c) | ($int1 >> (32 - $c)) ), 0xffffffff & ( ($int1 << $c) | ($int0 >> (32 - $c)) ), ); } /** * Implements Siphash-2-4 using only 32-bit numbers. * * When we split an int into two, the higher bits go to the lower index. * e.g. 0xDEADBEEFAB10C92D becomes [ * 0 => 0xDEADBEEF, * 1 => 0xAB10C92D * ]. * * @internal You should not use this directly from another application * * @param string $in * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function sipHash24($in, $key) { $inlen = self::strlen($in); # /* "somepseudorandomlygeneratedbytes" */ # u64 v0 = 0x736f6d6570736575ULL; # u64 v1 = 0x646f72616e646f6dULL; # u64 v2 = 0x6c7967656e657261ULL; # u64 v3 = 0x7465646279746573ULL; $v = array( 0x736f6d65, // 0 0x70736575, // 1 0x646f7261, // 2 0x6e646f6d, // 3 0x6c796765, // 4 0x6e657261, // 5 0x74656462, // 6 0x79746573 // 7 ); // v0 => $v[0], $v[1] // v1 => $v[2], $v[3] // v2 => $v[4], $v[5] // v3 => $v[6], $v[7] # u64 k0 = LOAD64_LE( k ); # u64 k1 = LOAD64_LE( k + 8 ); $k = array( self::load_4(self::substr($key, 4, 4)), self::load_4(self::substr($key, 0, 4)), self::load_4(self::substr($key, 12, 4)), self::load_4(self::substr($key, 8, 4)) ); // k0 => $k[0], $k[1] // k1 => $k[2], $k[3] # b = ( ( u64 )inlen ) << 56; $b = array( $inlen << 24, 0 ); // See docblock for why the 0th index gets the higher bits. # v3 ^= k1; $v[6] ^= $k[2]; $v[7] ^= $k[3]; # v2 ^= k0; $v[4] ^= $k[0]; $v[5] ^= $k[1]; # v1 ^= k1; $v[2] ^= $k[2]; $v[3] ^= $k[3]; # v0 ^= k0; $v[0] ^= $k[0]; $v[1] ^= $k[1]; $left = $inlen; # for ( ; in != end; in += 8 ) while ($left >= 8) { # m = LOAD64_LE( in ); $m = array( self::load_4(self::substr($in, 4, 4)), self::load_4(self::substr($in, 0, 4)) ); # v3 ^= m; $v[6] ^= $m[0]; $v[7] ^= $m[1]; # SIPROUND; # SIPROUND; $v = self::sipRound($v); $v = self::sipRound($v); # v0 ^= m; $v[0] ^= $m[0]; $v[1] ^= $m[1]; $in = self::substr($in, 8); $left -= 8; } # switch( left ) # { # case 7: b |= ( ( u64 )in[ 6] ) << 48; # case 6: b |= ( ( u64 )in[ 5] ) << 40; # case 5: b |= ( ( u64 )in[ 4] ) << 32; # case 4: b |= ( ( u64 )in[ 3] ) << 24; # case 3: b |= ( ( u64 )in[ 2] ) << 16; # case 2: b |= ( ( u64 )in[ 1] ) << 8; # case 1: b |= ( ( u64 )in[ 0] ); break; # case 0: break; # } switch ($left) { case 7: $b[0] |= self::chrToInt($in[6]) << 16; case 6: $b[0] |= self::chrToInt($in[5]) << 8; case 5: $b[0] |= self::chrToInt($in[4]); case 4: $b[1] |= self::chrToInt($in[3]) << 24; case 3: $b[1] |= self::chrToInt($in[2]) << 16; case 2: $b[1] |= self::chrToInt($in[1]) << 8; case 1: $b[1] |= self::chrToInt($in[0]); case 0: break; } // See docblock for why the 0th index gets the higher bits. # v3 ^= b; $v[6] ^= $b[0]; $v[7] ^= $b[1]; # SIPROUND; # SIPROUND; $v = self::sipRound($v); $v = self::sipRound($v); # v0 ^= b; $v[0] ^= $b[0]; $v[1] ^= $b[1]; // Flip the lower 8 bits of v2 which is ($v[4], $v[5]) in our implementation # v2 ^= 0xff; $v[5] ^= 0xff; # SIPROUND; # SIPROUND; # SIPROUND; # SIPROUND; $v = self::sipRound($v); $v = self::sipRound($v); $v = self::sipRound($v); $v = self::sipRound($v); # b = v0 ^ v1 ^ v2 ^ v3; # STORE64_LE( out, b ); return self::store32_le($v[1] ^ $v[3] ^ $v[5] ^ $v[7]) . self::store32_le($v[0] ^ $v[2] ^ $v[4] ^ $v[6]); } } PK������ZumLD��LD����Core/Ed25519.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_Ed25519', false)) { return; } if (!class_exists('ParagonIE_Sodium_Core_Curve25519', false)) { require_once dirname(__FILE__) . '/Curve25519.php'; } /** * Class ParagonIE_Sodium_Core_Ed25519 */ abstract class ParagonIE_Sodium_Core_Ed25519 extends ParagonIE_Sodium_Core_Curve25519 { const KEYPAIR_BYTES = 96; const SEED_BYTES = 32; const SCALAR_BYTES = 32; /** * @internal You should not use this directly from another application * * @return string (96 bytes) * @throws Exception * @throws SodiumException * @throws TypeError */ public static function keypair() { $seed = random_bytes(self::SEED_BYTES); $pk = ''; $sk = ''; self::seed_keypair($pk, $sk, $seed); return $sk . $pk; } /** * @internal You should not use this directly from another application * * @param string $pk * @param string $sk * @param string $seed * @return string * @throws SodiumException * @throws TypeError */ public static function seed_keypair(&$pk, &$sk, $seed) { if (self::strlen($seed) !== self::SEED_BYTES) { throw new RangeException('crypto_sign keypair seed must be 32 bytes long'); } /** @var string $pk */ $pk = self::publickey_from_secretkey($seed); $sk = $seed . $pk; return $sk; } /** * @internal You should not use this directly from another application * * @param string $keypair * @return string * @throws TypeError */ public static function secretkey($keypair) { if (self::strlen($keypair) !== self::KEYPAIR_BYTES) { throw new RangeException('crypto_sign keypair must be 96 bytes long'); } return self::substr($keypair, 0, 64); } /** * @internal You should not use this directly from another application * * @param string $keypair * @return string * @throws TypeError */ public static function publickey($keypair) { if (self::strlen($keypair) !== self::KEYPAIR_BYTES) { throw new RangeException('crypto_sign keypair must be 96 bytes long'); } return self::substr($keypair, 64, 32); } /** * @internal You should not use this directly from another application * * @param string $sk * @return string * @throws SodiumException * @throws TypeError */ public static function publickey_from_secretkey($sk) { /** @var string $sk */ $sk = hash('sha512', self::substr($sk, 0, 32), true); $sk[0] = self::intToChr( self::chrToInt($sk[0]) & 248 ); $sk[31] = self::intToChr( (self::chrToInt($sk[31]) & 63) | 64 ); return self::sk_to_pk($sk); } /** * @param string $pk * @return string * @throws SodiumException * @throws TypeError */ public static function pk_to_curve25519($pk) { if (self::small_order($pk)) { throw new SodiumException('Public key is on a small order'); } $A = self::ge_frombytes_negate_vartime(self::substr($pk, 0, 32)); $p1 = self::ge_mul_l($A); if (!self::fe_isnonzero($p1->X)) { throw new SodiumException('Unexpected zero result'); } # fe_1(one_minus_y); # fe_sub(one_minus_y, one_minus_y, A.Y); # fe_invert(one_minus_y, one_minus_y); $one_minux_y = self::fe_invert( self::fe_sub( self::fe_1(), $A->Y ) ); # fe_1(x); # fe_add(x, x, A.Y); # fe_mul(x, x, one_minus_y); $x = self::fe_mul( self::fe_add(self::fe_1(), $A->Y), $one_minux_y ); # fe_tobytes(curve25519_pk, x); return self::fe_tobytes($x); } /** * @internal You should not use this directly from another application * * @param string $sk * @return string * @throws SodiumException * @throws TypeError */ public static function sk_to_pk($sk) { return self::ge_p3_tobytes( self::ge_scalarmult_base( self::substr($sk, 0, 32) ) ); } /** * @internal You should not use this directly from another application * * @param string $message * @param string $sk * @return string * @throws SodiumException * @throws TypeError */ public static function sign($message, $sk) { /** @var string $signature */ $signature = self::sign_detached($message, $sk); return $signature . $message; } /** * @internal You should not use this directly from another application * * @param string $message A signed message * @param string $pk Public key * @return string Message (without signature) * @throws SodiumException * @throws TypeError */ public static function sign_open($message, $pk) { /** @var string $signature */ $signature = self::substr($message, 0, 64); /** @var string $message */ $message = self::substr($message, 64); if (self::verify_detached($signature, $message, $pk)) { return $message; } throw new SodiumException('Invalid signature'); } /** * @internal You should not use this directly from another application * * @param string $message * @param string $sk * @return string * @throws SodiumException * @throws TypeError */ public static function sign_detached($message, $sk) { # crypto_hash_sha512(az, sk, 32); $az = hash('sha512', self::substr($sk, 0, 32), true); # az[0] &= 248; # az[31] &= 63; # az[31] |= 64; $az[0] = self::intToChr(self::chrToInt($az[0]) & 248); $az[31] = self::intToChr((self::chrToInt($az[31]) & 63) | 64); # crypto_hash_sha512_init(&hs); # crypto_hash_sha512_update(&hs, az + 32, 32); # crypto_hash_sha512_update(&hs, m, mlen); # crypto_hash_sha512_final(&hs, nonce); $hs = hash_init('sha512'); hash_update($hs, self::substr($az, 32, 32)); hash_update($hs, $message); $nonceHash = hash_final($hs, true); # memmove(sig + 32, sk + 32, 32); $pk = self::substr($sk, 32, 32); # sc_reduce(nonce); # ge_scalarmult_base(&R, nonce); # ge_p3_tobytes(sig, &R); $nonce = self::sc_reduce($nonceHash) . self::substr($nonceHash, 32); $sig = self::ge_p3_tobytes( self::ge_scalarmult_base($nonce) ); # crypto_hash_sha512_init(&hs); # crypto_hash_sha512_update(&hs, sig, 64); # crypto_hash_sha512_update(&hs, m, mlen); # crypto_hash_sha512_final(&hs, hram); $hs = hash_init('sha512'); hash_update($hs, self::substr($sig, 0, 32)); hash_update($hs, self::substr($pk, 0, 32)); hash_update($hs, $message); $hramHash = hash_final($hs, true); # sc_reduce(hram); # sc_muladd(sig + 32, hram, az, nonce); $hram = self::sc_reduce($hramHash); $sigAfter = self::sc_muladd($hram, $az, $nonce); $sig = self::substr($sig, 0, 32) . self::substr($sigAfter, 0, 32); try { ParagonIE_Sodium_Compat::memzero($az); } catch (SodiumException $ex) { $az = null; } return $sig; } /** * @internal You should not use this directly from another application * * @param string $sig * @param string $message * @param string $pk * @return bool * @throws SodiumException * @throws TypeError */ public static function verify_detached($sig, $message, $pk) { if (self::strlen($sig) < 64) { throw new SodiumException('Signature is too short'); } if ((self::chrToInt($sig[63]) & 240) && self::check_S_lt_L(self::substr($sig, 32, 32))) { throw new SodiumException('S < L - Invalid signature'); } if (self::small_order($sig)) { throw new SodiumException('Signature is on too small of an order'); } if ((self::chrToInt($sig[63]) & 224) !== 0) { throw new SodiumException('Invalid signature'); } $d = 0; for ($i = 0; $i < 32; ++$i) { $d |= self::chrToInt($pk[$i]); } if ($d === 0) { throw new SodiumException('All zero public key'); } /** @var bool The original value of ParagonIE_Sodium_Compat::$fastMult */ $orig = ParagonIE_Sodium_Compat::$fastMult; // Set ParagonIE_Sodium_Compat::$fastMult to true to speed up verification. ParagonIE_Sodium_Compat::$fastMult = true; /** @var ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A */ $A = self::ge_frombytes_negate_vartime($pk); /** @var string $hDigest */ $hDigest = hash( 'sha512', self::substr($sig, 0, 32) . self::substr($pk, 0, 32) . $message, true ); /** @var string $h */ $h = self::sc_reduce($hDigest) . self::substr($hDigest, 32); /** @var ParagonIE_Sodium_Core_Curve25519_Ge_P2 $R */ $R = self::ge_double_scalarmult_vartime( $h, $A, self::substr($sig, 32) ); /** @var string $rcheck */ $rcheck = self::ge_tobytes($R); // Reset ParagonIE_Sodium_Compat::$fastMult to what it was before. ParagonIE_Sodium_Compat::$fastMult = $orig; return self::verify_32($rcheck, self::substr($sig, 0, 32)); } /** * @internal You should not use this directly from another application * * @param string $S * @return bool * @throws SodiumException * @throws TypeError */ public static function check_S_lt_L($S) { if (self::strlen($S) < 32) { throw new SodiumException('Signature must be 32 bytes'); } $L = array( 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 ); $c = 0; $n = 1; $i = 32; /** @var array<int, int> $L */ do { --$i; $x = self::chrToInt($S[$i]); $c |= ( (($x - $L[$i]) >> 8) & $n ); $n &= ( (($x ^ $L[$i]) - 1) >> 8 ); } while ($i !== 0); return $c === 0; } /** * @param string $R * @return bool * @throws SodiumException * @throws TypeError */ public static function small_order($R) { /** @var array<int, array<int, int>> $blocklist */ $blocklist = array( /* 0 (order 4) */ array( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), /* 1 (order 1) */ array( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), /* 2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */ array( 0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05 ), /* 55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */ array( 0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a ), /* p-1 (order 2) */ array( 0x13, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x85 ), /* p (order 4) */ array( 0xb4, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa ), /* p+1 (order 1) */ array( 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f ), /* p+2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */ array( 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f ), /* p+55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */ array( 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f ), /* 2p-1 (order 2) */ array( 0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ), /* 2p (order 4) */ array( 0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ), /* 2p+1 (order 1) */ array( 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ) ); /** @var int $countBlocklist */ $countBlocklist = count($blocklist); for ($i = 0; $i < $countBlocklist; ++$i) { $c = 0; for ($j = 0; $j < 32; ++$j) { $c |= self::chrToInt($R[$j]) ^ (int) $blocklist[$i][$j]; } if ($c === 0) { return true; } } return false; } /** * @param string $s * @return string * @throws SodiumException */ public static function scalar_complement($s) { $t_ = self::L . str_repeat("\x00", 32); sodium_increment($t_); $s_ = $s . str_repeat("\x00", 32); ParagonIE_Sodium_Compat::sub($t_, $s_); return self::sc_reduce($t_); } /** * @return string * @throws SodiumException */ public static function scalar_random() { do { $r = ParagonIE_Sodium_Compat::randombytes_buf(self::SCALAR_BYTES); $r[self::SCALAR_BYTES - 1] = self::intToChr( self::chrToInt($r[self::SCALAR_BYTES - 1]) & 0x1f ); } while ( !self::check_S_lt_L($r) || ParagonIE_Sodium_Compat::is_zero($r) ); return $r; } /** * @param string $s * @return string * @throws SodiumException */ public static function scalar_negate($s) { $t_ = self::L . str_repeat("\x00", 32) ; $s_ = $s . str_repeat("\x00", 32) ; ParagonIE_Sodium_Compat::sub($t_, $s_); return self::sc_reduce($t_); } /** * @param string $a * @param string $b * @return string * @throws SodiumException */ public static function scalar_add($a, $b) { $a_ = $a . str_repeat("\x00", 32); $b_ = $b . str_repeat("\x00", 32); ParagonIE_Sodium_Compat::add($a_, $b_); return self::sc_reduce($a_); } /** * @param string $x * @param string $y * @return string * @throws SodiumException */ public static function scalar_sub($x, $y) { $yn = self::scalar_negate($y); return self::scalar_add($x, $yn); } } PK������Z=P������Core/HChaCha20.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_HChaCha20', false)) { return; } /** * Class ParagonIE_Sodium_Core_HChaCha20 */ class ParagonIE_Sodium_Core_HChaCha20 extends ParagonIE_Sodium_Core_ChaCha20 { /** * @param string $in * @param string $key * @param string|null $c * @return string * @throws TypeError */ public static function hChaCha20($in = '', $key = '', $c = null) { $ctx = array(); if ($c === null) { $ctx[0] = 0x61707865; $ctx[1] = 0x3320646e; $ctx[2] = 0x79622d32; $ctx[3] = 0x6b206574; } else { $ctx[0] = self::load_4(self::substr($c, 0, 4)); $ctx[1] = self::load_4(self::substr($c, 4, 4)); $ctx[2] = self::load_4(self::substr($c, 8, 4)); $ctx[3] = self::load_4(self::substr($c, 12, 4)); } $ctx[4] = self::load_4(self::substr($key, 0, 4)); $ctx[5] = self::load_4(self::substr($key, 4, 4)); $ctx[6] = self::load_4(self::substr($key, 8, 4)); $ctx[7] = self::load_4(self::substr($key, 12, 4)); $ctx[8] = self::load_4(self::substr($key, 16, 4)); $ctx[9] = self::load_4(self::substr($key, 20, 4)); $ctx[10] = self::load_4(self::substr($key, 24, 4)); $ctx[11] = self::load_4(self::substr($key, 28, 4)); $ctx[12] = self::load_4(self::substr($in, 0, 4)); $ctx[13] = self::load_4(self::substr($in, 4, 4)); $ctx[14] = self::load_4(self::substr($in, 8, 4)); $ctx[15] = self::load_4(self::substr($in, 12, 4)); return self::hChaCha20Bytes($ctx); } /** * @param array $ctx * @return string * @throws TypeError */ protected static function hChaCha20Bytes(array $ctx) { $x0 = (int) $ctx[0]; $x1 = (int) $ctx[1]; $x2 = (int) $ctx[2]; $x3 = (int) $ctx[3]; $x4 = (int) $ctx[4]; $x5 = (int) $ctx[5]; $x6 = (int) $ctx[6]; $x7 = (int) $ctx[7]; $x8 = (int) $ctx[8]; $x9 = (int) $ctx[9]; $x10 = (int) $ctx[10]; $x11 = (int) $ctx[11]; $x12 = (int) $ctx[12]; $x13 = (int) $ctx[13]; $x14 = (int) $ctx[14]; $x15 = (int) $ctx[15]; for ($i = 0; $i < 10; ++$i) { # QUARTERROUND( x0, x4, x8, x12) list($x0, $x4, $x8, $x12) = self::quarterRound($x0, $x4, $x8, $x12); # QUARTERROUND( x1, x5, x9, x13) list($x1, $x5, $x9, $x13) = self::quarterRound($x1, $x5, $x9, $x13); # QUARTERROUND( x2, x6, x10, x14) list($x2, $x6, $x10, $x14) = self::quarterRound($x2, $x6, $x10, $x14); # QUARTERROUND( x3, x7, x11, x15) list($x3, $x7, $x11, $x15) = self::quarterRound($x3, $x7, $x11, $x15); # QUARTERROUND( x0, x5, x10, x15) list($x0, $x5, $x10, $x15) = self::quarterRound($x0, $x5, $x10, $x15); # QUARTERROUND( x1, x6, x11, x12) list($x1, $x6, $x11, $x12) = self::quarterRound($x1, $x6, $x11, $x12); # QUARTERROUND( x2, x7, x8, x13) list($x2, $x7, $x8, $x13) = self::quarterRound($x2, $x7, $x8, $x13); # QUARTERROUND( x3, x4, x9, x14) list($x3, $x4, $x9, $x14) = self::quarterRound($x3, $x4, $x9, $x14); } return self::store32_le((int) ($x0 & 0xffffffff)) . self::store32_le((int) ($x1 & 0xffffffff)) . self::store32_le((int) ($x2 & 0xffffffff)) . self::store32_le((int) ($x3 & 0xffffffff)) . self::store32_le((int) ($x12 & 0xffffffff)) . self::store32_le((int) ($x13 & 0xffffffff)) . self::store32_le((int) ($x14 & 0xffffffff)) . self::store32_le((int) ($x15 & 0xffffffff)); } } PK������Zo|U��|U����Core/Ristretto255.phpnu�W+A��������<?php /** * Class ParagonIE_Sodium_Core_Ristretto255 */ class ParagonIE_Sodium_Core_Ristretto255 extends ParagonIE_Sodium_Core_Ed25519 { const crypto_core_ristretto255_HASHBYTES = 64; const HASH_SC_L = 48; const CORE_H2C_SHA256 = 1; const CORE_H2C_SHA512 = 2; /** * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @param int $b * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function fe_cneg(ParagonIE_Sodium_Core_Curve25519_Fe $f, $b) { $negf = self::fe_neg($f); return self::fe_cmov($f, $negf, $b); } /** * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @return ParagonIE_Sodium_Core_Curve25519_Fe * @throws SodiumException */ public static function fe_abs(ParagonIE_Sodium_Core_Curve25519_Fe $f) { return self::fe_cneg($f, self::fe_isnegative($f)); } /** * Returns 0 if this field element results in all NUL bytes. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @return int * @throws SodiumException */ public static function fe_iszero(ParagonIE_Sodium_Core_Curve25519_Fe $f) { static $zero; if ($zero === null) { $zero = str_repeat("\x00", 32); } /** @var string $zero */ $str = self::fe_tobytes($f); $d = 0; for ($i = 0; $i < 32; ++$i) { $d |= self::chrToInt($str[$i]); } return (($d - 1) >> 31) & 1; } /** * @param ParagonIE_Sodium_Core_Curve25519_Fe $u * @param ParagonIE_Sodium_Core_Curve25519_Fe $v * @return array{x: ParagonIE_Sodium_Core_Curve25519_Fe, nonsquare: int} * * @throws SodiumException */ public static function ristretto255_sqrt_ratio_m1( ParagonIE_Sodium_Core_Curve25519_Fe $u, ParagonIE_Sodium_Core_Curve25519_Fe $v ) { $sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1); $v3 = self::fe_mul( self::fe_sq($v), $v ); /* v3 = v^3 */ $x = self::fe_mul( self::fe_mul( self::fe_sq($v3), $u ), $v ); /* x = uv^7 */ $x = self::fe_mul( self::fe_mul( self::fe_pow22523($x), /* x = (uv^7)^((q-5)/8) */ $v3 ), $u ); /* x = uv^3(uv^7)^((q-5)/8) */ $vxx = self::fe_mul( self::fe_sq($x), $v ); /* vx^2 */ $m_root_check = self::fe_sub($vxx, $u); /* vx^2-u */ $p_root_check = self::fe_add($vxx, $u); /* vx^2+u */ $f_root_check = self::fe_mul($u, $sqrtm1); /* u*sqrt(-1) */ $f_root_check = self::fe_add($vxx, $f_root_check); /* vx^2+u*sqrt(-1) */ $has_m_root = self::fe_iszero($m_root_check); $has_p_root = self::fe_iszero($p_root_check); $has_f_root = self::fe_iszero($f_root_check); $x_sqrtm1 = self::fe_mul($x, $sqrtm1); /* x*sqrt(-1) */ $x = self::fe_abs( self::fe_cmov($x, $x_sqrtm1, $has_p_root | $has_f_root) ); return array( 'x' => $x, 'nonsquare' => $has_m_root | $has_p_root ); } /** * @param string $s * @return int * @throws SodiumException */ public static function ristretto255_point_is_canonical($s) { $c = (self::chrToInt($s[31]) & 0x7f) ^ 0x7f; for ($i = 30; $i > 0; --$i) { $c |= self::chrToInt($s[$i]) ^ 0xff; } $c = ($c - 1) >> 8; $d = (0xed - 1 - self::chrToInt($s[0])) >> 8; $e = self::chrToInt($s[31]) >> 7; return 1 - ((($c & $d) | $e | self::chrToInt($s[0])) & 1); } /** * @param string $s * @param bool $skipCanonicalCheck * @return array{h: ParagonIE_Sodium_Core_Curve25519_Ge_P3, res: int} * @throws SodiumException */ public static function ristretto255_frombytes($s, $skipCanonicalCheck = false) { if (!$skipCanonicalCheck) { if (!self::ristretto255_point_is_canonical($s)) { throw new SodiumException('S is not canonical'); } } $s_ = self::fe_frombytes($s); $ss = self::fe_sq($s_); /* ss = s^2 */ $u1 = self::fe_sub(self::fe_1(), $ss); /* u1 = 1-ss */ $u1u1 = self::fe_sq($u1); /* u1u1 = u1^2 */ $u2 = self::fe_add(self::fe_1(), $ss); /* u2 = 1+ss */ $u2u2 = self::fe_sq($u2); /* u2u2 = u2^2 */ $v = self::fe_mul( ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d), $u1u1 ); /* v = d*u1^2 */ $v = self::fe_neg($v); /* v = -d*u1^2 */ $v = self::fe_sub($v, $u2u2); /* v = -(d*u1^2)-u2^2 */ $v_u2u2 = self::fe_mul($v, $u2u2); /* v_u2u2 = v*u2^2 */ // fe25519_1(one); // notsquare = ristretto255_sqrt_ratio_m1(inv_sqrt, one, v_u2u2); $one = self::fe_1(); $result = self::ristretto255_sqrt_ratio_m1($one, $v_u2u2); $inv_sqrt = $result['x']; $notsquare = $result['nonsquare']; $h = new ParagonIE_Sodium_Core_Curve25519_Ge_P3(); $h->X = self::fe_mul($inv_sqrt, $u2); $h->Y = self::fe_mul(self::fe_mul($inv_sqrt, $h->X), $v); $h->X = self::fe_mul($h->X, $s_); $h->X = self::fe_abs( self::fe_add($h->X, $h->X) ); $h->Y = self::fe_mul($u1, $h->Y); $h->Z = self::fe_1(); $h->T = self::fe_mul($h->X, $h->Y); $res = - ((1 - $notsquare) | self::fe_isnegative($h->T) | self::fe_iszero($h->Y)); return array('h' => $h, 'res' => $res); } /** * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h * @return string * @throws SodiumException */ public static function ristretto255_p3_tobytes(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h) { $sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1); $invsqrtamd = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$invsqrtamd); $u1 = self::fe_add($h->Z, $h->Y); /* u1 = Z+Y */ $zmy = self::fe_sub($h->Z, $h->Y); /* zmy = Z-Y */ $u1 = self::fe_mul($u1, $zmy); /* u1 = (Z+Y)*(Z-Y) */ $u2 = self::fe_mul($h->X, $h->Y); /* u2 = X*Y */ $u1_u2u2 = self::fe_mul(self::fe_sq($u2), $u1); /* u1_u2u2 = u1*u2^2 */ $one = self::fe_1(); // fe25519_1(one); // (void) ristretto255_sqrt_ratio_m1(inv_sqrt, one, u1_u2u2); $result = self::ristretto255_sqrt_ratio_m1($one, $u1_u2u2); $inv_sqrt = $result['x']; $den1 = self::fe_mul($inv_sqrt, $u1); /* den1 = inv_sqrt*u1 */ $den2 = self::fe_mul($inv_sqrt, $u2); /* den2 = inv_sqrt*u2 */ $z_inv = self::fe_mul($h->T, self::fe_mul($den1, $den2)); /* z_inv = den1*den2*T */ $ix = self::fe_mul($h->X, $sqrtm1); /* ix = X*sqrt(-1) */ $iy = self::fe_mul($h->Y, $sqrtm1); /* iy = Y*sqrt(-1) */ $eden = self::fe_mul($den1, $invsqrtamd); $t_z_inv = self::fe_mul($h->T, $z_inv); /* t_z_inv = T*z_inv */ $rotate = self::fe_isnegative($t_z_inv); $x_ = self::fe_copy($h->X); $y_ = self::fe_copy($h->Y); $den_inv = self::fe_copy($den2); $x_ = self::fe_cmov($x_, $iy, $rotate); $y_ = self::fe_cmov($y_, $ix, $rotate); $den_inv = self::fe_cmov($den_inv, $eden, $rotate); $x_z_inv = self::fe_mul($x_, $z_inv); $y_ = self::fe_cneg($y_, self::fe_isnegative($x_z_inv)); // fe25519_sub(s_, h->Z, y_); // fe25519_mul(s_, den_inv, s_); // fe25519_abs(s_, s_); // fe25519_tobytes(s, s_); return self::fe_tobytes( self::fe_abs( self::fe_mul( $den_inv, self::fe_sub($h->Z, $y_) ) ) ); } /** * @param ParagonIE_Sodium_Core_Curve25519_Fe $t * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 * * @throws SodiumException */ public static function ristretto255_elligator(ParagonIE_Sodium_Core_Curve25519_Fe $t) { $sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1); $onemsqd = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$onemsqd); $d = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d); $sqdmone = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqdmone); $sqrtadm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtadm1); $one = self::fe_1(); $r = self::fe_mul($sqrtm1, self::fe_sq($t)); /* r = sqrt(-1)*t^2 */ $u = self::fe_mul(self::fe_add($r, $one), $onemsqd); /* u = (r+1)*(1-d^2) */ $c = self::fe_neg(self::fe_1()); /* c = -1 */ $rpd = self::fe_add($r, $d); /* rpd = r+d */ $v = self::fe_mul( self::fe_sub( $c, self::fe_mul($r, $d) ), $rpd ); /* v = (c-r*d)*(r+d) */ $result = self::ristretto255_sqrt_ratio_m1($u, $v); $s = $result['x']; $wasnt_square = 1 - $result['nonsquare']; $s_prime = self::fe_neg( self::fe_abs( self::fe_mul($s, $t) ) ); /* s_prime = -|s*t| */ $s = self::fe_cmov($s, $s_prime, $wasnt_square); $c = self::fe_cmov($c, $r, $wasnt_square); // fe25519_sub(n, r, one); /* n = r-1 */ // fe25519_mul(n, n, c); /* n = c*(r-1) */ // fe25519_mul(n, n, ed25519_sqdmone); /* n = c*(r-1)*(d-1)^2 */ // fe25519_sub(n, n, v); /* n = c*(r-1)*(d-1)^2-v */ $n = self::fe_sub( self::fe_mul( self::fe_mul( self::fe_sub($r, $one), $c ), $sqdmone ), $v ); /* n = c*(r-1)*(d-1)^2-v */ $w0 = self::fe_mul( self::fe_add($s, $s), $v ); /* w0 = 2s*v */ $w1 = self::fe_mul($n, $sqrtadm1); /* w1 = n*sqrt(ad-1) */ $ss = self::fe_sq($s); /* ss = s^2 */ $w2 = self::fe_sub($one, $ss); /* w2 = 1-s^2 */ $w3 = self::fe_add($one, $ss); /* w3 = 1+s^2 */ return new ParagonIE_Sodium_Core_Curve25519_Ge_P3( self::fe_mul($w0, $w3), self::fe_mul($w2, $w1), self::fe_mul($w1, $w3), self::fe_mul($w0, $w2) ); } /** * @param string $h * @return string * @throws SodiumException */ public static function ristretto255_from_hash($h) { if (self::strlen($h) !== 64) { throw new SodiumException('Hash must be 64 bytes'); } //fe25519_frombytes(r0, h); //fe25519_frombytes(r1, h + 32); $r0 = self::fe_frombytes(self::substr($h, 0, 32)); $r1 = self::fe_frombytes(self::substr($h, 32, 32)); //ristretto255_elligator(&p0, r0); //ristretto255_elligator(&p1, r1); $p0 = self::ristretto255_elligator($r0); $p1 = self::ristretto255_elligator($r1); //ge25519_p3_to_cached(&p1_cached, &p1); //ge25519_add_cached(&p_p1p1, &p0, &p1_cached); $p_p1p1 = self::ge_add( $p0, self::ge_p3_to_cached($p1) ); //ge25519_p1p1_to_p3(&p, &p_p1p1); //ristretto255_p3_tobytes(s, &p); return self::ristretto255_p3_tobytes( self::ge_p1p1_to_p3($p_p1p1) ); } /** * @param string $p * @return int * @throws SodiumException */ public static function is_valid_point($p) { $result = self::ristretto255_frombytes($p); if ($result['res'] !== 0) { return 0; } return 1; } /** * @param string $p * @param string $q * @return string * @throws SodiumException */ public static function ristretto255_add($p, $q) { $p_res = self::ristretto255_frombytes($p); $q_res = self::ristretto255_frombytes($q); if ($p_res['res'] !== 0 || $q_res['res'] !== 0) { throw new SodiumException('Could not add points'); } $p_p3 = $p_res['h']; $q_p3 = $q_res['h']; $q_cached = self::ge_p3_to_cached($q_p3); $r_p1p1 = self::ge_add($p_p3, $q_cached); $r_p3 = self::ge_p1p1_to_p3($r_p1p1); return self::ristretto255_p3_tobytes($r_p3); } /** * @param string $p * @param string $q * @return string * @throws SodiumException */ public static function ristretto255_sub($p, $q) { $p_res = self::ristretto255_frombytes($p); $q_res = self::ristretto255_frombytes($q); if ($p_res['res'] !== 0 || $q_res['res'] !== 0) { throw new SodiumException('Could not add points'); } $p_p3 = $p_res['h']; $q_p3 = $q_res['h']; $q_cached = self::ge_p3_to_cached($q_p3); $r_p1p1 = self::ge_sub($p_p3, $q_cached); $r_p3 = self::ge_p1p1_to_p3($r_p1p1); return self::ristretto255_p3_tobytes($r_p3); } /** * @param int $hLen * @param ?string $ctx * @param string $msg * @return string * @throws SodiumException * @psalm-suppress PossiblyInvalidArgument hash API */ protected static function h2c_string_to_hash_sha256($hLen, $ctx, $msg) { $h = array_fill(0, $hLen, 0); $ctx_len = !is_null($ctx) ? self::strlen($ctx) : 0; if ($hLen > 0xff) { throw new SodiumException('Hash must be less than 256 bytes'); } if ($ctx_len > 0xff) { $st = hash_init('sha256'); self::hash_update($st, "H2C-OVERSIZE-DST-"); self::hash_update($st, $ctx); $ctx = hash_final($st, true); $ctx_len = 32; } $t = array(0, $hLen, 0); $ux = str_repeat("\0", 64); $st = hash_init('sha256'); self::hash_update($st, $ux); self::hash_update($st, $msg); self::hash_update($st, self::intArrayToString($t)); self::hash_update($st, $ctx); self::hash_update($st, self::intToChr($ctx_len)); $u0 = hash_final($st, true); for ($i = 0; $i < $hLen; $i += 64) { $ux = self::xorStrings($ux, $u0); ++$t[2]; $st = hash_init('sha256'); self::hash_update($st, $ux); self::hash_update($st, self::intToChr($t[2])); self::hash_update($st, $ctx); self::hash_update($st, self::intToChr($ctx_len)); $ux = hash_final($st, true); $amount = min($hLen - $i, 64); for ($j = 0; $j < $amount; ++$j) { $h[$i + $j] = self::chrToInt($ux[$i]); } } return self::intArrayToString(array_slice($h, 0, $hLen)); } /** * @param int $hLen * @param ?string $ctx * @param string $msg * @return string * @throws SodiumException * @psalm-suppress PossiblyInvalidArgument hash API */ protected static function h2c_string_to_hash_sha512($hLen, $ctx, $msg) { $h = array_fill(0, $hLen, 0); $ctx_len = !is_null($ctx) ? self::strlen($ctx) : 0; if ($hLen > 0xff) { throw new SodiumException('Hash must be less than 256 bytes'); } if ($ctx_len > 0xff) { $st = hash_init('sha256'); self::hash_update($st, "H2C-OVERSIZE-DST-"); self::hash_update($st, $ctx); $ctx = hash_final($st, true); $ctx_len = 32; } $t = array(0, $hLen, 0); $ux = str_repeat("\0", 128); $st = hash_init('sha512'); self::hash_update($st, $ux); self::hash_update($st, $msg); self::hash_update($st, self::intArrayToString($t)); self::hash_update($st, $ctx); self::hash_update($st, self::intToChr($ctx_len)); $u0 = hash_final($st, true); for ($i = 0; $i < $hLen; $i += 128) { $ux = self::xorStrings($ux, $u0); ++$t[2]; $st = hash_init('sha512'); self::hash_update($st, $ux); self::hash_update($st, self::intToChr($t[2])); self::hash_update($st, $ctx); self::hash_update($st, self::intToChr($ctx_len)); $ux = hash_final($st, true); $amount = min($hLen - $i, 128); for ($j = 0; $j < $amount; ++$j) { $h[$i + $j] = self::chrToInt($ux[$i]); } } return self::intArrayToString(array_slice($h, 0, $hLen)); } /** * @param int $hLen * @param ?string $ctx * @param string $msg * @param int $hash_alg * @return string * @throws SodiumException */ public static function h2c_string_to_hash($hLen, $ctx, $msg, $hash_alg) { switch ($hash_alg) { case self::CORE_H2C_SHA256: return self::h2c_string_to_hash_sha256($hLen, $ctx, $msg); case self::CORE_H2C_SHA512: return self::h2c_string_to_hash_sha512($hLen, $ctx, $msg); default: throw new SodiumException('Invalid H2C hash algorithm'); } } /** * @param ?string $ctx * @param string $msg * @param int $hash_alg * @return string * @throws SodiumException */ protected static function _string_to_element($ctx, $msg, $hash_alg) { return self::ristretto255_from_hash( self::h2c_string_to_hash(self::crypto_core_ristretto255_HASHBYTES, $ctx, $msg, $hash_alg) ); } /** * @return string * @throws SodiumException * @throws Exception */ public static function ristretto255_random() { return self::ristretto255_from_hash( ParagonIE_Sodium_Compat::randombytes_buf(self::crypto_core_ristretto255_HASHBYTES) ); } /** * @return string * @throws SodiumException */ public static function ristretto255_scalar_random() { return self::scalar_random(); } /** * @param string $s * @return string * @throws SodiumException */ public static function ristretto255_scalar_complement($s) { return self::scalar_complement($s); } /** * @param string $s * @return string */ public static function ristretto255_scalar_invert($s) { return self::sc25519_invert($s); } /** * @param string $s * @return string * @throws SodiumException */ public static function ristretto255_scalar_negate($s) { return self::scalar_negate($s); } /** * @param string $x * @param string $y * @return string */ public static function ristretto255_scalar_add($x, $y) { return self::scalar_add($x, $y); } /** * @param string $x * @param string $y * @return string */ public static function ristretto255_scalar_sub($x, $y) { return self::scalar_sub($x, $y); } /** * @param string $x * @param string $y * @return string */ public static function ristretto255_scalar_mul($x, $y) { return self::sc25519_mul($x, $y); } /** * @param string $ctx * @param string $msg * @param int $hash_alg * @return string * @throws SodiumException */ public static function ristretto255_scalar_from_string($ctx, $msg, $hash_alg) { $h = array_fill(0, 64, 0); $h_be = self::stringToIntArray( self::h2c_string_to_hash( self::HASH_SC_L, $ctx, $msg, $hash_alg ) ); for ($i = 0; $i < self::HASH_SC_L; ++$i) { $h[$i] = $h_be[self::HASH_SC_L - 1 - $i]; } return self::ristretto255_scalar_reduce(self::intArrayToString($h)); } /** * @param string $s * @return string */ public static function ristretto255_scalar_reduce($s) { return self::sc_reduce($s); } /** * @param string $n * @param string $p * @return string * @throws SodiumException */ public static function scalarmult_ristretto255($n, $p) { if (self::strlen($n) !== 32) { throw new SodiumException('Scalar must be 32 bytes, ' . self::strlen($p) . ' given.'); } if (self::strlen($p) !== 32) { throw new SodiumException('Point must be 32 bytes, ' . self::strlen($p) . ' given.'); } $result = self::ristretto255_frombytes($p); if ($result['res'] !== 0) { throw new SodiumException('Could not multiply points'); } $P = $result['h']; $t = self::stringToIntArray($n); $t[31] &= 0x7f; $Q = self::ge_scalarmult(self::intArrayToString($t), $P); $q = self::ristretto255_p3_tobytes($Q); if (ParagonIE_Sodium_Compat::is_zero($q)) { throw new SodiumException('An unknown error has occurred'); } return $q; } /** * @param string $n * @return string * @throws SodiumException */ public static function scalarmult_ristretto255_base($n) { $t = self::stringToIntArray($n); $t[31] &= 0x7f; $Q = self::ge_scalarmult_base(self::intArrayToString($t)); $q = self::ristretto255_p3_tobytes($Q); if (ParagonIE_Sodium_Compat::is_zero($q)) { throw new SodiumException('An unknown error has occurred'); } return $q; } } PK������Z7�A������Core/AEGIS256.phpnu�W+A��������<?php if (!defined('SODIUM_COMPAT_AEGIS_C0')) { define('SODIUM_COMPAT_AEGIS_C0', "\x00\x01\x01\x02\x03\x05\x08\x0d\x15\x22\x37\x59\x90\xe9\x79\x62"); } if (!defined('SODIUM_COMPAT_AEGIS_C1')) { define('SODIUM_COMPAT_AEGIS_C1', "\xdb\x3d\x18\x55\x6d\xc2\x2f\xf1\x20\x11\x31\x42\x73\xb5\x28\xdd"); } class ParagonIE_Sodium_Core_AEGIS256 extends ParagonIE_Sodium_Core_AES { /** * @param string $ct * @param string $tag * @param string $ad * @param string $key * @param string $nonce * @return string * @throws SodiumException */ public static function decrypt($ct, $tag, $ad, $key, $nonce) { $state = self::init($key, $nonce); // ad_blocks = Split(ZeroPad(ad, 128), 128) $ad_blocks = (self::strlen($ad) + 15) >> 4; // for ai in ad_blocks: // Absorb(ai) for ($i = 0; $i < $ad_blocks; ++$i) { $ai = self::substr($ad, $i << 4, 16); if (self::strlen($ai) < 16) { $ai = str_pad($ai, 16, "\0", STR_PAD_RIGHT); } $state->absorb($ai); } $msg = ''; $cn = self::strlen($ct) & 15; $ct_blocks = self::strlen($ct) >> 4; // ct_blocks = Split(ZeroPad(ct, 128), 128) // cn = Tail(ct, |ct| mod 128) for ($i = 0; $i < $ct_blocks; ++$i) { $msg .= $state->dec(self::substr($ct, $i << 4, 16)); } // if cn is not empty: // msg = msg || DecPartial(cn) if ($cn) { $start = $ct_blocks << 4; $msg .= $state->decPartial(self::substr($ct, $start, $cn)); } $expected_tag = $state->finalize( self::strlen($ad) << 3, self::strlen($msg) << 3 ); if (!self::hashEquals($expected_tag, $tag)) { try { // The RFC says to erase msg, so we shall try: ParagonIE_Sodium_Compat::memzero($msg); } catch (SodiumException $ex) { // Do nothing if we cannot memzero } throw new SodiumException('verification failed'); } return $msg; } /** * @param string $msg * @param string $ad * @param string $key * @param string $nonce * @return array * @throws SodiumException */ public static function encrypt($msg, $ad, $key, $nonce) { $state = self::init($key, $nonce); $ad_len = self::strlen($ad); $msg_len = self::strlen($msg); $ad_blocks = ($ad_len + 15) >> 4; for ($i = 0; $i < $ad_blocks; ++$i) { $ai = self::substr($ad, $i << 4, 16); if (self::strlen($ai) < 16) { $ai = str_pad($ai, 16, "\0", STR_PAD_RIGHT); } $state->absorb($ai); } $ct = ''; $msg_blocks = ($msg_len + 15) >> 4; for ($i = 0; $i < $msg_blocks; ++$i) { $xi = self::substr($msg, $i << 4, 16); if (self::strlen($xi) < 16) { $xi = str_pad($xi, 16, "\0", STR_PAD_RIGHT); } $ct .= $state->enc($xi); } $tag = $state->finalize( $ad_len << 3, $msg_len << 3 ); return array( self::substr($ct, 0, $msg_len), $tag ); } /** * @param string $key * @param string $nonce * @return ParagonIE_Sodium_Core_AEGIS_State256 */ public static function init($key, $nonce) { return ParagonIE_Sodium_Core_AEGIS_State256::init($key, $nonce); } } PK������Z#AU$��$����Core/X25519.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_X25519', false)) { return; } /** * Class ParagonIE_Sodium_Core_X25519 */ abstract class ParagonIE_Sodium_Core_X25519 extends ParagonIE_Sodium_Core_Curve25519 { /** * Alters the objects passed to this method in place. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @param ParagonIE_Sodium_Core_Curve25519_Fe $g * @param int $b * @return void * @psalm-suppress MixedAssignment */ public static function fe_cswap( ParagonIE_Sodium_Core_Curve25519_Fe $f, ParagonIE_Sodium_Core_Curve25519_Fe $g, $b = 0 ) { $f0 = (int) $f[0]; $f1 = (int) $f[1]; $f2 = (int) $f[2]; $f3 = (int) $f[3]; $f4 = (int) $f[4]; $f5 = (int) $f[5]; $f6 = (int) $f[6]; $f7 = (int) $f[7]; $f8 = (int) $f[8]; $f9 = (int) $f[9]; $g0 = (int) $g[0]; $g1 = (int) $g[1]; $g2 = (int) $g[2]; $g3 = (int) $g[3]; $g4 = (int) $g[4]; $g5 = (int) $g[5]; $g6 = (int) $g[6]; $g7 = (int) $g[7]; $g8 = (int) $g[8]; $g9 = (int) $g[9]; $b = -$b; $x0 = ($f0 ^ $g0) & $b; $x1 = ($f1 ^ $g1) & $b; $x2 = ($f2 ^ $g2) & $b; $x3 = ($f3 ^ $g3) & $b; $x4 = ($f4 ^ $g4) & $b; $x5 = ($f5 ^ $g5) & $b; $x6 = ($f6 ^ $g6) & $b; $x7 = ($f7 ^ $g7) & $b; $x8 = ($f8 ^ $g8) & $b; $x9 = ($f9 ^ $g9) & $b; $f[0] = $f0 ^ $x0; $f[1] = $f1 ^ $x1; $f[2] = $f2 ^ $x2; $f[3] = $f3 ^ $x3; $f[4] = $f4 ^ $x4; $f[5] = $f5 ^ $x5; $f[6] = $f6 ^ $x6; $f[7] = $f7 ^ $x7; $f[8] = $f8 ^ $x8; $f[9] = $f9 ^ $x9; $g[0] = $g0 ^ $x0; $g[1] = $g1 ^ $x1; $g[2] = $g2 ^ $x2; $g[3] = $g3 ^ $x3; $g[4] = $g4 ^ $x4; $g[5] = $g5 ^ $x5; $g[6] = $g6 ^ $x6; $g[7] = $g7 ^ $x7; $g[8] = $g8 ^ $x8; $g[9] = $g9 ^ $x9; } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $f * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function fe_mul121666(ParagonIE_Sodium_Core_Curve25519_Fe $f) { $h = array( self::mul((int) $f[0], 121666, 17), self::mul((int) $f[1], 121666, 17), self::mul((int) $f[2], 121666, 17), self::mul((int) $f[3], 121666, 17), self::mul((int) $f[4], 121666, 17), self::mul((int) $f[5], 121666, 17), self::mul((int) $f[6], 121666, 17), self::mul((int) $f[7], 121666, 17), self::mul((int) $f[8], 121666, 17), self::mul((int) $f[9], 121666, 17) ); /** @var int $carry9 */ $carry9 = ($h[9] + (1 << 24)) >> 25; $h[0] += self::mul($carry9, 19, 5); $h[9] -= $carry9 << 25; /** @var int $carry1 */ $carry1 = ($h[1] + (1 << 24)) >> 25; $h[2] += $carry1; $h[1] -= $carry1 << 25; /** @var int $carry3 */ $carry3 = ($h[3] + (1 << 24)) >> 25; $h[4] += $carry3; $h[3] -= $carry3 << 25; /** @var int $carry5 */ $carry5 = ($h[5] + (1 << 24)) >> 25; $h[6] += $carry5; $h[5] -= $carry5 << 25; /** @var int $carry7 */ $carry7 = ($h[7] + (1 << 24)) >> 25; $h[8] += $carry7; $h[7] -= $carry7 << 25; /** @var int $carry0 */ $carry0 = ($h[0] + (1 << 25)) >> 26; $h[1] += $carry0; $h[0] -= $carry0 << 26; /** @var int $carry2 */ $carry2 = ($h[2] + (1 << 25)) >> 26; $h[3] += $carry2; $h[2] -= $carry2 << 26; /** @var int $carry4 */ $carry4 = ($h[4] + (1 << 25)) >> 26; $h[5] += $carry4; $h[4] -= $carry4 << 26; /** @var int $carry6 */ $carry6 = ($h[6] + (1 << 25)) >> 26; $h[7] += $carry6; $h[6] -= $carry6 << 26; /** @var int $carry8 */ $carry8 = ($h[8] + (1 << 25)) >> 26; $h[9] += $carry8; $h[8] -= $carry8 << 26; foreach ($h as $i => $value) { $h[$i] = (int) $value; } return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($h); } /** * @internal You should not use this directly from another application * * Inline comments preceded by # are from libsodium's ref10 code. * * @param string $n * @param string $p * @return string * @throws SodiumException * @throws TypeError */ public static function crypto_scalarmult_curve25519_ref10($n, $p) { # for (i = 0;i < 32;++i) e[i] = n[i]; $e = '' . $n; # e[0] &= 248; $e[0] = self::intToChr( self::chrToInt($e[0]) & 248 ); # e[31] &= 127; # e[31] |= 64; $e[31] = self::intToChr( (self::chrToInt($e[31]) & 127) | 64 ); # fe_frombytes(x1,p); $x1 = self::fe_frombytes($p); # fe_1(x2); $x2 = self::fe_1(); # fe_0(z2); $z2 = self::fe_0(); # fe_copy(x3,x1); $x3 = self::fe_copy($x1); # fe_1(z3); $z3 = self::fe_1(); # swap = 0; /** @var int $swap */ $swap = 0; # for (pos = 254;pos >= 0;--pos) { for ($pos = 254; $pos >= 0; --$pos) { # b = e[pos / 8] >> (pos & 7); /** @var int $b */ $b = self::chrToInt( $e[(int) floor($pos / 8)] ) >> ($pos & 7); # b &= 1; $b &= 1; # swap ^= b; $swap ^= $b; # fe_cswap(x2,x3,swap); self::fe_cswap($x2, $x3, $swap); # fe_cswap(z2,z3,swap); self::fe_cswap($z2, $z3, $swap); # swap = b; $swap = $b; # fe_sub(tmp0,x3,z3); $tmp0 = self::fe_sub($x3, $z3); # fe_sub(tmp1,x2,z2); $tmp1 = self::fe_sub($x2, $z2); # fe_add(x2,x2,z2); $x2 = self::fe_add($x2, $z2); # fe_add(z2,x3,z3); $z2 = self::fe_add($x3, $z3); # fe_mul(z3,tmp0,x2); $z3 = self::fe_mul($tmp0, $x2); # fe_mul(z2,z2,tmp1); $z2 = self::fe_mul($z2, $tmp1); # fe_sq(tmp0,tmp1); $tmp0 = self::fe_sq($tmp1); # fe_sq(tmp1,x2); $tmp1 = self::fe_sq($x2); # fe_add(x3,z3,z2); $x3 = self::fe_add($z3, $z2); # fe_sub(z2,z3,z2); $z2 = self::fe_sub($z3, $z2); # fe_mul(x2,tmp1,tmp0); $x2 = self::fe_mul($tmp1, $tmp0); # fe_sub(tmp1,tmp1,tmp0); $tmp1 = self::fe_sub($tmp1, $tmp0); # fe_sq(z2,z2); $z2 = self::fe_sq($z2); # fe_mul121666(z3,tmp1); $z3 = self::fe_mul121666($tmp1); # fe_sq(x3,x3); $x3 = self::fe_sq($x3); # fe_add(tmp0,tmp0,z3); $tmp0 = self::fe_add($tmp0, $z3); # fe_mul(z3,x1,z2); $z3 = self::fe_mul($x1, $z2); # fe_mul(z2,tmp1,tmp0); $z2 = self::fe_mul($tmp1, $tmp0); } # fe_cswap(x2,x3,swap); self::fe_cswap($x2, $x3, $swap); # fe_cswap(z2,z3,swap); self::fe_cswap($z2, $z3, $swap); # fe_invert(z2,z2); $z2 = self::fe_invert($z2); # fe_mul(x2,x2,z2); $x2 = self::fe_mul($x2, $z2); # fe_tobytes(q,x2); return self::fe_tobytes($x2); } /** * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $edwardsY * @param ParagonIE_Sodium_Core_Curve25519_Fe $edwardsZ * @return ParagonIE_Sodium_Core_Curve25519_Fe */ public static function edwards_to_montgomery( ParagonIE_Sodium_Core_Curve25519_Fe $edwardsY, ParagonIE_Sodium_Core_Curve25519_Fe $edwardsZ ) { $tempX = self::fe_add($edwardsZ, $edwardsY); $tempZ = self::fe_sub($edwardsZ, $edwardsY); $tempZ = self::fe_invert($tempZ); return self::fe_mul($tempX, $tempZ); } /** * @internal You should not use this directly from another application * * @param string $n * @return string * @throws SodiumException * @throws TypeError */ public static function crypto_scalarmult_curve25519_ref10_base($n) { # for (i = 0;i < 32;++i) e[i] = n[i]; $e = '' . $n; # e[0] &= 248; $e[0] = self::intToChr( self::chrToInt($e[0]) & 248 ); # e[31] &= 127; # e[31] |= 64; $e[31] = self::intToChr( (self::chrToInt($e[31]) & 127) | 64 ); $A = self::ge_scalarmult_base($e); if ( !($A->Y instanceof ParagonIE_Sodium_Core_Curve25519_Fe) || !($A->Z instanceof ParagonIE_Sodium_Core_Curve25519_Fe) ) { throw new TypeError('Null points encountered'); } $pk = self::edwards_to_montgomery($A->Y, $A->Z); return self::fe_tobytes($pk); } } PK������Z$T-��-����Core/Base64/Original.phpnu�W+A��������<?php /** * Class ParagonIE_Sodium_Core_Base64 * * Copyright (c) 2016 - 2018 Paragon Initiative Enterprises. * Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com) */ class ParagonIE_Sodium_Core_Base64_Original { // COPY ParagonIE_Sodium_Core_Base64_Common STARTING HERE /** * Encode into Base64 * * Base64 character set "[A-Z][a-z][0-9]+/" * * @param string $src * @return string * @throws TypeError */ public static function encode($src) { return self::doEncode($src, true); } /** * Encode into Base64, no = padding * * Base64 character set "[A-Z][a-z][0-9]+/" * * @param string $src * @return string * @throws TypeError */ public static function encodeUnpadded($src) { return self::doEncode($src, false); } /** * @param string $src * @param bool $pad Include = padding? * @return string * @throws TypeError */ protected static function doEncode($src, $pad = true) { $dest = ''; $srcLen = ParagonIE_Sodium_Core_Util::strlen($src); // Main loop (no padding): for ($i = 0; $i + 3 <= $srcLen; $i += 3) { /** @var array<int, int> $chunk */ $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 3)); $b0 = $chunk[1]; $b1 = $chunk[2]; $b2 = $chunk[3]; $dest .= self::encode6Bits( $b0 >> 2 ) . self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . self::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) . self::encode6Bits( $b2 & 63); } // The last chunk, which may have padding: if ($i < $srcLen) { /** @var array<int, int> $chunk */ $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i)); $b0 = $chunk[1]; if ($i + 1 < $srcLen) { $b1 = $chunk[2]; $dest .= self::encode6Bits($b0 >> 2) . self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . self::encode6Bits(($b1 << 2) & 63); if ($pad) { $dest .= '='; } } else { $dest .= self::encode6Bits( $b0 >> 2) . self::encode6Bits(($b0 << 4) & 63); if ($pad) { $dest .= '=='; } } } return $dest; } /** * decode from base64 into binary * * Base64 character set "./[A-Z][a-z][0-9]" * * @param string $src * @param bool $strictPadding * @return string * @throws RangeException * @throws TypeError * @psalm-suppress RedundantCondition */ public static function decode($src, $strictPadding = false) { // Remove padding $srcLen = ParagonIE_Sodium_Core_Util::strlen($src); if ($srcLen === 0) { return ''; } if ($strictPadding) { if (($srcLen & 3) === 0) { if ($src[$srcLen - 1] === '=') { $srcLen--; if ($src[$srcLen - 1] === '=') { $srcLen--; } } } if (($srcLen & 3) === 1) { throw new RangeException( 'Incorrect padding' ); } if ($src[$srcLen - 1] === '=') { throw new RangeException( 'Incorrect padding' ); } } else { $src = rtrim($src, '='); $srcLen = ParagonIE_Sodium_Core_Util::strlen($src); } $err = 0; $dest = ''; // Main loop (no padding): for ($i = 0; $i + 4 <= $srcLen; $i += 4) { /** @var array<int, int> $chunk */ $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 4)); $c0 = self::decode6Bits($chunk[1]); $c1 = self::decode6Bits($chunk[2]); $c2 = self::decode6Bits($chunk[3]); $c3 = self::decode6Bits($chunk[4]); $dest .= pack( 'CCC', ((($c0 << 2) | ($c1 >> 4)) & 0xff), ((($c1 << 4) | ($c2 >> 2)) & 0xff), ((($c2 << 6) | $c3) & 0xff) ); $err |= ($c0 | $c1 | $c2 | $c3) >> 8; } // The last chunk, which may have padding: if ($i < $srcLen) { /** @var array<int, int> $chunk */ $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i)); $c0 = self::decode6Bits($chunk[1]); if ($i + 2 < $srcLen) { $c1 = self::decode6Bits($chunk[2]); $c2 = self::decode6Bits($chunk[3]); $dest .= pack( 'CC', ((($c0 << 2) | ($c1 >> 4)) & 0xff), ((($c1 << 4) | ($c2 >> 2)) & 0xff) ); $err |= ($c0 | $c1 | $c2) >> 8; } elseif ($i + 1 < $srcLen) { $c1 = self::decode6Bits($chunk[2]); $dest .= pack( 'C', ((($c0 << 2) | ($c1 >> 4)) & 0xff) ); $err |= ($c0 | $c1) >> 8; } elseif ($i < $srcLen && $strictPadding) { $err |= 1; } } /** @var bool $check */ $check = ($err === 0); if (!$check) { throw new RangeException( 'Base64::decode() only expects characters in the correct base64 alphabet' ); } return $dest; } // COPY ParagonIE_Sodium_Core_Base64_Common ENDING HERE /** * Uses bitwise operators instead of table-lookups to turn 6-bit integers * into 8-bit integers. * * Base64 character set: * [A-Z] [a-z] [0-9] + / * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f * * @param int $src * @return int */ protected static function decode6Bits($src) { $ret = -1; // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64 $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64); // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70 $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70); // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5 $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5); // if ($src == 0x2b) $ret += 62 + 1; $ret += (((0x2a - $src) & ($src - 0x2c)) >> 8) & 63; // if ($src == 0x2f) ret += 63 + 1; $ret += (((0x2e - $src) & ($src - 0x30)) >> 8) & 64; return $ret; } /** * Uses bitwise operators instead of table-lookups to turn 8-bit integers * into 6-bit integers. * * @param int $src * @return string */ protected static function encode6Bits($src) { $diff = 0x41; // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6 $diff += ((25 - $src) >> 8) & 6; // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75 $diff -= ((51 - $src) >> 8) & 75; // if ($src > 61) $diff += 0x2b - 0x30 - 10; // -15 $diff -= ((61 - $src) >> 8) & 15; // if ($src > 62) $diff += 0x2f - 0x2b - 1; // 3 $diff += ((62 - $src) >> 8) & 3; return pack('C', $src + $diff); } } PK������ZLW3��3����Core/Base64/UrlSafe.phpnu�W+A��������<?php /** * Class ParagonIE_Sodium_Core_Base64UrlSafe * * Copyright (c) 2016 - 2018 Paragon Initiative Enterprises. * Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com) */ class ParagonIE_Sodium_Core_Base64_UrlSafe { // COPY ParagonIE_Sodium_Core_Base64_Common STARTING HERE /** * Encode into Base64 * * Base64 character set "[A-Z][a-z][0-9]+/" * * @param string $src * @return string * @throws TypeError */ public static function encode($src) { return self::doEncode($src, true); } /** * Encode into Base64, no = padding * * Base64 character set "[A-Z][a-z][0-9]+/" * * @param string $src * @return string * @throws TypeError */ public static function encodeUnpadded($src) { return self::doEncode($src, false); } /** * @param string $src * @param bool $pad Include = padding? * @return string * @throws TypeError */ protected static function doEncode($src, $pad = true) { $dest = ''; $srcLen = ParagonIE_Sodium_Core_Util::strlen($src); // Main loop (no padding): for ($i = 0; $i + 3 <= $srcLen; $i += 3) { /** @var array<int, int> $chunk */ $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 3)); $b0 = $chunk[1]; $b1 = $chunk[2]; $b2 = $chunk[3]; $dest .= self::encode6Bits( $b0 >> 2 ) . self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . self::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) . self::encode6Bits( $b2 & 63); } // The last chunk, which may have padding: if ($i < $srcLen) { /** @var array<int, int> $chunk */ $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i)); $b0 = $chunk[1]; if ($i + 1 < $srcLen) { $b1 = $chunk[2]; $dest .= self::encode6Bits($b0 >> 2) . self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . self::encode6Bits(($b1 << 2) & 63); if ($pad) { $dest .= '='; } } else { $dest .= self::encode6Bits( $b0 >> 2) . self::encode6Bits(($b0 << 4) & 63); if ($pad) { $dest .= '=='; } } } return $dest; } /** * decode from base64 into binary * * Base64 character set "./[A-Z][a-z][0-9]" * * @param string $src * @param bool $strictPadding * @return string * @throws RangeException * @throws TypeError * @psalm-suppress RedundantCondition */ public static function decode($src, $strictPadding = false) { // Remove padding $srcLen = ParagonIE_Sodium_Core_Util::strlen($src); if ($srcLen === 0) { return ''; } if ($strictPadding) { if (($srcLen & 3) === 0) { if ($src[$srcLen - 1] === '=') { $srcLen--; if ($src[$srcLen - 1] === '=') { $srcLen--; } } } if (($srcLen & 3) === 1) { throw new RangeException( 'Incorrect padding' ); } if ($src[$srcLen - 1] === '=') { throw new RangeException( 'Incorrect padding' ); } } else { $src = rtrim($src, '='); $srcLen = ParagonIE_Sodium_Core_Util::strlen($src); } $err = 0; $dest = ''; // Main loop (no padding): for ($i = 0; $i + 4 <= $srcLen; $i += 4) { /** @var array<int, int> $chunk */ $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 4)); $c0 = self::decode6Bits($chunk[1]); $c1 = self::decode6Bits($chunk[2]); $c2 = self::decode6Bits($chunk[3]); $c3 = self::decode6Bits($chunk[4]); $dest .= pack( 'CCC', ((($c0 << 2) | ($c1 >> 4)) & 0xff), ((($c1 << 4) | ($c2 >> 2)) & 0xff), ((($c2 << 6) | $c3) & 0xff) ); $err |= ($c0 | $c1 | $c2 | $c3) >> 8; } // The last chunk, which may have padding: if ($i < $srcLen) { /** @var array<int, int> $chunk */ $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i)); $c0 = self::decode6Bits($chunk[1]); if ($i + 2 < $srcLen) { $c1 = self::decode6Bits($chunk[2]); $c2 = self::decode6Bits($chunk[3]); $dest .= pack( 'CC', ((($c0 << 2) | ($c1 >> 4)) & 0xff), ((($c1 << 4) | ($c2 >> 2)) & 0xff) ); $err |= ($c0 | $c1 | $c2) >> 8; } elseif ($i + 1 < $srcLen) { $c1 = self::decode6Bits($chunk[2]); $dest .= pack( 'C', ((($c0 << 2) | ($c1 >> 4)) & 0xff) ); $err |= ($c0 | $c1) >> 8; } elseif ($i < $srcLen && $strictPadding) { $err |= 1; } } /** @var bool $check */ $check = ($err === 0); if (!$check) { throw new RangeException( 'Base64::decode() only expects characters in the correct base64 alphabet' ); } return $dest; } // COPY ParagonIE_Sodium_Core_Base64_Common ENDING HERE /** * Uses bitwise operators instead of table-lookups to turn 6-bit integers * into 8-bit integers. * * Base64 character set: * [A-Z] [a-z] [0-9] + / * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f * * @param int $src * @return int */ protected static function decode6Bits($src) { $ret = -1; // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64 $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64); // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70 $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70); // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5 $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5); // if ($src == 0x2c) $ret += 62 + 1; $ret += (((0x2c - $src) & ($src - 0x2e)) >> 8) & 63; // if ($src == 0x5f) ret += 63 + 1; $ret += (((0x5e - $src) & ($src - 0x60)) >> 8) & 64; return $ret; } /** * Uses bitwise operators instead of table-lookups to turn 8-bit integers * into 6-bit integers. * * @param int $src * @return string */ protected static function encode6Bits($src) { $diff = 0x41; // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6 $diff += ((25 - $src) >> 8) & 6; // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75 $diff -= ((51 - $src) >> 8) & 75; // if ($src > 61) $diff += 0x2d - 0x30 - 10; // -13 $diff -= ((61 - $src) >> 8) & 13; // if ($src > 62) $diff += 0x5f - 0x2b - 1; // 3 $diff += ((62 - $src) >> 8) & 49; return pack('C', $src + $diff); } } PK������ZӁ&��&����Core/Poly1305.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_Poly1305', false)) { return; } /** * Class ParagonIE_Sodium_Core_Poly1305 */ abstract class ParagonIE_Sodium_Core_Poly1305 extends ParagonIE_Sodium_Core_Util { const BLOCK_SIZE = 16; /** * @internal You should not use this directly from another application * * @param string $m * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function onetimeauth($m, $key) { if (self::strlen($key) < 32) { throw new InvalidArgumentException( 'Key must be 32 bytes long.' ); } $state = new ParagonIE_Sodium_Core_Poly1305_State( self::substr($key, 0, 32) ); return $state ->update($m) ->finish(); } /** * @internal You should not use this directly from another application * * @param string $mac * @param string $m * @param string $key * @return bool * @throws SodiumException * @throws TypeError */ public static function onetimeauth_verify($mac, $m, $key) { if (self::strlen($key) < 32) { throw new InvalidArgumentException( 'Key must be 32 bytes long.' ); } $state = new ParagonIE_Sodium_Core_Poly1305_State( self::substr($key, 0, 32) ); $calc = $state ->update($m) ->finish(); return self::verify_16($calc, $mac); } } PK������Zz-y9T��T����Core/AEGIS128L.phpnu�W+A��������<?php if (!defined('SODIUM_COMPAT_AEGIS_C0')) { define('SODIUM_COMPAT_AEGIS_C0', "\x00\x01\x01\x02\x03\x05\x08\x0d\x15\x22\x37\x59\x90\xe9\x79\x62"); } if (!defined('SODIUM_COMPAT_AEGIS_C1')) { define('SODIUM_COMPAT_AEGIS_C1', "\xdb\x3d\x18\x55\x6d\xc2\x2f\xf1\x20\x11\x31\x42\x73\xb5\x28\xdd"); } class ParagonIE_Sodium_Core_AEGIS128L extends ParagonIE_Sodium_Core_AES { /** * @param string $ct * @param string $tag * @param string $ad * @param string $key * @param string $nonce * @return string * @throws SodiumException */ public static function decrypt($ct, $tag, $ad, $key, $nonce) { $state = self::init($key, $nonce); $ad_blocks = (self::strlen($ad) + 31) >> 5; for ($i = 0; $i < $ad_blocks; ++$i) { $ai = self::substr($ad, $i << 5, 32); if (self::strlen($ai) < 32) { $ai = str_pad($ai, 32, "\0", STR_PAD_RIGHT); } $state->absorb($ai); } $msg = ''; $cn = self::strlen($ct) & 31; $ct_blocks = self::strlen($ct) >> 5; for ($i = 0; $i < $ct_blocks; ++$i) { $msg .= $state->dec(self::substr($ct, $i << 5, 32)); } if ($cn) { $start = $ct_blocks << 5; $msg .= $state->decPartial(self::substr($ct, $start, $cn)); } $expected_tag = $state->finalize( self::strlen($ad) << 3, self::strlen($msg) << 3 ); if (!self::hashEquals($expected_tag, $tag)) { try { // The RFC says to erase msg, so we shall try: ParagonIE_Sodium_Compat::memzero($msg); } catch (SodiumException $ex) { // Do nothing if we cannot memzero } throw new SodiumException('verification failed'); } return $msg; } /** * @param string $msg * @param string $ad * @param string $key * @param string $nonce * @return array * * @throws SodiumException */ public static function encrypt($msg, $ad, $key, $nonce) { $state = self::init($key, $nonce); // ad_blocks = Split(ZeroPad(ad, 256), 256) // for ai in ad_blocks: // Absorb(ai) $ad_len = self::strlen($ad); $msg_len = self::strlen($msg); $ad_blocks = ($ad_len + 31) >> 5; for ($i = 0; $i < $ad_blocks; ++$i) { $ai = self::substr($ad, $i << 5, 32); if (self::strlen($ai) < 32) { $ai = str_pad($ai, 32, "\0", STR_PAD_RIGHT); } $state->absorb($ai); } // msg_blocks = Split(ZeroPad(msg, 256), 256) // for xi in msg_blocks: // ct = ct || Enc(xi) $ct = ''; $msg_blocks = ($msg_len + 31) >> 5; for ($i = 0; $i < $msg_blocks; ++$i) { $xi = self::substr($msg, $i << 5, 32); if (self::strlen($xi) < 32) { $xi = str_pad($xi, 32, "\0", STR_PAD_RIGHT); } $ct .= $state->enc($xi); } // tag = Finalize(|ad|, |msg|) // ct = Truncate(ct, |msg|) $tag = $state->finalize( $ad_len << 3, $msg_len << 3 ); // return ct and tag return array( self::substr($ct, 0, $msg_len), $tag ); } /** * @param string $key * @param string $nonce * @return ParagonIE_Sodium_Core_AEGIS_State128L */ public static function init($key, $nonce) { return ParagonIE_Sodium_Core_AEGIS_State128L::init($key, $nonce); } } PK������Ze^��^����Core/BLAKE2b.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_BLAKE2b', false)) { return; } /** * Class ParagonIE_Sodium_Core_BLAKE2b * * Based on the work of Devi Mandiri in devi/salt. */ abstract class ParagonIE_Sodium_Core_BLAKE2b extends ParagonIE_Sodium_Core_Util { /** * @var SplFixedArray */ protected static $iv; /** * @var array<int, array<int, int>> */ protected static $sigma = array( array( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), array( 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3), array( 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4), array( 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8), array( 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13), array( 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9), array( 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11), array( 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10), array( 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5), array( 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0), array( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), array( 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3) ); const BLOCKBYTES = 128; const OUTBYTES = 64; const KEYBYTES = 64; /** * Turn two 32-bit integers into a fixed array representing a 64-bit integer. * * @internal You should not use this directly from another application * * @param int $high * @param int $low * @return SplFixedArray * @psalm-suppress MixedAssignment */ public static function new64($high, $low) { if (PHP_INT_SIZE === 4) { throw new SodiumException("Error, use 32-bit"); } $i64 = new SplFixedArray(2); $i64[0] = $high & 0xffffffff; $i64[1] = $low & 0xffffffff; return $i64; } /** * Convert an arbitrary number into an SplFixedArray of two 32-bit integers * that represents a 64-bit integer. * * @internal You should not use this directly from another application * * @param int $num * @return SplFixedArray */ protected static function to64($num) { list($hi, $lo) = self::numericTo64BitInteger($num); return self::new64($hi, $lo); } /** * Adds two 64-bit integers together, returning their sum as a SplFixedArray * containing two 32-bit integers (representing a 64-bit integer). * * @internal You should not use this directly from another application * * @param SplFixedArray $x * @param SplFixedArray $y * @return SplFixedArray * @psalm-suppress MixedArgument * @psalm-suppress MixedAssignment * @psalm-suppress MixedOperand */ protected static function add64($x, $y) { if (PHP_INT_SIZE === 4) { throw new SodiumException("Error, use 32-bit"); } $l = ($x[1] + $y[1]) & 0xffffffff; return self::new64( (int) ($x[0] + $y[0] + ( ($l < $x[1]) ? 1 : 0 )), (int) $l ); } /** * @internal You should not use this directly from another application * * @param SplFixedArray $x * @param SplFixedArray $y * @param SplFixedArray $z * @return SplFixedArray */ protected static function add364($x, $y, $z) { return self::add64($x, self::add64($y, $z)); } /** * @internal You should not use this directly from another application * * @param SplFixedArray $x * @param SplFixedArray $y * @return SplFixedArray * @throws SodiumException * @throws TypeError */ protected static function xor64(SplFixedArray $x, SplFixedArray $y) { if (PHP_INT_SIZE === 4) { throw new SodiumException("Error, use 32-bit"); } if (!is_numeric($x[0])) { throw new SodiumException('x[0] is not an integer'); } if (!is_numeric($x[1])) { throw new SodiumException('x[1] is not an integer'); } if (!is_numeric($y[0])) { throw new SodiumException('y[0] is not an integer'); } if (!is_numeric($y[1])) { throw new SodiumException('y[1] is not an integer'); } return self::new64( (int) (($x[0] ^ $y[0]) & 0xffffffff), (int) (($x[1] ^ $y[1]) & 0xffffffff) ); } /** * @internal You should not use this directly from another application * * @param SplFixedArray $x * @param int $c * @return SplFixedArray * @psalm-suppress MixedAssignment */ public static function rotr64($x, $c) { if (PHP_INT_SIZE === 4) { throw new SodiumException("Error, use 32-bit"); } if ($c >= 64) { $c %= 64; } if ($c >= 32) { /** @var int $tmp */ $tmp = $x[0]; $x[0] = $x[1]; $x[1] = $tmp; $c -= 32; } if ($c === 0) { return $x; } $l0 = 0; $c = 64 - $c; /** @var int $c */ if ($c < 32) { $h0 = ((int) ($x[0]) << $c) | ( ( (int) ($x[1]) & ((1 << $c) - 1) << (32 - $c) ) >> (32 - $c) ); $l0 = (int) ($x[1]) << $c; } else { $h0 = (int) ($x[1]) << ($c - 32); } $h1 = 0; $c1 = 64 - $c; if ($c1 < 32) { $h1 = (int) ($x[0]) >> $c1; $l1 = ((int) ($x[1]) >> $c1) | ((int) ($x[0]) & ((1 << $c1) - 1)) << (32 - $c1); } else { $l1 = (int) ($x[0]) >> ($c1 - 32); } return self::new64($h0 | $h1, $l0 | $l1); } /** * @internal You should not use this directly from another application * * @param SplFixedArray $x * @return int * @psalm-suppress MixedOperand */ protected static function flatten64($x) { return (int) ($x[0] * 4294967296 + $x[1]); } /** * @internal You should not use this directly from another application * * @param SplFixedArray $x * @param int $i * @return SplFixedArray * @psalm-suppress MixedArgument * @psalm-suppress MixedArrayOffset */ protected static function load64(SplFixedArray $x, $i) { /** @var int $l */ $l = (int) ($x[$i]) | ((int) ($x[$i+1]) << 8) | ((int) ($x[$i+2]) << 16) | ((int) ($x[$i+3]) << 24); /** @var int $h */ $h = (int) ($x[$i+4]) | ((int) ($x[$i+5]) << 8) | ((int) ($x[$i+6]) << 16) | ((int) ($x[$i+7]) << 24); return self::new64($h, $l); } /** * @internal You should not use this directly from another application * * @param SplFixedArray $x * @param int $i * @param SplFixedArray $u * @return void * @psalm-suppress MixedAssignment */ protected static function store64(SplFixedArray $x, $i, SplFixedArray $u) { $maxLength = $x->getSize() - 1; for ($j = 0; $j < 8; ++$j) { /* [0, 1, 2, 3, 4, 5, 6, 7] ... becomes ... [0, 0, 0, 0, 1, 1, 1, 1] */ /** @var int $uIdx */ $uIdx = ((7 - $j) & 4) >> 2; $x[$i] = ((int) ($u[$uIdx]) & 0xff); if (++$i > $maxLength) { return; } /** @psalm-suppress MixedOperand */ $u[$uIdx] >>= 8; } } /** * This just sets the $iv static variable. * * @internal You should not use this directly from another application * * @return void */ public static function pseudoConstructor() { static $called = false; if ($called) { return; } self::$iv = new SplFixedArray(8); self::$iv[0] = self::new64(0x6a09e667, 0xf3bcc908); self::$iv[1] = self::new64(0xbb67ae85, 0x84caa73b); self::$iv[2] = self::new64(0x3c6ef372, 0xfe94f82b); self::$iv[3] = self::new64(0xa54ff53a, 0x5f1d36f1); self::$iv[4] = self::new64(0x510e527f, 0xade682d1); self::$iv[5] = self::new64(0x9b05688c, 0x2b3e6c1f); self::$iv[6] = self::new64(0x1f83d9ab, 0xfb41bd6b); self::$iv[7] = self::new64(0x5be0cd19, 0x137e2179); $called = true; } /** * Returns a fresh BLAKE2 context. * * @internal You should not use this directly from another application * * @return SplFixedArray * @psalm-suppress MixedAssignment * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayAssignment */ protected static function context() { $ctx = new SplFixedArray(6); $ctx[0] = new SplFixedArray(8); // h $ctx[1] = new SplFixedArray(2); // t $ctx[2] = new SplFixedArray(2); // f $ctx[3] = new SplFixedArray(256); // buf $ctx[4] = 0; // buflen $ctx[5] = 0; // last_node (uint8_t) for ($i = 8; $i--;) { $ctx[0][$i] = self::$iv[$i]; } for ($i = 256; $i--;) { $ctx[3][$i] = 0; } $zero = self::new64(0, 0); $ctx[1][0] = $zero; $ctx[1][1] = $zero; $ctx[2][0] = $zero; $ctx[2][1] = $zero; return $ctx; } /** * @internal You should not use this directly from another application * * @param SplFixedArray $ctx * @param SplFixedArray $buf * @return void * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedAssignment * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayAssignment * @psalm-suppress MixedArrayOffset */ protected static function compress(SplFixedArray $ctx, SplFixedArray $buf) { $m = new SplFixedArray(16); $v = new SplFixedArray(16); for ($i = 16; $i--;) { $m[$i] = self::load64($buf, $i << 3); } for ($i = 8; $i--;) { $v[$i] = $ctx[0][$i]; } $v[ 8] = self::$iv[0]; $v[ 9] = self::$iv[1]; $v[10] = self::$iv[2]; $v[11] = self::$iv[3]; $v[12] = self::xor64($ctx[1][0], self::$iv[4]); $v[13] = self::xor64($ctx[1][1], self::$iv[5]); $v[14] = self::xor64($ctx[2][0], self::$iv[6]); $v[15] = self::xor64($ctx[2][1], self::$iv[7]); for ($r = 0; $r < 12; ++$r) { $v = self::G($r, 0, 0, 4, 8, 12, $v, $m); $v = self::G($r, 1, 1, 5, 9, 13, $v, $m); $v = self::G($r, 2, 2, 6, 10, 14, $v, $m); $v = self::G($r, 3, 3, 7, 11, 15, $v, $m); $v = self::G($r, 4, 0, 5, 10, 15, $v, $m); $v = self::G($r, 5, 1, 6, 11, 12, $v, $m); $v = self::G($r, 6, 2, 7, 8, 13, $v, $m); $v = self::G($r, 7, 3, 4, 9, 14, $v, $m); } for ($i = 8; $i--;) { $ctx[0][$i] = self::xor64( $ctx[0][$i], self::xor64($v[$i], $v[$i+8]) ); } } /** * @internal You should not use this directly from another application * * @param int $r * @param int $i * @param int $a * @param int $b * @param int $c * @param int $d * @param SplFixedArray $v * @param SplFixedArray $m * @return SplFixedArray * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedArrayOffset */ public static function G($r, $i, $a, $b, $c, $d, SplFixedArray $v, SplFixedArray $m) { $v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][$i << 1]]); $v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 32); $v[$c] = self::add64($v[$c], $v[$d]); $v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 24); $v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][($i << 1) + 1]]); $v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 16); $v[$c] = self::add64($v[$c], $v[$d]); $v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 63); return $v; } /** * @internal You should not use this directly from another application * * @param SplFixedArray $ctx * @param int $inc * @return void * @throws SodiumException * @psalm-suppress MixedArgument * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayAssignment */ public static function increment_counter($ctx, $inc) { if ($inc < 0) { throw new SodiumException('Increasing by a negative number makes no sense.'); } $t = self::to64($inc); # S->t is $ctx[1] in our implementation # S->t[0] = ( uint64_t )( t >> 0 ); $ctx[1][0] = self::add64($ctx[1][0], $t); # S->t[1] += ( S->t[0] < inc ); if (self::flatten64($ctx[1][0]) < $inc) { $ctx[1][1] = self::add64($ctx[1][1], self::to64(1)); } } /** * @internal You should not use this directly from another application * * @param SplFixedArray $ctx * @param SplFixedArray $p * @param int $plen * @return void * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedAssignment * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayAssignment * @psalm-suppress MixedArrayOffset * @psalm-suppress MixedOperand */ public static function update(SplFixedArray $ctx, SplFixedArray $p, $plen) { self::pseudoConstructor(); $offset = 0; while ($plen > 0) { $left = $ctx[4]; $fill = 256 - $left; if ($plen > $fill) { # memcpy( S->buf + left, in, fill ); /* Fill buffer */ for ($i = $fill; $i--;) { $ctx[3][$i + $left] = $p[$i + $offset]; } # S->buflen += fill; $ctx[4] += $fill; # blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); self::increment_counter($ctx, 128); # blake2b_compress( S, S->buf ); /* Compress */ self::compress($ctx, $ctx[3]); # memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); /* Shift buffer left */ for ($i = 128; $i--;) { $ctx[3][$i] = $ctx[3][$i + 128]; } # S->buflen -= BLAKE2B_BLOCKBYTES; $ctx[4] -= 128; # in += fill; $offset += $fill; # inlen -= fill; $plen -= $fill; } else { for ($i = $plen; $i--;) { $ctx[3][$i + $left] = $p[$i + $offset]; } $ctx[4] += $plen; $offset += $plen; $plen -= $plen; } } } /** * @internal You should not use this directly from another application * * @param SplFixedArray $ctx * @param SplFixedArray $out * @return SplFixedArray * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedAssignment * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayAssignment * @psalm-suppress MixedArrayOffset * @psalm-suppress MixedOperand */ public static function finish(SplFixedArray $ctx, SplFixedArray $out) { self::pseudoConstructor(); if ($ctx[4] > 128) { self::increment_counter($ctx, 128); self::compress($ctx, $ctx[3]); $ctx[4] -= 128; if ($ctx[4] > 128) { throw new SodiumException('Failed to assert that buflen <= 128 bytes'); } for ($i = $ctx[4]; $i--;) { $ctx[3][$i] = $ctx[3][$i + 128]; } } self::increment_counter($ctx, $ctx[4]); $ctx[2][0] = self::new64(0xffffffff, 0xffffffff); for ($i = 256 - $ctx[4]; $i--;) { $ctx[3][$i+$ctx[4]] = 0; } self::compress($ctx, $ctx[3]); $i = (int) (($out->getSize() - 1) / 8); for (; $i >= 0; --$i) { self::store64($out, $i << 3, $ctx[0][$i]); } return $out; } /** * @internal You should not use this directly from another application * * @param SplFixedArray|null $key * @param int $outlen * @param SplFixedArray|null $salt * @param SplFixedArray|null $personal * @return SplFixedArray * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedAssignment * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayAssignment * @psalm-suppress MixedArrayOffset */ public static function init( $key = null, $outlen = 64, $salt = null, $personal = null ) { self::pseudoConstructor(); $klen = 0; if ($key !== null) { if (count($key) > 64) { throw new SodiumException('Invalid key size'); } $klen = count($key); } if ($outlen > 64) { throw new SodiumException('Invalid output size'); } $ctx = self::context(); $p = new SplFixedArray(64); // Zero our param buffer... for ($i = 64; --$i;) { $p[$i] = 0; } $p[0] = $outlen; // digest_length $p[1] = $klen; // key_length $p[2] = 1; // fanout $p[3] = 1; // depth if ($salt instanceof SplFixedArray) { // salt: [32] through [47] for ($i = 0; $i < 16; ++$i) { $p[32 + $i] = (int) $salt[$i]; } } if ($personal instanceof SplFixedArray) { // personal: [48] through [63] for ($i = 0; $i < 16; ++$i) { $p[48 + $i] = (int) $personal[$i]; } } $ctx[0][0] = self::xor64( $ctx[0][0], self::load64($p, 0) ); if ($salt instanceof SplFixedArray || $personal instanceof SplFixedArray) { // We need to do what blake2b_init_param() does: for ($i = 1; $i < 8; ++$i) { $ctx[0][$i] = self::xor64( $ctx[0][$i], self::load64($p, $i << 3) ); } } if ($klen > 0 && $key instanceof SplFixedArray) { $block = new SplFixedArray(128); for ($i = 128; $i--;) { $block[$i] = 0; } for ($i = $klen; $i--;) { $block[$i] = $key[$i]; } self::update($ctx, $block, 128); $ctx[4] = 128; } return $ctx; } /** * Convert a string into an SplFixedArray of integers * * @internal You should not use this directly from another application * * @param string $str * @return SplFixedArray * @psalm-suppress MixedArgumentTypeCoercion */ public static function stringToSplFixedArray($str = '') { $values = unpack('C*', $str); return SplFixedArray::fromArray(array_values($values)); } /** * Convert an SplFixedArray of integers into a string * * @internal You should not use this directly from another application * * @param SplFixedArray $a * @return string * @throws TypeError */ public static function SplFixedArrayToString(SplFixedArray $a) { /** * @var array<int, int|string> $arr */ $arr = $a->toArray(); $c = $a->count(); array_unshift($arr, str_repeat('C', $c)); return (string) (call_user_func_array('pack', $arr)); } /** * @internal You should not use this directly from another application * * @param SplFixedArray $ctx * @return string * @throws TypeError * @psalm-suppress MixedArgument * @psalm-suppress MixedAssignment * @psalm-suppress MixedArrayAccess * @psalm-suppress MixedArrayAssignment * @psalm-suppress MixedArrayOffset * @psalm-suppress MixedMethodCall */ public static function contextToString(SplFixedArray $ctx) { $str = ''; /** @var array<int, array<int, int>> $ctxA */ $ctxA = $ctx[0]->toArray(); # uint64_t h[8]; for ($i = 0; $i < 8; ++$i) { $str .= self::store32_le($ctxA[$i][1]); $str .= self::store32_le($ctxA[$i][0]); } # uint64_t t[2]; # uint64_t f[2]; for ($i = 1; $i < 3; ++$i) { $ctxA = $ctx[$i]->toArray(); $str .= self::store32_le($ctxA[0][1]); $str .= self::store32_le($ctxA[0][0]); $str .= self::store32_le($ctxA[1][1]); $str .= self::store32_le($ctxA[1][0]); } # uint8_t buf[2 * 128]; $str .= self::SplFixedArrayToString($ctx[3]); /** @var int $ctx4 */ $ctx4 = (int) $ctx[4]; # size_t buflen; $str .= implode('', array( self::intToChr($ctx4 & 0xff), self::intToChr(($ctx4 >> 8) & 0xff), self::intToChr(($ctx4 >> 16) & 0xff), self::intToChr(($ctx4 >> 24) & 0xff), self::intToChr(($ctx4 >> 32) & 0xff), self::intToChr(($ctx4 >> 40) & 0xff), self::intToChr(($ctx4 >> 48) & 0xff), self::intToChr(($ctx4 >> 56) & 0xff) )); # uint8_t last_node; return $str . self::intToChr($ctx[5]) . str_repeat("\x00", 23); } /** * Creates an SplFixedArray containing other SplFixedArray elements, from * a string (compatible with \Sodium\crypto_generichash_{init, update, final}) * * @internal You should not use this directly from another application * * @param string $string * @return SplFixedArray * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArrayAssignment */ public static function stringToContext($string) { $ctx = self::context(); # uint64_t h[8]; for ($i = 0; $i < 8; ++$i) { $ctx[0][$i] = SplFixedArray::fromArray( array( self::load_4( self::substr($string, (($i << 3) + 4), 4) ), self::load_4( self::substr($string, (($i << 3) + 0), 4) ) ) ); } # uint64_t t[2]; # uint64_t f[2]; for ($i = 1; $i < 3; ++$i) { $ctx[$i][1] = SplFixedArray::fromArray( array( self::load_4(self::substr($string, 76 + (($i - 1) << 4), 4)), self::load_4(self::substr($string, 72 + (($i - 1) << 4), 4)) ) ); $ctx[$i][0] = SplFixedArray::fromArray( array( self::load_4(self::substr($string, 68 + (($i - 1) << 4), 4)), self::load_4(self::substr($string, 64 + (($i - 1) << 4), 4)) ) ); } # uint8_t buf[2 * 128]; $ctx[3] = self::stringToSplFixedArray(self::substr($string, 96, 256)); # uint8_t buf[2 * 128]; $int = 0; for ($i = 0; $i < 8; ++$i) { $int |= self::chrToInt($string[352 + $i]) << ($i << 3); } $ctx[4] = $int; return $ctx; } } PK������Z* ��* ����Core/XChaCha20.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_XChaCha20', false)) { return; } /** * Class ParagonIE_Sodium_Core_XChaCha20 */ class ParagonIE_Sodium_Core_XChaCha20 extends ParagonIE_Sodium_Core_HChaCha20 { /** * @internal You should not use this directly from another application * * @param int $len * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function stream($len = 64, $nonce = '', $key = '') { if (self::strlen($nonce) !== 24) { throw new SodiumException('Nonce must be 24 bytes long'); } return self::encryptBytes( new ParagonIE_Sodium_Core_ChaCha20_Ctx( self::hChaCha20( self::substr($nonce, 0, 16), $key ), self::substr($nonce, 16, 8) ), str_repeat("\x00", $len) ); } /** * @internal You should not use this directly from another application * * @param int $len * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function ietfStream($len = 64, $nonce = '', $key = '') { if (self::strlen($nonce) !== 24) { throw new SodiumException('Nonce must be 24 bytes long'); } return self::encryptBytes( new ParagonIE_Sodium_Core_ChaCha20_IetfCtx( self::hChaCha20( self::substr($nonce, 0, 16), $key ), "\x00\x00\x00\x00" . self::substr($nonce, 16, 8) ), str_repeat("\x00", $len) ); } /** * @internal You should not use this directly from another application * * @param string $message * @param string $nonce * @param string $key * @param string $ic * @return string * @throws SodiumException * @throws TypeError */ public static function streamXorIc($message, $nonce = '', $key = '', $ic = '') { if (self::strlen($nonce) !== 24) { throw new SodiumException('Nonce must be 24 bytes long'); } return self::encryptBytes( new ParagonIE_Sodium_Core_ChaCha20_Ctx( self::hChaCha20(self::substr($nonce, 0, 16), $key), self::substr($nonce, 16, 8), $ic ), $message ); } /** * @internal You should not use this directly from another application * * @param string $message * @param string $nonce * @param string $key * @param string $ic * @return string * @throws SodiumException * @throws TypeError */ public static function ietfStreamXorIc($message, $nonce = '', $key = '', $ic = '') { if (self::strlen($nonce) !== 24) { throw new SodiumException('Nonce must be 24 bytes long'); } return self::encryptBytes( new ParagonIE_Sodium_Core_ChaCha20_IetfCtx( self::hChaCha20(self::substr($nonce, 0, 16), $key), "\x00\x00\x00\x00" . self::substr($nonce, 16, 8), $ic ), $message ); } } PK������ZY��Y����Core/HSalsa20.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_HSalsa20', false)) { return; } /** * Class ParagonIE_Sodium_Core_HSalsa20 */ abstract class ParagonIE_Sodium_Core_HSalsa20 extends ParagonIE_Sodium_Core_Salsa20 { /** * Calculate an hsalsa20 hash of a single block * * HSalsa20 doesn't have a counter and will never be used for more than * one block (used to derive a subkey for xsalsa20). * * @internal You should not use this directly from another application * * @param string $in * @param string $k * @param string|null $c * @return string * @throws TypeError */ public static function hsalsa20($in, $k, $c = null) { if ($c === null) { $x0 = 0x61707865; $x5 = 0x3320646e; $x10 = 0x79622d32; $x15 = 0x6b206574; } else { $x0 = self::load_4(self::substr($c, 0, 4)); $x5 = self::load_4(self::substr($c, 4, 4)); $x10 = self::load_4(self::substr($c, 8, 4)); $x15 = self::load_4(self::substr($c, 12, 4)); } $x1 = self::load_4(self::substr($k, 0, 4)); $x2 = self::load_4(self::substr($k, 4, 4)); $x3 = self::load_4(self::substr($k, 8, 4)); $x4 = self::load_4(self::substr($k, 12, 4)); $x11 = self::load_4(self::substr($k, 16, 4)); $x12 = self::load_4(self::substr($k, 20, 4)); $x13 = self::load_4(self::substr($k, 24, 4)); $x14 = self::load_4(self::substr($k, 28, 4)); $x6 = self::load_4(self::substr($in, 0, 4)); $x7 = self::load_4(self::substr($in, 4, 4)); $x8 = self::load_4(self::substr($in, 8, 4)); $x9 = self::load_4(self::substr($in, 12, 4)); for ($i = self::ROUNDS; $i > 0; $i -= 2) { $x4 ^= self::rotate($x0 + $x12, 7); $x8 ^= self::rotate($x4 + $x0, 9); $x12 ^= self::rotate($x8 + $x4, 13); $x0 ^= self::rotate($x12 + $x8, 18); $x9 ^= self::rotate($x5 + $x1, 7); $x13 ^= self::rotate($x9 + $x5, 9); $x1 ^= self::rotate($x13 + $x9, 13); $x5 ^= self::rotate($x1 + $x13, 18); $x14 ^= self::rotate($x10 + $x6, 7); $x2 ^= self::rotate($x14 + $x10, 9); $x6 ^= self::rotate($x2 + $x14, 13); $x10 ^= self::rotate($x6 + $x2, 18); $x3 ^= self::rotate($x15 + $x11, 7); $x7 ^= self::rotate($x3 + $x15, 9); $x11 ^= self::rotate($x7 + $x3, 13); $x15 ^= self::rotate($x11 + $x7, 18); $x1 ^= self::rotate($x0 + $x3, 7); $x2 ^= self::rotate($x1 + $x0, 9); $x3 ^= self::rotate($x2 + $x1, 13); $x0 ^= self::rotate($x3 + $x2, 18); $x6 ^= self::rotate($x5 + $x4, 7); $x7 ^= self::rotate($x6 + $x5, 9); $x4 ^= self::rotate($x7 + $x6, 13); $x5 ^= self::rotate($x4 + $x7, 18); $x11 ^= self::rotate($x10 + $x9, 7); $x8 ^= self::rotate($x11 + $x10, 9); $x9 ^= self::rotate($x8 + $x11, 13); $x10 ^= self::rotate($x9 + $x8, 18); $x12 ^= self::rotate($x15 + $x14, 7); $x13 ^= self::rotate($x12 + $x15, 9); $x14 ^= self::rotate($x13 + $x12, 13); $x15 ^= self::rotate($x14 + $x13, 18); } return self::store32_le($x0) . self::store32_le($x5) . self::store32_le($x10) . self::store32_le($x15) . self::store32_le($x6) . self::store32_le($x7) . self::store32_le($x8) . self::store32_le($x9); } } PK������ZCUg �� ����Core/Curve25519/Fe.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_Curve25519_Fe', false)) { return; } /** * Class ParagonIE_Sodium_Core_Curve25519_Fe * * This represents a Field Element */ class ParagonIE_Sodium_Core_Curve25519_Fe implements ArrayAccess { /** * @var array<int, int> */ protected $container = array(); /** * @var int */ protected $size = 10; /** * @internal You should not use this directly from another application * * @param array<int, int> $array * @param bool $save_indexes * @return self */ public static function fromArray($array, $save_indexes = null) { $count = count($array); if ($save_indexes) { $keys = array_keys($array); } else { $keys = range(0, $count - 1); } $array = array_values($array); /** @var array<int, int> $keys */ $obj = new ParagonIE_Sodium_Core_Curve25519_Fe(); if ($save_indexes) { for ($i = 0; $i < $count; ++$i) { $obj->offsetSet($keys[$i], $array[$i]); } } else { for ($i = 0; $i < $count; ++$i) { $obj->offsetSet($i, $array[$i]); } } return $obj; } /** * @internal You should not use this directly from another application * * @param int|null $offset * @param int $value * @return void * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetSet($offset, $value) { if (!is_int($value)) { throw new InvalidArgumentException('Expected an integer'); } if (is_null($offset)) { $this->container[] = $value; } else { $this->container[$offset] = $value; } } /** * @internal You should not use this directly from another application * * @param int $offset * @return bool * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->container[$offset]); } /** * @internal You should not use this directly from another application * * @param int $offset * @return void * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->container[$offset]); } /** * @internal You should not use this directly from another application * * @param int $offset * @return int * @psalm-suppress MixedArrayOffset */ #[ReturnTypeWillChange] public function offsetGet($offset) { if (!isset($this->container[$offset])) { $this->container[$offset] = 0; } return (int) ($this->container[$offset]); } /** * @internal You should not use this directly from another application * * @return array */ public function __debugInfo() { return array(implode(', ', $this->container)); } } PK������Z珉��������Core/Curve25519/README.mdnu�W+A��������# Curve25519 Data Structures These are PHP implementation of the [structs used in the ref10 curve25519 code](https://github.com/jedisct1/libsodium/blob/master/src/libsodium/include/sodium/private/curve25519_ref10.h). PK������Zr��r����Core/Curve25519/Ge/Precomp.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_Curve25519_Ge_Precomp', false)) { return; } /** * Class ParagonIE_Sodium_Core_Curve25519_Ge_Precomp */ class ParagonIE_Sodium_Core_Curve25519_Ge_Precomp { /** * @var ParagonIE_Sodium_Core_Curve25519_Fe */ public $yplusx; /** * @var ParagonIE_Sodium_Core_Curve25519_Fe */ public $yminusx; /** * @var ParagonIE_Sodium_Core_Curve25519_Fe */ public $xy2d; /** * ParagonIE_Sodium_Core_Curve25519_Ge_Precomp constructor. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe $yplusx * @param ParagonIE_Sodium_Core_Curve25519_Fe $yminusx * @param ParagonIE_Sodium_Core_Curve25519_Fe $xy2d */ public function __construct( $yplusx = null, $yminusx = null, $xy2d = null ) { if ($yplusx === null) { $yplusx = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($yplusx instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 1 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->yplusx = $yplusx; if ($yminusx === null) { $yminusx = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($yminusx instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 2 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->yminusx = $yminusx; if ($xy2d === null) { $xy2d = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($xy2d instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 3 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->xy2d = $xy2d; } } PK������Z������Core/Curve25519/Ge/P1p1.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_Curve25519_Ge_P1p1', false)) { return; } /** * Class ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 */ class ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 { /** * @var ParagonIE_Sodium_Core_Curve25519_Fe */ public $X; /** * @var ParagonIE_Sodium_Core_Curve25519_Fe */ public $Y; /** * @var ParagonIE_Sodium_Core_Curve25519_Fe */ public $Z; /** * @var ParagonIE_Sodium_Core_Curve25519_Fe */ public $T; /** * ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 constructor. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $x * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $y * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $z * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $t */ public function __construct( $x = null, $y = null, $z = null, $t = null ) { if ($x === null) { $x = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($x instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 1 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->X = $x; if ($y === null) { $y = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($y instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 2 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->Y = $y; if ($z === null) { $z = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($z instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 3 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->Z = $z; if ($t === null) { $t = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($t instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 4 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->T = $t; } } PK������ZrB ��B ����Core/Curve25519/Ge/Cached.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_Curve25519_Ge_Cached', false)) { return; } /** * Class ParagonIE_Sodium_Core_Curve25519_Ge_Cached */ class ParagonIE_Sodium_Core_Curve25519_Ge_Cached { /** * @var ParagonIE_Sodium_Core_Curve25519_Fe */ public $YplusX; /** * @var ParagonIE_Sodium_Core_Curve25519_Fe */ public $YminusX; /** * @var ParagonIE_Sodium_Core_Curve25519_Fe */ public $Z; /** * @var ParagonIE_Sodium_Core_Curve25519_Fe */ public $T2d; /** * ParagonIE_Sodium_Core_Curve25519_Ge_Cached constructor. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $YplusX * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $YminusX * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $Z * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $T2d */ public function __construct( $YplusX = null, $YminusX = null, $Z = null, $T2d = null ) { if ($YplusX === null) { $YplusX = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($YplusX instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 1 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->YplusX = $YplusX; if ($YminusX === null) { $YminusX = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($YminusX instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 2 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->YminusX = $YminusX; if ($Z === null) { $Z = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($Z instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 3 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->Z = $Z; if ($T2d === null) { $T2d = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($T2d instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 4 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->T2d = $T2d; } } PK������Z������Core/Curve25519/Ge/P2.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_Curve25519_Ge_P2', false)) { return; } /** * Class ParagonIE_Sodium_Core_Curve25519_Ge_P2 */ class ParagonIE_Sodium_Core_Curve25519_Ge_P2 { /** * @var ParagonIE_Sodium_Core_Curve25519_Fe */ public $X; /** * @var ParagonIE_Sodium_Core_Curve25519_Fe */ public $Y; /** * @var ParagonIE_Sodium_Core_Curve25519_Fe */ public $Z; /** * ParagonIE_Sodium_Core_Curve25519_Ge_P2 constructor. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $x * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $y * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $z */ public function __construct( $x = null, $y = null, $z = null ) { if ($x === null) { $x = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($x instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 1 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->X = $x; if ($y === null) { $y = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($y instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 2 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->Y = $y; if ($z === null) { $z = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($z instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 3 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->Z = $z; } } PK������Z"M������Core/Curve25519/Ge/P3.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_Curve25519_Ge_P3', false)) { return; } /** * Class ParagonIE_Sodium_Core_Curve25519_Ge_P3 */ class ParagonIE_Sodium_Core_Curve25519_Ge_P3 { /** * @var ParagonIE_Sodium_Core_Curve25519_Fe */ public $X; /** * @var ParagonIE_Sodium_Core_Curve25519_Fe */ public $Y; /** * @var ParagonIE_Sodium_Core_Curve25519_Fe */ public $Z; /** * @var ParagonIE_Sodium_Core_Curve25519_Fe */ public $T; /** * ParagonIE_Sodium_Core_Curve25519_Ge_P3 constructor. * * @internal You should not use this directly from another application * * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $x * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $y * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $z * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $t */ public function __construct( $x = null, $y = null, $z = null, $t = null ) { if ($x === null) { $x = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($x instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 1 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->X = $x; if ($y === null) { $y = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($y instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 2 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->Y = $y; if ($z === null) { $z = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($z instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 3 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->Z = $z; if ($t === null) { $t = new ParagonIE_Sodium_Core_Curve25519_Fe(); } if (!($t instanceof ParagonIE_Sodium_Core_Curve25519_Fe)) { throw new TypeError('Argument 4 must be an instance of ParagonIE_Sodium_Core_Curve25519_Fe'); } $this->T = $t; } } PK������Z}ڢTy�y���Core/Curve25519/H.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_Curve25519_H', false)) { return; } /** * Class ParagonIE_Sodium_Core_Curve25519_H * * This just contains the constants in the ref10/base.h file */ class ParagonIE_Sodium_Core_Curve25519_H extends ParagonIE_Sodium_Core_Util { /** * See: libsodium's crypto_core/curve25519/ref10/base.h * * @var array<int, array<int, array<int, array<int, int>>>> Basically, int[32][8][3][10] */ protected static $base = array( array( array( array(25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605), array(-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378), array(-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546), ), array( array(-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303), array(-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081), array(26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697), ), array( array(15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024), array(16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574), array(30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357), ), array( array(-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540), array(23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397), array(7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325), ), array( array(10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380), array(4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306), array(19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942), ), array( array(-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777), array(-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737), array(-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652), ), array( array(5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766), array(-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701), array(28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300), ), array( array(14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726), array(-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955), array(27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425), ), ), array( array( array(-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171), array(27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510), array(17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660), ), array( array(-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639), array(29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963), array(5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950), ), array( array(-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568), array(12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335), array(25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628), ), array( array(-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007), array(-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772), array(-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653), ), array( array(2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567), array(13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686), array(21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372), ), array( array(-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887), array(-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954), array(-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953), ), array( array(24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833), array(-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532), array(-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876), ), array( array(2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268), array(33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214), array(1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038), ), ), array( array( array(6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800), array(4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645), array(-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664), ), array( array(1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933), array(-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182), array(-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222), ), array( array(-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991), array(20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880), array(9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092), ), array( array(-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295), array(19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788), array(8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553), ), array( array(-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026), array(11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347), array(-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033), ), array( array(-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395), array(-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278), array(1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890), ), array( array(32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995), array(-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596), array(-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891), ), array( array(31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060), array(11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608), array(-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606), ), ), array( array( array(7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389), array(-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016), array(-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341), ), array( array(-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505), array(14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553), array(-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655), ), array( array(15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220), array(12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631), array(-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099), ), array( array(26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556), array(14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749), array(236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930), ), array( array(1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391), array(5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253), array(20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066), ), array( array(24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958), array(-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082), array(-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383), ), array( array(-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521), array(-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807), array(23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948), ), array( array(9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134), array(-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455), array(27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629), ), ), array( array( array(-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069), array(-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746), array(24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919), ), array( array(11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837), array(8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906), array(-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771), ), array( array(-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817), array(10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098), array(10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409), ), array( array(-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504), array(-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727), array(28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420), ), array( array(-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003), array(-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605), array(-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384), ), array( array(-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701), array(-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683), array(29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708), ), array( array(-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563), array(-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260), array(-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387), ), array( array(-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672), array(23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686), array(-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665), ), ), array( array( array(11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182), array(-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277), array(14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628), ), array( array(-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474), array(-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539), array(-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822), ), array( array(-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970), array(19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756), array(-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508), ), array( array(-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683), array(-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655), array(-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158), ), array( array(-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125), array(-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839), array(-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664), ), array( array(27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294), array(-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899), array(-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070), ), array( array(3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294), array(-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949), array(-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083), ), array( array(31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420), array(-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940), array(29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396), ), ), array( array( array(-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567), array(20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127), array(-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294), ), array( array(-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887), array(22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964), array(16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195), ), array( array(9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244), array(24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999), array(-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762), ), array( array(-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274), array(-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236), array(-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605), ), array( array(-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761), array(-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884), array(-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482), ), array( array(-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638), array(-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490), array(-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170), ), array( array(5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736), array(10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124), array(-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392), ), array( array(8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029), array(6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048), array(28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958), ), ), array( array( array(24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593), array(26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071), array(-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692), ), array( array(11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687), array(-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441), array(-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001), ), array( array(-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460), array(-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007), array(-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762), ), array( array(15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005), array(-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674), array(4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035), ), array( array(7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590), array(-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957), array(-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812), ), array( array(33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740), array(-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122), array(-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158), ), array( array(8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885), array(26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140), array(19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857), ), array( array(801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155), array(19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260), array(19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483), ), ), array( array( array(-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677), array(32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815), array(22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751), ), array( array(-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203), array(-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208), array(1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230), ), array( array(16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850), array(-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389), array(-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968), ), array( array(-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689), array(14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880), array(5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304), ), array( array(30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632), array(-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412), array(20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566), ), array( array(-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038), array(-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232), array(-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943), ), array( array(17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856), array(23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738), array(15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971), ), array( array(-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718), array(-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697), array(-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883), ), ), array( array( array(5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912), array(-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358), array(3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849), ), array( array(29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307), array(-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977), array(-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335), ), array( array(-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644), array(-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616), array(-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735), ), array( array(-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099), array(29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341), array(-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336), ), array( array(-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646), array(31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425), array(-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388), ), array( array(-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743), array(-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822), array(-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462), ), array( array(18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985), array(9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702), array(-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797), ), array( array(21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293), array(27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100), array(19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688), ), ), array( array( array(12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186), array(2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610), array(-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707), ), array( array(7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220), array(915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025), array(32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044), ), array( array(32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992), array(-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027), array(21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197), ), array( array(8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901), array(31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952), array(19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878), ), array( array(-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390), array(32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730), array(2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730), ), array( array(-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180), array(-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272), array(-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715), ), array( array(-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970), array(-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772), array(-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865), ), array( array(15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750), array(20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373), array(32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348), ), ), array( array( array(9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144), array(-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195), array(5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086), ), array( array(-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684), array(-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518), array(-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233), ), array( array(-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793), array(-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794), array(580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435), ), array( array(23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921), array(13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518), array(2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563), ), array( array(14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278), array(-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024), array(4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030), ), array( array(10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783), array(27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717), array(6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844), ), array( array(14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333), array(16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048), array(22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760), ), array( array(-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760), array(-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757), array(-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112), ), ), array( array( array(-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468), array(3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184), array(10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289), ), array( array(15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066), array(24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882), array(13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226), ), array( array(16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101), array(29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279), array(-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811), ), array( array(27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709), array(20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714), array(-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121), ), array( array(9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464), array(12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847), array(13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400), ), array( array(4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414), array(-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158), array(17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045), ), array( array(-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415), array(-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459), array(-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079), ), array( array(21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412), array(-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743), array(-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836), ), ), array( array( array(12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022), array(18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429), array(-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065), ), array( array(30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861), array(10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000), array(-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101), ), array( array(32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815), array(29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642), array(10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966), ), array( array(25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574), array(-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742), array(-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689), ), array( array(12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020), array(-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772), array(3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982), ), array( array(-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953), array(-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218), array(-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265), ), array( array(29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073), array(-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325), array(-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798), ), array( array(-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870), array(-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863), array(-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927), ), ), array( array( array(-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267), array(-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663), array(22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862), ), array( array(-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673), array(15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943), array(15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020), ), array( array(-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238), array(11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064), array(14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795), ), array( array(15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052), array(-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904), array(29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531), ), array( array(-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979), array(-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841), array(10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431), ), array( array(10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324), array(-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940), array(10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320), ), array( array(-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184), array(14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114), array(30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878), ), array( array(12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784), array(-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091), array(-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585), ), ), array( array( array(-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208), array(10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864), array(17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661), ), array( array(7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233), array(26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212), array(-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525), ), array( array(-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068), array(9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397), array(-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988), ), array( array(5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889), array(32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038), array(14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697), ), array( array(20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875), array(-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905), array(-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656), ), array( array(11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818), array(27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714), array(10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203), ), array( array(20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931), array(-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024), array(-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084), ), array( array(-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204), array(20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817), array(27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667), ), ), array( array( array(11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504), array(-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768), array(-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255), ), array( array(6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790), array(1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438), array(-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333), ), array( array(17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971), array(31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905), array(29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409), ), array( array(12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409), array(6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499), array(-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363), ), array( array(28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664), array(-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324), array(-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940), ), array( array(13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990), array(-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914), array(-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290), ), array( array(24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257), array(-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433), array(-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236), ), array( array(-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045), array(11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093), array(-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347), ), ), array( array( array(-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191), array(-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507), array(-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906), ), array( array(3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018), array(-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109), array(-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926), ), array( array(-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528), array(8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625), array(-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286), ), array( array(2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033), array(27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866), array(21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896), ), array( array(30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075), array(26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347), array(-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437), ), array( array(-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165), array(-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588), array(-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193), ), array( array(-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017), array(-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883), array(21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961), ), array( array(8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043), array(29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663), array(-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362), ), ), array( array( array(-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860), array(2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466), array(-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063), ), array( array(-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997), array(-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295), array(-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369), ), array( array(9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385), array(18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109), array(2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906), ), array( array(4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424), array(-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185), array(7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962), ), array( array(-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325), array(10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593), array(696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404), ), array( array(-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644), array(17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801), array(26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804), ), array( array(-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884), array(-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577), array(-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849), ), array( array(32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473), array(-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644), array(-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319), ), ), array( array( array(-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599), array(-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768), array(-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084), ), array( array(-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328), array(-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369), array(20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920), ), array( array(12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815), array(-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025), array(-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397), ), array( array(-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448), array(6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981), array(30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165), ), array( array(32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501), array(17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073), array(-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861), ), array( array(14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845), array(-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211), array(18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870), ), array( array(10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096), array(33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803), array(-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168), ), array( array(30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965), array(-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505), array(18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598), ), ), array( array( array(5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782), array(5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900), array(-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479), ), array( array(-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208), array(8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232), array(17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719), ), array( array(16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271), array(-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326), array(-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132), ), array( array(14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300), array(8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570), array(15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670), ), array( array(-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994), array(-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913), array(31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317), ), array( array(-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730), array(842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096), array(-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078), ), array( array(-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411), array(-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905), array(-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654), ), array( array(-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870), array(-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498), array(12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579), ), ), array( array( array(14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677), array(10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647), array(-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743), ), array( array(-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468), array(21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375), array(-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155), ), array( array(6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725), array(-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612), array(-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943), ), array( array(-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944), array(30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928), array(9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406), ), array( array(22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139), array(-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963), array(-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693), ), array( array(1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734), array(-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680), array(-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410), ), array( array(-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931), array(-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654), array(22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710), ), array( array(29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180), array(-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684), array(-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895), ), ), array( array( array(22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501), array(-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413), array(6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880), ), array( array(-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874), array(22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962), array(-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899), ), array( array(21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152), array(9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063), array(7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080), ), array( array(-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146), array(-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183), array(-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133), ), array( array(-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421), array(-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622), array(-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197), ), array( array(2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663), array(31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753), array(4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755), ), array( array(-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862), array(-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118), array(26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171), ), array( array(15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380), array(16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824), array(28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270), ), ), array( array( array(-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438), array(-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584), array(-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562), ), array( array(30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471), array(18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610), array(19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269), ), array( array(-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650), array(14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369), array(19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461), ), array( array(30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462), array(-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793), array(-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218), ), array( array(-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226), array(18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019), array(-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037), ), array( array(31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171), array(-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132), array(-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841), ), array( array(21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181), array(-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210), array(-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040), ), array( array(3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935), array(24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105), array(-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814), ), ), array( array( array(793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852), array(5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581), array(-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646), ), array( array(10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844), array(10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025), array(27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453), ), array( array(-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068), array(4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192), array(-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921), ), array( array(-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259), array(-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426), array(-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072), ), array( array(-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305), array(13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832), array(28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943), ), array( array(-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011), array(24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447), array(17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494), ), array( array(-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245), array(-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859), array(28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915), ), array( array(16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707), array(10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848), array(-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224), ), ), array( array( array(-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391), array(15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215), array(-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101), ), array( array(23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713), array(21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849), array(-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930), ), array( array(-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940), array(-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031), array(-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404), ), array( array(-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243), array(-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116), array(-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525), ), array( array(-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509), array(-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883), array(15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865), ), array( array(-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660), array(4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273), array(-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138), ), array( array(-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560), array(-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135), array(2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941), ), array( array(-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739), array(18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756), array(-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819), ), ), array( array( array(-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347), array(-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028), array(21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075), ), array( array(16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799), array(-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609), array(-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817), ), array( array(-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989), array(-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523), array(4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278), ), array( array(31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045), array(19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377), array(24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480), ), array( array(17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016), array(510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426), array(18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525), ), array( array(13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396), array(9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080), array(12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892), ), array( array(15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275), array(11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074), array(20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140), ), array( array(-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717), array(-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101), array(24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127), ), ), array( array( array(-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632), array(-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415), array(-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160), ), array( array(31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876), array(22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625), array(-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478), ), array( array(27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164), array(26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595), array(-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248), ), array( array(-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858), array(15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193), array(8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184), ), array( array(-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942), array(-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635), array(21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948), ), array( array(11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935), array(-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415), array(-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416), ), array( array(-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018), array(4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778), array(366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659), ), array( array(-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385), array(18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503), array(476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329), ), ), array( array( array(20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056), array(-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838), array(24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948), ), array( array(-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691), array(-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118), array(-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517), ), array( array(-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269), array(-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904), array(-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589), ), array( array(-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193), array(-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910), array(-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930), ), array( array(-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667), array(25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481), array(-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876), ), array( array(22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640), array(-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278), array(-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112), ), array( array(26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272), array(17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012), array(-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221), ), array( array(30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046), array(13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345), array(-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310), ), ), array( array( array(19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937), array(31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636), array(-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008), ), array( array(-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429), array(-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576), array(31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066), ), array( array(-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490), array(-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104), array(33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053), ), array( array(31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275), array(-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511), array(22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095), ), array( array(-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439), array(23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939), array(-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424), ), array( array(2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310), array(3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608), array(-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079), ), array( array(-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101), array(21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418), array(18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576), ), array( array(30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356), array(9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996), array(-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099), ), ), array( array( array(-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728), array(-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658), array(-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242), ), array( array(-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001), array(-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766), array(18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373), ), array( array(26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458), array(-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628), array(-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657), ), array( array(-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062), array(25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616), array(31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014), ), array( array(24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383), array(-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814), array(-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718), ), array( array(30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417), array(2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222), array(33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444), ), array( array(-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597), array(23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970), array(1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799), ), array( array(-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647), array(13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511), array(-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032), ), ), array( array( array(9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834), array(-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461), array(29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062), ), array( array(-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516), array(-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547), array(-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240), ), array( array(-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038), array(-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741), array(16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103), ), array( array(-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747), array(-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323), array(31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016), ), array( array(-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373), array(15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228), array(-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141), ), array( array(16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399), array(11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831), array(-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376), ), array( array(-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313), array(-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958), array(-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577), ), array( array(-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743), array(29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684), array(-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476), ), ) ); /** * See: libsodium's crypto_core/curve25519/ref10/base2.h * * @var array basically int[8][3] */ protected static $base2 = array( array( array(25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605), array(-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378), array(-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546), ), array( array(15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024), array(16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574), array(30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357), ), array( array(10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380), array(4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306), array(19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942), ), array( array(5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766), array(-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701), array(28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300), ), array( array(-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877), array(-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951), array(4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784), ), array( array(-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436), array(25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918), array(23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877), ), array( array(-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800), array(-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305), array(-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300), ), array( array(-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876), array(-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619), array(-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683), ) ); /** * 37095705934669439343138083508754565189542113879843219016388785533085940283555 * * @var array<int, int> */ protected static $d = array( -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116 ); /** * 2 * d = 16295367250680780974490674513165176452449235426866156013048779062215315747161 * * @var array<int, int> */ protected static $d2 = array( -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199 ); /** * sqrt(-1) * * @var array<int, int> */ protected static $sqrtm1 = array( -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482 ); /** * 1 / sqrt(a - d) * * @var array<int, int> */ protected static $invsqrtamd = array( 6111485, 4156064, -27798727, 12243468, -25904040, 120897, 20826367, -7060776, 6093568, -1986012 ); /** * sqrt(ad - 1) with a = -1 (mod p) * * @var array<int, int> */ protected static $sqrtadm1 = array( 24849947, -153582, -23613485, 6347715, -21072328, -667138, -25271143, -15367704, -870347, 14525639 ); /** * 1 - d ^ 2 * * @var array<int, int> */ protected static $onemsqd = array( 6275446, -16617371, -22938544, -3773710, 11667077, 7397348, -27922721, 1766195, -24433858, 672203 ); /** * (d - 1) ^ 2 * @var array<int, int> */ protected static $sqdmone = array( 15551795, -11097455, -13425098, -10125071, -11896535, 10178284, -26634327, 4729244, -5282110, -10116402 ); /* * 2^252+27742317777372353535851937790883648493 static const unsigned char L[] = { 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 }; */ const L = "\xed\xd3\xf5\x5c\x1a\x63\x12\x58\xd6\x9c\xf7\xa2\xde\xf9\xde\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10"; } PK������ZR>p��p�� ��Core/Util.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Core_Util', false)) { return; } /** * Class ParagonIE_Sodium_Core_Util */ abstract class ParagonIE_Sodium_Core_Util { const U32_MAX = 0xFFFFFFFF; /** * @param int $integer * @param int $size (16, 32, 64) * @return int */ public static function abs($integer, $size = 0) { /** @var int $realSize */ $realSize = (PHP_INT_SIZE << 3) - 1; if ($size) { --$size; } else { /** @var int $size */ $size = $realSize; } $negative = -(($integer >> $size) & 1); return (int) ( ($integer ^ $negative) + (($negative >> $realSize) & 1) ); } /** * @param string $a * @param string $b * @return string * @throws SodiumException */ public static function andStrings($a, $b) { /* Type checks: */ if (!is_string($a)) { throw new TypeError('Argument 1 must be a string'); } if (!is_string($b)) { throw new TypeError('Argument 2 must be a string'); } $len = self::strlen($a); if (self::strlen($b) !== $len) { throw new SodiumException('Both strings must be of equal length to combine with bitwise AND'); } return $a & $b; } /** * Convert a binary string into a hexadecimal string without cache-timing * leaks * * @internal You should not use this directly from another application * * @param string $binaryString (raw binary) * @return string * @throws TypeError */ public static function bin2hex($binaryString) { /* Type checks: */ if (!is_string($binaryString)) { throw new TypeError('Argument 1 must be a string, ' . gettype($binaryString) . ' given.'); } $hex = ''; $len = self::strlen($binaryString); for ($i = 0; $i < $len; ++$i) { /** @var array<int, int> $chunk */ $chunk = unpack('C', $binaryString[$i]); /** @var int $c */ $c = $chunk[1] & 0xf; /** @var int $b */ $b = $chunk[1] >> 4; $hex .= pack( 'CC', (87 + $b + ((($b - 10) >> 8) & ~38)), (87 + $c + ((($c - 10) >> 8) & ~38)) ); } return $hex; } /** * Convert a binary string into a hexadecimal string without cache-timing * leaks, returning uppercase letters (as per RFC 4648) * * @internal You should not use this directly from another application * * @param string $bin_string (raw binary) * @return string * @throws TypeError */ public static function bin2hexUpper($bin_string) { $hex = ''; $len = self::strlen($bin_string); for ($i = 0; $i < $len; ++$i) { /** @var array<int, int> $chunk */ $chunk = unpack('C', $bin_string[$i]); /** * Lower 16 bits * * @var int $c */ $c = $chunk[1] & 0xf; /** * Upper 16 bits * @var int $b */ $b = $chunk[1] >> 4; /** * Use pack() and binary operators to turn the two integers * into hexadecimal characters. We don't use chr() here, because * it uses a lookup table internally and we want to avoid * cache-timing side-channels. */ $hex .= pack( 'CC', (55 + $b + ((($b - 10) >> 8) & ~6)), (55 + $c + ((($c - 10) >> 8) & ~6)) ); } return $hex; } /** * Cache-timing-safe variant of ord() * * @internal You should not use this directly from another application * * @param string $chr * @return int * @throws SodiumException * @throws TypeError */ public static function chrToInt($chr) { /* Type checks: */ if (!is_string($chr)) { throw new TypeError('Argument 1 must be a string, ' . gettype($chr) . ' given.'); } if (self::strlen($chr) !== 1) { throw new SodiumException('chrToInt() expects a string that is exactly 1 character long'); } /** @var array<int, int> $chunk */ $chunk = unpack('C', $chr); return (int) ($chunk[1]); } /** * Compares two strings. * * @internal You should not use this directly from another application * * @param string $left * @param string $right * @param int $len * @return int * @throws SodiumException * @throws TypeError */ public static function compare($left, $right, $len = null) { $leftLen = self::strlen($left); $rightLen = self::strlen($right); if ($len === null) { $len = max($leftLen, $rightLen); $left = str_pad($left, $len, "\x00", STR_PAD_RIGHT); $right = str_pad($right, $len, "\x00", STR_PAD_RIGHT); } $gt = 0; $eq = 1; $i = $len; while ($i !== 0) { --$i; $gt |= ((self::chrToInt($right[$i]) - self::chrToInt($left[$i])) >> 8) & $eq; $eq &= ((self::chrToInt($right[$i]) ^ self::chrToInt($left[$i])) - 1) >> 8; } return ($gt + $gt + $eq) - 1; } /** * If a variable does not match a given type, throw a TypeError. * * @param mixed $mixedVar * @param string $type * @param int $argumentIndex * @throws TypeError * @throws SodiumException * @return void */ public static function declareScalarType(&$mixedVar = null, $type = 'void', $argumentIndex = 0) { if (func_num_args() === 0) { /* Tautology, by default */ return; } if (func_num_args() === 1) { throw new TypeError('Declared void, but passed a variable'); } $realType = strtolower(gettype($mixedVar)); $type = strtolower($type); switch ($type) { case 'null': if ($mixedVar !== null) { throw new TypeError('Argument ' . $argumentIndex . ' must be null, ' . $realType . ' given.'); } break; case 'integer': case 'int': $allow = array('int', 'integer'); if (!in_array($type, $allow)) { throw new TypeError('Argument ' . $argumentIndex . ' must be an integer, ' . $realType . ' given.'); } $mixedVar = (int) $mixedVar; break; case 'boolean': case 'bool': $allow = array('bool', 'boolean'); if (!in_array($type, $allow)) { throw new TypeError('Argument ' . $argumentIndex . ' must be a boolean, ' . $realType . ' given.'); } $mixedVar = (bool) $mixedVar; break; case 'string': if (!is_string($mixedVar)) { throw new TypeError('Argument ' . $argumentIndex . ' must be a string, ' . $realType . ' given.'); } $mixedVar = (string) $mixedVar; break; case 'decimal': case 'double': case 'float': $allow = array('decimal', 'double', 'float'); if (!in_array($type, $allow)) { throw new TypeError('Argument ' . $argumentIndex . ' must be a float, ' . $realType . ' given.'); } $mixedVar = (float) $mixedVar; break; case 'object': if (!is_object($mixedVar)) { throw new TypeError('Argument ' . $argumentIndex . ' must be an object, ' . $realType . ' given.'); } break; case 'array': if (!is_array($mixedVar)) { if (is_object($mixedVar)) { if ($mixedVar instanceof ArrayAccess) { return; } } throw new TypeError('Argument ' . $argumentIndex . ' must be an array, ' . $realType . ' given.'); } break; default: throw new SodiumException('Unknown type (' . $realType .') does not match expect type (' . $type . ')'); } } /** * Evaluate whether or not two strings are equal (in constant-time) * * @param string $left * @param string $right * @return bool * @throws SodiumException * @throws TypeError */ public static function hashEquals($left, $right) { /* Type checks: */ if (!is_string($left)) { throw new TypeError('Argument 1 must be a string, ' . gettype($left) . ' given.'); } if (!is_string($right)) { throw new TypeError('Argument 2 must be a string, ' . gettype($right) . ' given.'); } if (is_callable('hash_equals')) { return hash_equals($left, $right); } $d = 0; /** @var int $len */ $len = self::strlen($left); if ($len !== self::strlen($right)) { return false; } for ($i = 0; $i < $len; ++$i) { $d |= self::chrToInt($left[$i]) ^ self::chrToInt($right[$i]); } if ($d !== 0) { return false; } return $left === $right; } /** * Catch hash_update() failures and throw instead of silently proceeding * * @param HashContext|resource &$hs * @param string $data * @return void * @throws SodiumException * @psalm-suppress PossiblyInvalidArgument */ protected static function hash_update(&$hs, $data) { if (!hash_update($hs, $data)) { throw new SodiumException('hash_update() failed'); } } /** * Convert a hexadecimal string into a binary string without cache-timing * leaks * * @internal You should not use this directly from another application * * @param string $hexString * @param string $ignore * @param bool $strictPadding * @return string (raw binary) * @throws RangeException * @throws TypeError */ public static function hex2bin($hexString, $ignore = '', $strictPadding = false) { /* Type checks: */ if (!is_string($hexString)) { throw new TypeError('Argument 1 must be a string, ' . gettype($hexString) . ' given.'); } if (!is_string($ignore)) { throw new TypeError('Argument 2 must be a string, ' . gettype($hexString) . ' given.'); } $hex_pos = 0; $bin = ''; $c_acc = 0; $hex_len = self::strlen($hexString); $state = 0; if (($hex_len & 1) !== 0) { if ($strictPadding) { throw new RangeException( 'Expected an even number of hexadecimal characters' ); } else { $hexString = '0' . $hexString; ++$hex_len; } } $chunk = unpack('C*', $hexString); while ($hex_pos < $hex_len) { ++$hex_pos; /** @var int $c */ $c = $chunk[$hex_pos]; $c_num = $c ^ 48; $c_num0 = ($c_num - 10) >> 8; $c_alpha = ($c & ~32) - 55; $c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8; if (($c_num0 | $c_alpha0) === 0) { if ($ignore && $state === 0 && strpos($ignore, self::intToChr($c)) !== false) { continue; } throw new RangeException( 'hex2bin() only expects hexadecimal characters' ); } $c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0); if ($state === 0) { $c_acc = $c_val * 16; } else { $bin .= pack('C', $c_acc | $c_val); } $state ^= 1; } return $bin; } /** * Turn an array of integers into a string * * @internal You should not use this directly from another application * * @param array<int, int> $ints * @return string */ public static function intArrayToString(array $ints) { $args = $ints; foreach ($args as $i => $v) { $args[$i] = (int) ($v & 0xff); } array_unshift($args, str_repeat('C', count($ints))); return (string) (call_user_func_array('pack', $args)); } /** * Cache-timing-safe variant of ord() * * @internal You should not use this directly from another application * * @param int $int * @return string * @throws TypeError */ public static function intToChr($int) { return pack('C', $int); } /** * Load a 3 character substring into an integer * * @internal You should not use this directly from another application * * @param string $string * @return int * @throws RangeException * @throws TypeError */ public static function load_3($string) { /* Type checks: */ if (!is_string($string)) { throw new TypeError('Argument 1 must be a string, ' . gettype($string) . ' given.'); } /* Input validation: */ if (self::strlen($string) < 3) { throw new RangeException( 'String must be 3 bytes or more; ' . self::strlen($string) . ' given.' ); } /** @var array<int, int> $unpacked */ $unpacked = unpack('V', $string . "\0"); return (int) ($unpacked[1] & 0xffffff); } /** * Load a 4 character substring into an integer * * @internal You should not use this directly from another application * * @param string $string * @return int * @throws RangeException * @throws TypeError */ public static function load_4($string) { /* Type checks: */ if (!is_string($string)) { throw new TypeError('Argument 1 must be a string, ' . gettype($string) . ' given.'); } /* Input validation: */ if (self::strlen($string) < 4) { throw new RangeException( 'String must be 4 bytes or more; ' . self::strlen($string) . ' given.' ); } /** @var array<int, int> $unpacked */ $unpacked = unpack('V', $string); return (int) $unpacked[1]; } /** * Load a 8 character substring into an integer * * @internal You should not use this directly from another application * * @param string $string * @return int * @throws RangeException * @throws SodiumException * @throws TypeError */ public static function load64_le($string) { /* Type checks: */ if (!is_string($string)) { throw new TypeError('Argument 1 must be a string, ' . gettype($string) . ' given.'); } /* Input validation: */ if (self::strlen($string) < 4) { throw new RangeException( 'String must be 4 bytes or more; ' . self::strlen($string) . ' given.' ); } if (PHP_VERSION_ID >= 50603 && PHP_INT_SIZE === 8) { /** @var array<int, int> $unpacked */ $unpacked = unpack('P', $string); return (int) $unpacked[1]; } /** @var int $result */ $result = (self::chrToInt($string[0]) & 0xff); $result |= (self::chrToInt($string[1]) & 0xff) << 8; $result |= (self::chrToInt($string[2]) & 0xff) << 16; $result |= (self::chrToInt($string[3]) & 0xff) << 24; $result |= (self::chrToInt($string[4]) & 0xff) << 32; $result |= (self::chrToInt($string[5]) & 0xff) << 40; $result |= (self::chrToInt($string[6]) & 0xff) << 48; $result |= (self::chrToInt($string[7]) & 0xff) << 56; return (int) $result; } /** * @internal You should not use this directly from another application * * @param string $left * @param string $right * @return int * @throws SodiumException * @throws TypeError */ public static function memcmp($left, $right) { if (self::hashEquals($left, $right)) { return 0; } return -1; } /** * Multiply two integers in constant-time * * Micro-architecture timing side-channels caused by how your CPU * implements multiplication are best prevented by never using the * multiplication operators and ensuring that our code always takes * the same number of operations to complete, regardless of the values * of $a and $b. * * @internal You should not use this directly from another application * * @param int $a * @param int $b * @param int $size Limits the number of operations (useful for small, * constant operands) * @return int */ public static function mul($a, $b, $size = 0) { if (ParagonIE_Sodium_Compat::$fastMult) { return (int) ($a * $b); } static $defaultSize = null; /** @var int $defaultSize */ if (!$defaultSize) { /** @var int $defaultSize */ $defaultSize = (PHP_INT_SIZE << 3) - 1; } if ($size < 1) { /** @var int $size */ $size = $defaultSize; } /** @var int $size */ $c = 0; /** * Mask is either -1 or 0. * * -1 in binary looks like 0x1111 ... 1111 * 0 in binary looks like 0x0000 ... 0000 * * @var int */ $mask = -(($b >> ((int) $defaultSize)) & 1); /** * Ensure $b is a positive integer, without creating * a branching side-channel * * @var int $b */ $b = ($b & ~$mask) | ($mask & -$b); /** * Unless $size is provided: * * This loop always runs 32 times when PHP_INT_SIZE is 4. * This loop always runs 64 times when PHP_INT_SIZE is 8. */ for ($i = $size; $i >= 0; --$i) { $c += (int) ($a & -($b & 1)); $a <<= 1; $b >>= 1; } $c = (int) @($c & -1); /** * If $b was negative, we then apply the same value to $c here. * It doesn't matter much if $a was negative; the $c += above would * have produced a negative integer to begin with. But a negative $b * makes $b >>= 1 never return 0, so we would end up with incorrect * results. * * The end result is what we'd expect from integer multiplication. */ return (int) (($c & ~$mask) | ($mask & -$c)); } /** * Convert any arbitrary numbers into two 32-bit integers that represent * a 64-bit integer. * * @internal You should not use this directly from another application * * @param int|float $num * @return array<int, int> */ public static function numericTo64BitInteger($num) { $high = 0; /** @var int $low */ if (PHP_INT_SIZE === 4) { $low = (int) $num; } else { $low = $num & 0xffffffff; } if ((+(abs($num))) >= 1) { if ($num > 0) { /** @var int $high */ $high = min((+(floor($num/4294967296))), 4294967295); } else { /** @var int $high */ $high = ~~((+(ceil(($num - (+((~~($num)))))/4294967296)))); } } return array((int) $high, (int) $low); } /** * Store a 24-bit integer into a string, treating it as big-endian. * * @internal You should not use this directly from another application * * @param int $int * @return string * @throws TypeError */ public static function store_3($int) { /* Type checks: */ if (!is_int($int)) { if (is_numeric($int)) { $int = (int) $int; } else { throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.'); } } /** @var string $packed */ $packed = pack('N', $int); return self::substr($packed, 1, 3); } /** * Store a 32-bit integer into a string, treating it as little-endian. * * @internal You should not use this directly from another application * * @param int $int * @return string * @throws TypeError */ public static function store32_le($int) { /* Type checks: */ if (!is_int($int)) { if (is_numeric($int)) { $int = (int) $int; } else { throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.'); } } /** @var string $packed */ $packed = pack('V', $int); return $packed; } /** * Store a 32-bit integer into a string, treating it as big-endian. * * @internal You should not use this directly from another application * * @param int $int * @return string * @throws TypeError */ public static function store_4($int) { /* Type checks: */ if (!is_int($int)) { if (is_numeric($int)) { $int = (int) $int; } else { throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.'); } } /** @var string $packed */ $packed = pack('N', $int); return $packed; } /** * Stores a 64-bit integer as an string, treating it as little-endian. * * @internal You should not use this directly from another application * * @param int $int * @return string * @throws TypeError */ public static function store64_le($int) { /* Type checks: */ if (!is_int($int)) { if (is_numeric($int)) { $int = (int) $int; } else { throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.'); } } if (PHP_INT_SIZE === 8) { if (PHP_VERSION_ID >= 50603) { /** @var string $packed */ $packed = pack('P', $int); return $packed; } return self::intToChr($int & 0xff) . self::intToChr(($int >> 8) & 0xff) . self::intToChr(($int >> 16) & 0xff) . self::intToChr(($int >> 24) & 0xff) . self::intToChr(($int >> 32) & 0xff) . self::intToChr(($int >> 40) & 0xff) . self::intToChr(($int >> 48) & 0xff) . self::intToChr(($int >> 56) & 0xff); } if ($int > PHP_INT_MAX) { list($hiB, $int) = self::numericTo64BitInteger($int); } else { $hiB = 0; } return self::intToChr(($int ) & 0xff) . self::intToChr(($int >> 8) & 0xff) . self::intToChr(($int >> 16) & 0xff) . self::intToChr(($int >> 24) & 0xff) . self::intToChr($hiB & 0xff) . self::intToChr(($hiB >> 8) & 0xff) . self::intToChr(($hiB >> 16) & 0xff) . self::intToChr(($hiB >> 24) & 0xff); } /** * Safe string length * * @internal You should not use this directly from another application * * @ref mbstring.func_overload * * @param string $str * @return int * @throws TypeError */ public static function strlen($str) { /* Type checks: */ if (!is_string($str)) { throw new TypeError('String expected'); } return (int) ( self::isMbStringOverride() ? mb_strlen($str, '8bit') : strlen($str) ); } /** * Turn a string into an array of integers * * @internal You should not use this directly from another application * * @param string $string * @return array<int, int> * @throws TypeError */ public static function stringToIntArray($string) { if (!is_string($string)) { throw new TypeError('String expected'); } /** * @var array<int, int> */ $values = array_values( unpack('C*', $string) ); return $values; } /** * Safe substring * * @internal You should not use this directly from another application * * @ref mbstring.func_overload * * @param string $str * @param int $start * @param int $length * @return string * @throws TypeError */ public static function substr($str, $start = 0, $length = null) { /* Type checks: */ if (!is_string($str)) { throw new TypeError('String expected'); } if ($length === 0) { return ''; } if (self::isMbStringOverride()) { if (PHP_VERSION_ID < 50400 && $length === null) { $length = self::strlen($str); } $sub = (string) mb_substr($str, $start, $length, '8bit'); } elseif ($length === null) { $sub = (string) substr($str, $start); } else { $sub = (string) substr($str, $start, $length); } if ($sub !== '') { return $sub; } return ''; } /** * Compare a 16-character byte string in constant time. * * @internal You should not use this directly from another application * * @param string $a * @param string $b * @return bool * @throws SodiumException * @throws TypeError */ public static function verify_16($a, $b) { /* Type checks: */ if (!is_string($a)) { throw new TypeError('String expected'); } if (!is_string($b)) { throw new TypeError('String expected'); } return self::hashEquals( self::substr($a, 0, 16), self::substr($b, 0, 16) ); } /** * Compare a 32-character byte string in constant time. * * @internal You should not use this directly from another application * * @param string $a * @param string $b * @return bool * @throws SodiumException * @throws TypeError */ public static function verify_32($a, $b) { /* Type checks: */ if (!is_string($a)) { throw new TypeError('String expected'); } if (!is_string($b)) { throw new TypeError('String expected'); } return self::hashEquals( self::substr($a, 0, 32), self::substr($b, 0, 32) ); } /** * Calculate $a ^ $b for two strings. * * @internal You should not use this directly from another application * * @param string $a * @param string $b * @return string * @throws TypeError */ public static function xorStrings($a, $b) { /* Type checks: */ if (!is_string($a)) { throw new TypeError('Argument 1 must be a string'); } if (!is_string($b)) { throw new TypeError('Argument 2 must be a string'); } return (string) ($a ^ $b); } /** * Returns whether or not mbstring.func_overload is in effect. * * @internal You should not use this directly from another application * * Note: MB_OVERLOAD_STRING === 2, but we don't reference the constant * (for nuisance-free PHP 8 support) * * @return bool */ protected static function isMbStringOverride() { static $mbstring = null; if ($mbstring === null) { if (!defined('MB_OVERLOAD_STRING')) { $mbstring = false; return $mbstring; } $mbstring = extension_loaded('mbstring') && defined('MB_OVERLOAD_STRING') && ((int) (ini_get('mbstring.func_overload')) & 2); // MB_OVERLOAD_STRING === 2 } /** @var bool $mbstring */ return $mbstring; } } PK������Zk=������PHP52/SplFixedArray.phpnu�W+A��������<?php if (class_exists('SplFixedArray')) { return; } /** * The SplFixedArray class provides the main functionalities of array. The * main differences between a SplFixedArray and a normal PHP array is that * the SplFixedArray is of fixed length and allows only integers within * the range as indexes. The advantage is that it allows a faster array * implementation. */ class SplFixedArray implements Iterator, ArrayAccess, Countable { /** @var array<int, mixed> */ private $internalArray = array(); /** @var int $size */ private $size = 0; /** * SplFixedArray constructor. * @param int $size */ public function __construct($size = 0) { $this->size = $size; $this->internalArray = array(); } /** * @return int */ public function count() { return count($this->internalArray); } /** * @return array */ public function toArray() { ksort($this->internalArray); return (array) $this->internalArray; } /** * @param array $array * @param bool $save_indexes * @return SplFixedArray * @psalm-suppress MixedAssignment */ public static function fromArray(array $array, $save_indexes = true) { $self = new SplFixedArray(count($array)); if($save_indexes) { foreach($array as $key => $value) { $self[(int) $key] = $value; } } else { $i = 0; foreach (array_values($array) as $value) { $self[$i] = $value; $i++; } } return $self; } /** * @return int */ public function getSize() { return $this->size; } /** * @param int $size * @return bool */ public function setSize($size) { $this->size = $size; return true; } /** * @param string|int $index * @return bool */ public function offsetExists($index) { return array_key_exists((int) $index, $this->internalArray); } /** * @param string|int $index * @return mixed */ public function offsetGet($index) { /** @psalm-suppress MixedReturnStatement */ return $this->internalArray[(int) $index]; } /** * @param string|int $index * @param mixed $newval * @psalm-suppress MixedAssignment */ public function offsetSet($index, $newval) { $this->internalArray[(int) $index] = $newval; } /** * @param string|int $index */ public function offsetUnset($index) { unset($this->internalArray[(int) $index]); } /** * Rewind iterator back to the start * @link https://php.net/manual/en/splfixedarray.rewind.php * @return void * @since 5.3.0 */ public function rewind() { reset($this->internalArray); } /** * Return current array entry * @link https://php.net/manual/en/splfixedarray.current.php * @return mixed The current element value. * @since 5.3.0 */ public function current() { /** @psalm-suppress MixedReturnStatement */ return current($this->internalArray); } /** * Return current array index * @return int The current array index. */ public function key() { return key($this->internalArray); } /** * @return void */ public function next() { next($this->internalArray); } /** * Check whether the array contains more elements * @link https://php.net/manual/en/splfixedarray.valid.php * @return bool true if the array contains any more elements, false otherwise. */ public function valid() { if (empty($this->internalArray)) { return false; } $result = next($this->internalArray) !== false; prev($this->internalArray); return $result; } /** * Do nothing. */ public function __wakeup() { // NOP } }PK������ZӈO��O�� ��Crypto32.phpnu�W+A��������<?php if (class_exists('ParagonIE_Sodium_Crypto32', false)) { return; } /** * Class ParagonIE_Sodium_Crypto * * ATTENTION! * * If you are using this library, you should be using * ParagonIE_Sodium_Compat in your code, not this class. */ abstract class ParagonIE_Sodium_Crypto32 { const aead_chacha20poly1305_KEYBYTES = 32; const aead_chacha20poly1305_NSECBYTES = 0; const aead_chacha20poly1305_NPUBBYTES = 8; const aead_chacha20poly1305_ABYTES = 16; const aead_chacha20poly1305_IETF_KEYBYTES = 32; const aead_chacha20poly1305_IETF_NSECBYTES = 0; const aead_chacha20poly1305_IETF_NPUBBYTES = 12; const aead_chacha20poly1305_IETF_ABYTES = 16; const aead_xchacha20poly1305_IETF_KEYBYTES = 32; const aead_xchacha20poly1305_IETF_NSECBYTES = 0; const aead_xchacha20poly1305_IETF_NPUBBYTES = 24; const aead_xchacha20poly1305_IETF_ABYTES = 16; const box_curve25519xsalsa20poly1305_SEEDBYTES = 32; const box_curve25519xsalsa20poly1305_PUBLICKEYBYTES = 32; const box_curve25519xsalsa20poly1305_SECRETKEYBYTES = 32; const box_curve25519xsalsa20poly1305_BEFORENMBYTES = 32; const box_curve25519xsalsa20poly1305_NONCEBYTES = 24; const box_curve25519xsalsa20poly1305_MACBYTES = 16; const box_curve25519xsalsa20poly1305_BOXZEROBYTES = 16; const box_curve25519xsalsa20poly1305_ZEROBYTES = 32; const onetimeauth_poly1305_BYTES = 16; const onetimeauth_poly1305_KEYBYTES = 32; const secretbox_xsalsa20poly1305_KEYBYTES = 32; const secretbox_xsalsa20poly1305_NONCEBYTES = 24; const secretbox_xsalsa20poly1305_MACBYTES = 16; const secretbox_xsalsa20poly1305_BOXZEROBYTES = 16; const secretbox_xsalsa20poly1305_ZEROBYTES = 32; const secretbox_xchacha20poly1305_KEYBYTES = 32; const secretbox_xchacha20poly1305_NONCEBYTES = 24; const secretbox_xchacha20poly1305_MACBYTES = 16; const secretbox_xchacha20poly1305_BOXZEROBYTES = 16; const secretbox_xchacha20poly1305_ZEROBYTES = 32; const stream_salsa20_KEYBYTES = 32; /** * AEAD Decryption with ChaCha20-Poly1305 * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $ad * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function aead_chacha20poly1305_decrypt( $message = '', $ad = '', $nonce = '', $key = '' ) { /** @var int $len - Length of message (ciphertext + MAC) */ $len = ParagonIE_Sodium_Core32_Util::strlen($message); /** @var int $clen - Length of ciphertext */ $clen = $len - self::aead_chacha20poly1305_ABYTES; /** @var int $adlen - Length of associated data */ $adlen = ParagonIE_Sodium_Core32_Util::strlen($ad); /** @var string $mac - Message authentication code */ $mac = ParagonIE_Sodium_Core32_Util::substr( $message, $clen, self::aead_chacha20poly1305_ABYTES ); /** @var string $ciphertext - The encrypted message (sans MAC) */ $ciphertext = ParagonIE_Sodium_Core32_Util::substr($message, 0, $clen); /** @var string The first block of the chacha20 keystream, used as a poly1305 key */ $block0 = ParagonIE_Sodium_Core32_ChaCha20::stream( 32, $nonce, $key ); /* Recalculate the Poly1305 authentication tag (MAC): */ $state = new ParagonIE_Sodium_Core32_Poly1305_State($block0); try { ParagonIE_Sodium_Compat::memzero($block0); } catch (SodiumException $ex) { $block0 = null; } $state->update($ad); $state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen)); $state->update($ciphertext); $state->update(ParagonIE_Sodium_Core32_Util::store64_le($clen)); $computed_mac = $state->finish(); /* Compare the given MAC with the recalculated MAC: */ if (!ParagonIE_Sodium_Core32_Util::verify_16($computed_mac, $mac)) { throw new SodiumException('Invalid MAC'); } // Here, we know that the MAC is valid, so we decrypt and return the plaintext return ParagonIE_Sodium_Core32_ChaCha20::streamXorIc( $ciphertext, $nonce, $key, ParagonIE_Sodium_Core32_Util::store64_le(1) ); } /** * AEAD Encryption with ChaCha20-Poly1305 * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $ad * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function aead_chacha20poly1305_encrypt( $message = '', $ad = '', $nonce = '', $key = '' ) { /** @var int $len - Length of the plaintext message */ $len = ParagonIE_Sodium_Core32_Util::strlen($message); /** @var int $adlen - Length of the associated data */ $adlen = ParagonIE_Sodium_Core32_Util::strlen($ad); /** @var string The first block of the chacha20 keystream, used as a poly1305 key */ $block0 = ParagonIE_Sodium_Core32_ChaCha20::stream( 32, $nonce, $key ); $state = new ParagonIE_Sodium_Core32_Poly1305_State($block0); try { ParagonIE_Sodium_Compat::memzero($block0); } catch (SodiumException $ex) { $block0 = null; } /** @var string $ciphertext - Raw encrypted data */ $ciphertext = ParagonIE_Sodium_Core32_ChaCha20::streamXorIc( $message, $nonce, $key, ParagonIE_Sodium_Core32_Util::store64_le(1) ); $state->update($ad); $state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen)); $state->update($ciphertext); $state->update(ParagonIE_Sodium_Core32_Util::store64_le($len)); return $ciphertext . $state->finish(); } /** * AEAD Decryption with ChaCha20-Poly1305, IETF mode (96-bit nonce) * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $ad * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function aead_chacha20poly1305_ietf_decrypt( $message = '', $ad = '', $nonce = '', $key = '' ) { /** @var int $adlen - Length of associated data */ $adlen = ParagonIE_Sodium_Core32_Util::strlen($ad); /** @var int $len - Length of message (ciphertext + MAC) */ $len = ParagonIE_Sodium_Core32_Util::strlen($message); /** @var int $clen - Length of ciphertext */ $clen = $len - self::aead_chacha20poly1305_IETF_ABYTES; /** @var string The first block of the chacha20 keystream, used as a poly1305 key */ $block0 = ParagonIE_Sodium_Core32_ChaCha20::ietfStream( 32, $nonce, $key ); /** @var string $mac - Message authentication code */ $mac = ParagonIE_Sodium_Core32_Util::substr( $message, $len - self::aead_chacha20poly1305_IETF_ABYTES, self::aead_chacha20poly1305_IETF_ABYTES ); /** @var string $ciphertext - The encrypted message (sans MAC) */ $ciphertext = ParagonIE_Sodium_Core32_Util::substr( $message, 0, $len - self::aead_chacha20poly1305_IETF_ABYTES ); /* Recalculate the Poly1305 authentication tag (MAC): */ $state = new ParagonIE_Sodium_Core32_Poly1305_State($block0); try { ParagonIE_Sodium_Compat::memzero($block0); } catch (SodiumException $ex) { $block0 = null; } $state->update($ad); $state->update(str_repeat("\x00", ((0x10 - $adlen) & 0xf))); $state->update($ciphertext); $state->update(str_repeat("\x00", (0x10 - $clen) & 0xf)); $state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen)); $state->update(ParagonIE_Sodium_Core32_Util::store64_le($clen)); $computed_mac = $state->finish(); /* Compare the given MAC with the recalculated MAC: */ if (!ParagonIE_Sodium_Core32_Util::verify_16($computed_mac, $mac)) { throw new SodiumException('Invalid MAC'); } // Here, we know that the MAC is valid, so we decrypt and return the plaintext return ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc( $ciphertext, $nonce, $key, ParagonIE_Sodium_Core32_Util::store64_le(1) ); } /** * AEAD Encryption with ChaCha20-Poly1305, IETF mode (96-bit nonce) * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $ad * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function aead_chacha20poly1305_ietf_encrypt( $message = '', $ad = '', $nonce = '', $key = '' ) { /** @var int $len - Length of the plaintext message */ $len = ParagonIE_Sodium_Core32_Util::strlen($message); /** @var int $adlen - Length of the associated data */ $adlen = ParagonIE_Sodium_Core32_Util::strlen($ad); /** @var string The first block of the chacha20 keystream, used as a poly1305 key */ $block0 = ParagonIE_Sodium_Core32_ChaCha20::ietfStream( 32, $nonce, $key ); $state = new ParagonIE_Sodium_Core32_Poly1305_State($block0); try { ParagonIE_Sodium_Compat::memzero($block0); } catch (SodiumException $ex) { $block0 = null; } /** @var string $ciphertext - Raw encrypted data */ $ciphertext = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc( $message, $nonce, $key, ParagonIE_Sodium_Core32_Util::store64_le(1) ); $state->update($ad); $state->update(str_repeat("\x00", ((0x10 - $adlen) & 0xf))); $state->update($ciphertext); $state->update(str_repeat("\x00", ((0x10 - $len) & 0xf))); $state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen)); $state->update(ParagonIE_Sodium_Core32_Util::store64_le($len)); return $ciphertext . $state->finish(); } /** * AEAD Decryption with ChaCha20-Poly1305, IETF mode (96-bit nonce) * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $ad * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function aead_xchacha20poly1305_ietf_decrypt( $message = '', $ad = '', $nonce = '', $key = '' ) { $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20( ParagonIE_Sodium_Core32_Util::substr($nonce, 0, 16), $key ); $nonceLast = "\x00\x00\x00\x00" . ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8); return self::aead_chacha20poly1305_ietf_decrypt($message, $ad, $nonceLast, $subkey); } /** * AEAD Encryption with ChaCha20-Poly1305, IETF mode (96-bit nonce) * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $ad * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function aead_xchacha20poly1305_ietf_encrypt( $message = '', $ad = '', $nonce = '', $key = '' ) { $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20( ParagonIE_Sodium_Core32_Util::substr($nonce, 0, 16), $key ); $nonceLast = "\x00\x00\x00\x00" . ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8); return self::aead_chacha20poly1305_ietf_encrypt($message, $ad, $nonceLast, $subkey); } /** * HMAC-SHA-512-256 (a.k.a. the leftmost 256 bits of HMAC-SHA-512) * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $key * @return string * @throws TypeError */ public static function auth($message, $key) { return ParagonIE_Sodium_Core32_Util::substr( hash_hmac('sha512', $message, $key, true), 0, 32 ); } /** * HMAC-SHA-512-256 validation. Constant-time via hash_equals(). * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $mac * @param string $message * @param string $key * @return bool * @throws SodiumException * @throws TypeError */ public static function auth_verify($mac, $message, $key) { return ParagonIE_Sodium_Core32_Util::hashEquals( $mac, self::auth($message, $key) ); } /** * X25519 key exchange followed by XSalsa20Poly1305 symmetric encryption * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $plaintext * @param string $nonce * @param string $keypair * @return string * @throws SodiumException * @throws TypeError */ public static function box($plaintext, $nonce, $keypair) { return self::secretbox( $plaintext, $nonce, self::box_beforenm( self::box_secretkey($keypair), self::box_publickey($keypair) ) ); } /** * X25519-XSalsa20-Poly1305 with one ephemeral X25519 keypair. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $publicKey * @return string * @throws SodiumException * @throws TypeError */ public static function box_seal($message, $publicKey) { /** @var string $ephemeralKeypair */ $ephemeralKeypair = self::box_keypair(); /** @var string $ephemeralSK */ $ephemeralSK = self::box_secretkey($ephemeralKeypair); /** @var string $ephemeralPK */ $ephemeralPK = self::box_publickey($ephemeralKeypair); /** @var string $nonce */ $nonce = self::generichash( $ephemeralPK . $publicKey, '', 24 ); /** @var string $keypair - The combined keypair used in crypto_box() */ $keypair = self::box_keypair_from_secretkey_and_publickey($ephemeralSK, $publicKey); /** @var string $ciphertext Ciphertext + MAC from crypto_box */ $ciphertext = self::box($message, $nonce, $keypair); try { ParagonIE_Sodium_Compat::memzero($ephemeralKeypair); ParagonIE_Sodium_Compat::memzero($ephemeralSK); ParagonIE_Sodium_Compat::memzero($nonce); } catch (SodiumException $ex) { $ephemeralKeypair = null; $ephemeralSK = null; $nonce = null; } return $ephemeralPK . $ciphertext; } /** * Opens a message encrypted via box_seal(). * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $keypair * @return string * @throws SodiumException * @throws TypeError */ public static function box_seal_open($message, $keypair) { /** @var string $ephemeralPK */ $ephemeralPK = ParagonIE_Sodium_Core32_Util::substr($message, 0, 32); /** @var string $ciphertext (ciphertext + MAC) */ $ciphertext = ParagonIE_Sodium_Core32_Util::substr($message, 32); /** @var string $secretKey */ $secretKey = self::box_secretkey($keypair); /** @var string $publicKey */ $publicKey = self::box_publickey($keypair); /** @var string $nonce */ $nonce = self::generichash( $ephemeralPK . $publicKey, '', 24 ); /** @var string $keypair */ $keypair = self::box_keypair_from_secretkey_and_publickey($secretKey, $ephemeralPK); /** @var string $m */ $m = self::box_open($ciphertext, $nonce, $keypair); try { ParagonIE_Sodium_Compat::memzero($secretKey); ParagonIE_Sodium_Compat::memzero($ephemeralPK); ParagonIE_Sodium_Compat::memzero($nonce); } catch (SodiumException $ex) { $secretKey = null; $ephemeralPK = null; $nonce = null; } return $m; } /** * Used by crypto_box() to get the crypto_secretbox() key. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $sk * @param string $pk * @return string * @throws SodiumException * @throws TypeError */ public static function box_beforenm($sk, $pk) { return ParagonIE_Sodium_Core32_HSalsa20::hsalsa20( str_repeat("\x00", 16), self::scalarmult($sk, $pk) ); } /** * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @return string * @throws Exception * @throws SodiumException * @throws TypeError */ public static function box_keypair() { $sKey = random_bytes(32); $pKey = self::scalarmult_base($sKey); return $sKey . $pKey; } /** * @param string $seed * @return string * @throws SodiumException * @throws TypeError */ public static function box_seed_keypair($seed) { $sKey = ParagonIE_Sodium_Core32_Util::substr( hash('sha512', $seed, true), 0, 32 ); $pKey = self::scalarmult_base($sKey); return $sKey . $pKey; } /** * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $sKey * @param string $pKey * @return string * @throws TypeError */ public static function box_keypair_from_secretkey_and_publickey($sKey, $pKey) { return ParagonIE_Sodium_Core32_Util::substr($sKey, 0, 32) . ParagonIE_Sodium_Core32_Util::substr($pKey, 0, 32); } /** * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $keypair * @return string * @throws RangeException * @throws TypeError */ public static function box_secretkey($keypair) { if (ParagonIE_Sodium_Core32_Util::strlen($keypair) !== 64) { throw new RangeException( 'Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES bytes long.' ); } return ParagonIE_Sodium_Core32_Util::substr($keypair, 0, 32); } /** * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $keypair * @return string * @throws RangeException * @throws TypeError */ public static function box_publickey($keypair) { if (ParagonIE_Sodium_Core32_Util::strlen($keypair) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) { throw new RangeException( 'Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES bytes long.' ); } return ParagonIE_Sodium_Core32_Util::substr($keypair, 32, 32); } /** * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $sKey * @return string * @throws RangeException * @throws SodiumException * @throws TypeError */ public static function box_publickey_from_secretkey($sKey) { if (ParagonIE_Sodium_Core32_Util::strlen($sKey) !== ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES) { throw new RangeException( 'Must be ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES bytes long.' ); } return self::scalarmult_base($sKey); } /** * Decrypt a message encrypted with box(). * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $ciphertext * @param string $nonce * @param string $keypair * @return string * @throws SodiumException * @throws TypeError */ public static function box_open($ciphertext, $nonce, $keypair) { return self::secretbox_open( $ciphertext, $nonce, self::box_beforenm( self::box_secretkey($keypair), self::box_publickey($keypair) ) ); } /** * Calculate a BLAKE2b hash. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string|null $key * @param int $outlen * @return string * @throws RangeException * @throws SodiumException * @throws TypeError */ public static function generichash($message, $key = '', $outlen = 32) { // This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is initialized ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor(); $k = null; if (!empty($key)) { /** @var SplFixedArray $k */ $k = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($key); if ($k->count() > ParagonIE_Sodium_Core32_BLAKE2b::KEYBYTES) { throw new RangeException('Invalid key size'); } } /** @var SplFixedArray $in */ $in = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($message); /** @var SplFixedArray $ctx */ $ctx = ParagonIE_Sodium_Core32_BLAKE2b::init($k, $outlen); ParagonIE_Sodium_Core32_BLAKE2b::update($ctx, $in, $in->count()); /** @var SplFixedArray $out */ $out = new SplFixedArray($outlen); $out = ParagonIE_Sodium_Core32_BLAKE2b::finish($ctx, $out); /** @var array<int, int> */ $outArray = $out->toArray(); return ParagonIE_Sodium_Core32_Util::intArrayToString($outArray); } /** * Finalize a BLAKE2b hashing context, returning the hash. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $ctx * @param int $outlen * @return string * @throws SodiumException * @throws TypeError */ public static function generichash_final($ctx, $outlen = 32) { if (!is_string($ctx)) { throw new TypeError('Context must be a string'); } $out = new SplFixedArray($outlen); /** @var SplFixedArray $context */ $context = ParagonIE_Sodium_Core32_BLAKE2b::stringToContext($ctx); /** @var SplFixedArray $out */ $out = ParagonIE_Sodium_Core32_BLAKE2b::finish($context, $out); /** @var array<int, int> */ $outArray = $out->toArray(); return ParagonIE_Sodium_Core32_Util::intArrayToString($outArray); } /** * Initialize a hashing context for BLAKE2b. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $key * @param int $outputLength * @return string * @throws RangeException * @throws SodiumException * @throws TypeError */ public static function generichash_init($key = '', $outputLength = 32) { // This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is initialized ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor(); $k = null; if (!empty($key)) { $k = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($key); if ($k->count() > ParagonIE_Sodium_Core32_BLAKE2b::KEYBYTES) { throw new RangeException('Invalid key size'); } } /** @var SplFixedArray $ctx */ $ctx = ParagonIE_Sodium_Core32_BLAKE2b::init($k, $outputLength); return ParagonIE_Sodium_Core32_BLAKE2b::contextToString($ctx); } /** * Initialize a hashing context for BLAKE2b. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $key * @param int $outputLength * @param string $salt * @param string $personal * @return string * @throws RangeException * @throws SodiumException * @throws TypeError */ public static function generichash_init_salt_personal( $key = '', $outputLength = 32, $salt = '', $personal = '' ) { // This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is initialized ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor(); $k = null; if (!empty($key)) { $k = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($key); if ($k->count() > ParagonIE_Sodium_Core32_BLAKE2b::KEYBYTES) { throw new RangeException('Invalid key size'); } } if (!empty($salt)) { $s = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($salt); } else { $s = null; } if (!empty($salt)) { $p = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($personal); } else { $p = null; } /** @var SplFixedArray $ctx */ $ctx = ParagonIE_Sodium_Core32_BLAKE2b::init($k, $outputLength, $s, $p); return ParagonIE_Sodium_Core32_BLAKE2b::contextToString($ctx); } /** * Update a hashing context for BLAKE2b with $message * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $ctx * @param string $message * @return string * @throws SodiumException * @throws TypeError */ public static function generichash_update($ctx, $message) { // This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is initialized ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor(); /** @var SplFixedArray $context */ $context = ParagonIE_Sodium_Core32_BLAKE2b::stringToContext($ctx); /** @var SplFixedArray $in */ $in = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($message); ParagonIE_Sodium_Core32_BLAKE2b::update($context, $in, $in->count()); return ParagonIE_Sodium_Core32_BLAKE2b::contextToString($context); } /** * Libsodium's crypto_kx(). * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $my_sk * @param string $their_pk * @param string $client_pk * @param string $server_pk * @return string * @throws SodiumException * @throws TypeError */ public static function keyExchange($my_sk, $their_pk, $client_pk, $server_pk) { return self::generichash( self::scalarmult($my_sk, $their_pk) . $client_pk . $server_pk ); } /** * ECDH over Curve25519 * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $sKey * @param string $pKey * @return string * * @throws SodiumException * @throws TypeError */ public static function scalarmult($sKey, $pKey) { $q = ParagonIE_Sodium_Core32_X25519::crypto_scalarmult_curve25519_ref10($sKey, $pKey); self::scalarmult_throw_if_zero($q); return $q; } /** * ECDH over Curve25519, using the basepoint. * Used to get a secret key from a public key. * * @param string $secret * @return string * * @throws SodiumException * @throws TypeError */ public static function scalarmult_base($secret) { $q = ParagonIE_Sodium_Core32_X25519::crypto_scalarmult_curve25519_ref10_base($secret); self::scalarmult_throw_if_zero($q); return $q; } /** * This throws an Error if a zero public key was passed to the function. * * @param string $q * @return void * @throws SodiumException * @throws TypeError */ protected static function scalarmult_throw_if_zero($q) { $d = 0; for ($i = 0; $i < self::box_curve25519xsalsa20poly1305_SECRETKEYBYTES; ++$i) { $d |= ParagonIE_Sodium_Core32_Util::chrToInt($q[$i]); } /* branch-free variant of === 0 */ if (-(1 & (($d - 1) >> 8))) { throw new SodiumException('Zero public key is not allowed'); } } /** * XSalsa20-Poly1305 authenticated symmetric-key encryption. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $plaintext * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function secretbox($plaintext, $nonce, $key) { /** @var string $subkey */ $subkey = ParagonIE_Sodium_Core32_HSalsa20::hsalsa20($nonce, $key); /** @var string $block0 */ $block0 = str_repeat("\x00", 32); /** @var int $mlen - Length of the plaintext message */ $mlen = ParagonIE_Sodium_Core32_Util::strlen($plaintext); $mlen0 = $mlen; if ($mlen0 > 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES) { $mlen0 = 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES; } $block0 .= ParagonIE_Sodium_Core32_Util::substr($plaintext, 0, $mlen0); /** @var string $block0 */ $block0 = ParagonIE_Sodium_Core32_Salsa20::salsa20_xor( $block0, ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8), $subkey ); /** @var string $c */ $c = ParagonIE_Sodium_Core32_Util::substr( $block0, self::secretbox_xsalsa20poly1305_ZEROBYTES ); if ($mlen > $mlen0) { $c .= ParagonIE_Sodium_Core32_Salsa20::salsa20_xor_ic( ParagonIE_Sodium_Core32_Util::substr( $plaintext, self::secretbox_xsalsa20poly1305_ZEROBYTES ), ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8), 1, $subkey ); } $state = new ParagonIE_Sodium_Core32_Poly1305_State( ParagonIE_Sodium_Core32_Util::substr( $block0, 0, self::onetimeauth_poly1305_KEYBYTES ) ); try { ParagonIE_Sodium_Compat::memzero($block0); ParagonIE_Sodium_Compat::memzero($subkey); } catch (SodiumException $ex) { $block0 = null; $subkey = null; } $state->update($c); /** @var string $c - MAC || ciphertext */ $c = $state->finish() . $c; unset($state); return $c; } /** * Decrypt a ciphertext generated via secretbox(). * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $ciphertext * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function secretbox_open($ciphertext, $nonce, $key) { /** @var string $mac */ $mac = ParagonIE_Sodium_Core32_Util::substr( $ciphertext, 0, self::secretbox_xsalsa20poly1305_MACBYTES ); /** @var string $c */ $c = ParagonIE_Sodium_Core32_Util::substr( $ciphertext, self::secretbox_xsalsa20poly1305_MACBYTES ); /** @var int $clen */ $clen = ParagonIE_Sodium_Core32_Util::strlen($c); /** @var string $subkey */ $subkey = ParagonIE_Sodium_Core32_HSalsa20::hsalsa20($nonce, $key); /** @var string $block0 */ $block0 = ParagonIE_Sodium_Core32_Salsa20::salsa20( 64, ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8), $subkey ); $verified = ParagonIE_Sodium_Core32_Poly1305::onetimeauth_verify( $mac, $c, ParagonIE_Sodium_Core32_Util::substr($block0, 0, 32) ); if (!$verified) { try { ParagonIE_Sodium_Compat::memzero($subkey); } catch (SodiumException $ex) { $subkey = null; } throw new SodiumException('Invalid MAC'); } /** @var string $m - Decrypted message */ $m = ParagonIE_Sodium_Core32_Util::xorStrings( ParagonIE_Sodium_Core32_Util::substr($block0, self::secretbox_xsalsa20poly1305_ZEROBYTES), ParagonIE_Sodium_Core32_Util::substr($c, 0, self::secretbox_xsalsa20poly1305_ZEROBYTES) ); if ($clen > self::secretbox_xsalsa20poly1305_ZEROBYTES) { // We had more than 1 block, so let's continue to decrypt the rest. $m .= ParagonIE_Sodium_Core32_Salsa20::salsa20_xor_ic( ParagonIE_Sodium_Core32_Util::substr( $c, self::secretbox_xsalsa20poly1305_ZEROBYTES ), ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8), 1, (string) $subkey ); } return $m; } /** * XChaCha20-Poly1305 authenticated symmetric-key encryption. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $plaintext * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function secretbox_xchacha20poly1305($plaintext, $nonce, $key) { /** @var string $subkey */ $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20( ParagonIE_Sodium_Core32_Util::substr($nonce, 0, 16), $key ); $nonceLast = ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8); /** @var string $block0 */ $block0 = str_repeat("\x00", 32); /** @var int $mlen - Length of the plaintext message */ $mlen = ParagonIE_Sodium_Core32_Util::strlen($plaintext); $mlen0 = $mlen; if ($mlen0 > 64 - self::secretbox_xchacha20poly1305_ZEROBYTES) { $mlen0 = 64 - self::secretbox_xchacha20poly1305_ZEROBYTES; } $block0 .= ParagonIE_Sodium_Core32_Util::substr($plaintext, 0, $mlen0); /** @var string $block0 */ $block0 = ParagonIE_Sodium_Core32_ChaCha20::streamXorIc( $block0, $nonceLast, $subkey ); /** @var string $c */ $c = ParagonIE_Sodium_Core32_Util::substr( $block0, self::secretbox_xchacha20poly1305_ZEROBYTES ); if ($mlen > $mlen0) { $c .= ParagonIE_Sodium_Core32_ChaCha20::streamXorIc( ParagonIE_Sodium_Core32_Util::substr( $plaintext, self::secretbox_xchacha20poly1305_ZEROBYTES ), $nonceLast, $subkey, ParagonIE_Sodium_Core32_Util::store64_le(1) ); } $state = new ParagonIE_Sodium_Core32_Poly1305_State( ParagonIE_Sodium_Core32_Util::substr( $block0, 0, self::onetimeauth_poly1305_KEYBYTES ) ); try { ParagonIE_Sodium_Compat::memzero($block0); ParagonIE_Sodium_Compat::memzero($subkey); } catch (SodiumException $ex) { $block0 = null; $subkey = null; } $state->update($c); /** @var string $c - MAC || ciphertext */ $c = $state->finish() . $c; unset($state); return $c; } /** * Decrypt a ciphertext generated via secretbox_xchacha20poly1305(). * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $ciphertext * @param string $nonce * @param string $key * @return string * @throws SodiumException * @throws TypeError */ public static function secretbox_xchacha20poly1305_open($ciphertext, $nonce, $key) { /** @var string $mac */ $mac = ParagonIE_Sodium_Core32_Util::substr( $ciphertext, 0, self::secretbox_xchacha20poly1305_MACBYTES ); /** @var string $c */ $c = ParagonIE_Sodium_Core32_Util::substr( $ciphertext, self::secretbox_xchacha20poly1305_MACBYTES ); /** @var int $clen */ $clen = ParagonIE_Sodium_Core32_Util::strlen($c); /** @var string $subkey */ $subkey = ParagonIE_Sodium_Core32_HChaCha20::hchacha20($nonce, $key); /** @var string $block0 */ $block0 = ParagonIE_Sodium_Core32_ChaCha20::stream( 64, ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8), $subkey ); $verified = ParagonIE_Sodium_Core32_Poly1305::onetimeauth_verify( $mac, $c, ParagonIE_Sodium_Core32_Util::substr($block0, 0, 32) ); if (!$verified) { try { ParagonIE_Sodium_Compat::memzero($subkey); } catch (SodiumException $ex) { $subkey = null; } throw new SodiumException('Invalid MAC'); } /** @var string $m - Decrypted message */ $m = ParagonIE_Sodium_Core32_Util::xorStrings( ParagonIE_Sodium_Core32_Util::substr($block0, self::secretbox_xchacha20poly1305_ZEROBYTES), ParagonIE_Sodium_Core32_Util::substr($c, 0, self::secretbox_xchacha20poly1305_ZEROBYTES) ); if ($clen > self::secretbox_xchacha20poly1305_ZEROBYTES) { // We had more than 1 block, so let's continue to decrypt the rest. $m .= ParagonIE_Sodium_Core32_ChaCha20::streamXorIc( ParagonIE_Sodium_Core32_Util::substr( $c, self::secretbox_xchacha20poly1305_ZEROBYTES ), ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8), (string) $subkey, ParagonIE_Sodium_Core32_Util::store64_le(1) ); } return $m; } /** * @param string $key * @return array<int, string> Returns a state and a header. * @throws Exception * @throws SodiumException */ public static function secretstream_xchacha20poly1305_init_push($key) { # randombytes_buf(out, crypto_secretstream_xchacha20poly1305_HEADERBYTES); $out = random_bytes(24); # crypto_core_hchacha20(state->k, out, k, NULL); $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20($out, $key); $state = new ParagonIE_Sodium_Core32_SecretStream_State( $subkey, ParagonIE_Sodium_Core32_Util::substr($out, 16, 8) . str_repeat("\0", 4) ); # _crypto_secretstream_xchacha20poly1305_counter_reset(state); $state->counterReset(); # memcpy(STATE_INONCE(state), out + crypto_core_hchacha20_INPUTBYTES, # crypto_secretstream_xchacha20poly1305_INONCEBYTES); # memset(state->_pad, 0, sizeof state->_pad); return array( $state->toString(), $out ); } /** * @param string $key * @param string $header * @return string Returns a state. * @throws Exception */ public static function secretstream_xchacha20poly1305_init_pull($key, $header) { # crypto_core_hchacha20(state->k, in, k, NULL); $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20( ParagonIE_Sodium_Core32_Util::substr($header, 0, 16), $key ); $state = new ParagonIE_Sodium_Core32_SecretStream_State( $subkey, ParagonIE_Sodium_Core32_Util::substr($header, 16) ); $state->counterReset(); # memcpy(STATE_INONCE(state), in + crypto_core_hchacha20_INPUTBYTES, # crypto_secretstream_xchacha20poly1305_INONCEBYTES); # memset(state->_pad, 0, sizeof state->_pad); # return 0; return $state->toString(); } /** * @param string $state * @param string $msg * @param string $aad * @param int $tag * @return string * @throws SodiumException */ public static function secretstream_xchacha20poly1305_push(&$state, $msg, $aad = '', $tag = 0) { $st = ParagonIE_Sodium_Core32_SecretStream_State::fromString($state); # crypto_onetimeauth_poly1305_state poly1305_state; # unsigned char block[64U]; # unsigned char slen[8U]; # unsigned char *c; # unsigned char *mac; $msglen = ParagonIE_Sodium_Core32_Util::strlen($msg); $aadlen = ParagonIE_Sodium_Core32_Util::strlen($aad); if ((($msglen + 63) >> 6) > 0xfffffffe) { throw new SodiumException( 'message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes' ); } # if (outlen_p != NULL) { # *outlen_p = 0U; # } # if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) { # sodium_misuse(); # } # crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k); # crypto_onetimeauth_poly1305_init(&poly1305_state, block); # sodium_memzero(block, sizeof block); $auth = new ParagonIE_Sodium_Core32_Poly1305_State( ParagonIE_Sodium_Core32_ChaCha20::ietfStream(32, $st->getCombinedNonce(), $st->getKey()) ); # crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen); $auth->update($aad); # crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0, # (0x10 - adlen) & 0xf); $auth->update(str_repeat("\0", ((0x10 - $aadlen) & 0xf))); # memset(block, 0, sizeof block); # block[0] = tag; # crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block, # state->nonce, 1U, state->k); $block = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc( ParagonIE_Sodium_Core32_Util::intToChr($tag) . str_repeat("\0", 63), $st->getCombinedNonce(), $st->getKey(), ParagonIE_Sodium_Core32_Util::store64_le(1) ); # crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block); $auth->update($block); # out[0] = block[0]; $out = $block[0]; # c = out + (sizeof tag); # crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, state->nonce, 2U, state->k); $cipher = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc( $msg, $st->getCombinedNonce(), $st->getKey(), ParagonIE_Sodium_Core32_Util::store64_le(2) ); # crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen); $auth->update($cipher); $out .= $cipher; unset($cipher); # crypto_onetimeauth_poly1305_update # (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf); $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen) & 0xf))); # STORE64_LE(slen, (uint64_t) adlen); $slen = ParagonIE_Sodium_Core32_Util::store64_le($aadlen); # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); $auth->update($slen); # STORE64_LE(slen, (sizeof block) + mlen); $slen = ParagonIE_Sodium_Core32_Util::store64_le(64 + $msglen); # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); $auth->update($slen); # mac = c + mlen; # crypto_onetimeauth_poly1305_final(&poly1305_state, mac); $mac = $auth->finish(); $out .= $mac; # sodium_memzero(&poly1305_state, sizeof poly1305_state); unset($auth); # XOR_BUF(STATE_INONCE(state), mac, # crypto_secretstream_xchacha20poly1305_INONCEBYTES); $st->xorNonce($mac); # sodium_increment(STATE_COUNTER(state), # crypto_secretstream_xchacha20poly1305_COUNTERBYTES); $st->incrementCounter(); // Overwrite by reference: $state = $st->toString(); /** @var bool $rekey */ $rekey = ($tag & ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY) !== 0; # if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 || # sodium_is_zero(STATE_COUNTER(state), # crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) { # crypto_secretstream_xchacha20poly1305_rekey(state); # } if ($rekey || $st->needsRekey()) { // DO REKEY self::secretstream_xchacha20poly1305_rekey($state); } # if (outlen_p != NULL) { # *outlen_p = crypto_secretstream_xchacha20poly1305_ABYTES + mlen; # } return $out; } /** * @param string $state * @param string $cipher * @param string $aad * @return bool|array{0: string, 1: int} * @throws SodiumException */ public static function secretstream_xchacha20poly1305_pull(&$state, $cipher, $aad = '') { $st = ParagonIE_Sodium_Core32_SecretStream_State::fromString($state); $cipherlen = ParagonIE_Sodium_Core32_Util::strlen($cipher); # mlen = inlen - crypto_secretstream_xchacha20poly1305_ABYTES; $msglen = $cipherlen - ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES; $aadlen = ParagonIE_Sodium_Core32_Util::strlen($aad); # if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) { # sodium_misuse(); # } if ((($msglen + 63) >> 6) > 0xfffffffe) { throw new SodiumException( 'message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes' ); } # crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k); # crypto_onetimeauth_poly1305_init(&poly1305_state, block); # sodium_memzero(block, sizeof block); $auth = new ParagonIE_Sodium_Core32_Poly1305_State( ParagonIE_Sodium_Core32_ChaCha20::ietfStream(32, $st->getCombinedNonce(), $st->getKey()) ); # crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen); $auth->update($aad); # crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0, # (0x10 - adlen) & 0xf); $auth->update(str_repeat("\0", ((0x10 - $aadlen) & 0xf))); # memset(block, 0, sizeof block); # block[0] = in[0]; # crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block, # state->nonce, 1U, state->k); $block = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc( $cipher[0] . str_repeat("\0", 63), $st->getCombinedNonce(), $st->getKey(), ParagonIE_Sodium_Core32_Util::store64_le(1) ); # tag = block[0]; # block[0] = in[0]; # crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block); $tag = ParagonIE_Sodium_Core32_Util::chrToInt($block[0]); $block[0] = $cipher[0]; $auth->update($block); # c = in + (sizeof tag); # crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen); $auth->update(ParagonIE_Sodium_Core32_Util::substr($cipher, 1, $msglen)); # crypto_onetimeauth_poly1305_update # (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf); $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen) & 0xf))); # STORE64_LE(slen, (uint64_t) adlen); # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); $slen = ParagonIE_Sodium_Core32_Util::store64_le($aadlen); $auth->update($slen); # STORE64_LE(slen, (sizeof block) + mlen); # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); $slen = ParagonIE_Sodium_Core32_Util::store64_le(64 + $msglen); $auth->update($slen); # crypto_onetimeauth_poly1305_final(&poly1305_state, mac); # sodium_memzero(&poly1305_state, sizeof poly1305_state); $mac = $auth->finish(); # stored_mac = c + mlen; # if (sodium_memcmp(mac, stored_mac, sizeof mac) != 0) { # sodium_memzero(mac, sizeof mac); # return -1; # } $stored = ParagonIE_Sodium_Core32_Util::substr($cipher, $msglen + 1, 16); if (!ParagonIE_Sodium_Core32_Util::hashEquals($mac, $stored)) { return false; } # crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, state->nonce, 2U, state->k); $out = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc( ParagonIE_Sodium_Core32_Util::substr($cipher, 1, $msglen), $st->getCombinedNonce(), $st->getKey(), ParagonIE_Sodium_Core32_Util::store64_le(2) ); # XOR_BUF(STATE_INONCE(state), mac, # crypto_secretstream_xchacha20poly1305_INONCEBYTES); $st->xorNonce($mac); # sodium_increment(STATE_COUNTER(state), # crypto_secretstream_xchacha20poly1305_COUNTERBYTES); $st->incrementCounter(); # if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 || # sodium_is_zero(STATE_COUNTER(state), # crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) { # crypto_secretstream_xchacha20poly1305_rekey(state); # } // Overwrite by reference: $state = $st->toString(); /** @var bool $rekey */ $rekey = ($tag & ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY) !== 0; if ($rekey || $st->needsRekey()) { // DO REKEY self::secretstream_xchacha20poly1305_rekey($state); } return array($out, $tag); } /** * @param string $state * @return void * @throws SodiumException */ public static function secretstream_xchacha20poly1305_rekey(&$state) { $st = ParagonIE_Sodium_Core32_SecretStream_State::fromString($state); # unsigned char new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + # crypto_secretstream_xchacha20poly1305_INONCEBYTES]; # size_t i; # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) { # new_key_and_inonce[i] = state->k[i]; # } $new_key_and_inonce = $st->getKey(); # for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) { # new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i] = # STATE_INONCE(state)[i]; # } $new_key_and_inonce .= ParagonIE_Sodium_Core32_Util::substR($st->getNonce(), 0, 8); # crypto_stream_chacha20_ietf_xor(new_key_and_inonce, new_key_and_inonce, # sizeof new_key_and_inonce, # state->nonce, state->k); $st->rekey(ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc( $new_key_and_inonce, $st->getCombinedNonce(), $st->getKey(), ParagonIE_Sodium_Core32_Util::store64_le(0) )); # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) { # state->k[i] = new_key_and_inonce[i]; # } # for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) { # STATE_INONCE(state)[i] = # new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i]; # } # _crypto_secretstream_xchacha20poly1305_counter_reset(state); $st->counterReset(); $state = $st->toString(); } /** * Detached Ed25519 signature. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $sk * @return string * @throws SodiumException * @throws TypeError */ public static function sign_detached($message, $sk) { return ParagonIE_Sodium_Core32_Ed25519::sign_detached($message, $sk); } /** * Attached Ed25519 signature. (Returns a signed message.) * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $message * @param string $sk * @return string * @throws SodiumException * @throws TypeError */ public static function sign($message, $sk) { return ParagonIE_Sodium_Core32_Ed25519::sign($message, $sk); } /** * Opens a signed message. If valid, returns the message. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $signedMessage * @param string $pk * @return string * @throws SodiumException * @throws TypeError */ public static function sign_open($signedMessage, $pk) { return ParagonIE_Sodium_Core32_Ed25519::sign_open($signedMessage, $pk); } /** * Verify a detached signature of a given message and public key. * * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. * * @param string $signature * @param string $message * @param string $pk * @return bool * @throws SodiumException * @throws TypeError */ public static function sign_verify_detached($signature, $message, $pk) { return ParagonIE_Sodium_Core32_Ed25519::verify_detached($signature, $message, $pk); } } PK������zZ+&��������Carbon/Doctrine/CarbonType.phpnu�W+A��������<?php declare(strict_types=1); namespace Carbon\Doctrine; class CarbonType extends DateTimeType implements CarbonDoctrineType { } PK������zZE����&��Carbon/Doctrine/CarbonDoctrineType.phpnu�W+A��������<?php declare(strict_types=1); namespace Carbon\Doctrine; use Doctrine\DBAL\Platforms\AbstractPlatform; interface CarbonDoctrineType { public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform); public function convertToPHPValue(mixed $value, AbstractPlatform $platform); public function convertToDatabaseValue($value, AbstractPlatform $platform); } PK������zZPa7��7��,��Carbon/Doctrine/DateTimeDefaultPrecision.phpnu�W+A��������<?php declare(strict_types=1); namespace Carbon\Doctrine; class DateTimeDefaultPrecision { private static $precision = 6; /** * Change the default Doctrine datetime and datetime_immutable precision. * * @param int $precision */ public static function set(int $precision): void { self::$precision = $precision; } /** * Get the default Doctrine datetime and datetime_immutable precision. * * @return int */ public static function get(): int { return self::$precision; } } PK������zZ"ɗ������'��Carbon/Doctrine/CarbonImmutableType.phpnu�W+A��������<?php declare(strict_types=1); namespace Carbon\Doctrine; class CarbonImmutableType extends DateTimeImmutableType implements CarbonDoctrineType { } PK������zZ2 �� ��'��Carbon/Doctrine/CarbonTypeConverter.phpnu�W+A��������<?php declare(strict_types=1); namespace Carbon\Doctrine; use Carbon\Carbon; use Carbon\CarbonInterface; use DateTimeInterface; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\DB2Platform; use Doctrine\DBAL\Platforms\OraclePlatform; use Doctrine\DBAL\Platforms\SQLitePlatform; use Doctrine\DBAL\Platforms\SQLServerPlatform; use Doctrine\DBAL\Types\Exception\InvalidType; use Doctrine\DBAL\Types\Exception\ValueNotConvertible; use Exception; /** * @template T of CarbonInterface */ trait CarbonTypeConverter { /** * This property differentiates types installed by carbonphp/carbon-doctrine-types * from the ones embedded previously in nesbot/carbon source directly. * * @readonly */ public bool $external = true; /** * @return class-string<T> */ protected function getCarbonClassName(): string { return Carbon::class; } public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform): string { $precision = min( $fieldDeclaration['precision'] ?? DateTimeDefaultPrecision::get(), $this->getMaximumPrecision($platform), ); $type = parent::getSQLDeclaration($fieldDeclaration, $platform); if (!$precision) { return $type; } if (str_contains($type, '(')) { return preg_replace('/\(\d+\)/', "($precision)", $type); } [$before, $after] = explode(' ', "$type "); return trim("$before($precision) $after"); } /** * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string { if ($value === null) { return $value; } if ($value instanceof DateTimeInterface) { return $value->format('Y-m-d H:i:s.u'); } throw InvalidType::new( $value, static::class, ['null', 'DateTime', 'Carbon'] ); } private function doConvertToPHPValue(mixed $value) { $class = $this->getCarbonClassName(); if ($value === null || is_a($value, $class)) { return $value; } if ($value instanceof DateTimeInterface) { return $class::instance($value); } $date = null; $error = null; try { $date = $class::parse($value); } catch (Exception $exception) { $error = $exception; } if (!$date) { throw ValueNotConvertible::new( $value, static::class, 'Y-m-d H:i:s.u or any format supported by '.$class.'::parse()', $error ); } return $date; } private function getMaximumPrecision(AbstractPlatform $platform): int { if ($platform instanceof DB2Platform) { return 12; } if ($platform instanceof OraclePlatform) { return 9; } if ($platform instanceof SQLServerPlatform || $platform instanceof SQLitePlatform) { return 3; } return 6; } } PK������zZpBl����)��Carbon/Doctrine/DateTimeImmutableType.phpnu�W+A��������<?php declare(strict_types=1); namespace Carbon\Doctrine; use Carbon\CarbonImmutable; use DateTimeImmutable; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\VarDateTimeImmutableType; class DateTimeImmutableType extends VarDateTimeImmutableType implements CarbonDoctrineType { /** @use CarbonTypeConverter<CarbonImmutable> */ use CarbonTypeConverter; /** * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?CarbonImmutable { return $this->doConvertToPHPValue($value); } /** * @return class-string<CarbonImmutable> */ protected function getCarbonClassName(): string { return CarbonImmutable::class; } } PK������zZש+��+�� ��Carbon/Doctrine/DateTimeType.phpnu�W+A��������<?php declare(strict_types=1); namespace Carbon\Doctrine; use Carbon\Carbon; use DateTime; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\VarDateTimeType; class DateTimeType extends VarDateTimeType implements CarbonDoctrineType { /** @use CarbonTypeConverter<Carbon> */ use CarbonTypeConverter; /** * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?Carbon { return $this->doConvertToPHPValue($value); } } PK������rZ$>,��,��'��Auth/bootstrap-stubs/auth/register.stubnu�W+A��������@extends('layouts.app') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">{{ __('Register') }}</div> <div class="card-body"> <form method="POST" action="{{ route('register') }}"> @csrf <div class="row mb-3"> <label for="name" class="col-md-4 col-form-label text-md-end">{{ __('Name') }}</label> <div class="col-md-6"> <input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name') }}" required autocomplete="name" autofocus> @error('name') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div> <div class="row mb-3"> <label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label> <div class="col-md-6"> <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email"> @error('email') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div> <div class="row mb-3"> <label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label> <div class="col-md-6"> <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password"> @error('password') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div> <div class="row mb-3"> <label for="password-confirm" class="col-md-4 col-form-label text-md-end">{{ __('Confirm Password') }}</label> <div class="col-md-6"> <input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password"> </div> </div> <div class="row mb-0"> <div class="col-md-6 offset-md-4"> <button type="submit" class="btn btn-primary"> {{ __('Register') }} </button> </div> </div> </form> </div> </div> </div> </div> </div> @endsection PK������rZ.On��n��%��Auth/bootstrap-stubs/auth/verify.stubnu�W+A��������@extends('layouts.app') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">{{ __('Verify Your Email Address') }}</div> <div class="card-body"> @if (session('resent')) <div class="alert alert-success" role="alert"> {{ __('A fresh verification link has been sent to your email address.') }} </div> @endif {{ __('Before proceeding, please check your email for a verification link.') }} {{ __('If you did not receive the email') }}, <form class="d-inline" method="POST" action="{{ route('verification.resend') }}"> @csrf <button type="submit" class="btn btn-link p-0 m-0 align-baseline">{{ __('click here to request another') }}</button>. </form> </div> </div> </div> </div> </div> @endsection PK������rZ8%g �� ��$��Auth/bootstrap-stubs/auth/login.stubnu�W+A��������@extends('layouts.app') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">{{ __('Login') }}</div> <div class="card-body"> <form method="POST" action="{{ route('login') }}"> @csrf <div class="row mb-3"> <label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label> <div class="col-md-6"> <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus> @error('email') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div> <div class="row mb-3"> <label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label> <div class="col-md-6"> <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password"> @error('password') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div> <div class="row mb-3"> <div class="col-md-6 offset-md-4"> <div class="form-check"> <input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}> <label class="form-check-label" for="remember"> {{ __('Remember Me') }} </label> </div> </div> </div> <div class="row mb-0"> <div class="col-md-8 offset-md-4"> <button type="submit" class="btn btn-primary"> {{ __('Login') }} </button> @if (Route::has('password.request')) <a class="btn btn-link" href="{{ route('password.request') }}"> {{ __('Forgot Your Password?') }} </a> @endif </div> </div> </form> </div> </div> </div> </div> </div> @endsection PK������rZ [����0��Auth/bootstrap-stubs/auth/passwords/confirm.stubnu�W+A��������@extends('layouts.app') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">{{ __('Confirm Password') }}</div> <div class="card-body"> {{ __('Please confirm your password before continuing.') }} <form method="POST" action="{{ route('password.confirm') }}"> @csrf <div class="row mb-3"> <label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label> <div class="col-md-6"> <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password"> @error('password') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div> <div class="row mb-0"> <div class="col-md-8 offset-md-4"> <button type="submit" class="btn btn-primary"> {{ __('Confirm Password') }} </button> @if (Route::has('password.request')) <a class="btn btn-link" href="{{ route('password.request') }}"> {{ __('Forgot Your Password?') }} </a> @endif </div> </div> </form> </div> </div> </div> </div> </div> @endsection PK������rZCTF �� ��.��Auth/bootstrap-stubs/auth/passwords/reset.stubnu�W+A��������@extends('layouts.app') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">{{ __('Reset Password') }}</div> <div class="card-body"> <form method="POST" action="{{ route('password.update') }}"> @csrf <input type="hidden" name="token" value="{{ $token }}"> <div class="row mb-3"> <label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label> <div class="col-md-6"> <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ $email ?? old('email') }}" required autocomplete="email" autofocus> @error('email') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div> <div class="row mb-3"> <label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label> <div class="col-md-6"> <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password"> @error('password') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div> <div class="row mb-3"> <label for="password-confirm" class="col-md-4 col-form-label text-md-end">{{ __('Confirm Password') }}</label> <div class="col-md-6"> <input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password"> </div> </div> <div class="row mb-0"> <div class="col-md-6 offset-md-4"> <button type="submit" class="btn btn-primary"> {{ __('Reset Password') }} </button> </div> </div> </form> </div> </div> </div> </div> </div> @endsection PK������rZsKjf��f��.��Auth/bootstrap-stubs/auth/passwords/email.stubnu�W+A��������@extends('layouts.app') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">{{ __('Reset Password') }}</div> <div class="card-body"> @if (session('status')) <div class="alert alert-success" role="alert"> {{ session('status') }} </div> @endif <form method="POST" action="{{ route('password.email') }}"> @csrf <div class="row mb-3"> <label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label> <div class="col-md-6"> <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus> @error('email') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div> <div class="row mb-0"> <div class="col-md-6 offset-md-4"> <button type="submit" class="btn btn-primary"> {{ __('Send Password Reset Link') }} </button> </div> </div> </form> </div> </div> </div> </div> </div> @endsection PK������rZ �� ��%��Auth/bootstrap-stubs/layouts/app.stubnu�W+A��������<!doctype html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- CSRF Token --> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>{{ config('app.name', 'Laravel') }} @vite(['resources/sass/app.scss', 'resources/js/app.js'])
@yield('content')
PKrZ\FAuth/bootstrap-stubs/home.stubnuW+A@extends('layouts.app') @section('content')
{{ __('Dashboard') }}
@if (session('status')) @endif {{ __('You are logged in!') }}
@endsection PKrZw?llAuth/stubs/routes.stubnuW+A Auth::routes(); Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home'); PKrZd^44&Auth/stubs/controllers/Controller.stubnuW+Amiddleware('auth'); } /** * Show the application dashboard. * * @return \Illuminate\Contracts\Support\Renderable */ public function index() { return view('home'); } } PKrZs@  UiCommand.phpnuW+Aargument('type'))) { return call_user_func(static::$macros[$this->argument('type')], $this); } if (! in_array($this->argument('type'), ['bootstrap', 'vue', 'react'])) { throw new InvalidArgumentException('Invalid preset.'); } if ($this->option('auth')) { $this->call('ui:auth'); } $this->{$this->argument('type')}(); } /** * Install the "bootstrap" preset. * * @return void */ protected function bootstrap() { Presets\Bootstrap::install(); $this->components->info('Bootstrap scaffolding installed successfully.'); $this->components->warn('Please run [npm install && npm run dev] to compile your fresh scaffolding.'); } /** * Install the "vue" preset. * * @return void */ protected function vue() { Presets\Bootstrap::install(); Presets\Vue::install(); $this->components->info('Vue scaffolding installed successfully.'); $this->components->warn('Please run [npm install && npm run dev] to compile your fresh scaffolding.'); } /** * Install the "react" preset. * * @return void */ protected function react() { Presets\Bootstrap::install(); Presets\React::install(); $this->components->info('React scaffolding installed successfully.'); $this->components->warn('Please run [npm install && npm run dev] to compile your fresh scaffolding.'); } } PKrZ22ControllersCommand.phpnuW+AallFiles(__DIR__.'/../stubs/Auth')) ->each(function (SplFileInfo $file) use ($filesystem) { $filesystem->copy( $file->getPathname(), app_path('Http/Controllers/Auth/'.Str::replaceLast('.stub', '.php', $file->getFilename())) ); }); $this->components->info('Authentication scaffolding generated successfully.'); } } PKrZ*AuthCommand.phpnuW+A 'auth/login.blade.php', 'auth/passwords/confirm.stub' => 'auth/passwords/confirm.blade.php', 'auth/passwords/email.stub' => 'auth/passwords/email.blade.php', 'auth/passwords/reset.stub' => 'auth/passwords/reset.blade.php', 'auth/register.stub' => 'auth/register.blade.php', 'auth/verify.stub' => 'auth/verify.blade.php', 'home.stub' => 'home.blade.php', 'layouts/app.stub' => 'layouts/app.blade.php', ]; /** * Execute the console command. * * @return void * * @throws \InvalidArgumentException */ public function handle() { if (static::hasMacro($this->argument('type'))) { return call_user_func(static::$macros[$this->argument('type')], $this); } if (! in_array($this->argument('type'), ['bootstrap'])) { throw new InvalidArgumentException('Invalid preset.'); } $this->ensureDirectoriesExist(); $this->exportViews(); if (! $this->option('views')) { $this->exportBackend(); } $this->components->info('Authentication scaffolding generated successfully.'); } /** * Create the directories for the files. * * @return void */ protected function ensureDirectoriesExist() { if (! is_dir($directory = $this->getViewPath('layouts'))) { mkdir($directory, 0755, true); } if (! is_dir($directory = $this->getViewPath('auth/passwords'))) { mkdir($directory, 0755, true); } } /** * Export the authentication views. * * @return void */ protected function exportViews() { foreach ($this->views as $key => $value) { if (file_exists($view = $this->getViewPath($value)) && ! $this->option('force')) { if (! $this->components->confirm("The [$value] view already exists. Do you want to replace it?")) { continue; } } copy( __DIR__.'/Auth/'.$this->argument('type').'-stubs/'.$key, $view ); } } /** * Export the authentication backend. * * @return void */ protected function exportBackend() { $this->callSilent('ui:controllers'); $controller = app_path('Http/Controllers/HomeController.php'); if (file_exists($controller) && ! $this->option('force')) { if ($this->components->confirm("The [HomeController.php] file already exists. Do you want to replace it?", true)) { file_put_contents($controller, $this->compileStub('controllers/HomeController')); } } else { file_put_contents($controller, $this->compileStub('controllers/HomeController')); } $baseController = app_path('Http/Controllers/Controller.php'); if (file_exists($baseController) && ! $this->option('force')) { if ($this->components->confirm("The [Controller.php] file already exists. Do you want to replace it?", true)) { file_put_contents($baseController, $this->compileStub('controllers/Controller')); } } else { file_put_contents($baseController, $this->compileStub('controllers/Controller')); } if (! file_exists(database_path('migrations/0001_01_01_000000_create_users_table.php'))) { copy( __DIR__.'/../stubs/migrations/2014_10_12_100000_create_password_resets_table.php', base_path('database/migrations/2014_10_12_100000_create_password_resets_table.php') ); } file_put_contents( base_path('routes/web.php'), file_get_contents(__DIR__.'/Auth/stubs/routes.stub'), FILE_APPEND ); } /** * Compiles the given stub. * * @param string $stub * @return string */ protected function compileStub($stub) { return str_replace( '{{namespace}}', $this->laravel->getNamespace(), file_get_contents(__DIR__.'/Auth/stubs/'.$stub.'.stub') ); } /** * Get full view path relative to the application's configured view path. * * @param string $path * @return string */ protected function getViewPath($path) { return implode(DIRECTORY_SEPARATOR, [ config('view.paths')[0] ?? resource_path('views'), $path, ]); } } PKrZd AuthRouteMethods.phpnuW+AprependGroupNamespace('Auth\LoginController')) ? null : 'App\Http\Controllers'; $this->group(['namespace' => $namespace], function() use($options) { // Login Routes... if ($options['login'] ?? true) { $this->get('login', 'Auth\LoginController@showLoginForm')->name('login'); $this->post('login', 'Auth\LoginController@login'); } // Logout Routes... if ($options['logout'] ?? true) { $this->post('logout', 'Auth\LoginController@logout')->name('logout'); } // Registration Routes... if ($options['register'] ?? true) { $this->get('register', 'Auth\RegisterController@showRegistrationForm')->name('register'); $this->post('register', 'Auth\RegisterController@register'); } // Password Reset Routes... if ($options['reset'] ?? true) { $this->resetPassword(); } // Password Confirmation Routes... if ($options['confirm'] ?? class_exists($this->prependGroupNamespace('Auth\ConfirmPasswordController'))) { $this->confirmPassword(); } // Email Verification Routes... if ($options['verify'] ?? false) { $this->emailVerification(); } }); }; } /** * Register the typical reset password routes for an application. * * @return callable */ public function resetPassword() { return function () { $this->get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('password.request'); $this->post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('password.email'); $this->get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('password.reset'); $this->post('password/reset', 'Auth\ResetPasswordController@reset')->name('password.update'); }; } /** * Register the typical confirm password routes for an application. * * @return callable */ public function confirmPassword() { return function () { $this->get('password/confirm', 'Auth\ConfirmPasswordController@showConfirmForm')->name('password.confirm'); $this->post('password/confirm', 'Auth\ConfirmPasswordController@confirm'); }; } /** * Register the typical email verification routes for an application. * * @return callable */ public function emailVerification() { return function () { $this->get('email/verify', 'Auth\VerificationController@show')->name('verification.notice'); $this->get('email/verify/{id}/{hash}', 'Auth\VerificationController@verify')->name('verification.verify'); $this->post('email/resend', 'Auth\VerificationController@resend')->name('verification.resend'); }; } } PKrZ,SUiServiceProvider.phpnuW+Aapp->runningInConsole()) { $this->commands([ AuthCommand::class, ControllersCommand::class, UiCommand::class, ]); } } /** * Bootstrap any application services. * * @return void */ public function boot() { Route::mixin(new AuthRouteMethods); } } PKrZ Presets/React.phpnuW+A '^4.2.0', 'react' => '^18.2.0', 'react-dom' => '^18.2.0', ] + Arr::except($packages, [ '@vitejs/plugin-vue', 'vue' ]); } /** * Update the Vite configuration. * * @return void */ protected static function updateViteConfiguration() { copy(__DIR__.'/react-stubs/vite.config.js', base_path('vite.config.js')); } /** * Update the example component. * * @return void */ protected static function updateComponent() { (new Filesystem)->delete( resource_path('js/components/ExampleComponent.vue') ); copy( __DIR__.'/react-stubs/Example.jsx', resource_path('js/components/Example.jsx') ); } /** * Update the bootstrapping files. * * @return void */ protected static function updateBootstrapping() { copy(__DIR__.'/react-stubs/app.js', resource_path('js/app.js')); } /** * Add Vite's React Refresh Runtime * * @return void */ protected static function addViteReactRefreshDirective() { $view = static::getViewPath('layouts/app.blade.php'); if (! file_exists($view)) { return; } file_put_contents( $view, str_replace('@vite(', '@viteReactRefresh'.PHP_EOL.' @vite(', file_get_contents($view)) ); } /** * Get full view path relative to the application's configured view path. * * @param string $path * @return string */ protected static function getViewPath($path) { return implode(DIRECTORY_SEPARATOR, [ config('view.paths')[0] ?? resource_path('views'), $path, ]); } } PKrZNPPresets/Vue.phpnuW+A '^4.5.0', 'vue' => '^3.2.37', ] + Arr::except($packages, [ '@vitejs/plugin-react', 'react', 'react-dom', ]); } /** * Update the Vite configuration. * * @return void */ protected static function updateViteConfiguration() { copy(__DIR__.'/vue-stubs/vite.config.js', base_path('vite.config.js')); } /** * Update the example component. * * @return void */ protected static function updateComponent() { (new Filesystem)->delete( resource_path('js/components/Example.js') ); copy( __DIR__.'/vue-stubs/ExampleComponent.vue', resource_path('js/components/ExampleComponent.vue') ); } /** * Update the bootstrapping files. * * @return void */ protected static function updateBootstrapping() { copy(__DIR__.'/vue-stubs/app.js', resource_path('js/app.js')); } } PKrZp$Presets/bootstrap-stubs/bootstrap.jsnuW+Aimport 'bootstrap'; /** * We'll load the axios HTTP library which allows us to easily issue requests * to our Laravel back-end. This library automatically handles sending the * CSRF token as a header based on the value of the "XSRF" token cookie. */ import axios from 'axios'; window.axios = axios; window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; /** * Echo exposes an expressive API for subscribing to channels and listening * for events that are broadcast by Laravel. Echo and event broadcasting * allows your team to easily build robust real-time web applications. */ // import Echo from 'laravel-echo'; // import Pusher from 'pusher-js'; // window.Pusher = Pusher; // window.Echo = new Echo({ // broadcaster: 'pusher', // key: import.meta.env.VITE_PUSHER_APP_KEY, // cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER ?? 'mt1', // wsHost: import.meta.env.VITE_PUSHER_HOST ?? `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`, // wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80, // wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443, // forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https', // enabledTransports: ['ws', 'wss'], // }); PKrZ888&Presets/bootstrap-stubs/vite.config.jsnuW+Aimport { defineConfig } from 'vite'; import laravel from 'laravel-vite-plugin'; export default defineConfig({ plugins: [ laravel({ input: [ 'resources/sass/app.scss', 'resources/js/app.js', ], refresh: true, }), ], }); PKrZ>#Š'Presets/bootstrap-stubs/_variables.scssnuW+A// Body $body-bg: #f8fafc; // Typography $font-family-sans-serif: 'Nunito', sans-serif; $font-size-base: 0.9rem; $line-height-base: 1.6; PKrZO Presets/bootstrap-stubs/app.scssnuW+A// Fonts @import url('https://fonts.bunny.net/css?family=Nunito'); // Variables @import 'variables'; // Bootstrap @import 'bootstrap/scss/bootstrap'; PKrZ5ccPresets/Bootstrap.phpnuW+A '^5.2.3', '@popperjs/core' => '^2.11.6', 'sass' => '^1.56.1', ] + $packages; } /** * Update the Vite configuration. * * @return void */ protected static function updateViteConfiguration() { copy(__DIR__.'/bootstrap-stubs/vite.config.js', base_path('vite.config.js')); } /** * Update the Sass files for the application. * * @return void */ protected static function updateSass() { (new Filesystem)->ensureDirectoryExists(resource_path('sass')); copy(__DIR__.'/bootstrap-stubs/_variables.scss', resource_path('sass/_variables.scss')); copy(__DIR__.'/bootstrap-stubs/app.scss', resource_path('sass/app.scss')); } /** * Update the bootstrapping files. * * @return void */ protected static function updateBootstrapping() { copy(__DIR__.'/bootstrap-stubs/bootstrap.js', resource_path('js/bootstrap.js')); } } PKrZF Presets/vue-stubs/vite.config.jsnuW+Aimport { defineConfig } from 'vite'; import laravel from 'laravel-vite-plugin'; import vue from '@vitejs/plugin-vue'; export default defineConfig({ plugins: [ laravel({ input: [ 'resources/sass/app.scss', 'resources/js/app.js', ], refresh: true, }), vue({ template: { transformAssetUrls: { base: null, includeAbsolute: false, }, }, }), ], resolve: { alias: { vue: 'vue/dist/vue.esm-bundler.js', }, }, }); PKrZ6 ((&Presets/vue-stubs/ExampleComponent.vuenuW+A PKrZpPresets/vue-stubs/app.jsnuW+A/** * First we will load all of this project's JavaScript dependencies which * includes Vue and other libraries. It is a great starting point when * building robust, powerful web applications using Vue and Laravel. */ import './bootstrap'; import { createApp } from 'vue'; /** * Next, we will create a fresh Vue application instance. You may then begin * registering components with the application instance so they are ready * to use in your application's views. An example is included for you. */ const app = createApp({}); import ExampleComponent from './components/ExampleComponent.vue'; app.component('example-component', ExampleComponent); /** * The following block of code may be used to automatically register your * Vue components. It will recursively scan this directory for the Vue * components and automatically register them with their "basename". * * Eg. ./components/ExampleComponent.vue -> */ // Object.entries(import.meta.glob('./**/*.vue', { eager: true })).forEach(([path, definition]) => { // app.component(path.split('/').pop().replace(/\.\w+$/, ''), definition.default); // }); /** * Finally, we will attach the application instance to a HTML element with * an "id" attribute of "app". This element is included with the "auth" * scaffolding. Otherwise, you will need to add an element yourself. */ app.mount('#app'); PKrZ(֙__Presets/Preset.phpnuW+AisDirectory($directory = resource_path('js/components'))) { $filesystem->makeDirectory($directory, 0755, true); } } /** * Update the "package.json" file. * * @param bool $dev * @return void */ protected static function updatePackages($dev = true) { if (! file_exists(base_path('package.json'))) { return; } $configurationKey = $dev ? 'devDependencies' : 'dependencies'; $packages = json_decode(file_get_contents(base_path('package.json')), true); $packages[$configurationKey] = static::updatePackageArray( array_key_exists($configurationKey, $packages) ? $packages[$configurationKey] : [], $configurationKey ); ksort($packages[$configurationKey]); file_put_contents( base_path('package.json'), json_encode($packages, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT).PHP_EOL ); } /** * Remove the installed Node modules. * * @return void */ protected static function removeNodeModules() { tap(new Filesystem, function ($files) { $files->deleteDirectory(base_path('node_modules')); $files->delete(base_path('yarn.lock')); }); } } PKrZC<ss"Presets/react-stubs/vite.config.jsnuW+Aimport { defineConfig } from 'vite'; import laravel from 'laravel-vite-plugin'; import react from '@vitejs/plugin-react'; export default defineConfig({ plugins: [ laravel({ input: [ 'resources/sass/app.scss', 'resources/js/app.js', ], refresh: true, }), react(), ], }); PKrZBPresets/react-stubs/Example.jsxnuW+Aimport React from 'react'; import ReactDOM from 'react-dom/client'; function Example() { return (
Example Component
I'm an example component!
); } export default Example; if (document.getElementById('example')) { const Index = ReactDOM.createRoot(document.getElementById("example")); Index.render( ) } PKrZ sPresets/react-stubs/app.jsnuW+A/** * First we will load all of this project's JavaScript dependencies which * includes React and other helpers. It's a great starting point while * building robust, powerful web applications using React + Laravel. */ import './bootstrap'; /** * Next, we will create a fresh React component instance and attach it to * the page. Then, you may begin adding components to this application * or customize the JavaScript scaffolding to fit your unique needs. */ import './components/Example'; PKZ)%@@ HTML5/Serializer/OutputRules.phpnuW+A'http://www.w3.org/1999/xhtml', 'attrNamespace'=>'http://www.w3.org/1999/xhtml', 'nodeName'=>'img', 'nodeName'=>array('img', 'a'), 'attrName'=>'alt', 'attrName'=>array('title', 'alt'), ), */ array( 'nodeNamespace' => 'http://www.w3.org/1999/xhtml', 'attrName' => array('href', 'hreflang', 'http-equiv', 'icon', 'id', 'keytype', 'kind', 'label', 'lang', 'language', 'list', 'maxlength', 'media', 'method', 'name', 'placeholder', 'rel', 'rows', 'rowspan', 'sandbox', 'spellcheck', 'scope', 'seamless', 'shape', 'size', 'sizes', 'span', 'src', 'srcdoc', 'srclang', 'srcset', 'start', 'step', 'style', 'summary', 'tabindex', 'target', 'title', 'type', 'value', 'width', 'border', 'charset', 'cite', 'class', 'code', 'codebase', 'color', 'cols', 'colspan', 'content', 'coords', 'data', 'datetime', 'default', 'dir', 'dirname', 'enctype', 'for', 'form', 'formaction', 'headers', 'height', 'accept', 'accept-charset', 'accesskey', 'action', 'align', 'alt', 'bgcolor', ), ), array( 'nodeNamespace' => 'http://www.w3.org/1999/xhtml', 'xpath' => 'starts-with(local-name(), \'data-\')', ), ); const DOCTYPE = ''; public function __construct($output, $options = array()) { if (isset($options['encode_entities'])) { $this->encode = $options['encode_entities']; } $this->outputMode = static::IM_IN_HTML; $this->out = $output; $this->hasHTML5 = defined('ENT_HTML5'); } public function addRule(array $rule) { $this->nonBooleanAttributes[] = $rule; } public function setTraverser(Traverser $traverser) { $this->traverser = $traverser; return $this; } public function unsetTraverser() { $this->traverser = null; return $this; } public function document($dom) { $this->doctype(); if ($dom->documentElement) { foreach ($dom->childNodes as $node) { $this->traverser->node($node); } $this->nl(); } } protected function doctype() { $this->wr(static::DOCTYPE); $this->nl(); } public function element($ele) { $name = $ele->tagName; // Per spec: // If the element has a declared namespace in the HTML, MathML or // SVG namespaces, we use the lname instead of the tagName. if ($this->traverser->isLocalElement($ele)) { $name = $ele->localName; } // If we are in SVG or MathML there is special handling. // Using if/elseif instead of switch because it's faster in PHP. if ('svg' == $name) { $this->outputMode = static::IM_IN_SVG; $name = Elements::normalizeSvgElement($name); } elseif ('math' == $name) { $this->outputMode = static::IM_IN_MATHML; } $this->openTag($ele); if (Elements::isA($name, Elements::TEXT_RAW)) { foreach ($ele->childNodes as $child) { if ($child instanceof \DOMCharacterData) { $this->wr($child->data); } elseif ($child instanceof \DOMElement) { $this->element($child); } } } else { // Handle children. if ($ele->hasChildNodes()) { $this->traverser->children($ele->childNodes); } // Close out the SVG or MathML special handling. if ('svg' == $name || 'math' == $name) { $this->outputMode = static::IM_IN_HTML; } } // If not unary, add a closing tag. if (!Elements::isA($name, Elements::VOID_TAG)) { $this->closeTag($ele); } } /** * Write a text node. * * @param \DOMText $ele The text node to write. */ public function text($ele) { if (isset($ele->parentNode) && isset($ele->parentNode->tagName) && Elements::isA($ele->parentNode->localName, Elements::TEXT_RAW)) { $this->wr($ele->data); return; } // FIXME: This probably needs some flags set. $this->wr($this->enc($ele->data)); } public function cdata($ele) { // This encodes CDATA. $this->wr($ele->ownerDocument->saveXML($ele)); } public function comment($ele) { // These produce identical output. // $this->wr(''); $this->wr($ele->ownerDocument->saveXML($ele)); } public function processorInstruction($ele) { $this->wr('wr($ele->target) ->wr(' ') ->wr($ele->data) ->wr('?>'); } /** * Write the namespace attributes. * * @param \DOMNode $ele The element being written. */ protected function namespaceAttrs($ele) { if (!$this->xpath || $this->xpath->document !== $ele->ownerDocument) { $this->xpath = new \DOMXPath($ele->ownerDocument); } foreach ($this->xpath->query('namespace::*[not(.=../../namespace::*)]', $ele) as $nsNode) { if (!in_array($nsNode->nodeValue, $this->implicitNamespaces)) { $this->wr(' ')->wr($nsNode->nodeName)->wr('="')->wr($nsNode->nodeValue)->wr('"'); } } } /** * Write the opening tag. * * Tags for HTML, MathML, and SVG are in the local name. Otherwise, use the * qualified name (8.3). * * @param \DOMNode $ele The element being written. */ protected function openTag($ele) { $this->wr('<')->wr($this->traverser->isLocalElement($ele) ? $ele->localName : $ele->tagName); $this->attrs($ele); $this->namespaceAttrs($ele); if ($this->outputMode == static::IM_IN_HTML) { $this->wr('>'); } // If we are not in html mode we are in SVG, MathML, or XML embedded content. else { if ($ele->hasChildNodes()) { $this->wr('>'); } // If there are no children this is self closing. else { $this->wr(' />'); } } } protected function attrs($ele) { // FIXME: Needs support for xml, xmlns, xlink, and namespaced elements. if (!$ele->hasAttributes()) { return $this; } // TODO: Currently, this always writes name="value", and does not do // value-less attributes. $map = $ele->attributes; $len = $map->length; for ($i = 0; $i < $len; ++$i) { $node = $map->item($i); $val = $this->enc($node->value, true); // XXX: The spec says that we need to ensure that anything in // the XML, XMLNS, or XLink NS's should use the canonical // prefix. It seems that DOM does this for us already, but there // may be exceptions. $name = $node->nodeName; // Special handling for attributes in SVG and MathML. // Using if/elseif instead of switch because it's faster in PHP. if ($this->outputMode == static::IM_IN_SVG) { $name = Elements::normalizeSvgAttribute($name); } elseif ($this->outputMode == static::IM_IN_MATHML) { $name = Elements::normalizeMathMlAttribute($name); } $this->wr(' ')->wr($name); if ((isset($val) && '' !== $val) || $this->nonBooleanAttribute($node)) { $this->wr('="')->wr($val)->wr('"'); } } } protected function nonBooleanAttribute(\DOMAttr $attr) { $ele = $attr->ownerElement; foreach ($this->nonBooleanAttributes as $rule) { if (isset($rule['nodeNamespace']) && $rule['nodeNamespace'] !== $ele->namespaceURI) { continue; } if (isset($rule['attNamespace']) && $rule['attNamespace'] !== $attr->namespaceURI) { continue; } if (isset($rule['nodeName']) && !is_array($rule['nodeName']) && $rule['nodeName'] !== $ele->localName) { continue; } if (isset($rule['nodeName']) && is_array($rule['nodeName']) && !in_array($ele->localName, $rule['nodeName'], true)) { continue; } if (isset($rule['attrName']) && !is_array($rule['attrName']) && $rule['attrName'] !== $attr->localName) { continue; } if (isset($rule['attrName']) && is_array($rule['attrName']) && !in_array($attr->localName, $rule['attrName'], true)) { continue; } if (isset($rule['xpath'])) { $xp = $this->getXPath($attr); if (isset($rule['prefixes'])) { foreach ($rule['prefixes'] as $nsPrefix => $ns) { $xp->registerNamespace($nsPrefix, $ns); } } if (!$xp->evaluate($rule['xpath'], $attr)) { continue; } } return true; } return false; } private function getXPath(\DOMNode $node) { if (!$this->xpath) { $this->xpath = new \DOMXPath($node->ownerDocument); } return $this->xpath; } /** * Write the closing tag. * * Tags for HTML, MathML, and SVG are in the local name. Otherwise, use the * qualified name (8.3). * * @param \DOMNode $ele The element being written. */ protected function closeTag($ele) { if ($this->outputMode == static::IM_IN_HTML || $ele->hasChildNodes()) { $this->wr('wr($this->traverser->isLocalElement($ele) ? $ele->localName : $ele->tagName)->wr('>'); } } /** * Write to the output. * * @param string $text The string to put into the output * * @return $this */ protected function wr($text) { fwrite($this->out, $text); return $this; } /** * Write a new line character. * * @return $this */ protected function nl() { fwrite($this->out, PHP_EOL); return $this; } /** * Encode text. * * When encode is set to false, the default value, the text passed in is * escaped per section 8.3 of the html5 spec. For details on how text is * escaped see the escape() method. * * When encoding is set to true the text is converted to named character * references where appropriate. Section 8.1.4 Character references of the * html5 spec refers to using named character references. This is useful for * characters that can't otherwise legally be used in the text. * * The named character references are listed in section 8.5. * * @see http://www.w3.org/TR/2013/CR-html5-20130806/syntax.html#named-character-references True encoding will turn all named character references into their entities. * This includes such characters as +.# and many other common ones. By default * encoding here will just escape &'<>". * * Note, PHP 5.4+ has better html5 encoding. * * @todo Use the Entities class in php 5.3 to have html5 entities. * * @param string $text Text to encode. * @param bool $attribute True if we are encoding an attrubute, false otherwise. * * @return string The encoded text. */ protected function enc($text, $attribute = false) { // Escape the text rather than convert to named character references. if (!$this->encode) { return $this->escape($text, $attribute); } // If we are in PHP 5.4+ we can use the native html5 entity functionality to // convert the named character references. if ($this->hasHTML5) { return htmlentities($text, ENT_HTML5 | ENT_SUBSTITUTE | ENT_QUOTES, 'UTF-8', false); } // If a version earlier than 5.4 html5 entities are not entirely handled. // This manually handles them. else { return strtr($text, HTML5Entities::$map); } } /** * Escape test. * * According to the html5 spec section 8.3 Serializing HTML fragments, text * within tags that are not style, script, xmp, iframe, noembed, and noframes * need to be properly escaped. * * The & should be converted to &, no breaking space unicode characters * converted to  , when in attribute mode the " should be converted to * ", and when not in attribute mode the < and > should be converted to * < and >. * * @see http://www.w3.org/TR/2013/CR-html5-20130806/syntax.html#escapingString * * @param string $text Text to escape. * @param bool $attribute True if we are escaping an attrubute, false otherwise. */ protected function escape($text, $attribute = false) { // Not using htmlspecialchars because, while it does escaping, it doesn't // match the requirements of section 8.5. For example, it doesn't handle // non-breaking spaces. if ($attribute) { $replace = array( '"' => '"', '&' => '&', "\xc2\xa0" => ' ', ); } else { $replace = array( '<' => '<', '>' => '>', '&' => '&', "\xc2\xa0" => ' ', ); } return strtr($text, $replace); } } PKZlEHTML5/Serializer/Traverser.phpnuW+A 'html', 'http://www.w3.org/1998/Math/MathML' => 'math', 'http://www.w3.org/2000/svg' => 'svg', ); protected $dom; protected $options; protected $encode = false; protected $rules; protected $out; /** * Create a traverser. * * @param \DOMNode|\DOMNodeList $dom The document or node to traverse. * @param resource $out A stream that allows writing. The traverser will output into this * stream. * @param array $options An array of options for the traverser as key/value pairs. These include: * - encode_entities: A bool to specify if full encding should happen for all named * charachter references. Defaults to false which escapes &'<>". * - output_rules: The path to the class handling the output rules. */ public function __construct($dom, $out, RulesInterface $rules, $options = array()) { $this->dom = $dom; $this->out = $out; $this->rules = $rules; $this->options = $options; $this->rules->setTraverser($this); } /** * Tell the traverser to walk the DOM. * * @return resource $out Returns the output stream. */ public function walk() { if ($this->dom instanceof \DOMDocument) { $this->rules->document($this->dom); } elseif ($this->dom instanceof \DOMDocumentFragment) { // Document fragments are a special case. Only the children need to // be serialized. if ($this->dom->hasChildNodes()) { $this->children($this->dom->childNodes); } } // If NodeList, loop elseif ($this->dom instanceof \DOMNodeList) { // If this is a NodeList of DOMDocuments this will not work. $this->children($this->dom); } // Else assume this is a DOMNode-like datastructure. else { $this->node($this->dom); } return $this->out; } /** * Process a node in the DOM. * * @param mixed $node A node implementing \DOMNode. */ public function node($node) { // A listing of types is at http://php.net/manual/en/dom.constants.php switch ($node->nodeType) { case XML_ELEMENT_NODE: $this->rules->element($node); break; case XML_TEXT_NODE: $this->rules->text($node); break; case XML_CDATA_SECTION_NODE: $this->rules->cdata($node); break; case XML_PI_NODE: $this->rules->processorInstruction($node); break; case XML_COMMENT_NODE: $this->rules->comment($node); break; // Currently we don't support embedding DTDs. default: //print ''; break; } } /** * Walk through all the nodes on a node list. * * @param \DOMNodeList $nl A list of child elements to walk through. */ public function children($nl) { foreach ($nl as $node) { $this->node($node); } } /** * Is an element local? * * @param mixed $ele An element that implement \DOMNode. * * @return bool true if local and false otherwise. */ public function isLocalElement($ele) { $uri = $ele->namespaceURI; if (empty($uri)) { return false; } return isset(static::$local_ns[$uri]); } } PKZ n"HTML5/Serializer/HTML5Entities.phpnuW+A ' ', "\n" => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => ''', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '.' => '.', '/' => '/', ':' => ':', ';' => ';', '<' => '<', '<⃒' => '&nvlt', '=' => '=', '=⃥' => '&bne', '>' => '>', '>⃒' => '&nvgt', '?' => '?', '@' => '@', '[' => '[', '\\' => '\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'fj' => '&fjlig', '{' => '{', '|' => '|', '}' => '}', ' ' => ' ', '¡' => '¡', '¢' => '¢', '£' => '£', '¤' => '¤', '¥' => '¥', '¦' => '¦', '§' => '§', '¨' => '¨', '©' => '©', 'ª' => 'ª', '«' => '«', '¬' => '¬', '­' => '­', '®' => '®', '¯' => '¯', '°' => '°', '±' => '±', '²' => '²', '³' => '³', '´' => '´', 'µ' => 'µ', '¶' => '¶', '·' => '·', '¸' => '¸', '¹' => '¹', 'º' => 'º', '»' => '»', '¼' => '¼', '½' => '½', '¾' => '¾', '¿' => '¿', 'À' => 'À', 'Á' => 'Á', 'Â' => 'Â', 'Ã' => 'Ã', 'Ä' => 'Ä', 'Å' => 'Å', 'Æ' => 'Æ', 'Ç' => 'Ç', 'È' => 'È', 'É' => 'É', 'Ê' => 'Ê', 'Ë' => 'Ë', 'Ì' => 'Ì', 'Í' => 'Í', 'Î' => 'Î', 'Ï' => 'Ï', 'Ð' => 'Ð', 'Ñ' => 'Ñ', 'Ò' => 'Ò', 'Ó' => 'Ó', 'Ô' => 'Ô', 'Õ' => 'Õ', 'Ö' => 'Ö', '×' => '×', 'Ø' => 'Ø', 'Ù' => 'Ù', 'Ú' => 'Ú', 'Û' => 'Û', 'Ü' => 'Ü', 'Ý' => 'Ý', 'Þ' => 'Þ', 'ß' => 'ß', 'à' => 'à', 'á' => 'á', 'â' => 'â', 'ã' => 'ã', 'ä' => 'ä', 'å' => 'å', 'æ' => 'æ', 'ç' => 'ç', 'è' => 'è', 'é' => 'é', 'ê' => 'ê', 'ë' => 'ë', 'ì' => 'ì', 'í' => 'í', 'î' => 'î', 'ï' => 'ï', 'ð' => 'ð', 'ñ' => 'ñ', 'ò' => 'ò', 'ó' => 'ó', 'ô' => 'ô', 'õ' => 'õ', 'ö' => 'ö', '÷' => '÷', 'ø' => 'ø', 'ù' => 'ù', 'ú' => 'ú', 'û' => 'û', 'ü' => 'ü', 'ý' => 'ý', 'þ' => 'þ', 'ÿ' => 'ÿ', 'Ā' => 'Ā', 'ā' => 'ā', 'Ă' => 'Ă', 'ă' => 'ă', 'Ą' => 'Ą', 'ą' => 'ą', 'Ć' => 'Ć', 'ć' => 'ć', 'Ĉ' => 'Ĉ', 'ĉ' => 'ĉ', 'Ċ' => 'Ċ', 'ċ' => 'ċ', 'Č' => 'Č', 'č' => 'č', 'Ď' => 'Ď', 'ď' => 'ď', 'Đ' => 'Đ', 'đ' => 'đ', 'Ē' => 'Ē', 'ē' => 'ē', 'Ė' => 'Ė', 'ė' => 'ė', 'Ę' => 'Ę', 'ę' => 'ę', 'Ě' => 'Ě', 'ě' => 'ě', 'Ĝ' => 'Ĝ', 'ĝ' => 'ĝ', 'Ğ' => 'Ğ', 'ğ' => 'ğ', 'Ġ' => 'Ġ', 'ġ' => 'ġ', 'Ģ' => 'Ģ', 'Ĥ' => 'Ĥ', 'ĥ' => 'ĥ', 'Ħ' => 'Ħ', 'ħ' => 'ħ', 'Ĩ' => 'Ĩ', 'ĩ' => 'ĩ', 'Ī' => 'Ī', 'ī' => 'ī', 'Į' => 'Į', 'į' => 'į', 'İ' => 'İ', 'ı' => 'ı', 'IJ' => 'IJ', 'ij' => 'ij', 'Ĵ' => 'Ĵ', 'ĵ' => 'ĵ', 'Ķ' => 'Ķ', 'ķ' => 'ķ', 'ĸ' => 'ĸ', 'Ĺ' => 'Ĺ', 'ĺ' => 'ĺ', 'Ļ' => 'Ļ', 'ļ' => 'ļ', 'Ľ' => 'Ľ', 'ľ' => 'ľ', 'Ŀ' => 'Ŀ', 'ŀ' => 'ŀ', 'Ł' => 'Ł', 'ł' => 'ł', 'Ń' => 'Ń', 'ń' => 'ń', 'Ņ' => 'Ņ', 'ņ' => 'ņ', 'Ň' => 'Ň', 'ň' => 'ň', 'ʼn' => 'ʼn', 'Ŋ' => 'Ŋ', 'ŋ' => 'ŋ', 'Ō' => 'Ō', 'ō' => 'ō', 'Ő' => 'Ő', 'ő' => 'ő', 'Œ' => 'Œ', 'œ' => 'œ', 'Ŕ' => 'Ŕ', 'ŕ' => 'ŕ', 'Ŗ' => 'Ŗ', 'ŗ' => 'ŗ', 'Ř' => 'Ř', 'ř' => 'ř', 'Ś' => 'Ś', 'ś' => 'ś', 'Ŝ' => 'Ŝ', 'ŝ' => 'ŝ', 'Ş' => 'Ş', 'ş' => 'ş', 'Š' => 'Š', 'š' => 'š', 'Ţ' => 'Ţ', 'ţ' => 'ţ', 'Ť' => 'Ť', 'ť' => 'ť', 'Ŧ' => 'Ŧ', 'ŧ' => 'ŧ', 'Ũ' => 'Ũ', 'ũ' => 'ũ', 'Ū' => 'Ū', 'ū' => 'ū', 'Ŭ' => 'Ŭ', 'ŭ' => 'ŭ', 'Ů' => 'Ů', 'ů' => 'ů', 'Ű' => 'Ű', 'ű' => 'ű', 'Ų' => 'Ų', 'ų' => 'ų', 'Ŵ' => 'Ŵ', 'ŵ' => 'ŵ', 'Ŷ' => 'Ŷ', 'ŷ' => 'ŷ', 'Ÿ' => 'Ÿ', 'Ź' => 'Ź', 'ź' => 'ź', 'Ż' => 'Ż', 'ż' => 'ż', 'Ž' => 'Ž', 'ž' => 'ž', 'ƒ' => 'ƒ', 'Ƶ' => 'Ƶ', 'ǵ' => 'ǵ', 'ȷ' => 'ȷ', 'ˆ' => 'ˆ', 'ˇ' => 'ˇ', '˘' => '˘', '˙' => '˙', '˚' => '˚', '˛' => '˛', '˜' => '˜', '˝' => '˝', '̑' => '̑', 'Α' => 'Α', 'Β' => 'Β', 'Γ' => 'Γ', 'Δ' => 'Δ', 'Ε' => 'Ε', 'Ζ' => 'Ζ', 'Η' => 'Η', 'Θ' => 'Θ', 'Ι' => 'Ι', 'Κ' => 'Κ', 'Λ' => 'Λ', 'Μ' => 'Μ', 'Ν' => 'Ν', 'Ξ' => 'Ξ', 'Ο' => 'Ο', 'Π' => 'Π', 'Ρ' => 'Ρ', 'Σ' => 'Σ', 'Τ' => 'Τ', 'Υ' => 'Υ', 'Φ' => 'Φ', 'Χ' => 'Χ', 'Ψ' => 'Ψ', 'Ω' => 'Ω', 'α' => 'α', 'β' => 'β', 'γ' => 'γ', 'δ' => 'δ', 'ε' => 'ε', 'ζ' => 'ζ', 'η' => 'η', 'θ' => 'θ', 'ι' => 'ι', 'κ' => 'κ', 'λ' => 'λ', 'μ' => 'μ', 'ν' => 'ν', 'ξ' => 'ξ', 'ο' => 'ο', 'π' => 'π', 'ρ' => 'ρ', 'ς' => 'ς', 'σ' => 'σ', 'τ' => 'τ', 'υ' => 'υ', 'φ' => 'φ', 'χ' => 'χ', 'ψ' => 'ψ', 'ω' => 'ω', 'ϑ' => 'ϑ', 'ϒ' => 'ϒ', 'ϕ' => 'ϕ', 'ϖ' => 'ϖ', 'Ϝ' => 'Ϝ', 'ϝ' => 'ϝ', 'ϰ' => 'ϰ', 'ϱ' => 'ϱ', 'ϵ' => 'ϵ', '϶' => '϶', 'Ё' => 'Ё', 'Ђ' => 'Ђ', 'Ѓ' => 'Ѓ', 'Є' => 'Є', 'Ѕ' => 'Ѕ', 'І' => 'І', 'Ї' => 'Ї', 'Ј' => 'Ј', 'Љ' => 'Љ', 'Њ' => 'Њ', 'Ћ' => 'Ћ', 'Ќ' => 'Ќ', 'Ў' => 'Ў', 'Џ' => 'Џ', 'А' => 'А', 'Б' => 'Б', 'В' => 'В', 'Г' => 'Г', 'Д' => 'Д', 'Е' => 'Е', 'Ж' => 'Ж', 'З' => 'З', 'И' => 'И', 'Й' => 'Й', 'К' => 'К', 'Л' => 'Л', 'М' => 'М', 'Н' => 'Н', 'О' => 'О', 'П' => 'П', 'Р' => 'Р', 'С' => 'С', 'Т' => 'Т', 'У' => 'У', 'Ф' => 'Ф', 'Х' => 'Х', 'Ц' => 'Ц', 'Ч' => 'Ч', 'Ш' => 'Ш', 'Щ' => 'Щ', 'Ъ' => 'Ъ', 'Ы' => 'Ы', 'Ь' => 'Ь', 'Э' => 'Э', 'Ю' => 'Ю', 'Я' => 'Я', 'а' => 'а', 'б' => 'б', 'в' => 'в', 'г' => 'г', 'д' => 'д', 'е' => 'е', 'ж' => 'ж', 'з' => 'з', 'и' => 'и', 'й' => 'й', 'к' => 'к', 'л' => 'л', 'м' => 'м', 'н' => 'н', 'о' => 'о', 'п' => 'п', 'р' => 'р', 'с' => 'с', 'т' => 'т', 'у' => 'у', 'ф' => 'ф', 'х' => 'х', 'ц' => 'ц', 'ч' => 'ч', 'ш' => 'ш', 'щ' => 'щ', 'ъ' => 'ъ', 'ы' => 'ы', 'ь' => 'ь', 'э' => 'э', 'ю' => 'ю', 'я' => 'я', 'ё' => 'ё', 'ђ' => 'ђ', 'ѓ' => 'ѓ', 'є' => 'є', 'ѕ' => 'ѕ', 'і' => 'і', 'ї' => 'ї', 'ј' => 'ј', 'љ' => 'љ', 'њ' => 'њ', 'ћ' => 'ћ', 'ќ' => 'ќ', 'ў' => 'ў', 'џ' => 'џ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '​' => '​', '‌' => '‌', '‍' => '‍', '‎' => '‎', '‏' => '‏', '‐' => '‐', '–' => '–', '—' => '—', '―' => '―', '‖' => '‖', '‘' => '‘', '’' => '’', '‚' => '‚', '“' => '“', '”' => '”', '„' => '„', '†' => '†', '‡' => '‡', '•' => '•', '‥' => '‥', '…' => '…', '‰' => '‰', '‱' => '‱', '′' => '′', '″' => '″', '‴' => '‴', '‵' => '‵', '‹' => '‹', '›' => '›', '‾' => '‾', '⁁' => '⁁', '⁃' => '⁃', '⁄' => '⁄', '⁏' => '⁏', '⁗' => '⁗', ' ' => ' ', '  ' => '&ThickSpace', '⁠' => '⁠', '⁡' => '⁡', '⁢' => '⁢', '⁣' => '⁣', '€' => '€', '⃛' => '⃛', '⃜' => '⃜', 'ℂ' => 'ℂ', '℅' => '℅', 'ℊ' => 'ℊ', 'ℋ' => 'ℋ', 'ℌ' => 'ℌ', 'ℍ' => 'ℍ', 'ℎ' => 'ℎ', 'ℏ' => 'ℏ', 'ℐ' => 'ℐ', 'ℑ' => 'ℑ', 'ℒ' => 'ℒ', 'ℓ' => 'ℓ', 'ℕ' => 'ℕ', '№' => '№', '℗' => '℗', '℘' => '℘', 'ℙ' => 'ℙ', 'ℚ' => 'ℚ', 'ℛ' => 'ℛ', 'ℜ' => 'ℜ', 'ℝ' => 'ℝ', '℞' => '℞', '™' => '™', 'ℤ' => 'ℤ', '℧' => '℧', 'ℨ' => 'ℨ', '℩' => '℩', 'ℬ' => 'ℬ', 'ℭ' => 'ℭ', 'ℯ' => 'ℯ', 'ℰ' => 'ℰ', 'ℱ' => 'ℱ', 'ℳ' => 'ℳ', 'ℴ' => 'ℴ', 'ℵ' => 'ℵ', 'ℶ' => 'ℶ', 'ℷ' => 'ℷ', 'ℸ' => 'ℸ', 'ⅅ' => 'ⅅ', 'ⅆ' => 'ⅆ', 'ⅇ' => 'ⅇ', 'ⅈ' => 'ⅈ', '⅓' => '⅓', '⅔' => '⅔', '⅕' => '⅕', '⅖' => '⅖', '⅗' => '⅗', '⅘' => '⅘', '⅙' => '⅙', '⅚' => '⅚', '⅛' => '⅛', '⅜' => '⅜', '⅝' => '⅝', '⅞' => '⅞', '←' => '←', '↑' => '↑', '→' => '→', '↓' => '↓', '↔' => '↔', '↕' => '↕', '↖' => '↖', '↗' => '↗', '↘' => '↘', '↙' => '↙', '↚' => '↚', '↛' => '↛', '↝' => '↝', '↝̸' => '&nrarrw', '↞' => '↞', '↟' => '↟', '↠' => '↠', '↡' => '↡', '↢' => '↢', '↣' => '↣', '↤' => '↤', '↥' => '↥', '↦' => '↦', '↧' => '↧', '↩' => '↩', '↪' => '↪', '↫' => '↫', '↬' => '↬', '↭' => '↭', '↮' => '↮', '↰' => '↰', '↱' => '↱', '↲' => '↲', '↳' => '↳', '↵' => '↵', '↶' => '↶', '↷' => '↷', '↺' => '↺', '↻' => '↻', '↼' => '↼', '↽' => '↽', '↾' => '↾', '↿' => '↿', '⇀' => '⇀', '⇁' => '⇁', '⇂' => '⇂', '⇃' => '⇃', '⇄' => '⇄', '⇅' => '⇅', '⇆' => '⇆', '⇇' => '⇇', '⇈' => '⇈', '⇉' => '⇉', '⇊' => '⇊', '⇋' => '⇋', '⇌' => '⇌', '⇍' => '⇍', '⇎' => '⇎', '⇏' => '⇏', '⇐' => '⇐', '⇑' => '⇑', '⇒' => '⇒', '⇓' => '⇓', '⇔' => '⇔', '⇕' => '⇕', '⇖' => '⇖', '⇗' => '⇗', '⇘' => '⇘', '⇙' => '⇙', '⇚' => '⇚', '⇛' => '⇛', '⇝' => '⇝', '⇤' => '⇤', '⇥' => '⇥', '⇵' => '⇵', '⇽' => '⇽', '⇾' => '⇾', '⇿' => '⇿', '∀' => '∀', '∁' => '∁', '∂' => '∂', '∂̸' => '&npart', '∃' => '∃', '∄' => '∄', '∅' => '∅', '∇' => '∇', '∈' => '∈', '∉' => '∉', '∋' => '∋', '∌' => '∌', '∏' => '∏', '∐' => '∐', '∑' => '∑', '−' => '−', '∓' => '∓', '∔' => '∔', '∖' => '∖', '∗' => '∗', '∘' => '∘', '√' => '√', '∝' => '∝', '∞' => '∞', '∟' => '∟', '∠' => '∠', '∠⃒' => '&nang', '∡' => '∡', '∢' => '∢', '∣' => '∣', '∤' => '∤', '∥' => '∥', '∦' => '∦', '∧' => '∧', '∨' => '∨', '∩' => '∩', '∩︀' => '&caps', '∪' => '∪', '∪︀' => '&cups', '∫' => '∫', '∬' => '∬', '∭' => '∭', '∮' => '∮', '∯' => '∯', '∰' => '∰', '∱' => '∱', '∲' => '∲', '∳' => '∳', '∴' => '∴', '∵' => '∵', '∶' => '∶', '∷' => '∷', '∸' => '∸', '∺' => '∺', '∻' => '∻', '∼' => '∼', '∼⃒' => '&nvsim', '∽' => '∽', '∽̱' => '&race', '∾' => '∾', '∾̳' => '&acE', '∿' => '∿', '≀' => '≀', '≁' => '≁', '≂' => '≂', '≂̸' => '&nesim', '≃' => '≃', '≄' => '≄', '≅' => '≅', '≆' => '≆', '≇' => '≇', '≈' => '≈', '≉' => '≉', '≊' => '≊', '≋' => '≋', '≋̸' => '&napid', '≌' => '≌', '≍' => '≍', '≍⃒' => '&nvap', '≎' => '≎', '≎̸' => '&nbump', '≏' => '≏', '≏̸' => '&nbumpe', '≐' => '≐', '≐̸' => '&nedot', '≑' => '≑', '≒' => '≒', '≓' => '≓', '≔' => '≔', '≕' => '≕', '≖' => '≖', '≗' => '≗', '≙' => '≙', '≚' => '≚', '≜' => '≜', '≟' => '≟', '≠' => '≠', '≡' => '≡', '≡⃥' => '&bnequiv', '≢' => '≢', '≤' => '≤', '≤⃒' => '&nvle', '≥' => '≥', '≥⃒' => '&nvge', '≦' => '≦', '≦̸' => '&nlE', '≧' => '≧', '≧̸' => '&NotGreaterFullEqual', '≨' => '≨', '≨︀' => '&lvertneqq', '≩' => '≩', '≩︀' => '&gvertneqq', '≪' => '≪', '≪̸' => '&nLtv', '≪⃒' => '&nLt', '≫' => '≫', '≫̸' => '&NotGreaterGreater', '≫⃒' => '&nGt', '≬' => '≬', '≭' => '≭', '≮' => '≮', '≯' => '≯', '≰' => '≰', '≱' => '≱', '≲' => '≲', '≳' => '≳', '≴' => '≴', '≵' => '≵', '≶' => '≶', '≷' => '≷', '≸' => '≸', '≹' => '≹', '≺' => '≺', '≻' => '≻', '≼' => '≼', '≽' => '≽', '≾' => '≾', '≿' => '≿', '≿̸' => '&NotSucceedsTilde', '⊀' => '⊀', '⊁' => '⊁', '⊂' => '⊂', '⊂⃒' => '&vnsub', '⊃' => '⊃', '⊃⃒' => '&nsupset', '⊄' => '⊄', '⊅' => '⊅', '⊆' => '⊆', '⊇' => '⊇', '⊈' => '⊈', '⊉' => '⊉', '⊊' => '⊊', '⊊︀' => '&vsubne', '⊋' => '⊋', '⊋︀' => '&vsupne', '⊍' => '⊍', '⊎' => '⊎', '⊏' => '⊏', '⊏̸' => '&NotSquareSubset', '⊐' => '⊐', '⊐̸' => '&NotSquareSuperset', '⊑' => '⊑', '⊒' => '⊒', '⊓' => '⊓', '⊓︀' => '&sqcaps', '⊔' => '⊔', '⊔︀' => '&sqcups', '⊕' => '⊕', '⊖' => '⊖', '⊗' => '⊗', '⊘' => '⊘', '⊙' => '⊙', '⊚' => '⊚', '⊛' => '⊛', '⊝' => '⊝', '⊞' => '⊞', '⊟' => '⊟', '⊠' => '⊠', '⊡' => '⊡', '⊢' => '⊢', '⊣' => '⊣', '⊤' => '⊤', '⊥' => '⊥', '⊧' => '⊧', '⊨' => '⊨', '⊩' => '⊩', '⊪' => '⊪', '⊫' => '⊫', '⊬' => '⊬', '⊭' => '⊭', '⊮' => '⊮', '⊯' => '⊯', '⊰' => '⊰', '⊲' => '⊲', '⊳' => '⊳', '⊴' => '⊴', '⊴⃒' => '&nvltrie', '⊵' => '⊵', '⊵⃒' => '&nvrtrie', '⊶' => '⊶', '⊷' => '⊷', '⊸' => '⊸', '⊹' => '⊹', '⊺' => '⊺', '⊻' => '⊻', '⊽' => '⊽', '⊾' => '⊾', '⊿' => '⊿', '⋀' => '⋀', '⋁' => '⋁', '⋂' => '⋂', '⋃' => '⋃', '⋄' => '⋄', '⋅' => '⋅', '⋆' => '⋆', '⋇' => '⋇', '⋈' => '⋈', '⋉' => '⋉', '⋊' => '⋊', '⋋' => '⋋', '⋌' => '⋌', '⋍' => '⋍', '⋎' => '⋎', '⋏' => '⋏', '⋐' => '⋐', '⋑' => '⋑', '⋒' => '⋒', '⋓' => '⋓', '⋔' => '⋔', '⋕' => '⋕', '⋖' => '⋖', '⋗' => '⋗', '⋘' => '⋘', '⋘̸' => '&nLl', '⋙' => '⋙', '⋙̸' => '&nGg', '⋚' => '⋚', '⋚︀' => '&lesg', '⋛' => '⋛', '⋛︀' => '&gesl', '⋞' => '⋞', '⋟' => '⋟', '⋠' => '⋠', '⋡' => '⋡', '⋢' => '⋢', '⋣' => '⋣', '⋦' => '⋦', '⋧' => '⋧', '⋨' => '⋨', '⋩' => '⋩', '⋪' => '⋪', '⋫' => '⋫', '⋬' => '⋬', '⋭' => '⋭', '⋮' => '⋮', '⋯' => '⋯', '⋰' => '⋰', '⋱' => '⋱', '⋲' => '⋲', '⋳' => '⋳', '⋴' => '⋴', '⋵' => '⋵', '⋵̸' => '¬indot', '⋶' => '⋶', '⋷' => '⋷', '⋹' => '⋹', '⋹̸' => '¬inE', '⋺' => '⋺', '⋻' => '⋻', '⋼' => '⋼', '⋽' => '⋽', '⋾' => '⋾', '⌅' => '⌅', '⌆' => '⌆', '⌈' => '⌈', '⌉' => '⌉', '⌊' => '⌊', '⌋' => '⌋', '⌌' => '⌌', '⌍' => '⌍', '⌎' => '⌎', '⌏' => '⌏', '⌐' => '⌐', '⌒' => '⌒', '⌓' => '⌓', '⌕' => '⌕', '⌖' => '⌖', '⌜' => '⌜', '⌝' => '⌝', '⌞' => '⌞', '⌟' => '⌟', '⌢' => '⌢', '⌣' => '⌣', '⌭' => '⌭', '⌮' => '⌮', '⌶' => '⌶', '⌽' => '⌽', '⌿' => '⌿', '⍼' => '⍼', '⎰' => '⎰', '⎱' => '⎱', '⎴' => '⎴', '⎵' => '⎵', '⎶' => '⎶', '⏜' => '⏜', '⏝' => '⏝', '⏞' => '⏞', '⏟' => '⏟', '⏢' => '⏢', '⏧' => '⏧', '␣' => '␣', 'Ⓢ' => 'Ⓢ', '─' => '─', '│' => '│', '┌' => '┌', '┐' => '┐', '└' => '└', '┘' => '┘', '├' => '├', '┤' => '┤', '┬' => '┬', '┴' => '┴', '┼' => '┼', '═' => '═', '║' => '║', '╒' => '╒', '╓' => '╓', '╔' => '╔', '╕' => '╕', '╖' => '╖', '╗' => '╗', '╘' => '╘', '╙' => '╙', '╚' => '╚', '╛' => '╛', '╜' => '╜', '╝' => '╝', '╞' => '╞', '╟' => '╟', '╠' => '╠', '╡' => '╡', '╢' => '╢', '╣' => '╣', '╤' => '╤', '╥' => '╥', '╦' => '╦', '╧' => '╧', '╨' => '╨', '╩' => '╩', '╪' => '╪', '╫' => '╫', '╬' => '╬', '▀' => '▀', '▄' => '▄', '█' => '█', '░' => '░', '▒' => '▒', '▓' => '▓', '□' => '□', '▪' => '▪', '▫' => '▫', '▭' => '▭', '▮' => '▮', '▱' => '▱', '△' => '△', '▴' => '▴', '▵' => '▵', '▸' => '▸', '▹' => '▹', '▽' => '▽', '▾' => '▾', '▿' => '▿', '◂' => '◂', '◃' => '◃', '◊' => '◊', '○' => '○', '◬' => '◬', '◯' => '◯', '◸' => '◸', '◹' => '◹', '◺' => '◺', '◻' => '◻', '◼' => '◼', '★' => '★', '☆' => '☆', '☎' => '☎', '♀' => '♀', '♂' => '♂', '♠' => '♠', '♣' => '♣', '♥' => '♥', '♦' => '♦', '♪' => '♪', '♭' => '♭', '♮' => '♮', '♯' => '♯', '✓' => '✓', '✗' => '✗', '✠' => '✠', '✶' => '✶', '❘' => '❘', '❲' => '❲', '❳' => '❳', '⟈' => '⟈', '⟉' => '⟉', '⟦' => '⟦', '⟧' => '⟧', '⟨' => '⟨', '⟩' => '⟩', '⟪' => '⟪', '⟫' => '⟫', '⟬' => '⟬', '⟭' => '⟭', '⟵' => '⟵', '⟶' => '⟶', '⟷' => '⟷', '⟸' => '⟸', '⟹' => '⟹', '⟺' => '⟺', '⟼' => '⟼', '⟿' => '⟿', '⤂' => '⤂', '⤃' => '⤃', '⤄' => '⤄', '⤅' => '⤅', '⤌' => '⤌', '⤍' => '⤍', '⤎' => '⤎', '⤏' => '⤏', '⤐' => '⤐', '⤑' => '⤑', '⤒' => '⤒', '⤓' => '⤓', '⤖' => '⤖', '⤙' => '⤙', '⤚' => '⤚', '⤛' => '⤛', '⤜' => '⤜', '⤝' => '⤝', '⤞' => '⤞', '⤟' => '⤟', '⤠' => '⤠', '⤣' => '⤣', '⤤' => '⤤', '⤥' => '⤥', '⤦' => '⤦', '⤧' => '⤧', '⤨' => '⤨', '⤩' => '⤩', '⤪' => '⤪', '⤳' => '⤳', '⤳̸' => '&nrarrc', '⤵' => '⤵', '⤶' => '⤶', '⤷' => '⤷', '⤸' => '⤸', '⤹' => '⤹', '⤼' => '⤼', '⤽' => '⤽', '⥅' => '⥅', '⥈' => '⥈', '⥉' => '⥉', '⥊' => '⥊', '⥋' => '⥋', '⥎' => '⥎', '⥏' => '⥏', '⥐' => '⥐', '⥑' => '⥑', '⥒' => '⥒', '⥓' => '⥓', '⥔' => '⥔', '⥕' => '⥕', '⥖' => '⥖', '⥗' => '⥗', '⥘' => '⥘', '⥙' => '⥙', '⥚' => '⥚', '⥛' => '⥛', '⥜' => '⥜', '⥝' => '⥝', '⥞' => '⥞', '⥟' => '⥟', '⥠' => '⥠', '⥡' => '⥡', '⥢' => '⥢', '⥣' => '⥣', '⥤' => '⥤', '⥥' => '⥥', '⥦' => '⥦', '⥧' => '⥧', '⥨' => '⥨', '⥩' => '⥩', '⥪' => '⥪', '⥫' => '⥫', '⥬' => '⥬', '⥭' => '⥭', '⥮' => '⥮', '⥯' => '⥯', '⥰' => '⥰', '⥱' => '⥱', '⥲' => '⥲', '⥳' => '⥳', '⥴' => '⥴', '⥵' => '⥵', '⥶' => '⥶', '⥸' => '⥸', '⥹' => '⥹', '⥻' => '⥻', '⥼' => '⥼', '⥽' => '⥽', '⥾' => '⥾', '⥿' => '⥿', '⦅' => '⦅', '⦆' => '⦆', '⦋' => '⦋', '⦌' => '⦌', '⦍' => '⦍', '⦎' => '⦎', '⦏' => '⦏', '⦐' => '⦐', '⦑' => '⦑', '⦒' => '⦒', '⦓' => '⦓', '⦔' => '⦔', '⦕' => '⦕', '⦖' => '⦖', '⦚' => '⦚', '⦜' => '⦜', '⦝' => '⦝', '⦤' => '⦤', '⦥' => '⦥', '⦦' => '⦦', '⦧' => '⦧', '⦨' => '⦨', '⦩' => '⦩', '⦪' => '⦪', '⦫' => '⦫', '⦬' => '⦬', '⦭' => '⦭', '⦮' => '⦮', '⦯' => '⦯', '⦰' => '⦰', '⦱' => '⦱', '⦲' => '⦲', '⦳' => '⦳', '⦴' => '⦴', '⦵' => '⦵', '⦶' => '⦶', '⦷' => '⦷', '⦹' => '⦹', '⦻' => '⦻', '⦼' => '⦼', '⦾' => '⦾', '⦿' => '⦿', '⧀' => '⧀', '⧁' => '⧁', '⧂' => '⧂', '⧃' => '⧃', '⧄' => '⧄', '⧅' => '⧅', '⧉' => '⧉', '⧍' => '⧍', '⧎' => '⧎', '⧏' => '⧏', '⧏̸' => '&NotLeftTriangleBar', '⧐' => '⧐', '⧐̸' => '&NotRightTriangleBar', '⧜' => '⧜', '⧝' => '⧝', '⧞' => '⧞', '⧣' => '⧣', '⧤' => '⧤', '⧥' => '⧥', '⧫' => '⧫', '⧴' => '⧴', '⧶' => '⧶', '⨀' => '⨀', '⨁' => '⨁', '⨂' => '⨂', '⨄' => '⨄', '⨆' => '⨆', '⨌' => '⨌', '⨍' => '⨍', '⨐' => '⨐', '⨑' => '⨑', '⨒' => '⨒', '⨓' => '⨓', '⨔' => '⨔', '⨕' => '⨕', '⨖' => '⨖', '⨗' => '⨗', '⨢' => '⨢', '⨣' => '⨣', '⨤' => '⨤', '⨥' => '⨥', '⨦' => '⨦', '⨧' => '⨧', '⨩' => '⨩', '⨪' => '⨪', '⨭' => '⨭', '⨮' => '⨮', '⨯' => '⨯', '⨰' => '⨰', '⨱' => '⨱', '⨳' => '⨳', '⨴' => '⨴', '⨵' => '⨵', '⨶' => '⨶', '⨷' => '⨷', '⨸' => '⨸', '⨹' => '⨹', '⨺' => '⨺', '⨻' => '⨻', '⨼' => '⨼', '⨿' => '⨿', '⩀' => '⩀', '⩂' => '⩂', '⩃' => '⩃', '⩄' => '⩄', '⩅' => '⩅', '⩆' => '⩆', '⩇' => '⩇', '⩈' => '⩈', '⩉' => '⩉', '⩊' => '⩊', '⩋' => '⩋', '⩌' => '⩌', '⩍' => '⩍', '⩐' => '⩐', '⩓' => '⩓', '⩔' => '⩔', '⩕' => '⩕', '⩖' => '⩖', '⩗' => '⩗', '⩘' => '⩘', '⩚' => '⩚', '⩛' => '⩛', '⩜' => '⩜', '⩝' => '⩝', '⩟' => '⩟', '⩦' => '⩦', '⩪' => '⩪', '⩭' => '⩭', '⩭̸' => '&ncongdot', '⩮' => '⩮', '⩯' => '⩯', '⩰' => '⩰', '⩰̸' => '&napE', '⩱' => '⩱', '⩲' => '⩲', '⩳' => '⩳', '⩴' => '⩴', '⩵' => '⩵', '⩷' => '⩷', '⩸' => '⩸', '⩹' => '⩹', '⩺' => '⩺', '⩻' => '⩻', '⩼' => '⩼', '⩽' => '⩽', '⩽̸' => '&nles', '⩾' => '⩾', '⩾̸' => '&nges', '⩿' => '⩿', '⪀' => '⪀', '⪁' => '⪁', '⪂' => '⪂', '⪃' => '⪃', '⪄' => '⪄', '⪅' => '⪅', '⪆' => '⪆', '⪇' => '⪇', '⪈' => '⪈', '⪉' => '⪉', '⪊' => '⪊', '⪋' => '⪋', '⪌' => '⪌', '⪍' => '⪍', '⪎' => '⪎', '⪏' => '⪏', '⪐' => '⪐', '⪑' => '⪑', '⪒' => '⪒', '⪓' => '⪓', '⪔' => '⪔', '⪕' => '⪕', '⪖' => '⪖', '⪗' => '⪗', '⪘' => '⪘', '⪙' => '⪙', '⪚' => '⪚', '⪝' => '⪝', '⪞' => '⪞', '⪟' => '⪟', '⪠' => '⪠', '⪡' => '⪡', '⪡̸' => '&NotNestedLessLess', '⪢' => '⪢', '⪢̸' => '&NotNestedGreaterGreater', '⪤' => '⪤', '⪥' => '⪥', '⪦' => '⪦', '⪧' => '⪧', '⪨' => '⪨', '⪩' => '⪩', '⪪' => '⪪', '⪫' => '⪫', '⪬' => '⪬', '⪬︀' => '&smtes', '⪭' => '⪭', '⪭︀' => '&lates', '⪮' => '⪮', '⪯' => '⪯', '⪯̸' => '&NotPrecedesEqual', '⪰' => '⪰', '⪰̸' => '&NotSucceedsEqual', '⪳' => '⪳', '⪴' => '⪴', '⪵' => '⪵', '⪶' => '⪶', '⪷' => '⪷', '⪸' => '⪸', '⪹' => '⪹', '⪺' => '⪺', '⪻' => '⪻', '⪼' => '⪼', '⪽' => '⪽', '⪾' => '⪾', '⪿' => '⪿', '⫀' => '⫀', '⫁' => '⫁', '⫂' => '⫂', '⫃' => '⫃', '⫄' => '⫄', '⫅' => '⫅', '⫅̸' => '&nsubE', '⫆' => '⫆', '⫆̸' => '&nsupseteqq', '⫇' => '⫇', '⫈' => '⫈', '⫋' => '⫋', '⫋︀' => '&vsubnE', '⫌' => '⫌', '⫌︀' => '&varsupsetneqq', '⫏' => '⫏', '⫐' => '⫐', '⫑' => '⫑', '⫒' => '⫒', '⫓' => '⫓', '⫔' => '⫔', '⫕' => '⫕', '⫖' => '⫖', '⫗' => '⫗', '⫘' => '⫘', '⫙' => '⫙', '⫚' => '⫚', '⫛' => '⫛', '⫤' => '⫤', '⫦' => '⫦', '⫧' => '⫧', '⫨' => '⫨', '⫩' => '⫩', '⫫' => '⫫', '⫬' => '⫬', '⫭' => '⫭', '⫮' => '⫮', '⫯' => '⫯', '⫰' => '⫰', '⫱' => '⫱', '⫲' => '⫲', '⫳' => '⫳', '⫽︀' => '&varsupsetneqq', 'ff' => 'ff', 'fi' => 'fi', 'fl' => 'fl', 'ffi' => 'ffi', 'ffl' => 'ffl', '𝒜' => '𝒜', '𝒞' => '𝒞', '𝒟' => '𝒟', '𝒢' => '𝒢', '𝒥' => '𝒥', '𝒦' => '𝒦', '𝒩' => '𝒩', '𝒪' => '𝒪', '𝒫' => '𝒫', '𝒬' => '𝒬', '𝒮' => '𝒮', '𝒯' => '𝒯', '𝒰' => '𝒰', '𝒱' => '𝒱', '𝒲' => '𝒲', '𝒳' => '𝒳', '𝒴' => '𝒴', '𝒵' => '𝒵', '𝒶' => '𝒶', '𝒷' => '𝒷', '𝒸' => '𝒸', '𝒹' => '𝒹', '𝒻' => '𝒻', '𝒽' => '𝒽', '𝒾' => '𝒾', '𝒿' => '𝒿', '𝓀' => '𝓀', '𝓁' => '𝓁', '𝓂' => '𝓂', '𝓃' => '𝓃', '𝓅' => '𝓅', '𝓆' => '𝓆', '𝓇' => '𝓇', '𝓈' => '𝓈', '𝓉' => '𝓉', '𝓊' => '𝓊', '𝓋' => '𝓋', '𝓌' => '𝓌', '𝓍' => '𝓍', '𝓎' => '𝓎', '𝓏' => '𝓏', '𝔄' => '𝔄', '𝔅' => '𝔅', '𝔇' => '𝔇', '𝔈' => '𝔈', '𝔉' => '𝔉', '𝔊' => '𝔊', '𝔍' => '𝔍', '𝔎' => '𝔎', '𝔏' => '𝔏', '𝔐' => '𝔐', '𝔑' => '𝔑', '𝔒' => '𝔒', '𝔓' => '𝔓', '𝔔' => '𝔔', '𝔖' => '𝔖', '𝔗' => '𝔗', '𝔘' => '𝔘', '𝔙' => '𝔙', '𝔚' => '𝔚', '𝔛' => '𝔛', '𝔜' => '𝔜', '𝔞' => '𝔞', '𝔟' => '𝔟', '𝔠' => '𝔠', '𝔡' => '𝔡', '𝔢' => '𝔢', '𝔣' => '𝔣', '𝔤' => '𝔤', '𝔥' => '𝔥', '𝔦' => '𝔦', '𝔧' => '𝔧', '𝔨' => '𝔨', '𝔩' => '𝔩', '𝔪' => '𝔪', '𝔫' => '𝔫', '𝔬' => '𝔬', '𝔭' => '𝔭', '𝔮' => '𝔮', '𝔯' => '𝔯', '𝔰' => '𝔰', '𝔱' => '𝔱', '𝔲' => '𝔲', '𝔳' => '𝔳', '𝔴' => '𝔴', '𝔵' => '𝔵', '𝔶' => '𝔶', '𝔷' => '𝔷', '𝔸' => '𝔸', '𝔹' => '𝔹', '𝔻' => '𝔻', '𝔼' => '𝔼', '𝔽' => '𝔽', '𝔾' => '𝔾', '𝕀' => '𝕀', '𝕁' => '𝕁', '𝕂' => '𝕂', '𝕃' => '𝕃', '𝕄' => '𝕄', '𝕆' => '𝕆', '𝕊' => '𝕊', '𝕋' => '𝕋', '𝕌' => '𝕌', '𝕍' => '𝕍', '𝕎' => '𝕎', '𝕏' => '𝕏', '𝕐' => '𝕐', '𝕒' => '𝕒', '𝕓' => '𝕓', '𝕔' => '𝕔', '𝕕' => '𝕕', '𝕖' => '𝕖', '𝕗' => '𝕗', '𝕘' => '𝕘', '𝕙' => '𝕙', '𝕚' => '𝕚', '𝕛' => '𝕛', '𝕜' => '𝕜', '𝕝' => '𝕝', '𝕞' => '𝕞', '𝕟' => '𝕟', '𝕠' => '𝕠', '𝕡' => '𝕡', '𝕢' => '𝕢', '𝕣' => '𝕣', '𝕤' => '𝕤', '𝕥' => '𝕥', '𝕦' => '𝕦', '𝕧' => '𝕧', '𝕨' => '𝕨', '𝕩' => '𝕩', '𝕪' => '𝕪', '𝕫' => '𝕫', ); } PKZe%աHTML5/Serializer/README.mdnuW+A# The Serializer (Writer) Model The serializer roughly follows sections _8.1 Writing HTML documents_ and section _8.3 Serializing HTML fragments_ by converting DOMDocument, DOMDocumentFragment, and DOMNodeList into HTML5. [ HTML5 ] // Interface for saving. || [ Traverser ] // Walk the DOM || [ Rules ] // Convert DOM elements into strings. || [ HTML5 ] // HTML5 document or fragment in text. ## HTML5 Class Provides the top level interface for saving. ## The Traverser Walks the DOM finding each element and passing it off to the output rules to convert to HTML5. ## Output Rules The output rules are defined in the RulesInterface which can have multiple implementations. Currently, the OutputRules is the default implementation that converts a DOM as is into HTML5. ## HTML5 String The output of the process it HTML5 as a string or saved to a file.PKZ{7 7 #HTML5/Serializer/RulesInterface.phpnuW+A 'Á', 'Aacut' => 'Á', 'aacute' => 'á', 'aacut' => 'á', 'Abreve' => 'Ă', 'abreve' => 'ă', 'ac' => '∾', 'acd' => '∿', 'acE' => '∾̳', 'Acirc' => 'Â', 'Acir' => 'Â', 'acirc' => 'â', 'acir' => 'â', 'acute' => '´', 'acut' => '´', 'Acy' => 'А', 'acy' => 'а', 'AElig' => 'Æ', 'AEli' => 'Æ', 'aelig' => 'æ', 'aeli' => 'æ', 'af' => '⁡', 'Afr' => '𝔄', 'afr' => '𝔞', 'Agrave' => 'À', 'Agrav' => 'À', 'agrave' => 'à', 'agrav' => 'à', 'alefsym' => 'ℵ', 'aleph' => 'ℵ', 'Alpha' => 'Α', 'alpha' => 'α', 'Amacr' => 'Ā', 'amacr' => 'ā', 'amalg' => '⨿', 'AMP' => '&', 'AM' => '&', 'amp' => '&', 'am' => '&', 'And' => '⩓', 'and' => '∧', 'andand' => '⩕', 'andd' => '⩜', 'andslope' => '⩘', 'andv' => '⩚', 'ang' => '∠', 'ange' => '⦤', 'angle' => '∠', 'angmsd' => '∡', 'angmsdaa' => '⦨', 'angmsdab' => '⦩', 'angmsdac' => '⦪', 'angmsdad' => '⦫', 'angmsdae' => '⦬', 'angmsdaf' => '⦭', 'angmsdag' => '⦮', 'angmsdah' => '⦯', 'angrt' => '∟', 'angrtvb' => '⊾', 'angrtvbd' => '⦝', 'angsph' => '∢', 'angst' => 'Å', 'angzarr' => '⍼', 'Aogon' => 'Ą', 'aogon' => 'ą', 'Aopf' => '𝔸', 'aopf' => '𝕒', 'ap' => '≈', 'apacir' => '⩯', 'apE' => '⩰', 'ape' => '≊', 'apid' => '≋', 'apos' => '\'', 'ApplyFunction' => '⁡', 'approx' => '≈', 'approxeq' => '≊', 'Aring' => 'Å', 'Arin' => 'Å', 'aring' => 'å', 'arin' => 'å', 'Ascr' => '𝒜', 'ascr' => '𝒶', 'Assign' => '≔', 'ast' => '*', 'asymp' => '≈', 'asympeq' => '≍', 'Atilde' => 'Ã', 'Atild' => 'Ã', 'atilde' => 'ã', 'atild' => 'ã', 'Auml' => 'Ä', 'Aum' => 'Ä', 'auml' => 'ä', 'aum' => 'ä', 'awconint' => '∳', 'awint' => '⨑', 'backcong' => '≌', 'backepsilon' => '϶', 'backprime' => '‵', 'backsim' => '∽', 'backsimeq' => '⋍', 'Backslash' => '∖', 'Barv' => '⫧', 'barvee' => '⊽', 'Barwed' => '⌆', 'barwed' => '⌅', 'barwedge' => '⌅', 'bbrk' => '⎵', 'bbrktbrk' => '⎶', 'bcong' => '≌', 'Bcy' => 'Б', 'bcy' => 'б', 'bdquo' => '„', 'becaus' => '∵', 'Because' => '∵', 'because' => '∵', 'bemptyv' => '⦰', 'bepsi' => '϶', 'bernou' => 'ℬ', 'Bernoullis' => 'ℬ', 'Beta' => 'Β', 'beta' => 'β', 'beth' => 'ℶ', 'between' => '≬', 'Bfr' => '𝔅', 'bfr' => '𝔟', 'bigcap' => '⋂', 'bigcirc' => '◯', 'bigcup' => '⋃', 'bigodot' => '⨀', 'bigoplus' => '⨁', 'bigotimes' => '⨂', 'bigsqcup' => '⨆', 'bigstar' => '★', 'bigtriangledown' => '▽', 'bigtriangleup' => '△', 'biguplus' => '⨄', 'bigvee' => '⋁', 'bigwedge' => '⋀', 'bkarow' => '⤍', 'blacklozenge' => '⧫', 'blacksquare' => '▪', 'blacktriangle' => '▴', 'blacktriangledown' => '▾', 'blacktriangleleft' => '◂', 'blacktriangleright' => '▸', 'blank' => '␣', 'blk12' => '▒', 'blk14' => '░', 'blk34' => '▓', 'block' => '█', 'bne' => '=⃥', 'bnequiv' => '≡⃥', 'bNot' => '⫭', 'bnot' => '⌐', 'Bopf' => '𝔹', 'bopf' => '𝕓', 'bot' => '⊥', 'bottom' => '⊥', 'bowtie' => '⋈', 'boxbox' => '⧉', 'boxDL' => '╗', 'boxDl' => '╖', 'boxdL' => '╕', 'boxdl' => '┐', 'boxDR' => '╔', 'boxDr' => '╓', 'boxdR' => '╒', 'boxdr' => '┌', 'boxH' => '═', 'boxh' => '─', 'boxHD' => '╦', 'boxHd' => '╤', 'boxhD' => '╥', 'boxhd' => '┬', 'boxHU' => '╩', 'boxHu' => '╧', 'boxhU' => '╨', 'boxhu' => '┴', 'boxminus' => '⊟', 'boxplus' => '⊞', 'boxtimes' => '⊠', 'boxUL' => '╝', 'boxUl' => '╜', 'boxuL' => '╛', 'boxul' => '┘', 'boxUR' => '╚', 'boxUr' => '╙', 'boxuR' => '╘', 'boxur' => '└', 'boxV' => '║', 'boxv' => '│', 'boxVH' => '╬', 'boxVh' => '╫', 'boxvH' => '╪', 'boxvh' => '┼', 'boxVL' => '╣', 'boxVl' => '╢', 'boxvL' => '╡', 'boxvl' => '┤', 'boxVR' => '╠', 'boxVr' => '╟', 'boxvR' => '╞', 'boxvr' => '├', 'bprime' => '‵', 'Breve' => '˘', 'breve' => '˘', 'brvbar' => '¦', 'brvba' => '¦', 'Bscr' => 'ℬ', 'bscr' => '𝒷', 'bsemi' => '⁏', 'bsim' => '∽', 'bsime' => '⋍', 'bsol' => '\\', 'bsolb' => '⧅', 'bsolhsub' => '⟈', 'bull' => '•', 'bullet' => '•', 'bump' => '≎', 'bumpE' => '⪮', 'bumpe' => '≏', 'Bumpeq' => '≎', 'bumpeq' => '≏', 'Cacute' => 'Ć', 'cacute' => 'ć', 'Cap' => '⋒', 'cap' => '∩', 'capand' => '⩄', 'capbrcup' => '⩉', 'capcap' => '⩋', 'capcup' => '⩇', 'capdot' => '⩀', 'CapitalDifferentialD' => 'ⅅ', 'caps' => '∩︀', 'caret' => '⁁', 'caron' => 'ˇ', 'Cayleys' => 'ℭ', 'ccaps' => '⩍', 'Ccaron' => 'Č', 'ccaron' => 'č', 'Ccedil' => 'Ç', 'Ccedi' => 'Ç', 'ccedil' => 'ç', 'ccedi' => 'ç', 'Ccirc' => 'Ĉ', 'ccirc' => 'ĉ', 'Cconint' => '∰', 'ccups' => '⩌', 'ccupssm' => '⩐', 'Cdot' => 'Ċ', 'cdot' => 'ċ', 'cedil' => '¸', 'cedi' => '¸', 'Cedilla' => '¸', 'cemptyv' => '⦲', 'cent' => '¢', 'cen' => '¢', 'CenterDot' => '·', 'centerdot' => '·', 'Cfr' => 'ℭ', 'cfr' => '𝔠', 'CHcy' => 'Ч', 'chcy' => 'ч', 'check' => '✓', 'checkmark' => '✓', 'Chi' => 'Χ', 'chi' => 'χ', 'cir' => '○', 'circ' => 'ˆ', 'circeq' => '≗', 'circlearrowleft' => '↺', 'circlearrowright' => '↻', 'circledast' => '⊛', 'circledcirc' => '⊚', 'circleddash' => '⊝', 'CircleDot' => '⊙', 'circledR' => '®', 'circledS' => 'Ⓢ', 'CircleMinus' => '⊖', 'CirclePlus' => '⊕', 'CircleTimes' => '⊗', 'cirE' => '⧃', 'cire' => '≗', 'cirfnint' => '⨐', 'cirmid' => '⫯', 'cirscir' => '⧂', 'ClockwiseContourIntegral' => '∲', 'CloseCurlyDoubleQuote' => '”', 'CloseCurlyQuote' => '’', 'clubs' => '♣', 'clubsuit' => '♣', 'Colon' => '∷', 'colon' => ':', 'Colone' => '⩴', 'colone' => '≔', 'coloneq' => '≔', 'comma' => ',', 'commat' => '@', 'comp' => '∁', 'compfn' => '∘', 'complement' => '∁', 'complexes' => 'ℂ', 'cong' => '≅', 'congdot' => '⩭', 'Congruent' => '≡', 'Conint' => '∯', 'conint' => '∮', 'ContourIntegral' => '∮', 'Copf' => 'ℂ', 'copf' => '𝕔', 'coprod' => '∐', 'Coproduct' => '∐', 'COPY' => '©', 'COP' => '©', 'copy' => '©', 'cop' => '©', 'copysr' => '℗', 'CounterClockwiseContourIntegral' => '∳', 'crarr' => '↵', 'Cross' => '⨯', 'cross' => '✗', 'Cscr' => '𝒞', 'cscr' => '𝒸', 'csub' => '⫏', 'csube' => '⫑', 'csup' => '⫐', 'csupe' => '⫒', 'ctdot' => '⋯', 'cudarrl' => '⤸', 'cudarrr' => '⤵', 'cuepr' => '⋞', 'cuesc' => '⋟', 'cularr' => '↶', 'cularrp' => '⤽', 'Cup' => '⋓', 'cup' => '∪', 'cupbrcap' => '⩈', 'CupCap' => '≍', 'cupcap' => '⩆', 'cupcup' => '⩊', 'cupdot' => '⊍', 'cupor' => '⩅', 'cups' => '∪︀', 'curarr' => '↷', 'curarrm' => '⤼', 'curlyeqprec' => '⋞', 'curlyeqsucc' => '⋟', 'curlyvee' => '⋎', 'curlywedge' => '⋏', 'curren' => '¤', 'curre' => '¤', 'curvearrowleft' => '↶', 'curvearrowright' => '↷', 'cuvee' => '⋎', 'cuwed' => '⋏', 'cwconint' => '∲', 'cwint' => '∱', 'cylcty' => '⌭', 'Dagger' => '‡', 'dagger' => '†', 'daleth' => 'ℸ', 'Darr' => '↡', 'dArr' => '⇓', 'darr' => '↓', 'dash' => '‐', 'Dashv' => '⫤', 'dashv' => '⊣', 'dbkarow' => '⤏', 'dblac' => '˝', 'Dcaron' => 'Ď', 'dcaron' => 'ď', 'Dcy' => 'Д', 'dcy' => 'д', 'DD' => 'ⅅ', 'dd' => 'ⅆ', 'ddagger' => '‡', 'ddarr' => '⇊', 'DDotrahd' => '⤑', 'ddotseq' => '⩷', 'deg' => '°', 'de' => '°', 'Del' => '∇', 'Delta' => 'Δ', 'delta' => 'δ', 'demptyv' => '⦱', 'dfisht' => '⥿', 'Dfr' => '𝔇', 'dfr' => '𝔡', 'dHar' => '⥥', 'dharl' => '⇃', 'dharr' => '⇂', 'DiacriticalAcute' => '´', 'DiacriticalDot' => '˙', 'DiacriticalDoubleAcute' => '˝', 'DiacriticalGrave' => '`', 'DiacriticalTilde' => '˜', 'diam' => '⋄', 'Diamond' => '⋄', 'diamond' => '⋄', 'diamondsuit' => '♦', 'diams' => '♦', 'die' => '¨', 'DifferentialD' => 'ⅆ', 'digamma' => 'ϝ', 'disin' => '⋲', 'div' => '÷', 'divide' => '÷', 'divid' => '÷', 'divideontimes' => '⋇', 'divonx' => '⋇', 'DJcy' => 'Ђ', 'djcy' => 'ђ', 'dlcorn' => '⌞', 'dlcrop' => '⌍', 'dollar' => '$', 'Dopf' => '𝔻', 'dopf' => '𝕕', 'Dot' => '¨', 'dot' => '˙', 'DotDot' => '⃜', 'doteq' => '≐', 'doteqdot' => '≑', 'DotEqual' => '≐', 'dotminus' => '∸', 'dotplus' => '∔', 'dotsquare' => '⊡', 'doublebarwedge' => '⌆', 'DoubleContourIntegral' => '∯', 'DoubleDot' => '¨', 'DoubleDownArrow' => '⇓', 'DoubleLeftArrow' => '⇐', 'DoubleLeftRightArrow' => '⇔', 'DoubleLeftTee' => '⫤', 'DoubleLongLeftArrow' => '⟸', 'DoubleLongLeftRightArrow' => '⟺', 'DoubleLongRightArrow' => '⟹', 'DoubleRightArrow' => '⇒', 'DoubleRightTee' => '⊨', 'DoubleUpArrow' => '⇑', 'DoubleUpDownArrow' => '⇕', 'DoubleVerticalBar' => '∥', 'DownArrow' => '↓', 'Downarrow' => '⇓', 'downarrow' => '↓', 'DownArrowBar' => '⤓', 'DownArrowUpArrow' => '⇵', 'DownBreve' => '̑', 'downdownarrows' => '⇊', 'downharpoonleft' => '⇃', 'downharpoonright' => '⇂', 'DownLeftRightVector' => '⥐', 'DownLeftTeeVector' => '⥞', 'DownLeftVector' => '↽', 'DownLeftVectorBar' => '⥖', 'DownRightTeeVector' => '⥟', 'DownRightVector' => '⇁', 'DownRightVectorBar' => '⥗', 'DownTee' => '⊤', 'DownTeeArrow' => '↧', 'drbkarow' => '⤐', 'drcorn' => '⌟', 'drcrop' => '⌌', 'Dscr' => '𝒟', 'dscr' => '𝒹', 'DScy' => 'Ѕ', 'dscy' => 'ѕ', 'dsol' => '⧶', 'Dstrok' => 'Đ', 'dstrok' => 'đ', 'dtdot' => '⋱', 'dtri' => '▿', 'dtrif' => '▾', 'duarr' => '⇵', 'duhar' => '⥯', 'dwangle' => '⦦', 'DZcy' => 'Џ', 'dzcy' => 'џ', 'dzigrarr' => '⟿', 'Eacute' => 'É', 'Eacut' => 'É', 'eacute' => 'é', 'eacut' => 'é', 'easter' => '⩮', 'Ecaron' => 'Ě', 'ecaron' => 'ě', 'ecir' => 'ê', 'Ecirc' => 'Ê', 'Ecir' => 'Ê', 'ecirc' => 'ê', 'ecolon' => '≕', 'Ecy' => 'Э', 'ecy' => 'э', 'eDDot' => '⩷', 'Edot' => 'Ė', 'eDot' => '≑', 'edot' => 'ė', 'ee' => 'ⅇ', 'efDot' => '≒', 'Efr' => '𝔈', 'efr' => '𝔢', 'eg' => '⪚', 'Egrave' => 'È', 'Egrav' => 'È', 'egrave' => 'è', 'egrav' => 'è', 'egs' => '⪖', 'egsdot' => '⪘', 'el' => '⪙', 'Element' => '∈', 'elinters' => '⏧', 'ell' => 'ℓ', 'els' => '⪕', 'elsdot' => '⪗', 'Emacr' => 'Ē', 'emacr' => 'ē', 'empty' => '∅', 'emptyset' => '∅', 'EmptySmallSquare' => '◻', 'emptyv' => '∅', 'EmptyVerySmallSquare' => '▫', 'emsp' => ' ', 'emsp13' => ' ', 'emsp14' => ' ', 'ENG' => 'Ŋ', 'eng' => 'ŋ', 'ensp' => ' ', 'Eogon' => 'Ę', 'eogon' => 'ę', 'Eopf' => '𝔼', 'eopf' => '𝕖', 'epar' => '⋕', 'eparsl' => '⧣', 'eplus' => '⩱', 'epsi' => 'ε', 'Epsilon' => 'Ε', 'epsilon' => 'ε', 'epsiv' => 'ϵ', 'eqcirc' => '≖', 'eqcolon' => '≕', 'eqsim' => '≂', 'eqslantgtr' => '⪖', 'eqslantless' => '⪕', 'Equal' => '⩵', 'equals' => '=', 'EqualTilde' => '≂', 'equest' => '≟', 'Equilibrium' => '⇌', 'equiv' => '≡', 'equivDD' => '⩸', 'eqvparsl' => '⧥', 'erarr' => '⥱', 'erDot' => '≓', 'Escr' => 'ℰ', 'escr' => 'ℯ', 'esdot' => '≐', 'Esim' => '⩳', 'esim' => '≂', 'Eta' => 'Η', 'eta' => 'η', 'ETH' => 'Ð', 'ET' => 'Ð', 'eth' => 'ð', 'et' => 'ð', 'Euml' => 'Ë', 'Eum' => 'Ë', 'euml' => 'ë', 'eum' => 'ë', 'euro' => '€', 'excl' => '!', 'exist' => '∃', 'Exists' => '∃', 'expectation' => 'ℰ', 'ExponentialE' => 'ⅇ', 'exponentiale' => 'ⅇ', 'fallingdotseq' => '≒', 'Fcy' => 'Ф', 'fcy' => 'ф', 'female' => '♀', 'ffilig' => 'ffi', 'fflig' => 'ff', 'ffllig' => 'ffl', 'Ffr' => '𝔉', 'ffr' => '𝔣', 'filig' => 'fi', 'FilledSmallSquare' => '◼', 'FilledVerySmallSquare' => '▪', 'fjlig' => 'fj', 'flat' => '♭', 'fllig' => 'fl', 'fltns' => '▱', 'fnof' => 'ƒ', 'Fopf' => '𝔽', 'fopf' => '𝕗', 'ForAll' => '∀', 'forall' => '∀', 'fork' => '⋔', 'forkv' => '⫙', 'Fouriertrf' => 'ℱ', 'fpartint' => '⨍', 'frac12' => '½', 'frac1' => '¼', 'frac13' => '⅓', 'frac14' => '¼', 'frac15' => '⅕', 'frac16' => '⅙', 'frac18' => '⅛', 'frac23' => '⅔', 'frac25' => '⅖', 'frac34' => '¾', 'frac3' => '¾', 'frac35' => '⅗', 'frac38' => '⅜', 'frac45' => '⅘', 'frac56' => '⅚', 'frac58' => '⅝', 'frac78' => '⅞', 'frasl' => '⁄', 'frown' => '⌢', 'Fscr' => 'ℱ', 'fscr' => '𝒻', 'gacute' => 'ǵ', 'Gamma' => 'Γ', 'gamma' => 'γ', 'Gammad' => 'Ϝ', 'gammad' => 'ϝ', 'gap' => '⪆', 'Gbreve' => 'Ğ', 'gbreve' => 'ğ', 'Gcedil' => 'Ģ', 'Gcirc' => 'Ĝ', 'gcirc' => 'ĝ', 'Gcy' => 'Г', 'gcy' => 'г', 'Gdot' => 'Ġ', 'gdot' => 'ġ', 'gE' => '≧', 'ge' => '≥', 'gEl' => '⪌', 'gel' => '⋛', 'geq' => '≥', 'geqq' => '≧', 'geqslant' => '⩾', 'ges' => '⩾', 'gescc' => '⪩', 'gesdot' => '⪀', 'gesdoto' => '⪂', 'gesdotol' => '⪄', 'gesl' => '⋛︀', 'gesles' => '⪔', 'Gfr' => '𝔊', 'gfr' => '𝔤', 'Gg' => '⋙', 'gg' => '≫', 'ggg' => '⋙', 'gimel' => 'ℷ', 'GJcy' => 'Ѓ', 'gjcy' => 'ѓ', 'gl' => '≷', 'gla' => '⪥', 'glE' => '⪒', 'glj' => '⪤', 'gnap' => '⪊', 'gnapprox' => '⪊', 'gnE' => '≩', 'gne' => '⪈', 'gneq' => '⪈', 'gneqq' => '≩', 'gnsim' => '⋧', 'Gopf' => '𝔾', 'gopf' => '𝕘', 'grave' => '`', 'GreaterEqual' => '≥', 'GreaterEqualLess' => '⋛', 'GreaterFullEqual' => '≧', 'GreaterGreater' => '⪢', 'GreaterLess' => '≷', 'GreaterSlantEqual' => '⩾', 'GreaterTilde' => '≳', 'Gscr' => '𝒢', 'gscr' => 'ℊ', 'gsim' => '≳', 'gsime' => '⪎', 'gsiml' => '⪐', 'GT' => '>', 'G' => '>', 'Gt' => '≫', 'gt' => '>', 'g' => '>', 'gtcc' => '⪧', 'gtcir' => '⩺', 'gtdot' => '⋗', 'gtlPar' => '⦕', 'gtquest' => '⩼', 'gtrapprox' => '⪆', 'gtrarr' => '⥸', 'gtrdot' => '⋗', 'gtreqless' => '⋛', 'gtreqqless' => '⪌', 'gtrless' => '≷', 'gtrsim' => '≳', 'gvertneqq' => '≩︀', 'gvnE' => '≩︀', 'Hacek' => 'ˇ', 'hairsp' => ' ', 'half' => '½', 'hamilt' => 'ℋ', 'HARDcy' => 'Ъ', 'hardcy' => 'ъ', 'hArr' => '⇔', 'harr' => '↔', 'harrcir' => '⥈', 'harrw' => '↭', 'Hat' => '^', 'hbar' => 'ℏ', 'Hcirc' => 'Ĥ', 'hcirc' => 'ĥ', 'hearts' => '♥', 'heartsuit' => '♥', 'hellip' => '…', 'hercon' => '⊹', 'Hfr' => 'ℌ', 'hfr' => '𝔥', 'HilbertSpace' => 'ℋ', 'hksearow' => '⤥', 'hkswarow' => '⤦', 'hoarr' => '⇿', 'homtht' => '∻', 'hookleftarrow' => '↩', 'hookrightarrow' => '↪', 'Hopf' => 'ℍ', 'hopf' => '𝕙', 'horbar' => '―', 'HorizontalLine' => '─', 'Hscr' => 'ℋ', 'hscr' => '𝒽', 'hslash' => 'ℏ', 'Hstrok' => 'Ħ', 'hstrok' => 'ħ', 'HumpDownHump' => '≎', 'HumpEqual' => '≏', 'hybull' => '⁃', 'hyphen' => '‐', 'Iacute' => 'Í', 'Iacut' => 'Í', 'iacute' => 'í', 'iacut' => 'í', 'ic' => '⁣', 'Icirc' => 'Î', 'Icir' => 'Î', 'icirc' => 'î', 'icir' => 'î', 'Icy' => 'И', 'icy' => 'и', 'Idot' => 'İ', 'IEcy' => 'Е', 'iecy' => 'е', 'iexcl' => '¡', 'iexc' => '¡', 'iff' => '⇔', 'Ifr' => 'ℑ', 'ifr' => '𝔦', 'Igrave' => 'Ì', 'Igrav' => 'Ì', 'igrave' => 'ì', 'igrav' => 'ì', 'ii' => 'ⅈ', 'iiiint' => '⨌', 'iiint' => '∭', 'iinfin' => '⧜', 'iiota' => '℩', 'IJlig' => 'IJ', 'ijlig' => 'ij', 'Im' => 'ℑ', 'Imacr' => 'Ī', 'imacr' => 'ī', 'image' => 'ℑ', 'ImaginaryI' => 'ⅈ', 'imagline' => 'ℐ', 'imagpart' => 'ℑ', 'imath' => 'ı', 'imof' => '⊷', 'imped' => 'Ƶ', 'Implies' => '⇒', 'in' => '∈', 'incare' => '℅', 'infin' => '∞', 'infintie' => '⧝', 'inodot' => 'ı', 'Int' => '∬', 'int' => '∫', 'intcal' => '⊺', 'integers' => 'ℤ', 'Integral' => '∫', 'intercal' => '⊺', 'Intersection' => '⋂', 'intlarhk' => '⨗', 'intprod' => '⨼', 'InvisibleComma' => '⁣', 'InvisibleTimes' => '⁢', 'IOcy' => 'Ё', 'iocy' => 'ё', 'Iogon' => 'Į', 'iogon' => 'į', 'Iopf' => '𝕀', 'iopf' => '𝕚', 'Iota' => 'Ι', 'iota' => 'ι', 'iprod' => '⨼', 'iquest' => '¿', 'iques' => '¿', 'Iscr' => 'ℐ', 'iscr' => '𝒾', 'isin' => '∈', 'isindot' => '⋵', 'isinE' => '⋹', 'isins' => '⋴', 'isinsv' => '⋳', 'isinv' => '∈', 'it' => '⁢', 'Itilde' => 'Ĩ', 'itilde' => 'ĩ', 'Iukcy' => 'І', 'iukcy' => 'і', 'Iuml' => 'Ï', 'Ium' => 'Ï', 'iuml' => 'ï', 'ium' => 'ï', 'Jcirc' => 'Ĵ', 'jcirc' => 'ĵ', 'Jcy' => 'Й', 'jcy' => 'й', 'Jfr' => '𝔍', 'jfr' => '𝔧', 'jmath' => 'ȷ', 'Jopf' => '𝕁', 'jopf' => '𝕛', 'Jscr' => '𝒥', 'jscr' => '𝒿', 'Jsercy' => 'Ј', 'jsercy' => 'ј', 'Jukcy' => 'Є', 'jukcy' => 'є', 'Kappa' => 'Κ', 'kappa' => 'κ', 'kappav' => 'ϰ', 'Kcedil' => 'Ķ', 'kcedil' => 'ķ', 'Kcy' => 'К', 'kcy' => 'к', 'Kfr' => '𝔎', 'kfr' => '𝔨', 'kgreen' => 'ĸ', 'KHcy' => 'Х', 'khcy' => 'х', 'KJcy' => 'Ќ', 'kjcy' => 'ќ', 'Kopf' => '𝕂', 'kopf' => '𝕜', 'Kscr' => '𝒦', 'kscr' => '𝓀', 'lAarr' => '⇚', 'Lacute' => 'Ĺ', 'lacute' => 'ĺ', 'laemptyv' => '⦴', 'lagran' => 'ℒ', 'Lambda' => 'Λ', 'lambda' => 'λ', 'Lang' => '⟪', 'lang' => '⟨', 'langd' => '⦑', 'langle' => '⟨', 'lap' => '⪅', 'Laplacetrf' => 'ℒ', 'laquo' => '«', 'laqu' => '«', 'Larr' => '↞', 'lArr' => '⇐', 'larr' => '←', 'larrb' => '⇤', 'larrbfs' => '⤟', 'larrfs' => '⤝', 'larrhk' => '↩', 'larrlp' => '↫', 'larrpl' => '⤹', 'larrsim' => '⥳', 'larrtl' => '↢', 'lat' => '⪫', 'lAtail' => '⤛', 'latail' => '⤙', 'late' => '⪭', 'lates' => '⪭︀', 'lBarr' => '⤎', 'lbarr' => '⤌', 'lbbrk' => '❲', 'lbrace' => '{', 'lbrack' => '[', 'lbrke' => '⦋', 'lbrksld' => '⦏', 'lbrkslu' => '⦍', 'Lcaron' => 'Ľ', 'lcaron' => 'ľ', 'Lcedil' => 'Ļ', 'lcedil' => 'ļ', 'lceil' => '⌈', 'lcub' => '{', 'Lcy' => 'Л', 'lcy' => 'л', 'ldca' => '⤶', 'ldquo' => '“', 'ldquor' => '„', 'ldrdhar' => '⥧', 'ldrushar' => '⥋', 'ldsh' => '↲', 'lE' => '≦', 'le' => '≤', 'LeftAngleBracket' => '⟨', 'LeftArrow' => '←', 'Leftarrow' => '⇐', 'leftarrow' => '←', 'LeftArrowBar' => '⇤', 'LeftArrowRightArrow' => '⇆', 'leftarrowtail' => '↢', 'LeftCeiling' => '⌈', 'LeftDoubleBracket' => '⟦', 'LeftDownTeeVector' => '⥡', 'LeftDownVector' => '⇃', 'LeftDownVectorBar' => '⥙', 'LeftFloor' => '⌊', 'leftharpoondown' => '↽', 'leftharpoonup' => '↼', 'leftleftarrows' => '⇇', 'LeftRightArrow' => '↔', 'Leftrightarrow' => '⇔', 'leftrightarrow' => '↔', 'leftrightarrows' => '⇆', 'leftrightharpoons' => '⇋', 'leftrightsquigarrow' => '↭', 'LeftRightVector' => '⥎', 'LeftTee' => '⊣', 'LeftTeeArrow' => '↤', 'LeftTeeVector' => '⥚', 'leftthreetimes' => '⋋', 'LeftTriangle' => '⊲', 'LeftTriangleBar' => '⧏', 'LeftTriangleEqual' => '⊴', 'LeftUpDownVector' => '⥑', 'LeftUpTeeVector' => '⥠', 'LeftUpVector' => '↿', 'LeftUpVectorBar' => '⥘', 'LeftVector' => '↼', 'LeftVectorBar' => '⥒', 'lEg' => '⪋', 'leg' => '⋚', 'leq' => '≤', 'leqq' => '≦', 'leqslant' => '⩽', 'les' => '⩽', 'lescc' => '⪨', 'lesdot' => '⩿', 'lesdoto' => '⪁', 'lesdotor' => '⪃', 'lesg' => '⋚︀', 'lesges' => '⪓', 'lessapprox' => '⪅', 'lessdot' => '⋖', 'lesseqgtr' => '⋚', 'lesseqqgtr' => '⪋', 'LessEqualGreater' => '⋚', 'LessFullEqual' => '≦', 'LessGreater' => '≶', 'lessgtr' => '≶', 'LessLess' => '⪡', 'lesssim' => '≲', 'LessSlantEqual' => '⩽', 'LessTilde' => '≲', 'lfisht' => '⥼', 'lfloor' => '⌊', 'Lfr' => '𝔏', 'lfr' => '𝔩', 'lg' => '≶', 'lgE' => '⪑', 'lHar' => '⥢', 'lhard' => '↽', 'lharu' => '↼', 'lharul' => '⥪', 'lhblk' => '▄', 'LJcy' => 'Љ', 'ljcy' => 'љ', 'Ll' => '⋘', 'll' => '≪', 'llarr' => '⇇', 'llcorner' => '⌞', 'Lleftarrow' => '⇚', 'llhard' => '⥫', 'lltri' => '◺', 'Lmidot' => 'Ŀ', 'lmidot' => 'ŀ', 'lmoust' => '⎰', 'lmoustache' => '⎰', 'lnap' => '⪉', 'lnapprox' => '⪉', 'lnE' => '≨', 'lne' => '⪇', 'lneq' => '⪇', 'lneqq' => '≨', 'lnsim' => '⋦', 'loang' => '⟬', 'loarr' => '⇽', 'lobrk' => '⟦', 'LongLeftArrow' => '⟵', 'Longleftarrow' => '⟸', 'longleftarrow' => '⟵', 'LongLeftRightArrow' => '⟷', 'Longleftrightarrow' => '⟺', 'longleftrightarrow' => '⟷', 'longmapsto' => '⟼', 'LongRightArrow' => '⟶', 'Longrightarrow' => '⟹', 'longrightarrow' => '⟶', 'looparrowleft' => '↫', 'looparrowright' => '↬', 'lopar' => '⦅', 'Lopf' => '𝕃', 'lopf' => '𝕝', 'loplus' => '⨭', 'lotimes' => '⨴', 'lowast' => '∗', 'lowbar' => '_', 'LowerLeftArrow' => '↙', 'LowerRightArrow' => '↘', 'loz' => '◊', 'lozenge' => '◊', 'lozf' => '⧫', 'lpar' => '(', 'lparlt' => '⦓', 'lrarr' => '⇆', 'lrcorner' => '⌟', 'lrhar' => '⇋', 'lrhard' => '⥭', 'lrm' => '‎', 'lrtri' => '⊿', 'lsaquo' => '‹', 'Lscr' => 'ℒ', 'lscr' => '𝓁', 'Lsh' => '↰', 'lsh' => '↰', 'lsim' => '≲', 'lsime' => '⪍', 'lsimg' => '⪏', 'lsqb' => '[', 'lsquo' => '‘', 'lsquor' => '‚', 'Lstrok' => 'Ł', 'lstrok' => 'ł', 'LT' => '<', 'L' => '<', 'Lt' => '≪', 'lt' => '<', 'l' => '<', 'ltcc' => '⪦', 'ltcir' => '⩹', 'ltdot' => '⋖', 'lthree' => '⋋', 'ltimes' => '⋉', 'ltlarr' => '⥶', 'ltquest' => '⩻', 'ltri' => '◃', 'ltrie' => '⊴', 'ltrif' => '◂', 'ltrPar' => '⦖', 'lurdshar' => '⥊', 'luruhar' => '⥦', 'lvertneqq' => '≨︀', 'lvnE' => '≨︀', 'macr' => '¯', 'mac' => '¯', 'male' => '♂', 'malt' => '✠', 'maltese' => '✠', 'Map' => '⤅', 'map' => '↦', 'mapsto' => '↦', 'mapstodown' => '↧', 'mapstoleft' => '↤', 'mapstoup' => '↥', 'marker' => '▮', 'mcomma' => '⨩', 'Mcy' => 'М', 'mcy' => 'м', 'mdash' => '—', 'mDDot' => '∺', 'measuredangle' => '∡', 'MediumSpace' => ' ', 'Mellintrf' => 'ℳ', 'Mfr' => '𝔐', 'mfr' => '𝔪', 'mho' => '℧', 'micro' => 'µ', 'micr' => 'µ', 'mid' => '∣', 'midast' => '*', 'midcir' => '⫰', 'middot' => '·', 'middo' => '·', 'minus' => '−', 'minusb' => '⊟', 'minusd' => '∸', 'minusdu' => '⨪', 'MinusPlus' => '∓', 'mlcp' => '⫛', 'mldr' => '…', 'mnplus' => '∓', 'models' => '⊧', 'Mopf' => '𝕄', 'mopf' => '𝕞', 'mp' => '∓', 'Mscr' => 'ℳ', 'mscr' => '𝓂', 'mstpos' => '∾', 'Mu' => 'Μ', 'mu' => 'μ', 'multimap' => '⊸', 'mumap' => '⊸', 'nabla' => '∇', 'Nacute' => 'Ń', 'nacute' => 'ń', 'nang' => '∠⃒', 'nap' => '≉', 'napE' => '⩰̸', 'napid' => '≋̸', 'napos' => 'ʼn', 'napprox' => '≉', 'natur' => '♮', 'natural' => '♮', 'naturals' => 'ℕ', 'nbsp' => ' ', 'nbs' => ' ', 'nbump' => '≎̸', 'nbumpe' => '≏̸', 'ncap' => '⩃', 'Ncaron' => 'Ň', 'ncaron' => 'ň', 'Ncedil' => 'Ņ', 'ncedil' => 'ņ', 'ncong' => '≇', 'ncongdot' => '⩭̸', 'ncup' => '⩂', 'Ncy' => 'Н', 'ncy' => 'н', 'ndash' => '–', 'ne' => '≠', 'nearhk' => '⤤', 'neArr' => '⇗', 'nearr' => '↗', 'nearrow' => '↗', 'nedot' => '≐̸', 'NegativeMediumSpace' => '​', 'NegativeThickSpace' => '​', 'NegativeThinSpace' => '​', 'NegativeVeryThinSpace' => '​', 'nequiv' => '≢', 'nesear' => '⤨', 'nesim' => '≂̸', 'NestedGreaterGreater' => '≫', 'NestedLessLess' => '≪', 'NewLine' => ' ', 'nexist' => '∄', 'nexists' => '∄', 'Nfr' => '𝔑', 'nfr' => '𝔫', 'ngE' => '≧̸', 'nge' => '≱', 'ngeq' => '≱', 'ngeqq' => '≧̸', 'ngeqslant' => '⩾̸', 'nges' => '⩾̸', 'nGg' => '⋙̸', 'ngsim' => '≵', 'nGt' => '≫⃒', 'ngt' => '≯', 'ngtr' => '≯', 'nGtv' => '≫̸', 'nhArr' => '⇎', 'nharr' => '↮', 'nhpar' => '⫲', 'ni' => '∋', 'nis' => '⋼', 'nisd' => '⋺', 'niv' => '∋', 'NJcy' => 'Њ', 'njcy' => 'њ', 'nlArr' => '⇍', 'nlarr' => '↚', 'nldr' => '‥', 'nlE' => '≦̸', 'nle' => '≰', 'nLeftarrow' => '⇍', 'nleftarrow' => '↚', 'nLeftrightarrow' => '⇎', 'nleftrightarrow' => '↮', 'nleq' => '≰', 'nleqq' => '≦̸', 'nleqslant' => '⩽̸', 'nles' => '⩽̸', 'nless' => '≮', 'nLl' => '⋘̸', 'nlsim' => '≴', 'nLt' => '≪⃒', 'nlt' => '≮', 'nltri' => '⋪', 'nltrie' => '⋬', 'nLtv' => '≪̸', 'nmid' => '∤', 'NoBreak' => '⁠', 'NonBreakingSpace' => ' ', 'Nopf' => 'ℕ', 'nopf' => '𝕟', 'Not' => '⫬', 'not' => '¬', 'no' => '¬', 'NotCongruent' => '≢', 'NotCupCap' => '≭', 'NotDoubleVerticalBar' => '∦', 'NotElement' => '∉', 'NotEqual' => '≠', 'NotEqualTilde' => '≂̸', 'NotExists' => '∄', 'NotGreater' => '≯', 'NotGreaterEqual' => '≱', 'NotGreaterFullEqual' => '≧̸', 'NotGreaterGreater' => '≫̸', 'NotGreaterLess' => '≹', 'NotGreaterSlantEqual' => '⩾̸', 'NotGreaterTilde' => '≵', 'NotHumpDownHump' => '≎̸', 'NotHumpEqual' => '≏̸', 'notin' => '∉', 'notindot' => '⋵̸', 'notinE' => '⋹̸', 'notinva' => '∉', 'notinvb' => '⋷', 'notinvc' => '⋶', 'NotLeftTriangle' => '⋪', 'NotLeftTriangleBar' => '⧏̸', 'NotLeftTriangleEqual' => '⋬', 'NotLess' => '≮', 'NotLessEqual' => '≰', 'NotLessGreater' => '≸', 'NotLessLess' => '≪̸', 'NotLessSlantEqual' => '⩽̸', 'NotLessTilde' => '≴', 'NotNestedGreaterGreater' => '⪢̸', 'NotNestedLessLess' => '⪡̸', 'notni' => '∌', 'notniva' => '∌', 'notnivb' => '⋾', 'notnivc' => '⋽', 'NotPrecedes' => '⊀', 'NotPrecedesEqual' => '⪯̸', 'NotPrecedesSlantEqual' => '⋠', 'NotReverseElement' => '∌', 'NotRightTriangle' => '⋫', 'NotRightTriangleBar' => '⧐̸', 'NotRightTriangleEqual' => '⋭', 'NotSquareSubset' => '⊏̸', 'NotSquareSubsetEqual' => '⋢', 'NotSquareSuperset' => '⊐̸', 'NotSquareSupersetEqual' => '⋣', 'NotSubset' => '⊂⃒', 'NotSubsetEqual' => '⊈', 'NotSucceeds' => '⊁', 'NotSucceedsEqual' => '⪰̸', 'NotSucceedsSlantEqual' => '⋡', 'NotSucceedsTilde' => '≿̸', 'NotSuperset' => '⊃⃒', 'NotSupersetEqual' => '⊉', 'NotTilde' => '≁', 'NotTildeEqual' => '≄', 'NotTildeFullEqual' => '≇', 'NotTildeTilde' => '≉', 'NotVerticalBar' => '∤', 'npar' => '∦', 'nparallel' => '∦', 'nparsl' => '⫽⃥', 'npart' => '∂̸', 'npolint' => '⨔', 'npr' => '⊀', 'nprcue' => '⋠', 'npre' => '⪯̸', 'nprec' => '⊀', 'npreceq' => '⪯̸', 'nrArr' => '⇏', 'nrarr' => '↛', 'nrarrc' => '⤳̸', 'nrarrw' => '↝̸', 'nRightarrow' => '⇏', 'nrightarrow' => '↛', 'nrtri' => '⋫', 'nrtrie' => '⋭', 'nsc' => '⊁', 'nsccue' => '⋡', 'nsce' => '⪰̸', 'Nscr' => '𝒩', 'nscr' => '𝓃', 'nshortmid' => '∤', 'nshortparallel' => '∦', 'nsim' => '≁', 'nsime' => '≄', 'nsimeq' => '≄', 'nsmid' => '∤', 'nspar' => '∦', 'nsqsube' => '⋢', 'nsqsupe' => '⋣', 'nsub' => '⊄', 'nsubE' => '⫅̸', 'nsube' => '⊈', 'nsubset' => '⊂⃒', 'nsubseteq' => '⊈', 'nsubseteqq' => '⫅̸', 'nsucc' => '⊁', 'nsucceq' => '⪰̸', 'nsup' => '⊅', 'nsupE' => '⫆̸', 'nsupe' => '⊉', 'nsupset' => '⊃⃒', 'nsupseteq' => '⊉', 'nsupseteqq' => '⫆̸', 'ntgl' => '≹', 'Ntilde' => 'Ñ', 'Ntild' => 'Ñ', 'ntilde' => 'ñ', 'ntild' => 'ñ', 'ntlg' => '≸', 'ntriangleleft' => '⋪', 'ntrianglelefteq' => '⋬', 'ntriangleright' => '⋫', 'ntrianglerighteq' => '⋭', 'Nu' => 'Ν', 'nu' => 'ν', 'num' => '#', 'numero' => '№', 'numsp' => ' ', 'nvap' => '≍⃒', 'nVDash' => '⊯', 'nVdash' => '⊮', 'nvDash' => '⊭', 'nvdash' => '⊬', 'nvge' => '≥⃒', 'nvgt' => '>⃒', 'nvHarr' => '⤄', 'nvinfin' => '⧞', 'nvlArr' => '⤂', 'nvle' => '≤⃒', 'nvlt' => '<⃒', 'nvltrie' => '⊴⃒', 'nvrArr' => '⤃', 'nvrtrie' => '⊵⃒', 'nvsim' => '∼⃒', 'nwarhk' => '⤣', 'nwArr' => '⇖', 'nwarr' => '↖', 'nwarrow' => '↖', 'nwnear' => '⤧', 'Oacute' => 'Ó', 'Oacut' => 'Ó', 'oacute' => 'ó', 'oacut' => 'ó', 'oast' => '⊛', 'ocir' => 'ô', 'Ocirc' => 'Ô', 'Ocir' => 'Ô', 'ocirc' => 'ô', 'Ocy' => 'О', 'ocy' => 'о', 'odash' => '⊝', 'Odblac' => 'Ő', 'odblac' => 'ő', 'odiv' => '⨸', 'odot' => '⊙', 'odsold' => '⦼', 'OElig' => 'Œ', 'oelig' => 'œ', 'ofcir' => '⦿', 'Ofr' => '𝔒', 'ofr' => '𝔬', 'ogon' => '˛', 'Ograve' => 'Ò', 'Ograv' => 'Ò', 'ograve' => 'ò', 'ograv' => 'ò', 'ogt' => '⧁', 'ohbar' => '⦵', 'ohm' => 'Ω', 'oint' => '∮', 'olarr' => '↺', 'olcir' => '⦾', 'olcross' => '⦻', 'oline' => '‾', 'olt' => '⧀', 'Omacr' => 'Ō', 'omacr' => 'ō', 'Omega' => 'Ω', 'omega' => 'ω', 'Omicron' => 'Ο', 'omicron' => 'ο', 'omid' => '⦶', 'ominus' => '⊖', 'Oopf' => '𝕆', 'oopf' => '𝕠', 'opar' => '⦷', 'OpenCurlyDoubleQuote' => '“', 'OpenCurlyQuote' => '‘', 'operp' => '⦹', 'oplus' => '⊕', 'Or' => '⩔', 'or' => '∨', 'orarr' => '↻', 'ord' => 'º', 'order' => 'ℴ', 'orderof' => 'ℴ', 'ordf' => 'ª', 'ordm' => 'º', 'origof' => '⊶', 'oror' => '⩖', 'orslope' => '⩗', 'orv' => '⩛', 'oS' => 'Ⓢ', 'Oscr' => '𝒪', 'oscr' => 'ℴ', 'Oslash' => 'Ø', 'Oslas' => 'Ø', 'oslash' => 'ø', 'oslas' => 'ø', 'osol' => '⊘', 'Otilde' => 'Õ', 'Otild' => 'Õ', 'otilde' => 'õ', 'otild' => 'õ', 'Otimes' => '⨷', 'otimes' => '⊗', 'otimesas' => '⨶', 'Ouml' => 'Ö', 'Oum' => 'Ö', 'ouml' => 'ö', 'oum' => 'ö', 'ovbar' => '⌽', 'OverBar' => '‾', 'OverBrace' => '⏞', 'OverBracket' => '⎴', 'OverParenthesis' => '⏜', 'par' => '¶', 'para' => '¶', 'parallel' => '∥', 'parsim' => '⫳', 'parsl' => '⫽', 'part' => '∂', 'PartialD' => '∂', 'Pcy' => 'П', 'pcy' => 'п', 'percnt' => '%', 'period' => '.', 'permil' => '‰', 'perp' => '⊥', 'pertenk' => '‱', 'Pfr' => '𝔓', 'pfr' => '𝔭', 'Phi' => 'Φ', 'phi' => 'φ', 'phiv' => 'ϕ', 'phmmat' => 'ℳ', 'phone' => '☎', 'Pi' => 'Π', 'pi' => 'π', 'pitchfork' => '⋔', 'piv' => 'ϖ', 'planck' => 'ℏ', 'planckh' => 'ℎ', 'plankv' => 'ℏ', 'plus' => '+', 'plusacir' => '⨣', 'plusb' => '⊞', 'pluscir' => '⨢', 'plusdo' => '∔', 'plusdu' => '⨥', 'pluse' => '⩲', 'PlusMinus' => '±', 'plusmn' => '±', 'plusm' => '±', 'plussim' => '⨦', 'plustwo' => '⨧', 'pm' => '±', 'Poincareplane' => 'ℌ', 'pointint' => '⨕', 'Popf' => 'ℙ', 'popf' => '𝕡', 'pound' => '£', 'poun' => '£', 'Pr' => '⪻', 'pr' => '≺', 'prap' => '⪷', 'prcue' => '≼', 'prE' => '⪳', 'pre' => '⪯', 'prec' => '≺', 'precapprox' => '⪷', 'preccurlyeq' => '≼', 'Precedes' => '≺', 'PrecedesEqual' => '⪯', 'PrecedesSlantEqual' => '≼', 'PrecedesTilde' => '≾', 'preceq' => '⪯', 'precnapprox' => '⪹', 'precneqq' => '⪵', 'precnsim' => '⋨', 'precsim' => '≾', 'Prime' => '″', 'prime' => '′', 'primes' => 'ℙ', 'prnap' => '⪹', 'prnE' => '⪵', 'prnsim' => '⋨', 'prod' => '∏', 'Product' => '∏', 'profalar' => '⌮', 'profline' => '⌒', 'profsurf' => '⌓', 'prop' => '∝', 'Proportion' => '∷', 'Proportional' => '∝', 'propto' => '∝', 'prsim' => '≾', 'prurel' => '⊰', 'Pscr' => '𝒫', 'pscr' => '𝓅', 'Psi' => 'Ψ', 'psi' => 'ψ', 'puncsp' => ' ', 'Qfr' => '𝔔', 'qfr' => '𝔮', 'qint' => '⨌', 'Qopf' => 'ℚ', 'qopf' => '𝕢', 'qprime' => '⁗', 'Qscr' => '𝒬', 'qscr' => '𝓆', 'quaternions' => 'ℍ', 'quatint' => '⨖', 'quest' => '?', 'questeq' => '≟', 'QUOT' => '"', 'QUO' => '"', 'quot' => '"', 'quo' => '"', 'rAarr' => '⇛', 'race' => '∽̱', 'Racute' => 'Ŕ', 'racute' => 'ŕ', 'radic' => '√', 'raemptyv' => '⦳', 'Rang' => '⟫', 'rang' => '⟩', 'rangd' => '⦒', 'range' => '⦥', 'rangle' => '⟩', 'raquo' => '»', 'raqu' => '»', 'Rarr' => '↠', 'rArr' => '⇒', 'rarr' => '→', 'rarrap' => '⥵', 'rarrb' => '⇥', 'rarrbfs' => '⤠', 'rarrc' => '⤳', 'rarrfs' => '⤞', 'rarrhk' => '↪', 'rarrlp' => '↬', 'rarrpl' => '⥅', 'rarrsim' => '⥴', 'Rarrtl' => '⤖', 'rarrtl' => '↣', 'rarrw' => '↝', 'rAtail' => '⤜', 'ratail' => '⤚', 'ratio' => '∶', 'rationals' => 'ℚ', 'RBarr' => '⤐', 'rBarr' => '⤏', 'rbarr' => '⤍', 'rbbrk' => '❳', 'rbrace' => '}', 'rbrack' => ']', 'rbrke' => '⦌', 'rbrksld' => '⦎', 'rbrkslu' => '⦐', 'Rcaron' => 'Ř', 'rcaron' => 'ř', 'Rcedil' => 'Ŗ', 'rcedil' => 'ŗ', 'rceil' => '⌉', 'rcub' => '}', 'Rcy' => 'Р', 'rcy' => 'р', 'rdca' => '⤷', 'rdldhar' => '⥩', 'rdquo' => '”', 'rdquor' => '”', 'rdsh' => '↳', 'Re' => 'ℜ', 'real' => 'ℜ', 'realine' => 'ℛ', 'realpart' => 'ℜ', 'reals' => 'ℝ', 'rect' => '▭', 'REG' => '®', 'RE' => '®', 'reg' => '®', 're' => '®', 'ReverseElement' => '∋', 'ReverseEquilibrium' => '⇋', 'ReverseUpEquilibrium' => '⥯', 'rfisht' => '⥽', 'rfloor' => '⌋', 'Rfr' => 'ℜ', 'rfr' => '𝔯', 'rHar' => '⥤', 'rhard' => '⇁', 'rharu' => '⇀', 'rharul' => '⥬', 'Rho' => 'Ρ', 'rho' => 'ρ', 'rhov' => 'ϱ', 'RightAngleBracket' => '⟩', 'RightArrow' => '→', 'Rightarrow' => '⇒', 'rightarrow' => '→', 'RightArrowBar' => '⇥', 'RightArrowLeftArrow' => '⇄', 'rightarrowtail' => '↣', 'RightCeiling' => '⌉', 'RightDoubleBracket' => '⟧', 'RightDownTeeVector' => '⥝', 'RightDownVector' => '⇂', 'RightDownVectorBar' => '⥕', 'RightFloor' => '⌋', 'rightharpoondown' => '⇁', 'rightharpoonup' => '⇀', 'rightleftarrows' => '⇄', 'rightleftharpoons' => '⇌', 'rightrightarrows' => '⇉', 'rightsquigarrow' => '↝', 'RightTee' => '⊢', 'RightTeeArrow' => '↦', 'RightTeeVector' => '⥛', 'rightthreetimes' => '⋌', 'RightTriangle' => '⊳', 'RightTriangleBar' => '⧐', 'RightTriangleEqual' => '⊵', 'RightUpDownVector' => '⥏', 'RightUpTeeVector' => '⥜', 'RightUpVector' => '↾', 'RightUpVectorBar' => '⥔', 'RightVector' => '⇀', 'RightVectorBar' => '⥓', 'ring' => '˚', 'risingdotseq' => '≓', 'rlarr' => '⇄', 'rlhar' => '⇌', 'rlm' => '‏', 'rmoust' => '⎱', 'rmoustache' => '⎱', 'rnmid' => '⫮', 'roang' => '⟭', 'roarr' => '⇾', 'robrk' => '⟧', 'ropar' => '⦆', 'Ropf' => 'ℝ', 'ropf' => '𝕣', 'roplus' => '⨮', 'rotimes' => '⨵', 'RoundImplies' => '⥰', 'rpar' => ')', 'rpargt' => '⦔', 'rppolint' => '⨒', 'rrarr' => '⇉', 'Rrightarrow' => '⇛', 'rsaquo' => '›', 'Rscr' => 'ℛ', 'rscr' => '𝓇', 'Rsh' => '↱', 'rsh' => '↱', 'rsqb' => ']', 'rsquo' => '’', 'rsquor' => '’', 'rthree' => '⋌', 'rtimes' => '⋊', 'rtri' => '▹', 'rtrie' => '⊵', 'rtrif' => '▸', 'rtriltri' => '⧎', 'RuleDelayed' => '⧴', 'ruluhar' => '⥨', 'rx' => '℞', 'Sacute' => 'Ś', 'sacute' => 'ś', 'sbquo' => '‚', 'Sc' => '⪼', 'sc' => '≻', 'scap' => '⪸', 'Scaron' => 'Š', 'scaron' => 'š', 'sccue' => '≽', 'scE' => '⪴', 'sce' => '⪰', 'Scedil' => 'Ş', 'scedil' => 'ş', 'Scirc' => 'Ŝ', 'scirc' => 'ŝ', 'scnap' => '⪺', 'scnE' => '⪶', 'scnsim' => '⋩', 'scpolint' => '⨓', 'scsim' => '≿', 'Scy' => 'С', 'scy' => 'с', 'sdot' => '⋅', 'sdotb' => '⊡', 'sdote' => '⩦', 'searhk' => '⤥', 'seArr' => '⇘', 'searr' => '↘', 'searrow' => '↘', 'sect' => '§', 'sec' => '§', 'semi' => ';', 'seswar' => '⤩', 'setminus' => '∖', 'setmn' => '∖', 'sext' => '✶', 'Sfr' => '𝔖', 'sfr' => '𝔰', 'sfrown' => '⌢', 'sharp' => '♯', 'SHCHcy' => 'Щ', 'shchcy' => 'щ', 'SHcy' => 'Ш', 'shcy' => 'ш', 'ShortDownArrow' => '↓', 'ShortLeftArrow' => '←', 'shortmid' => '∣', 'shortparallel' => '∥', 'ShortRightArrow' => '→', 'ShortUpArrow' => '↑', 'shy' => '­', 'sh' => '­', 'Sigma' => 'Σ', 'sigma' => 'σ', 'sigmaf' => 'ς', 'sigmav' => 'ς', 'sim' => '∼', 'simdot' => '⩪', 'sime' => '≃', 'simeq' => '≃', 'simg' => '⪞', 'simgE' => '⪠', 'siml' => '⪝', 'simlE' => '⪟', 'simne' => '≆', 'simplus' => '⨤', 'simrarr' => '⥲', 'slarr' => '←', 'SmallCircle' => '∘', 'smallsetminus' => '∖', 'smashp' => '⨳', 'smeparsl' => '⧤', 'smid' => '∣', 'smile' => '⌣', 'smt' => '⪪', 'smte' => '⪬', 'smtes' => '⪬︀', 'SOFTcy' => 'Ь', 'softcy' => 'ь', 'sol' => '/', 'solb' => '⧄', 'solbar' => '⌿', 'Sopf' => '𝕊', 'sopf' => '𝕤', 'spades' => '♠', 'spadesuit' => '♠', 'spar' => '∥', 'sqcap' => '⊓', 'sqcaps' => '⊓︀', 'sqcup' => '⊔', 'sqcups' => '⊔︀', 'Sqrt' => '√', 'sqsub' => '⊏', 'sqsube' => '⊑', 'sqsubset' => '⊏', 'sqsubseteq' => '⊑', 'sqsup' => '⊐', 'sqsupe' => '⊒', 'sqsupset' => '⊐', 'sqsupseteq' => '⊒', 'squ' => '□', 'Square' => '□', 'square' => '□', 'SquareIntersection' => '⊓', 'SquareSubset' => '⊏', 'SquareSubsetEqual' => '⊑', 'SquareSuperset' => '⊐', 'SquareSupersetEqual' => '⊒', 'SquareUnion' => '⊔', 'squarf' => '▪', 'squf' => '▪', 'srarr' => '→', 'Sscr' => '𝒮', 'sscr' => '𝓈', 'ssetmn' => '∖', 'ssmile' => '⌣', 'sstarf' => '⋆', 'Star' => '⋆', 'star' => '☆', 'starf' => '★', 'straightepsilon' => 'ϵ', 'straightphi' => 'ϕ', 'strns' => '¯', 'Sub' => '⋐', 'sub' => '⊂', 'subdot' => '⪽', 'subE' => '⫅', 'sube' => '⊆', 'subedot' => '⫃', 'submult' => '⫁', 'subnE' => '⫋', 'subne' => '⊊', 'subplus' => '⪿', 'subrarr' => '⥹', 'Subset' => '⋐', 'subset' => '⊂', 'subseteq' => '⊆', 'subseteqq' => '⫅', 'SubsetEqual' => '⊆', 'subsetneq' => '⊊', 'subsetneqq' => '⫋', 'subsim' => '⫇', 'subsub' => '⫕', 'subsup' => '⫓', 'succ' => '≻', 'succapprox' => '⪸', 'succcurlyeq' => '≽', 'Succeeds' => '≻', 'SucceedsEqual' => '⪰', 'SucceedsSlantEqual' => '≽', 'SucceedsTilde' => '≿', 'succeq' => '⪰', 'succnapprox' => '⪺', 'succneqq' => '⪶', 'succnsim' => '⋩', 'succsim' => '≿', 'SuchThat' => '∋', 'Sum' => '∑', 'sum' => '∑', 'sung' => '♪', 'Sup' => '⋑', 'sup' => '³', 'sup1' => '¹', 'sup2' => '²', 'sup3' => '³', 'supdot' => '⪾', 'supdsub' => '⫘', 'supE' => '⫆', 'supe' => '⊇', 'supedot' => '⫄', 'Superset' => '⊃', 'SupersetEqual' => '⊇', 'suphsol' => '⟉', 'suphsub' => '⫗', 'suplarr' => '⥻', 'supmult' => '⫂', 'supnE' => '⫌', 'supne' => '⊋', 'supplus' => '⫀', 'Supset' => '⋑', 'supset' => '⊃', 'supseteq' => '⊇', 'supseteqq' => '⫆', 'supsetneq' => '⊋', 'supsetneqq' => '⫌', 'supsim' => '⫈', 'supsub' => '⫔', 'supsup' => '⫖', 'swarhk' => '⤦', 'swArr' => '⇙', 'swarr' => '↙', 'swarrow' => '↙', 'swnwar' => '⤪', 'szlig' => 'ß', 'szli' => 'ß', 'Tab' => ' ', 'target' => '⌖', 'Tau' => 'Τ', 'tau' => 'τ', 'tbrk' => '⎴', 'Tcaron' => 'Ť', 'tcaron' => 'ť', 'Tcedil' => 'Ţ', 'tcedil' => 'ţ', 'Tcy' => 'Т', 'tcy' => 'т', 'tdot' => '⃛', 'telrec' => '⌕', 'Tfr' => '𝔗', 'tfr' => '𝔱', 'there4' => '∴', 'Therefore' => '∴', 'therefore' => '∴', 'Theta' => 'Θ', 'theta' => 'θ', 'thetasym' => 'ϑ', 'thetav' => 'ϑ', 'thickapprox' => '≈', 'thicksim' => '∼', 'ThickSpace' => '  ', 'thinsp' => ' ', 'ThinSpace' => ' ', 'thkap' => '≈', 'thksim' => '∼', 'THORN' => 'Þ', 'THOR' => 'Þ', 'thorn' => 'þ', 'thor' => 'þ', 'Tilde' => '∼', 'tilde' => '˜', 'TildeEqual' => '≃', 'TildeFullEqual' => '≅', 'TildeTilde' => '≈', 'times' => '×', 'time' => '×', 'timesb' => '⊠', 'timesbar' => '⨱', 'timesd' => '⨰', 'tint' => '∭', 'toea' => '⤨', 'top' => '⊤', 'topbot' => '⌶', 'topcir' => '⫱', 'Topf' => '𝕋', 'topf' => '𝕥', 'topfork' => '⫚', 'tosa' => '⤩', 'tprime' => '‴', 'TRADE' => '™', 'trade' => '™', 'triangle' => '▵', 'triangledown' => '▿', 'triangleleft' => '◃', 'trianglelefteq' => '⊴', 'triangleq' => '≜', 'triangleright' => '▹', 'trianglerighteq' => '⊵', 'tridot' => '◬', 'trie' => '≜', 'triminus' => '⨺', 'TripleDot' => '⃛', 'triplus' => '⨹', 'trisb' => '⧍', 'tritime' => '⨻', 'trpezium' => '⏢', 'Tscr' => '𝒯', 'tscr' => '𝓉', 'TScy' => 'Ц', 'tscy' => 'ц', 'TSHcy' => 'Ћ', 'tshcy' => 'ћ', 'Tstrok' => 'Ŧ', 'tstrok' => 'ŧ', 'twixt' => '≬', 'twoheadleftarrow' => '↞', 'twoheadrightarrow' => '↠', 'Uacute' => 'Ú', 'Uacut' => 'Ú', 'uacute' => 'ú', 'uacut' => 'ú', 'Uarr' => '↟', 'uArr' => '⇑', 'uarr' => '↑', 'Uarrocir' => '⥉', 'Ubrcy' => 'Ў', 'ubrcy' => 'ў', 'Ubreve' => 'Ŭ', 'ubreve' => 'ŭ', 'Ucirc' => 'Û', 'Ucir' => 'Û', 'ucirc' => 'û', 'ucir' => 'û', 'Ucy' => 'У', 'ucy' => 'у', 'udarr' => '⇅', 'Udblac' => 'Ű', 'udblac' => 'ű', 'udhar' => '⥮', 'ufisht' => '⥾', 'Ufr' => '𝔘', 'ufr' => '𝔲', 'Ugrave' => 'Ù', 'Ugrav' => 'Ù', 'ugrave' => 'ù', 'ugrav' => 'ù', 'uHar' => '⥣', 'uharl' => '↿', 'uharr' => '↾', 'uhblk' => '▀', 'ulcorn' => '⌜', 'ulcorner' => '⌜', 'ulcrop' => '⌏', 'ultri' => '◸', 'Umacr' => 'Ū', 'umacr' => 'ū', 'uml' => '¨', 'um' => '¨', 'UnderBar' => '_', 'UnderBrace' => '⏟', 'UnderBracket' => '⎵', 'UnderParenthesis' => '⏝', 'Union' => '⋃', 'UnionPlus' => '⊎', 'Uogon' => 'Ų', 'uogon' => 'ų', 'Uopf' => '𝕌', 'uopf' => '𝕦', 'UpArrow' => '↑', 'Uparrow' => '⇑', 'uparrow' => '↑', 'UpArrowBar' => '⤒', 'UpArrowDownArrow' => '⇅', 'UpDownArrow' => '↕', 'Updownarrow' => '⇕', 'updownarrow' => '↕', 'UpEquilibrium' => '⥮', 'upharpoonleft' => '↿', 'upharpoonright' => '↾', 'uplus' => '⊎', 'UpperLeftArrow' => '↖', 'UpperRightArrow' => '↗', 'Upsi' => 'ϒ', 'upsi' => 'υ', 'upsih' => 'ϒ', 'Upsilon' => 'Υ', 'upsilon' => 'υ', 'UpTee' => '⊥', 'UpTeeArrow' => '↥', 'upuparrows' => '⇈', 'urcorn' => '⌝', 'urcorner' => '⌝', 'urcrop' => '⌎', 'Uring' => 'Ů', 'uring' => 'ů', 'urtri' => '◹', 'Uscr' => '𝒰', 'uscr' => '𝓊', 'utdot' => '⋰', 'Utilde' => 'Ũ', 'utilde' => 'ũ', 'utri' => '▵', 'utrif' => '▴', 'uuarr' => '⇈', 'Uuml' => 'Ü', 'Uum' => 'Ü', 'uuml' => 'ü', 'uum' => 'ü', 'uwangle' => '⦧', 'vangrt' => '⦜', 'varepsilon' => 'ϵ', 'varkappa' => 'ϰ', 'varnothing' => '∅', 'varphi' => 'ϕ', 'varpi' => 'ϖ', 'varpropto' => '∝', 'vArr' => '⇕', 'varr' => '↕', 'varrho' => 'ϱ', 'varsigma' => 'ς', 'varsubsetneq' => '⊊︀', 'varsubsetneqq' => '⫋︀', 'varsupsetneq' => '⊋︀', 'varsupsetneqq' => '⫌︀', 'vartheta' => 'ϑ', 'vartriangleleft' => '⊲', 'vartriangleright' => '⊳', 'Vbar' => '⫫', 'vBar' => '⫨', 'vBarv' => '⫩', 'Vcy' => 'В', 'vcy' => 'в', 'VDash' => '⊫', 'Vdash' => '⊩', 'vDash' => '⊨', 'vdash' => '⊢', 'Vdashl' => '⫦', 'Vee' => '⋁', 'vee' => '∨', 'veebar' => '⊻', 'veeeq' => '≚', 'vellip' => '⋮', 'Verbar' => '‖', 'verbar' => '|', 'Vert' => '‖', 'vert' => '|', 'VerticalBar' => '∣', 'VerticalLine' => '|', 'VerticalSeparator' => '❘', 'VerticalTilde' => '≀', 'VeryThinSpace' => ' ', 'Vfr' => '𝔙', 'vfr' => '𝔳', 'vltri' => '⊲', 'vnsub' => '⊂⃒', 'vnsup' => '⊃⃒', 'Vopf' => '𝕍', 'vopf' => '𝕧', 'vprop' => '∝', 'vrtri' => '⊳', 'Vscr' => '𝒱', 'vscr' => '𝓋', 'vsubnE' => '⫋︀', 'vsubne' => '⊊︀', 'vsupnE' => '⫌︀', 'vsupne' => '⊋︀', 'Vvdash' => '⊪', 'vzigzag' => '⦚', 'Wcirc' => 'Ŵ', 'wcirc' => 'ŵ', 'wedbar' => '⩟', 'Wedge' => '⋀', 'wedge' => '∧', 'wedgeq' => '≙', 'weierp' => '℘', 'Wfr' => '𝔚', 'wfr' => '𝔴', 'Wopf' => '𝕎', 'wopf' => '𝕨', 'wp' => '℘', 'wr' => '≀', 'wreath' => '≀', 'Wscr' => '𝒲', 'wscr' => '𝓌', 'xcap' => '⋂', 'xcirc' => '◯', 'xcup' => '⋃', 'xdtri' => '▽', 'Xfr' => '𝔛', 'xfr' => '𝔵', 'xhArr' => '⟺', 'xharr' => '⟷', 'Xi' => 'Ξ', 'xi' => 'ξ', 'xlArr' => '⟸', 'xlarr' => '⟵', 'xmap' => '⟼', 'xnis' => '⋻', 'xodot' => '⨀', 'Xopf' => '𝕏', 'xopf' => '𝕩', 'xoplus' => '⨁', 'xotime' => '⨂', 'xrArr' => '⟹', 'xrarr' => '⟶', 'Xscr' => '𝒳', 'xscr' => '𝓍', 'xsqcup' => '⨆', 'xuplus' => '⨄', 'xutri' => '△', 'xvee' => '⋁', 'xwedge' => '⋀', 'Yacute' => 'Ý', 'Yacut' => 'Ý', 'yacute' => 'ý', 'yacut' => 'ý', 'YAcy' => 'Я', 'yacy' => 'я', 'Ycirc' => 'Ŷ', 'ycirc' => 'ŷ', 'Ycy' => 'Ы', 'ycy' => 'ы', 'yen' => '¥', 'ye' => '¥', 'Yfr' => '𝔜', 'yfr' => '𝔶', 'YIcy' => 'Ї', 'yicy' => 'ї', 'Yopf' => '𝕐', 'yopf' => '𝕪', 'Yscr' => '𝒴', 'yscr' => '𝓎', 'YUcy' => 'Ю', 'yucy' => 'ю', 'Yuml' => 'Ÿ', 'yuml' => 'ÿ', 'yum' => 'ÿ', 'Zacute' => 'Ź', 'zacute' => 'ź', 'Zcaron' => 'Ž', 'zcaron' => 'ž', 'Zcy' => 'З', 'zcy' => 'з', 'Zdot' => 'Ż', 'zdot' => 'ż', 'zeetrf' => 'ℨ', 'ZeroWidthSpace' => '​', 'Zeta' => 'Ζ', 'zeta' => 'ζ', 'Zfr' => 'ℨ', 'zfr' => '𝔷', 'ZHcy' => 'Ж', 'zhcy' => 'ж', 'zigrarr' => '⇝', 'Zopf' => 'ℤ', 'zopf' => '𝕫', 'Zscr' => '𝒵', 'zscr' => '𝓏', 'zwj' => '‍', 'zwnj' => '‌', ); } PKZPkHTML5/InstructionProcessor.phpnuW+A [PARENT-TAG-NAME-TO-CLOSE1, PARENT-TAG-NAME-TO-CLOSE2, ...]. * * Order is important, after auto-closing one parent with might have to close also their parent. * * @var array */ public static $optionalEndElementsParentsToClose = array( 'tr' => array('td', 'tr'), 'td' => array('td', 'th'), 'th' => array('td', 'th'), 'tfoot' => array('td', 'th', 'tr', 'tbody', 'thead'), 'tbody' => array('td', 'th', 'tr', 'thead'), ); /** * The HTML5 elements as defined in http://dev.w3.org/html5/markup/elements.html. * * @var array */ public static $html5 = array( 'a' => 1, 'abbr' => 1, 'address' => 65, // NORMAL | BLOCK_TAG 'area' => 9, // NORMAL | VOID_TAG 'article' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'aside' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'audio' => 1, // NORMAL 'b' => 1, 'base' => 9, // NORMAL | VOID_TAG 'bdi' => 1, 'bdo' => 1, 'blockquote' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'body' => 1, 'br' => 9, // NORMAL | VOID_TAG 'button' => 1, 'canvas' => 65, // NORMAL | BLOCK_TAG 'caption' => 1, 'cite' => 1, 'code' => 1, 'col' => 9, // NORMAL | VOID_TAG 'colgroup' => 1, 'command' => 9, // NORMAL | VOID_TAG // "data" => 1, // This is highly experimental and only part of the whatwg spec (not w3c). See https://developer.mozilla.org/en-US/docs/HTML/Element/data 'datalist' => 1, 'dd' => 65, // NORMAL | BLOCK_TAG 'del' => 1, 'details' => 17, // NORMAL | AUTOCLOSE_P, 'dfn' => 1, 'dialog' => 17, // NORMAL | AUTOCLOSE_P, 'div' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'dl' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'dt' => 1, 'em' => 1, 'embed' => 9, // NORMAL | VOID_TAG 'fieldset' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'figcaption' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'figure' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'footer' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'form' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'h1' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'h2' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'h3' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'h4' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'h5' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'h6' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'head' => 1, 'header' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'hgroup' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'hr' => 73, // NORMAL | VOID_TAG 'html' => 1, 'i' => 1, 'iframe' => 3, // NORMAL | TEXT_RAW 'img' => 9, // NORMAL | VOID_TAG 'input' => 9, // NORMAL | VOID_TAG 'kbd' => 1, 'ins' => 1, 'keygen' => 9, // NORMAL | VOID_TAG 'label' => 1, 'legend' => 1, 'li' => 1, 'link' => 9, // NORMAL | VOID_TAG 'map' => 1, 'mark' => 1, 'menu' => 17, // NORMAL | AUTOCLOSE_P, 'meta' => 9, // NORMAL | VOID_TAG 'meter' => 1, 'nav' => 17, // NORMAL | AUTOCLOSE_P, 'noscript' => 65, // NORMAL | BLOCK_TAG 'object' => 1, 'ol' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'optgroup' => 1, 'option' => 1, 'output' => 65, // NORMAL | BLOCK_TAG 'p' => 209, // NORMAL | AUTOCLOSE_P | BLOCK_TAG | BLOCK_ONLY_INLINE 'param' => 9, // NORMAL | VOID_TAG 'pre' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'progress' => 1, 'q' => 1, 'rp' => 1, 'rt' => 1, 'ruby' => 1, 's' => 1, 'samp' => 1, 'script' => 3, // NORMAL | TEXT_RAW 'section' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'select' => 1, 'small' => 1, 'source' => 9, // NORMAL | VOID_TAG 'span' => 1, 'strong' => 1, 'style' => 3, // NORMAL | TEXT_RAW 'sub' => 1, 'summary' => 17, // NORMAL | AUTOCLOSE_P, 'sup' => 1, 'table' => 65, // NORMAL | BLOCK_TAG 'tbody' => 1, 'td' => 1, 'textarea' => 5, // NORMAL | TEXT_RCDATA 'tfoot' => 65, // NORMAL | BLOCK_TAG 'th' => 1, 'thead' => 1, 'time' => 1, 'title' => 5, // NORMAL | TEXT_RCDATA 'tr' => 1, 'track' => 9, // NORMAL | VOID_TAG 'u' => 1, 'ul' => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG 'var' => 1, 'video' => 1, 'wbr' => 9, // NORMAL | VOID_TAG // Legacy? 'basefont' => 8, // VOID_TAG 'bgsound' => 8, // VOID_TAG 'noframes' => 2, // RAW_TEXT 'frame' => 9, // NORMAL | VOID_TAG 'frameset' => 1, 'center' => 16, 'dir' => 16, 'listing' => 16, // AUTOCLOSE_P 'plaintext' => 48, // AUTOCLOSE_P | TEXT_PLAINTEXT 'applet' => 0, 'marquee' => 0, 'isindex' => 8, // VOID_TAG 'xmp' => 20, // AUTOCLOSE_P | VOID_TAG | RAW_TEXT 'noembed' => 2, // RAW_TEXT ); /** * The MathML elements. * See http://www.w3.org/wiki/MathML/Elements. * * In our case we are only concerned with presentation MathML and not content * MathML. There is a nice list of this subset at https://developer.mozilla.org/en-US/docs/MathML/Element. * * @var array */ public static $mathml = array( 'maction' => 1, 'maligngroup' => 1, 'malignmark' => 1, 'math' => 1, 'menclose' => 1, 'merror' => 1, 'mfenced' => 1, 'mfrac' => 1, 'mglyph' => 1, 'mi' => 1, 'mlabeledtr' => 1, 'mlongdiv' => 1, 'mmultiscripts' => 1, 'mn' => 1, 'mo' => 1, 'mover' => 1, 'mpadded' => 1, 'mphantom' => 1, 'mroot' => 1, 'mrow' => 1, 'ms' => 1, 'mscarries' => 1, 'mscarry' => 1, 'msgroup' => 1, 'msline' => 1, 'mspace' => 1, 'msqrt' => 1, 'msrow' => 1, 'mstack' => 1, 'mstyle' => 1, 'msub' => 1, 'msup' => 1, 'msubsup' => 1, 'mtable' => 1, 'mtd' => 1, 'mtext' => 1, 'mtr' => 1, 'munder' => 1, 'munderover' => 1, ); /** * The svg elements. * * The Mozilla documentation has a good list at https://developer.mozilla.org/en-US/docs/SVG/Element. * The w3c list appears to be lacking in some areas like filter effect elements. * That list can be found at http://www.w3.org/wiki/SVG/Elements. * * Note, FireFox appears to do a better job rendering filter effects than chrome. * While they are in the spec I'm not sure how widely implemented they are. * * @var array */ public static $svg = array( 'a' => 1, 'altGlyph' => 1, 'altGlyphDef' => 1, 'altGlyphItem' => 1, 'animate' => 1, 'animateColor' => 1, 'animateMotion' => 1, 'animateTransform' => 1, 'circle' => 1, 'clipPath' => 1, 'color-profile' => 1, 'cursor' => 1, 'defs' => 1, 'desc' => 1, 'ellipse' => 1, 'feBlend' => 1, 'feColorMatrix' => 1, 'feComponentTransfer' => 1, 'feComposite' => 1, 'feConvolveMatrix' => 1, 'feDiffuseLighting' => 1, 'feDisplacementMap' => 1, 'feDistantLight' => 1, 'feFlood' => 1, 'feFuncA' => 1, 'feFuncB' => 1, 'feFuncG' => 1, 'feFuncR' => 1, 'feGaussianBlur' => 1, 'feImage' => 1, 'feMerge' => 1, 'feMergeNode' => 1, 'feMorphology' => 1, 'feOffset' => 1, 'fePointLight' => 1, 'feSpecularLighting' => 1, 'feSpotLight' => 1, 'feTile' => 1, 'feTurbulence' => 1, 'filter' => 1, 'font' => 1, 'font-face' => 1, 'font-face-format' => 1, 'font-face-name' => 1, 'font-face-src' => 1, 'font-face-uri' => 1, 'foreignObject' => 1, 'g' => 1, 'glyph' => 1, 'glyphRef' => 1, 'hkern' => 1, 'image' => 1, 'line' => 1, 'linearGradient' => 1, 'marker' => 1, 'mask' => 1, 'metadata' => 1, 'missing-glyph' => 1, 'mpath' => 1, 'path' => 1, 'pattern' => 1, 'polygon' => 1, 'polyline' => 1, 'radialGradient' => 1, 'rect' => 1, 'script' => 3, // NORMAL | RAW_TEXT 'set' => 1, 'stop' => 1, 'style' => 3, // NORMAL | RAW_TEXT 'svg' => 1, 'switch' => 1, 'symbol' => 1, 'text' => 1, 'textPath' => 1, 'title' => 1, 'tref' => 1, 'tspan' => 1, 'use' => 1, 'view' => 1, 'vkern' => 1, ); /** * Some attributes in SVG are case sensitive. * * This map contains key/value pairs with the key as the lowercase attribute * name and the value with the correct casing. */ public static $svgCaseSensitiveAttributeMap = array( 'attributename' => 'attributeName', 'attributetype' => 'attributeType', 'basefrequency' => 'baseFrequency', 'baseprofile' => 'baseProfile', 'calcmode' => 'calcMode', 'clippathunits' => 'clipPathUnits', 'contentscripttype' => 'contentScriptType', 'contentstyletype' => 'contentStyleType', 'diffuseconstant' => 'diffuseConstant', 'edgemode' => 'edgeMode', 'externalresourcesrequired' => 'externalResourcesRequired', 'filterres' => 'filterRes', 'filterunits' => 'filterUnits', 'glyphref' => 'glyphRef', 'gradienttransform' => 'gradientTransform', 'gradientunits' => 'gradientUnits', 'kernelmatrix' => 'kernelMatrix', 'kernelunitlength' => 'kernelUnitLength', 'keypoints' => 'keyPoints', 'keysplines' => 'keySplines', 'keytimes' => 'keyTimes', 'lengthadjust' => 'lengthAdjust', 'limitingconeangle' => 'limitingConeAngle', 'markerheight' => 'markerHeight', 'markerunits' => 'markerUnits', 'markerwidth' => 'markerWidth', 'maskcontentunits' => 'maskContentUnits', 'maskunits' => 'maskUnits', 'numoctaves' => 'numOctaves', 'pathlength' => 'pathLength', 'patterncontentunits' => 'patternContentUnits', 'patterntransform' => 'patternTransform', 'patternunits' => 'patternUnits', 'pointsatx' => 'pointsAtX', 'pointsaty' => 'pointsAtY', 'pointsatz' => 'pointsAtZ', 'preservealpha' => 'preserveAlpha', 'preserveaspectratio' => 'preserveAspectRatio', 'primitiveunits' => 'primitiveUnits', 'refx' => 'refX', 'refy' => 'refY', 'repeatcount' => 'repeatCount', 'repeatdur' => 'repeatDur', 'requiredextensions' => 'requiredExtensions', 'requiredfeatures' => 'requiredFeatures', 'specularconstant' => 'specularConstant', 'specularexponent' => 'specularExponent', 'spreadmethod' => 'spreadMethod', 'startoffset' => 'startOffset', 'stddeviation' => 'stdDeviation', 'stitchtiles' => 'stitchTiles', 'surfacescale' => 'surfaceScale', 'systemlanguage' => 'systemLanguage', 'tablevalues' => 'tableValues', 'targetx' => 'targetX', 'targety' => 'targetY', 'textlength' => 'textLength', 'viewbox' => 'viewBox', 'viewtarget' => 'viewTarget', 'xchannelselector' => 'xChannelSelector', 'ychannelselector' => 'yChannelSelector', 'zoomandpan' => 'zoomAndPan', ); /** * Some SVG elements are case sensitive. * This map contains these. * * The map contains key/value store of the name is lowercase as the keys and * the correct casing as the value. */ public static $svgCaseSensitiveElementMap = array( 'altglyph' => 'altGlyph', 'altglyphdef' => 'altGlyphDef', 'altglyphitem' => 'altGlyphItem', 'animatecolor' => 'animateColor', 'animatemotion' => 'animateMotion', 'animatetransform' => 'animateTransform', 'clippath' => 'clipPath', 'feblend' => 'feBlend', 'fecolormatrix' => 'feColorMatrix', 'fecomponenttransfer' => 'feComponentTransfer', 'fecomposite' => 'feComposite', 'feconvolvematrix' => 'feConvolveMatrix', 'fediffuselighting' => 'feDiffuseLighting', 'fedisplacementmap' => 'feDisplacementMap', 'fedistantlight' => 'feDistantLight', 'feflood' => 'feFlood', 'fefunca' => 'feFuncA', 'fefuncb' => 'feFuncB', 'fefuncg' => 'feFuncG', 'fefuncr' => 'feFuncR', 'fegaussianblur' => 'feGaussianBlur', 'feimage' => 'feImage', 'femerge' => 'feMerge', 'femergenode' => 'feMergeNode', 'femorphology' => 'feMorphology', 'feoffset' => 'feOffset', 'fepointlight' => 'fePointLight', 'fespecularlighting' => 'feSpecularLighting', 'fespotlight' => 'feSpotLight', 'fetile' => 'feTile', 'feturbulence' => 'feTurbulence', 'foreignobject' => 'foreignObject', 'glyphref' => 'glyphRef', 'lineargradient' => 'linearGradient', 'radialgradient' => 'radialGradient', 'textpath' => 'textPath', ); /** * Check whether the given element meets the given criterion. * * Example: * * Elements::isA('script', Elements::TEXT_RAW); // Returns true. * * Elements::isA('script', Elements::TEXT_RCDATA); // Returns false. * * @param string $name The element name. * @param int $mask One of the constants on this class. * * @return bool true if the element matches the mask, false otherwise. */ public static function isA($name, $mask) { return (static::element($name) & $mask) === $mask; } /** * Test if an element is a valid html5 element. * * @param string $name The name of the element. * * @return bool true if a html5 element and false otherwise. */ public static function isHtml5Element($name) { // html5 element names are case insensitive. Forcing lowercase for the check. // Do we need this check or will all data passed here already be lowercase? return isset(static::$html5[strtolower($name)]); } /** * Test if an element name is a valid MathML presentation element. * * @param string $name The name of the element. * * @return bool true if a MathML name and false otherwise. */ public static function isMathMLElement($name) { // MathML is case-sensitive unlike html5 elements. return isset(static::$mathml[$name]); } /** * Test if an element is a valid SVG element. * * @param string $name The name of the element. * * @return bool true if a SVG element and false otherise. */ public static function isSvgElement($name) { // SVG is case-sensitive unlike html5 elements. return isset(static::$svg[$name]); } /** * Is an element name valid in an html5 document. * This includes html5 elements along with other allowed embedded content * such as svg and mathml. * * @param string $name The name of the element. * * @return bool true if valid and false otherwise. */ public static function isElement($name) { return static::isHtml5Element($name) || static::isMathMLElement($name) || static::isSvgElement($name); } /** * Get the element mask for the given element name. * * @param string $name The name of the element. * * @return int the element mask. */ public static function element($name) { if (isset(static::$html5[$name])) { return static::$html5[$name]; } if (isset(static::$svg[$name])) { return static::$svg[$name]; } if (isset(static::$mathml[$name])) { return static::$mathml[$name]; } return 0; } /** * Normalize a SVG element name to its proper case and form. * * @param string $name The name of the element. * * @return string the normalized form of the element name. */ public static function normalizeSvgElement($name) { $name = strtolower($name); if (isset(static::$svgCaseSensitiveElementMap[$name])) { $name = static::$svgCaseSensitiveElementMap[$name]; } return $name; } /** * Normalize a SVG attribute name to its proper case and form. * * @param string $name The name of the attribute. * * @return string The normalized form of the attribute name. */ public static function normalizeSvgAttribute($name) { $name = strtolower($name); if (isset(static::$svgCaseSensitiveAttributeMap[$name])) { $name = static::$svgCaseSensitiveAttributeMap[$name]; } return $name; } /** * Normalize a MathML attribute name to its proper case and form. * Note, all MathML element names are lowercase. * * @param string $name The name of the attribute. * * @return string The normalized form of the attribute name. */ public static function normalizeMathMlAttribute($name) { $name = strtolower($name); // Only one attribute has a mixed case form for MathML. if ('definitionurl' === $name) { $name = 'definitionURL'; } return $name; } } PKZ HTML5/Parser/InputStream.phpnuW+A self::NAMESPACE_HTML, 'svg' => self::NAMESPACE_SVG, 'math' => self::NAMESPACE_MATHML, ); /** * Holds the always available namespaces (which does not require the XMLNS declaration). * * @var array */ protected $implicitNamespaces = array( 'xml' => self::NAMESPACE_XML, 'xmlns' => self::NAMESPACE_XMLNS, 'xlink' => self::NAMESPACE_XLINK, ); /** * Holds a stack of currently active namespaces. * * @var array */ protected $nsStack = array(); /** * Holds the number of namespaces declared by a node. * * @var array */ protected $pushes = array(); /** * Defined in 8.2.5. */ const IM_INITIAL = 0; const IM_BEFORE_HTML = 1; const IM_BEFORE_HEAD = 2; const IM_IN_HEAD = 3; const IM_IN_HEAD_NOSCRIPT = 4; const IM_AFTER_HEAD = 5; const IM_IN_BODY = 6; const IM_TEXT = 7; const IM_IN_TABLE = 8; const IM_IN_TABLE_TEXT = 9; const IM_IN_CAPTION = 10; const IM_IN_COLUMN_GROUP = 11; const IM_IN_TABLE_BODY = 12; const IM_IN_ROW = 13; const IM_IN_CELL = 14; const IM_IN_SELECT = 15; const IM_IN_SELECT_IN_TABLE = 16; const IM_AFTER_BODY = 17; const IM_IN_FRAMESET = 18; const IM_AFTER_FRAMESET = 19; const IM_AFTER_AFTER_BODY = 20; const IM_AFTER_AFTER_FRAMESET = 21; const IM_IN_SVG = 22; const IM_IN_MATHML = 23; protected $options = array(); protected $stack = array(); protected $current; // Pointer in the tag hierarchy. protected $rules; protected $doc; protected $frag; protected $processor; protected $insertMode = 0; /** * Track if we are in an element that allows only inline child nodes. * * @var string|null */ protected $onlyInline; /** * Quirks mode is enabled by default. * Any document that is missing the DT will be considered to be in quirks mode. */ protected $quirks = true; protected $errors = array(); public function __construct($isFragment = false, array $options = array()) { $this->options = $options; if (isset($options[self::OPT_TARGET_DOC])) { $this->doc = $options[self::OPT_TARGET_DOC]; } else { $impl = new \DOMImplementation(); // XXX: // Create the doctype. For now, we are always creating HTML5 // documents, and attempting to up-convert any older DTDs to HTML5. $dt = $impl->createDocumentType('html'); // $this->doc = \DOMImplementation::createDocument(NULL, 'html', $dt); $this->doc = $impl->createDocument(null, '', $dt); $this->doc->encoding = !empty($options['encoding']) ? $options['encoding'] : 'UTF-8'; } $this->errors = array(); $this->current = $this->doc; // ->documentElement; // Create a rules engine for tags. $this->rules = new TreeBuildingRules(); $implicitNS = array(); if (isset($this->options[self::OPT_IMPLICIT_NS])) { $implicitNS = $this->options[self::OPT_IMPLICIT_NS]; } elseif (isset($this->options['implicitNamespaces'])) { $implicitNS = $this->options['implicitNamespaces']; } // Fill $nsStack with the defalut HTML5 namespaces, plus the "implicitNamespaces" array taken form $options array_unshift($this->nsStack, $implicitNS + array('' => self::NAMESPACE_HTML) + $this->implicitNamespaces); if ($isFragment) { $this->insertMode = static::IM_IN_BODY; $this->frag = $this->doc->createDocumentFragment(); $this->current = $this->frag; } } /** * Get the document. */ public function document() { return $this->doc; } /** * Get the DOM fragment for the body. * * This returns a DOMNodeList because a fragment may have zero or more * DOMNodes at its root. * * @see http://www.w3.org/TR/2012/CR-html5-20121217/syntax.html#concept-frag-parse-context * * @return \DOMDocumentFragment */ public function fragment() { return $this->frag; } /** * Provide an instruction processor. * * This is used for handling Processor Instructions as they are * inserted. If omitted, PI's are inserted directly into the DOM tree. * * @param InstructionProcessor $proc */ public function setInstructionProcessor(InstructionProcessor $proc) { $this->processor = $proc; } public function doctype($name, $idType = 0, $id = null, $quirks = false) { // This is used solely for setting quirks mode. Currently we don't // try to preserve the inbound DT. We convert it to HTML5. $this->quirks = $quirks; if ($this->insertMode > static::IM_INITIAL) { $this->parseError('Illegal placement of DOCTYPE tag. Ignoring: ' . $name); return; } $this->insertMode = static::IM_BEFORE_HTML; } /** * Process the start tag. * * @todo - XMLNS namespace handling (we need to parse, even if it's not valid) * - XLink, MathML and SVG namespace handling * - Omission rules: 8.1.2.4 Optional tags * * @param string $name * @param array $attributes * @param bool $selfClosing * * @return int */ public function startTag($name, $attributes = array(), $selfClosing = false) { $lname = $this->normalizeTagName($name); // Make sure we have an html element. if (!$this->doc->documentElement && 'html' !== $name && !$this->frag) { $this->startTag('html'); } // Set quirks mode if we're at IM_INITIAL with no doctype. if ($this->insertMode === static::IM_INITIAL) { $this->quirks = true; $this->parseError('No DOCTYPE specified.'); } // SPECIAL TAG HANDLING: // Spec says do this, and "don't ask." // find the spec where this is defined... looks problematic if ('image' === $name && !($this->insertMode === static::IM_IN_SVG || $this->insertMode === static::IM_IN_MATHML)) { $name = 'img'; } // Autoclose p tags where appropriate. if ($this->insertMode >= static::IM_IN_BODY && Elements::isA($name, Elements::AUTOCLOSE_P)) { $this->autoclose('p'); } // Set insert mode: switch ($name) { case 'html': $this->insertMode = static::IM_BEFORE_HEAD; break; case 'head': if ($this->insertMode > static::IM_BEFORE_HEAD) { $this->parseError('Unexpected head tag outside of head context.'); } else { $this->insertMode = static::IM_IN_HEAD; } break; case 'body': $this->insertMode = static::IM_IN_BODY; break; case 'svg': $this->insertMode = static::IM_IN_SVG; break; case 'math': $this->insertMode = static::IM_IN_MATHML; break; case 'noscript': if ($this->insertMode === static::IM_IN_HEAD) { $this->insertMode = static::IM_IN_HEAD_NOSCRIPT; } break; } // Special case handling for SVG. if ($this->insertMode === static::IM_IN_SVG) { $lname = Elements::normalizeSvgElement($lname); } $pushes = 0; // when we found a tag thats appears inside $nsRoots, we have to switch the defalut namespace if (isset($this->nsRoots[$lname]) && $this->nsStack[0][''] !== $this->nsRoots[$lname]) { array_unshift($this->nsStack, array( '' => $this->nsRoots[$lname], ) + $this->nsStack[0]); ++$pushes; } $needsWorkaround = false; if (isset($this->options['xmlNamespaces']) && $this->options['xmlNamespaces']) { // when xmlNamespaces is true a and we found a 'xmlns' or 'xmlns:*' attribute, we should add a new item to the $nsStack foreach ($attributes as $aName => $aVal) { if ('xmlns' === $aName) { $needsWorkaround = $aVal; array_unshift($this->nsStack, array( '' => $aVal, ) + $this->nsStack[0]); ++$pushes; } elseif ('xmlns' === (($pos = strpos($aName, ':')) ? substr($aName, 0, $pos) : '')) { array_unshift($this->nsStack, array( substr($aName, $pos + 1) => $aVal, ) + $this->nsStack[0]); ++$pushes; } } } if ($this->onlyInline && Elements::isA($lname, Elements::BLOCK_TAG)) { $this->autoclose($this->onlyInline); $this->onlyInline = null; } // some elements as table related tags might have optional end tags that force us to auto close multiple tags // https://www.w3.org/TR/html401/struct/tables.html if ($this->current instanceof \DOMElement && isset(Elements::$optionalEndElementsParentsToClose[$lname])) { foreach (Elements::$optionalEndElementsParentsToClose[$lname] as $parentElName) { if ($this->current instanceof \DOMElement && $this->current->tagName === $parentElName) { $this->autoclose($parentElName); } } } try { $prefix = ($pos = strpos($lname, ':')) ? substr($lname, 0, $pos) : ''; if (false !== $needsWorkaround) { $xml = "<$lname xmlns=\"$needsWorkaround\" " . (strlen($prefix) && isset($this->nsStack[0][$prefix]) ? ("xmlns:$prefix=\"" . $this->nsStack[0][$prefix] . '"') : '') . '/>'; $frag = new \DOMDocument('1.0', 'UTF-8'); $frag->loadXML($xml); $ele = $this->doc->importNode($frag->documentElement, true); } else { if (!isset($this->nsStack[0][$prefix]) || ('' === $prefix && isset($this->options[self::OPT_DISABLE_HTML_NS]) && $this->options[self::OPT_DISABLE_HTML_NS])) { $ele = $this->doc->createElement($lname); } else { $ele = $this->doc->createElementNS($this->nsStack[0][$prefix], $lname); } } } catch (\DOMException $e) { $this->parseError("Illegal tag name: <$lname>. Replaced with ."); $ele = $this->doc->createElement('invalid'); } if (Elements::isA($lname, Elements::BLOCK_ONLY_INLINE)) { $this->onlyInline = $lname; } // When we add some namespacess, we have to track them. Later, when "endElement" is invoked, we have to remove them. // When we are on a void tag, we do not need to care about namesapce nesting. if ($pushes > 0 && !Elements::isA($name, Elements::VOID_TAG)) { // PHP tends to free the memory used by DOM, // to avoid spl_object_hash collisions whe have to avoid garbage collection of $ele storing it into $pushes // see https://bugs.php.net/bug.php?id=67459 $this->pushes[spl_object_hash($ele)] = array($pushes, $ele); } foreach ($attributes as $aName => $aVal) { // xmlns attributes can't be set if ('xmlns' === $aName) { continue; } if ($this->insertMode === static::IM_IN_SVG) { $aName = Elements::normalizeSvgAttribute($aName); } elseif ($this->insertMode === static::IM_IN_MATHML) { $aName = Elements::normalizeMathMlAttribute($aName); } $aVal = (string) $aVal; try { $prefix = ($pos = strpos($aName, ':')) ? substr($aName, 0, $pos) : false; if ('xmlns' === $prefix) { $ele->setAttributeNS(self::NAMESPACE_XMLNS, $aName, $aVal); } elseif (false !== $prefix && isset($this->nsStack[0][$prefix])) { $ele->setAttributeNS($this->nsStack[0][$prefix], $aName, $aVal); } else { $ele->setAttribute($aName, $aVal); } } catch (\DOMException $e) { $this->parseError("Illegal attribute name for tag $name. Ignoring: $aName"); continue; } // This is necessary on a non-DTD schema, like HTML5. if ('id' === $aName) { $ele->setIdAttribute('id', true); } } if ($this->frag !== $this->current && $this->rules->hasRules($name)) { // Some elements have special processing rules. Handle those separately. $this->current = $this->rules->evaluate($ele, $this->current); } else { // Otherwise, it's a standard element. $this->current->appendChild($ele); if (!Elements::isA($name, Elements::VOID_TAG)) { $this->current = $ele; } // Self-closing tags should only be respected on foreign elements // (and are implied on void elements) // See: https://www.w3.org/TR/html5/syntax.html#start-tags if (Elements::isHtml5Element($name)) { $selfClosing = false; } } // This is sort of a last-ditch attempt to correct for cases where no head/body // elements are provided. if ($this->insertMode <= static::IM_BEFORE_HEAD && 'head' !== $name && 'html' !== $name) { $this->insertMode = static::IM_IN_BODY; } // When we are on a void tag, we do not need to care about namesapce nesting, // but we have to remove the namespaces pushed to $nsStack. if ($pushes > 0 && Elements::isA($name, Elements::VOID_TAG)) { // remove the namespaced definded by current node for ($i = 0; $i < $pushes; ++$i) { array_shift($this->nsStack); } } if ($selfClosing) { $this->endTag($name); } // Return the element mask, which the tokenizer can then use to set // various processing rules. return Elements::element($name); } public function endTag($name) { $lname = $this->normalizeTagName($name); // Special case within 12.2.6.4.7: An end tag whose tag name is "br" should be treated as an opening tag if ('br' === $name) { $this->parseError('Closing tag encountered for void element br.'); $this->startTag('br'); } // Ignore closing tags for other unary elements. elseif (Elements::isA($name, Elements::VOID_TAG)) { return; } if ($this->insertMode <= static::IM_BEFORE_HTML) { // 8.2.5.4.2 if (in_array($name, array( 'html', 'br', 'head', 'title', ))) { $this->startTag('html'); $this->endTag($name); $this->insertMode = static::IM_BEFORE_HEAD; return; } // Ignore the tag. $this->parseError('Illegal closing tag at global scope.'); return; } // Special case handling for SVG. if ($this->insertMode === static::IM_IN_SVG) { $lname = Elements::normalizeSvgElement($lname); } $cid = spl_object_hash($this->current); // XXX: HTML has no parent. What do we do, though, // if this element appears in the wrong place? if ('html' === $lname) { return; } // remove the namespaced definded by current node if (isset($this->pushes[$cid])) { for ($i = 0; $i < $this->pushes[$cid][0]; ++$i) { array_shift($this->nsStack); } unset($this->pushes[$cid]); } if (!$this->autoclose($lname)) { $this->parseError('Could not find closing tag for ' . $lname); } switch ($lname) { case 'head': $this->insertMode = static::IM_AFTER_HEAD; break; case 'body': $this->insertMode = static::IM_AFTER_BODY; break; case 'svg': case 'mathml': $this->insertMode = static::IM_IN_BODY; break; } } public function comment($cdata) { // TODO: Need to handle case where comment appears outside of the HTML tag. $node = $this->doc->createComment($cdata); $this->current->appendChild($node); } public function text($data) { // XXX: Hmmm.... should we really be this strict? if ($this->insertMode < static::IM_IN_HEAD) { // Per '8.2.5.4.3 The "before head" insertion mode' the characters // " \t\n\r\f" should be ignored but no mention of a parse error. This is // practical as most documents contain these characters. Other text is not // expected here so recording a parse error is necessary. $dataTmp = trim($data, " \t\n\r\f"); if (!empty($dataTmp)) { // fprintf(STDOUT, "Unexpected insert mode: %d", $this->insertMode); $this->parseError('Unexpected text. Ignoring: ' . $dataTmp); } return; } // fprintf(STDOUT, "Appending text %s.", $data); $node = $this->doc->createTextNode($data); $this->current->appendChild($node); } public function eof() { // If the $current isn't the $root, do we need to do anything? } public function parseError($msg, $line = 0, $col = 0) { $this->errors[] = sprintf('Line %d, Col %d: %s', $line, $col, $msg); } public function getErrors() { return $this->errors; } public function cdata($data) { $node = $this->doc->createCDATASection($data); $this->current->appendChild($node); } public function processingInstruction($name, $data = null) { // XXX: Ignore initial XML declaration, per the spec. if ($this->insertMode === static::IM_INITIAL && 'xml' === strtolower($name)) { return; } // Important: The processor may modify the current DOM tree however it sees fit. if ($this->processor instanceof InstructionProcessor) { $res = $this->processor->process($this->current, $name, $data); if (!empty($res)) { $this->current = $res; } return; } // Otherwise, this is just a dumb PI element. $node = $this->doc->createProcessingInstruction($name, $data); $this->current->appendChild($node); } // ========================================================================== // UTILITIES // ========================================================================== /** * Apply normalization rules to a tag name. * See sections 2.9 and 8.1.2. * * @param string $tagName * * @return string The normalized tag name. */ protected function normalizeTagName($tagName) { /* * Section 2.9 suggests that we should not do this. if (strpos($name, ':') !== false) { // We know from the grammar that there must be at least one other // char besides :, since : is not a legal tag start. $parts = explode(':', $name); return array_pop($parts); } */ return $tagName; } protected function quirksTreeResolver($name) { throw new \Exception('Not implemented.'); } /** * Automatically climb the tree and close the closest node with the matching $tag. * * @param string $tagName * * @return bool */ protected function autoclose($tagName) { $working = $this->current; do { if (XML_ELEMENT_NODE !== $working->nodeType) { return false; } if ($working->tagName === $tagName) { $this->current = $working->parentNode; return true; } } while ($working = $working->parentNode); return false; } /** * Checks if the given tagname is an ancestor of the present candidate. * * If $this->current or anything above $this->current matches the given tag * name, this returns true. * * @param string $tagName * * @return bool */ protected function isAncestor($tagName) { $candidate = $this->current; while (XML_ELEMENT_NODE === $candidate->nodeType) { if ($candidate->tagName === $tagName) { return true; } $candidate = $candidate->parentNode; } return false; } /** * Returns true if the immediate parent element is of the given tagname. * * @param string $tagName * * @return bool */ protected function isParent($tagName) { return $this->current->tagName === $tagName; } } PKZG#HTML5/Parser/CharacterReference.phpnuW+Aerrors = UTF8Utils::checkForIllegalCodepoints($data); $data = $this->replaceLinefeeds($data); $this->data = $data; $this->char = 0; $this->EOF = strlen($data); } /** * Check if upcomming chars match the given sequence. * * This will read the stream for the $sequence. If it's * found, this will return true. If not, return false. * Since this unconsumes any chars it reads, the caller * will still need to read the next sequence, even if * this returns true. * * Example: $this->scanner->sequenceMatches('') will * see if the input stream is at the start of a * '' string. * * @param string $sequence * @param bool $caseSensitive * * @return bool */ public function sequenceMatches($sequence, $caseSensitive = true) { $portion = substr($this->data, $this->char, strlen($sequence)); return $caseSensitive ? $portion === $sequence : 0 === strcasecmp($portion, $sequence); } /** * Get the current position. * * @return int The current intiger byte position. */ public function position() { return $this->char; } /** * Take a peek at the next character in the data. * * @return string The next character. */ public function peek() { if (($this->char + 1) < $this->EOF) { return $this->data[$this->char + 1]; } return false; } /** * Get the next character. * Note: This advances the pointer. * * @return string The next character. */ public function next() { ++$this->char; if ($this->char < $this->EOF) { return $this->data[$this->char]; } return false; } /** * Get the current character. * Note, this does not advance the pointer. * * @return string The current character. */ public function current() { if ($this->char < $this->EOF) { return $this->data[$this->char]; } return false; } /** * Silently consume N chars. * * @param int $count */ public function consume($count = 1) { $this->char += $count; } /** * Unconsume some of the data. * This moves the data pointer backwards. * * @param int $howMany The number of characters to move the pointer back. */ public function unconsume($howMany = 1) { if (($this->char - $howMany) >= 0) { $this->char -= $howMany; } } /** * Get the next group of that contains hex characters. * Note, along with getting the characters the pointer in the data will be * moved as well. * * @return string The next group that is hex characters. */ public function getHex() { return $this->doCharsWhile(static::CHARS_HEX); } /** * Get the next group of characters that are ASCII Alpha characters. * Note, along with getting the characters the pointer in the data will be * moved as well. * * @return string The next group of ASCII alpha characters. */ public function getAsciiAlpha() { return $this->doCharsWhile(static::CHARS_ALPHA); } /** * Get the next group of characters that are ASCII Alpha characters and numbers. * Note, along with getting the characters the pointer in the data will be * moved as well. * * @return string The next group of ASCII alpha characters and numbers. */ public function getAsciiAlphaNum() { return $this->doCharsWhile(static::CHARS_ALNUM); } /** * Get the next group of numbers. * Note, along with getting the characters the pointer in the data will be * moved as well. * * @return string The next group of numbers. */ public function getNumeric() { return $this->doCharsWhile('0123456789'); } /** * Consume whitespace. * Whitespace in HTML5 is: formfeed, tab, newline, space. * * @return int The length of the matched whitespaces. */ public function whitespace() { if ($this->char >= $this->EOF) { return false; } $len = strspn($this->data, "\n\t\f ", $this->char); $this->char += $len; return $len; } /** * Returns the current line that is being consumed. * * @return int The current line number. */ public function currentLine() { if (empty($this->EOF) || 0 === $this->char) { return 1; } // Add one to $this->char because we want the number for the next // byte to be processed. return substr_count($this->data, "\n", 0, min($this->char, $this->EOF)) + 1; } /** * Read chars until something in the mask is encountered. * * @param string $mask * * @return mixed */ public function charsUntil($mask) { return $this->doCharsUntil($mask); } /** * Read chars as long as the mask matches. * * @param string $mask * * @return int */ public function charsWhile($mask) { return $this->doCharsWhile($mask); } /** * Returns the current column of the current line that the tokenizer is at. * * Newlines are column 0. The first char after a newline is column 1. * * @return int The column number. */ public function columnOffset() { // Short circuit for the first char. if (0 === $this->char) { return 0; } // strrpos is weird, and the offset needs to be negative for what we // want (i.e., the last \n before $this->char). This needs to not have // one (to make it point to the next character, the one we want the // position of) added to it because strrpos's behaviour includes the // final offset byte. $backwardFrom = $this->char - 1 - strlen($this->data); $lastLine = strrpos($this->data, "\n", $backwardFrom); // However, for here we want the length up until the next byte to be // processed, so add one to the current byte ($this->char). if (false !== $lastLine) { $findLengthOf = substr($this->data, $lastLine + 1, $this->char - 1 - $lastLine); } else { // After a newline. $findLengthOf = substr($this->data, 0, $this->char); } return UTF8Utils::countChars($findLengthOf); } /** * Get all characters until EOF. * * This consumes characters until the EOF. * * @return int The number of characters remaining. */ public function remainingChars() { if ($this->char < $this->EOF) { $data = substr($this->data, $this->char); $this->char = $this->EOF; return $data; } return ''; // false; } /** * Replace linefeed characters according to the spec. * * @param $data * * @return string */ private function replaceLinefeeds($data) { /* * U+000D CARRIAGE RETURN (CR) characters and U+000A LINE FEED (LF) characters are treated specially. * Any CR characters that are followed by LF characters must be removed, and any CR characters not * followed by LF characters must be converted to LF characters. Thus, newlines in HTML DOMs are * represented by LF characters, and there are never any CR characters in the input to the tokenization * stage. */ $crlfTable = array( "\0" => "\xEF\xBF\xBD", "\r\n" => "\n", "\r" => "\n", ); return strtr($data, $crlfTable); } /** * Read to a particular match (or until $max bytes are consumed). * * This operates on byte sequences, not characters. * * Matches as far as possible until we reach a certain set of bytes * and returns the matched substring. * * @param string $bytes Bytes to match. * @param int $max Maximum number of bytes to scan. * * @return mixed Index or false if no match is found. You should use strong * equality when checking the result, since index could be 0. */ private function doCharsUntil($bytes, $max = null) { if ($this->char >= $this->EOF) { return false; } if (0 === $max || $max) { $len = strcspn($this->data, $bytes, $this->char, $max); } else { $len = strcspn($this->data, $bytes, $this->char); } $string = (string) substr($this->data, $this->char, $len); $this->char += $len; return $string; } /** * Returns the string so long as $bytes matches. * * Matches as far as possible with a certain set of bytes * and returns the matched substring. * * @param string $bytes A mask of bytes to match. If ANY byte in this mask matches the * current char, the pointer advances and the char is part of the * substring. * @param int $max The max number of chars to read. * * @return string */ private function doCharsWhile($bytes, $max = null) { if ($this->char >= $this->EOF) { return false; } if (0 === $max || $max) { $len = strspn($this->data, $bytes, $this->char, $max); } else { $len = strspn($this->data, $bytes, $this->char); } $string = (string) substr($this->data, $this->char, $len); $this->char += $len; return $string; } } PKZ0*rllHTML5/Parser/UTF8Utils.phpnuW+A Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ use Masterminds\HTML5\Exception; class UTF8Utils { /** * The Unicode replacement character. */ const FFFD = "\xEF\xBF\xBD"; /** * Count the number of characters in a string. * UTF-8 aware. This will try (in order) iconv, MB, and finally a custom counter. * * @param string $string * * @return int */ public static function countChars($string) { // Get the length for the string we need. if (function_exists('mb_strlen')) { return mb_strlen($string, 'utf-8'); } if (function_exists('iconv_strlen')) { return iconv_strlen($string, 'utf-8'); } $count = count_chars($string); // 0x80 = 0x7F - 0 + 1 (one added to get inclusive range) // 0x33 = 0xF4 - 0x2C + 1 (one added to get inclusive range) return array_sum(array_slice($count, 0, 0x80)) + array_sum(array_slice($count, 0xC2, 0x33)); } /** * Convert data from the given encoding to UTF-8. * * This has not yet been tested with charactersets other than UTF-8. * It should work with ISO-8859-1/-13 and standard Latin Win charsets. * * @param string $data The data to convert * @param string $encoding A valid encoding. Examples: http://www.php.net/manual/en/mbstring.supported-encodings.php * * @return string */ public static function convertToUTF8($data, $encoding = 'UTF-8') { /* * From the HTML5 spec: Given an encoding, the bytes in the input stream must be converted * to Unicode characters for the tokeniser, as described by the rules for that encoding, * except that the leading U+FEFF BYTE ORDER MARK character, if any, must not be stripped * by the encoding layer (it is stripped by the rule below). Bytes or sequences of bytes * in the original byte stream that could not be converted to Unicode characters must be * converted to U+FFFD REPLACEMENT CHARACTER code points. */ // mb_convert_encoding is chosen over iconv because of a bug. The best // details for the bug are on http://us1.php.net/manual/en/function.iconv.php#108643 // which contains links to the actual but reports as well as work around // details. if (function_exists('mb_convert_encoding')) { // mb library has the following behaviors: // - UTF-16 surrogates result in false. // - Overlongs and outside Plane 16 result in empty strings. // Before we run mb_convert_encoding we need to tell it what to do with // characters it does not know. This could be different than the parent // application executing this library so we store the value, change it // to our needs, and then change it back when we are done. This feels // a little excessive and it would be great if there was a better way. $save = mb_substitute_character(); mb_substitute_character('none'); $data = mb_convert_encoding($data, 'UTF-8', $encoding); mb_substitute_character($save); } // @todo Get iconv running in at least some environments if that is possible. elseif (function_exists('iconv') && 'auto' !== $encoding) { // fprintf(STDOUT, "iconv found\n"); // iconv has the following behaviors: // - Overlong representations are ignored. // - Beyond Plane 16 is replaced with a lower char. // - Incomplete sequences generate a warning. $data = @iconv($encoding, 'UTF-8//IGNORE', $data); } else { throw new Exception('Not implemented, please install mbstring or iconv'); } /* * One leading U+FEFF BYTE ORDER MARK character must be ignored if any are present. */ if ("\xEF\xBB\xBF" === substr($data, 0, 3)) { $data = substr($data, 3); } return $data; } /** * Checks for Unicode code points that are not valid in a document. * * @param string $data A string to analyze * * @return array An array of (string) error messages produced by the scanning */ public static function checkForIllegalCodepoints($data) { // Vestigal error handling. $errors = array(); /* * All U+0000 null characters in the input must be replaced by U+FFFD REPLACEMENT CHARACTERs. * Any occurrences of such characters is a parse error. */ for ($i = 0, $count = substr_count($data, "\0"); $i < $count; ++$i) { $errors[] = 'null-character'; } /* * Any occurrences of any characters in the ranges U+0001 to U+0008, U+000B, U+000E to U+001F, U+007F * to U+009F, U+D800 to U+DFFF , U+FDD0 to U+FDEF, and characters U+FFFE, U+FFFF, U+1FFFE, U+1FFFF, * U+2FFFE, U+2FFFF, U+3FFFE, U+3FFFF, U+4FFFE, U+4FFFF, U+5FFFE, U+5FFFF, U+6FFFE, U+6FFFF, U+7FFFE, * U+7FFFF, U+8FFFE, U+8FFFF, U+9FFFE, U+9FFFF, U+AFFFE, U+AFFFF, U+BFFFE, U+BFFFF, U+CFFFE, U+CFFFF, * U+DFFFE, U+DFFFF, U+EFFFE, U+EFFFF, U+FFFFE, U+FFFFF, U+10FFFE, and U+10FFFF are parse errors. * (These are all control characters or permanently undefined Unicode characters.) */ // Check PCRE is loaded. $count = preg_match_all( '/(?: [\x01-\x08\x0B\x0E-\x1F\x7F] # U+0001 to U+0008, U+000B, U+000E to U+001F and U+007F | \xC2[\x80-\x9F] # U+0080 to U+009F | \xED(?:\xA0[\x80-\xFF]|[\xA1-\xBE][\x00-\xFF]|\xBF[\x00-\xBF]) # U+D800 to U+DFFFF | \xEF\xB7[\x90-\xAF] # U+FDD0 to U+FDEF | \xEF\xBF[\xBE\xBF] # U+FFFE and U+FFFF | [\xF0-\xF4][\x8F-\xBF]\xBF[\xBE\xBF] # U+nFFFE and U+nFFFF (1 <= n <= 10_{16}) )/x', $data, $matches); for ($i = 0; $i < $count; ++$i) { $errors[] = 'invalid-codepoint'; } return $errors; } } PKZ%ɄHTML5/Parser/README.mdnuW+A# The Parser Model The parser model here follows the model in section [8.2.1](http://www.w3.org/TR/2012/CR-html5-20121217/syntax.html#parsing) of the HTML5 specification, though we do not assume a networking layer. [ InputStream ] // Generic support for reading input. || [ Scanner ] // Breaks down the stream into characters. || [ Tokenizer ] // Groups characters into syntactic || [ Tree Builder ] // Organizes units into a tree of objects || [ DOM Document ] // The final state of the parsed document. ## InputStream This is an interface with at least two concrete implementations: - StringInputStream: Reads an HTML5 string. - FileInputStream: Reads an HTML5 file. ## Scanner This is a mechanical piece of the parser. ## Tokenizer This follows section 8.4 of the HTML5 spec. It is (roughly) a recursive descent parser. (Though there are plenty of optimizations that are less than purely functional. ## EventHandler and DOMTree EventHandler is the interface for tree builders. Since not all implementations will necessarily build trees, we've chosen a more generic name. The event handler emits tokens during tokenization. The DOMTree is an event handler that builds a DOM tree. The output of the DOMTree builder is a DOMDocument. ## DOMDocument PHP has a DOMDocument class built-in (technically, it's part of libxml.) We use that, thus rendering the output of this process compatible with SimpleXML, QueryPath, and many other XML/HTML processing tools. For cases where the HTML5 is a fragment of a HTML5 document a DOMDocumentFragment is returned instead. This is another built-in class. PKZr%%"HTML5/Parser/StringInputStream.phpnuW+A Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ // Some conventions: // - /* */ indicates verbatim text from the HTML 5 specification // MPB: Not sure which version of the spec. Moving from HTML5lib to // HTML5-PHP, I have been using this version: // http://www.w3.org/TR/2012/CR-html5-20121217/Overview.html#contents // // - // indicates regular comments /** * @deprecated since 2.4, to remove in 3.0. Use a string in the scanner instead. */ class StringInputStream implements InputStream { /** * The string data we're parsing. */ private $data; /** * The current integer byte position we are in $data. */ private $char; /** * Length of $data; when $char === $data, we are at the end-of-file. */ private $EOF; /** * Parse errors. */ public $errors = array(); /** * Create a new InputStream wrapper. * * @param string $data Data to parse. * @param string $encoding The encoding to use for the data. * @param string $debug A fprintf format to use to echo the data on stdout. */ public function __construct($data, $encoding = 'UTF-8', $debug = '') { $data = UTF8Utils::convertToUTF8($data, $encoding); if ($debug) { fprintf(STDOUT, $debug, $data, strlen($data)); } // There is good reason to question whether it makes sense to // do this here, since most of these checks are done during // parsing, and since this check doesn't actually *do* anything. $this->errors = UTF8Utils::checkForIllegalCodepoints($data); $data = $this->replaceLinefeeds($data); $this->data = $data; $this->char = 0; $this->EOF = strlen($data); } public function __toString() { return $this->data; } /** * Replace linefeed characters according to the spec. */ protected function replaceLinefeeds($data) { /* * U+000D CARRIAGE RETURN (CR) characters and U+000A LINE FEED (LF) characters are treated specially. * Any CR characters that are followed by LF characters must be removed, and any CR characters not * followed by LF characters must be converted to LF characters. Thus, newlines in HTML DOMs are * represented by LF characters, and there are never any CR characters in the input to the tokenization * stage. */ $crlfTable = array( "\0" => "\xEF\xBF\xBD", "\r\n" => "\n", "\r" => "\n", ); return strtr($data, $crlfTable); } /** * Returns the current line that the tokenizer is at. */ public function currentLine() { if (empty($this->EOF) || 0 === $this->char) { return 1; } // Add one to $this->char because we want the number for the next // byte to be processed. return substr_count($this->data, "\n", 0, min($this->char, $this->EOF)) + 1; } /** * @deprecated */ public function getCurrentLine() { return $this->currentLine(); } /** * Returns the current column of the current line that the tokenizer is at. * Newlines are column 0. The first char after a newline is column 1. * * @return int The column number. */ public function columnOffset() { // Short circuit for the first char. if (0 === $this->char) { return 0; } // strrpos is weird, and the offset needs to be negative for what we // want (i.e., the last \n before $this->char). This needs to not have // one (to make it point to the next character, the one we want the // position of) added to it because strrpos's behaviour includes the // final offset byte. $backwardFrom = $this->char - 1 - strlen($this->data); $lastLine = strrpos($this->data, "\n", $backwardFrom); // However, for here we want the length up until the next byte to be // processed, so add one to the current byte ($this->char). if (false !== $lastLine) { $findLengthOf = substr($this->data, $lastLine + 1, $this->char - 1 - $lastLine); } else { // After a newline. $findLengthOf = substr($this->data, 0, $this->char); } return UTF8Utils::countChars($findLengthOf); } /** * @deprecated */ public function getColumnOffset() { return $this->columnOffset(); } /** * Get the current character. * * @return string The current character. */ #[\ReturnTypeWillChange] public function current() { return $this->data[$this->char]; } /** * Advance the pointer. * This is part of the Iterator interface. */ #[\ReturnTypeWillChange] public function next() { ++$this->char; } /** * Rewind to the start of the string. */ #[\ReturnTypeWillChange] public function rewind() { $this->char = 0; } /** * Is the current pointer location valid. * * @return bool Whether the current pointer location is valid. */ #[\ReturnTypeWillChange] public function valid() { return $this->char < $this->EOF; } /** * Get all characters until EOF. * * This reads to the end of the file, and sets the read marker at the * end of the file. * * Note this performs bounds checking. * * @return string Returns the remaining text. If called when the InputStream is * already exhausted, it returns an empty string. */ public function remainingChars() { if ($this->char < $this->EOF) { $data = substr($this->data, $this->char); $this->char = $this->EOF; return $data; } return ''; // false; } /** * Read to a particular match (or until $max bytes are consumed). * * This operates on byte sequences, not characters. * * Matches as far as possible until we reach a certain set of bytes * and returns the matched substring. * * @param string $bytes Bytes to match. * @param int $max Maximum number of bytes to scan. * * @return mixed Index or false if no match is found. You should use strong * equality when checking the result, since index could be 0. */ public function charsUntil($bytes, $max = null) { if ($this->char >= $this->EOF) { return false; } if (0 === $max || $max) { $len = strcspn($this->data, $bytes, $this->char, $max); } else { $len = strcspn($this->data, $bytes, $this->char); } $string = (string) substr($this->data, $this->char, $len); $this->char += $len; return $string; } /** * Returns the string so long as $bytes matches. * * Matches as far as possible with a certain set of bytes * and returns the matched substring. * * @param string $bytes A mask of bytes to match. If ANY byte in this mask matches the * current char, the pointer advances and the char is part of the * substring. * @param int $max The max number of chars to read. * * @return string */ public function charsWhile($bytes, $max = null) { if ($this->char >= $this->EOF) { return false; } if (0 === $max || $max) { $len = strspn($this->data, $bytes, $this->char, $max); } else { $len = strspn($this->data, $bytes, $this->char); } $string = (string) substr($this->data, $this->char, $len); $this->char += $len; return $string; } /** * Unconsume characters. * * @param int $howMany The number of characters to unconsume. */ public function unconsume($howMany = 1) { if (($this->char - $howMany) >= 0) { $this->char -= $howMany; } } /** * Look ahead without moving cursor. */ public function peek() { if (($this->char + 1) <= $this->EOF) { return $this->data[$this->char + 1]; } return false; } #[\ReturnTypeWillChange] public function key() { return $this->char; } } PKZP>HTML5/Parser/Tokenizer.phpnuW+Ascanner = $scanner; $this->events = $eventHandler; $this->mode = $mode; } /** * Begin parsing. * * This will begin scanning the document, tokenizing as it goes. * Tokens are emitted into the event handler. * * Tokenizing will continue until the document is completely * read. Errors are emitted into the event handler, but * the parser will attempt to continue parsing until the * entire input stream is read. */ public function parse() { do { $this->consumeData(); // FIXME: Add infinite loop protection. } while ($this->carryOn); } /** * Set the text mode for the character data reader. * * HTML5 defines three different modes for reading text: * - Normal: Read until a tag is encountered. * - RCDATA: Read until a tag is encountered, but skip a few otherwise- * special characters. * - Raw: Read until a special closing tag is encountered (viz. pre, script) * * This allows those modes to be set. * * Normally, setting is done by the event handler via a special return code on * startTag(), but it can also be set manually using this function. * * @param int $textmode One of Elements::TEXT_*. * @param string $untilTag The tag that should stop RAW or RCDATA mode. Normal mode does not * use this indicator. */ public function setTextMode($textmode, $untilTag = null) { $this->textMode = $textmode & (Elements::TEXT_RAW | Elements::TEXT_RCDATA); $this->untilTag = $untilTag; } /** * Consume a character and make a move. * HTML5 8.2.4.1. */ protected function consumeData() { $tok = $this->scanner->current(); if ('&' === $tok) { // Character reference $ref = $this->decodeCharacterReference(); $this->buffer($ref); $tok = $this->scanner->current(); } // Parse tag if ('<' === $tok) { // Any buffered text data can go out now. $this->flushBuffer(); $tok = $this->scanner->next(); if (false === $tok) { // end of string $this->parseError('Illegal tag opening'); } elseif ('!' === $tok) { $this->markupDeclaration(); } elseif ('/' === $tok) { $this->endTag(); } elseif ('?' === $tok) { $this->processingInstruction(); } elseif ($this->is_alpha($tok)) { $this->tagName(); } else { $this->parseError('Illegal tag opening'); // TODO is this necessary ? $this->characterData(); } $tok = $this->scanner->current(); } if (false === $tok) { // Handle end of document $this->eof(); } else { // Parse character switch ($this->textMode) { case Elements::TEXT_RAW: $this->rawText($tok); break; case Elements::TEXT_RCDATA: $this->rcdata($tok); break; default: if ('<' === $tok || '&' === $tok) { break; } // NULL character if ("\00" === $tok) { $this->parseError('Received null character.'); $this->text .= $tok; $this->scanner->consume(); break; } $this->text .= $this->scanner->charsUntil("<&\0"); } } return $this->carryOn; } /** * Parse anything that looks like character data. * * Different rules apply based on the current text mode. * * @see Elements::TEXT_RAW Elements::TEXT_RCDATA. */ protected function characterData() { $tok = $this->scanner->current(); if (false === $tok) { return false; } switch ($this->textMode) { case Elements::TEXT_RAW: return $this->rawText($tok); case Elements::TEXT_RCDATA: return $this->rcdata($tok); default: if ('<' === $tok || '&' === $tok) { return false; } return $this->text($tok); } } /** * This buffers the current token as character data. * * @param string $tok The current token. * * @return bool */ protected function text($tok) { // This should never happen... if (false === $tok) { return false; } // NULL character if ("\00" === $tok) { $this->parseError('Received null character.'); } $this->buffer($tok); $this->scanner->consume(); return true; } /** * Read text in RAW mode. * * @param string $tok The current token. * * @return bool */ protected function rawText($tok) { if (is_null($this->untilTag)) { return $this->text($tok); } $sequence = 'untilTag . '>'; $txt = $this->readUntilSequence($sequence); $this->events->text($txt); $this->setTextMode(0); return $this->endTag(); } /** * Read text in RCDATA mode. * * @param string $tok The current token. * * @return bool */ protected function rcdata($tok) { if (is_null($this->untilTag)) { return $this->text($tok); } $sequence = 'untilTag; $txt = ''; $caseSensitive = !Elements::isHtml5Element($this->untilTag); while (false !== $tok && !('<' == $tok && ($this->scanner->sequenceMatches($sequence, $caseSensitive)))) { if ('&' == $tok) { $txt .= $this->decodeCharacterReference(); $tok = $this->scanner->current(); } else { $txt .= $tok; $tok = $this->scanner->next(); } } $len = strlen($sequence); $this->scanner->consume($len); $len += $this->scanner->whitespace(); if ('>' !== $this->scanner->current()) { $this->parseError('Unclosed RCDATA end tag'); } $this->scanner->unconsume($len); $this->events->text($txt); $this->setTextMode(0); return $this->endTag(); } /** * If the document is read, emit an EOF event. */ protected function eof() { // fprintf(STDOUT, "EOF"); $this->flushBuffer(); $this->events->eof(); $this->carryOn = false; } /** * Look for markup. */ protected function markupDeclaration() { $tok = $this->scanner->next(); // Comment: if ('-' == $tok && '-' == $this->scanner->peek()) { $this->scanner->consume(2); return $this->comment(); } elseif ('D' == $tok || 'd' == $tok) { // Doctype return $this->doctype(); } elseif ('[' == $tok) { // CDATA section return $this->cdataSection(); } // FINISH $this->parseError('Expected . Emit an empty comment because 8.2.4.46 says to. if ('>' == $tok) { // Parse error. Emit the comment token. $this->parseError("Expected comment data, got '>'"); $this->events->comment(''); $this->scanner->consume(); return true; } // Replace NULL with the replacement char. if ("\0" == $tok) { $tok = UTF8Utils::FFFD; } while (!$this->isCommentEnd()) { $comment .= $tok; $tok = $this->scanner->next(); } $this->events->comment($comment); $this->scanner->consume(); return true; } /** * Check if the scanner has reached the end of a comment. * * @return bool */ protected function isCommentEnd() { $tok = $this->scanner->current(); // EOF if (false === $tok) { // Hit the end. $this->parseError('Unexpected EOF in a comment.'); return true; } // If next two tokens are not '--', not the end. if ('-' != $tok || '-' != $this->scanner->peek()) { return false; } $this->scanner->consume(2); // Consume '-' and one of '!' or '>' // Test for '>' if ('>' == $this->scanner->current()) { return true; } // Test for '!>' if ('!' == $this->scanner->current() && '>' == $this->scanner->peek()) { $this->scanner->consume(); // Consume the last '>' return true; } // Unread '-' and one of '!' or '>'; $this->scanner->unconsume(2); return false; } /** * Parse a DOCTYPE. * * Parse a DOCTYPE declaration. This method has strong bearing on whether or * not Quirksmode is enabled on the event handler. * * @todo This method is a little long. Should probably refactor. * * @return bool */ protected function doctype() { // Check that string is DOCTYPE. if ($this->scanner->sequenceMatches('DOCTYPE', false)) { $this->scanner->consume(7); } else { $chars = $this->scanner->charsWhile('DOCTYPEdoctype'); $this->parseError('Expected DOCTYPE, got %s', $chars); return $this->bogusComment('scanner->whitespace(); $tok = $this->scanner->current(); // EOF: die. if (false === $tok) { $this->events->doctype('html5', EventHandler::DOCTYPE_NONE, '', true); $this->eof(); return true; } // NULL char: convert. if ("\0" === $tok) { $this->parseError('Unexpected null character in DOCTYPE.'); } $stop = " \n\f>"; $doctypeName = $this->scanner->charsUntil($stop); // Lowercase ASCII, replace \0 with FFFD $doctypeName = strtolower(strtr($doctypeName, "\0", UTF8Utils::FFFD)); $tok = $this->scanner->current(); // If false, emit a parse error, DOCTYPE, and return. if (false === $tok) { $this->parseError('Unexpected EOF in DOCTYPE declaration.'); $this->events->doctype($doctypeName, EventHandler::DOCTYPE_NONE, null, true); return true; } // Short DOCTYPE, like if ('>' == $tok) { // DOCTYPE without a name. if (0 == strlen($doctypeName)) { $this->parseError('Expected a DOCTYPE name. Got nothing.'); $this->events->doctype($doctypeName, 0, null, true); $this->scanner->consume(); return true; } $this->events->doctype($doctypeName); $this->scanner->consume(); return true; } $this->scanner->whitespace(); $pub = strtoupper($this->scanner->getAsciiAlpha()); $white = $this->scanner->whitespace(); // Get ID, and flag it as pub or system. if (('PUBLIC' == $pub || 'SYSTEM' == $pub) && $white > 0) { // Get the sys ID. $type = 'PUBLIC' == $pub ? EventHandler::DOCTYPE_PUBLIC : EventHandler::DOCTYPE_SYSTEM; $id = $this->quotedString("\0>"); if (false === $id) { $this->events->doctype($doctypeName, $type, $pub, false); return true; } // Premature EOF. if (false === $this->scanner->current()) { $this->parseError('Unexpected EOF in DOCTYPE'); $this->events->doctype($doctypeName, $type, $id, true); return true; } // Well-formed complete DOCTYPE. $this->scanner->whitespace(); if ('>' == $this->scanner->current()) { $this->events->doctype($doctypeName, $type, $id, false); $this->scanner->consume(); return true; } // If we get here, we have scanner->charsUntil('>'); $this->parseError('Malformed DOCTYPE.'); $this->events->doctype($doctypeName, $type, $id, true); $this->scanner->consume(); return true; } // Else it's a bogus DOCTYPE. // Consume to > and trash. $this->scanner->charsUntil('>'); $this->parseError('Expected PUBLIC or SYSTEM. Got %s.', $pub); $this->events->doctype($doctypeName, 0, null, true); $this->scanner->consume(); return true; } /** * Utility for reading a quoted string. * * @param string $stopchars Characters (in addition to a close-quote) that should stop the string. * E.g. sometimes '>' is higher precedence than '"' or "'". * * @return mixed String if one is found (quotations omitted). */ protected function quotedString($stopchars) { $tok = $this->scanner->current(); if ('"' == $tok || "'" == $tok) { $this->scanner->consume(); $ret = $this->scanner->charsUntil($tok . $stopchars); if ($this->scanner->current() == $tok) { $this->scanner->consume(); } else { // Parse error because no close quote. $this->parseError('Expected %s, got %s', $tok, $this->scanner->current()); } return $ret; } return false; } /** * Handle a CDATA section. * * @return bool */ protected function cdataSection() { $cdata = ''; $this->scanner->consume(); $chars = $this->scanner->charsWhile('CDAT'); if ('CDATA' != $chars || '[' != $this->scanner->current()) { $this->parseError('Expected [CDATA[, got %s', $chars); return $this->bogusComment('scanner->next(); do { if (false === $tok) { $this->parseError('Unexpected EOF inside CDATA.'); $this->bogusComment('scanner->next(); } while (!$this->scanner->sequenceMatches(']]>')); // Consume ]]> $this->scanner->consume(3); $this->events->cdata($cdata); return true; } // ================================================================ // Non-HTML5 // ================================================================ /** * Handle a processing instruction. * * XML processing instructions are supposed to be ignored in HTML5, * treated as "bogus comments". However, since we're not a user * agent, we allow them. We consume until ?> and then issue a * EventListener::processingInstruction() event. * * @return bool */ protected function processingInstruction() { if ('?' != $this->scanner->current()) { return false; } $tok = $this->scanner->next(); $procName = $this->scanner->getAsciiAlpha(); $white = $this->scanner->whitespace(); // If not a PI, send to bogusComment. if (0 == strlen($procName) || 0 == $white || false == $this->scanner->current()) { $this->parseError("Expected processing instruction name, got $tok"); $this->bogusComment('. while (!('?' == $this->scanner->current() && '>' == $this->scanner->peek())) { $data .= $this->scanner->current(); $tok = $this->scanner->next(); if (false === $tok) { $this->parseError('Unexpected EOF in processing instruction.'); $this->events->processingInstruction($procName, $data); return true; } } $this->scanner->consume(2); // Consume the closing tag $this->events->processingInstruction($procName, $data); return true; } // ================================================================ // UTILITY FUNCTIONS // ================================================================ /** * Read from the input stream until we get to the desired sequene * or hit the end of the input stream. * * @param string $sequence * * @return string */ protected function readUntilSequence($sequence) { $buffer = ''; // Optimization for reading larger blocks faster. $first = substr($sequence, 0, 1); while (false !== $this->scanner->current()) { $buffer .= $this->scanner->charsUntil($first); // Stop as soon as we hit the stopping condition. if ($this->scanner->sequenceMatches($sequence, false)) { return $buffer; } $buffer .= $this->scanner->current(); $this->scanner->consume(); } // If we get here, we hit the EOF. $this->parseError('Unexpected EOF during text read.'); return $buffer; } /** * Check if upcomming chars match the given sequence. * * This will read the stream for the $sequence. If it's * found, this will return true. If not, return false. * Since this unconsumes any chars it reads, the caller * will still need to read the next sequence, even if * this returns true. * * Example: $this->scanner->sequenceMatches('') will * see if the input stream is at the start of a * '' string. * * @param string $sequence * @param bool $caseSensitive * * @return bool */ protected function sequenceMatches($sequence, $caseSensitive = true) { @trigger_error(__METHOD__ . ' method is deprecated since version 2.4 and will be removed in 3.0. Use Scanner::sequenceMatches() instead.', E_USER_DEPRECATED); return $this->scanner->sequenceMatches($sequence, $caseSensitive); } /** * Send a TEXT event with the contents of the text buffer. * * This emits an EventHandler::text() event with the current contents of the * temporary text buffer. (The buffer is used to group as much PCDATA * as we can instead of emitting lots and lots of TEXT events.) */ protected function flushBuffer() { if ('' === $this->text) { return; } $this->events->text($this->text); $this->text = ''; } /** * Add text to the temporary buffer. * * @see flushBuffer() * * @param string $str */ protected function buffer($str) { $this->text .= $str; } /** * Emit a parse error. * * A parse error always returns false because it never consumes any * characters. * * @param string $msg * * @return string */ protected function parseError($msg) { $args = func_get_args(); if (count($args) > 1) { array_shift($args); $msg = vsprintf($msg, $args); } $line = $this->scanner->currentLine(); $col = $this->scanner->columnOffset(); $this->events->parseError($msg, $line, $col); return false; } /** * Decode a character reference and return the string. * * If $inAttribute is set to true, a bare & will be returned as-is. * * @param bool $inAttribute Set to true if the text is inside of an attribute value. * false otherwise. * * @return string */ protected function decodeCharacterReference($inAttribute = false) { // Next char after &. $tok = $this->scanner->next(); $start = $this->scanner->position(); if (false === $tok) { return '&'; } // These indicate not an entity. We return just // the &. if ("\t" === $tok || "\n" === $tok || "\f" === $tok || ' ' === $tok || '&' === $tok || '<' === $tok) { // $this->scanner->next(); return '&'; } // Numeric entity if ('#' === $tok) { $tok = $this->scanner->next(); if (false === $tok) { $this->parseError('Expected &#DEC; &#HEX;, got EOF'); $this->scanner->unconsume(1); return '&'; } // Hexidecimal encoding. // X[0-9a-fA-F]+; // x[0-9a-fA-F]+; if ('x' === $tok || 'X' === $tok) { $tok = $this->scanner->next(); // Consume x // Convert from hex code to char. $hex = $this->scanner->getHex(); if (empty($hex)) { $this->parseError('Expected &#xHEX;, got &#x%s', $tok); // We unconsume because we don't know what parser rules might // be in effect for the remaining chars. For example. '&#>' // might result in a specific parsing rule inside of tag // contexts, while not inside of pcdata context. $this->scanner->unconsume(2); return '&'; } $entity = CharacterReference::lookupHex($hex); } // Decimal encoding. // [0-9]+; else { // Convert from decimal to char. $numeric = $this->scanner->getNumeric(); if (false === $numeric) { $this->parseError('Expected &#DIGITS;, got &#%s', $tok); $this->scanner->unconsume(2); return '&'; } $entity = CharacterReference::lookupDecimal($numeric); } } elseif ('=' === $tok && $inAttribute) { return '&'; } else { // String entity. // Attempt to consume a string up to a ';'. // [a-zA-Z0-9]+; $cname = $this->scanner->getAsciiAlphaNum(); $entity = CharacterReference::lookupName($cname); // When no entity is found provide the name of the unmatched string // and continue on as the & is not part of an entity. The & will // be converted to & elsewhere. if (null === $entity) { if (!$inAttribute || '' === $cname) { $this->parseError("No match in entity table for '%s'", $cname); } $this->scanner->unconsume($this->scanner->position() - $start); return '&'; } } // The scanner has advanced the cursor for us. $tok = $this->scanner->current(); // We have an entity. We're done here. if (';' === $tok) { $this->scanner->consume(); return $entity; } // Failing to match ; means unconsume the entire string. $this->scanner->unconsume($this->scanner->position() - $start); $this->parseError('Expected &ENTITY;, got &ENTITY%s (no trailing ;) ', $tok); return '&'; } /** * Checks whether a (single-byte) character is an ASCII letter or not. * * @param string $input A single-byte string * * @return bool True if it is a letter, False otherwise */ protected function is_alpha($input) { $code = ord($input); return ($code >= 97 && $code <= 122) || ($code >= 65 && $code <= 90); } } PKZ 3sg\\HTML5/Parser/EventHandler.phpnuW+A). * * @return int one of the Tokenizer::TEXTMODE_* constants */ public function startTag($name, $attributes = array(), $selfClosing = false); /** * An end-tag. */ public function endTag($name); /** * A comment section (unparsed character data). */ public function comment($cdata); /** * A unit of parsed character data. * * Entities in this text are *already decoded*. */ public function text($cdata); /** * Indicates that the document has been entirely processed. */ public function eof(); /** * Emitted when the parser encounters an error condition. */ public function parseError($msg, $line, $col); /** * A CDATA section. * * @param string $data * The unparsed character data */ public function cdata($data); /** * This is a holdover from the XML spec. * * While user agents don't get PIs, server-side does. * * @param string $name The name of the processor (e.g. 'php'). * @param string $data The unparsed data. */ public function processingInstruction($name, $data = null); } PKZr5u "HTML5/Parser/TreeBuildingRules.phpnuW+A 1, 'dd' => 1, 'dt' => 1, 'rt' => 1, 'rp' => 1, 'tr' => 1, 'th' => 1, 'td' => 1, 'thead' => 1, 'tfoot' => 1, 'tbody' => 1, 'table' => 1, 'optgroup' => 1, 'option' => 1, ); /** * Returns true if the given tagname has special processing rules. */ public function hasRules($tagname) { return isset(static::$tags[$tagname]); } /** * Evaluate the rule for the current tag name. * * This may modify the existing DOM. * * @return \DOMElement The new Current DOM element. */ public function evaluate($new, $current) { switch ($new->tagName) { case 'li': return $this->handleLI($new, $current); case 'dt': case 'dd': return $this->handleDT($new, $current); case 'rt': case 'rp': return $this->handleRT($new, $current); case 'optgroup': return $this->closeIfCurrentMatches($new, $current, array( 'optgroup', )); case 'option': return $this->closeIfCurrentMatches($new, $current, array( 'option', )); case 'tr': return $this->closeIfCurrentMatches($new, $current, array( 'tr', )); case 'td': case 'th': return $this->closeIfCurrentMatches($new, $current, array( 'th', 'td', )); case 'tbody': case 'thead': case 'tfoot': case 'table': // Spec isn't explicit about this, but it's necessary. return $this->closeIfCurrentMatches($new, $current, array( 'thead', 'tfoot', 'tbody', )); } return $current; } protected function handleLI($ele, $current) { return $this->closeIfCurrentMatches($ele, $current, array( 'li', )); } protected function handleDT($ele, $current) { return $this->closeIfCurrentMatches($ele, $current, array( 'dt', 'dd', )); } protected function handleRT($ele, $current) { return $this->closeIfCurrentMatches($ele, $current, array( 'rt', 'rp', )); } protected function closeIfCurrentMatches($ele, $current, $match) { if (in_array($current->tagName, $match, true)) { $current->parentNode->appendChild($ele); } else { $current->appendChild($ele); } return $ele; } } PKZw[ HTML5/Parser/FileInputStream.phpnuW+A false, // Prevents the parser from automatically assigning the HTML5 namespace to the DOM document. 'disable_html_ns' => false, ); protected $errors = array(); public function __construct(array $defaultOptions = array()) { $this->defaultOptions = array_merge($this->defaultOptions, $defaultOptions); } /** * Get the current default options. * * @return array */ public function getOptions() { return $this->defaultOptions; } /** * Load and parse an HTML file. * * This will apply the HTML5 parser, which is tolerant of many * varieties of HTML, including XHTML 1, HTML 4, and well-formed HTML * 3. Note that in these cases, not all of the old data will be * preserved. For example, XHTML's XML declaration will be removed. * * The rules governing parsing are set out in the HTML 5 spec. * * @param string|resource $file The path to the file to parse. If this is a resource, it is * assumed to be an open stream whose pointer is set to the first * byte of input. * @param array $options Configuration options when parsing the HTML. * * @return \DOMDocument A DOM document. These object type is defined by the libxml * library, and should have been included with your version of PHP. */ public function load($file, array $options = array()) { // Handle the case where file is a resource. if (is_resource($file)) { return $this->parse(stream_get_contents($file), $options); } return $this->parse(file_get_contents($file), $options); } /** * Parse a HTML Document from a string. * * Take a string of HTML 5 (or earlier) and parse it into a * DOMDocument. * * @param string $string A html5 document as a string. * @param array $options Configuration options when parsing the HTML. * * @return \DOMDocument A DOM document. DOM is part of libxml, which is included with * almost all distribtions of PHP. */ public function loadHTML($string, array $options = array()) { return $this->parse($string, $options); } /** * Convenience function to load an HTML file. * * This is here to provide backwards compatibility with the * PHP DOM implementation. It simply calls load(). * * @param string $file The path to the file to parse. If this is a resource, it is * assumed to be an open stream whose pointer is set to the first * byte of input. * @param array $options Configuration options when parsing the HTML. * * @return \DOMDocument A DOM document. These object type is defined by the libxml * library, and should have been included with your version of PHP. */ public function loadHTMLFile($file, array $options = array()) { return $this->load($file, $options); } /** * Parse a HTML fragment from a string. * * @param string $string the HTML5 fragment as a string * @param array $options Configuration options when parsing the HTML * * @return \DOMDocumentFragment A DOM fragment. The DOM is part of libxml, which is included with * almost all distributions of PHP. */ public function loadHTMLFragment($string, array $options = array()) { return $this->parseFragment($string, $options); } /** * Return all errors encountered into parsing phase. * * @return array */ public function getErrors() { return $this->errors; } /** * Return true it some errors were encountered into parsing phase. * * @return bool */ public function hasErrors() { return count($this->errors) > 0; } /** * Parse an input string. * * @param string $input * @param array $options * * @return \DOMDocument */ public function parse($input, array $options = array()) { $this->errors = array(); $options = array_merge($this->defaultOptions, $options); $events = new DOMTreeBuilder(false, $options); $scanner = new Scanner($input, !empty($options['encoding']) ? $options['encoding'] : 'UTF-8'); $parser = new Tokenizer($scanner, $events, !empty($options['xmlNamespaces']) ? Tokenizer::CONFORMANT_XML : Tokenizer::CONFORMANT_HTML); $parser->parse(); $this->errors = $events->getErrors(); return $events->document(); } /** * Parse an input stream where the stream is a fragment. * * Lower-level loading function. This requires an input stream instead * of a string, file, or resource. * * @param string $input The input data to parse in the form of a string. * @param array $options An array of options. * * @return \DOMDocumentFragment */ public function parseFragment($input, array $options = array()) { $options = array_merge($this->defaultOptions, $options); $events = new DOMTreeBuilder(true, $options); $scanner = new Scanner($input, !empty($options['encoding']) ? $options['encoding'] : 'UTF-8'); $parser = new Tokenizer($scanner, $events, !empty($options['xmlNamespaces']) ? Tokenizer::CONFORMANT_XML : Tokenizer::CONFORMANT_HTML); $parser->parse(); $this->errors = $events->getErrors(); return $events->fragment(); } /** * Save a DOM into a given file as HTML5. * * @param mixed $dom The DOM to be serialized. * @param string|resource $file The filename to be written or resource to write to. * @param array $options Configuration options when serializing the DOM. These include: * - encode_entities: Text written to the output is escaped by default and not all * entities are encoded. If this is set to true all entities will be encoded. * Defaults to false. */ public function save($dom, $file, $options = array()) { $close = true; if (is_resource($file)) { $stream = $file; $close = false; } else { $stream = fopen($file, 'wb'); } $options = array_merge($this->defaultOptions, $options); $rules = new OutputRules($stream, $options); $trav = new Traverser($dom, $stream, $rules, $options); $trav->walk(); /* * release the traverser to avoid cyclic references and allow PHP to free memory without waiting for gc_collect_cycles */ $rules->unsetTraverser(); if ($close) { fclose($stream); } } /** * Convert a DOM into an HTML5 string. * * @param mixed $dom The DOM to be serialized. * @param array $options Configuration options when serializing the DOM. These include: * - encode_entities: Text written to the output is escaped by default and not all * entities are encoded. If this is set to true all entities will be encoded. * Defaults to false. * * @return string A HTML5 documented generated from the DOM. */ public function saveHTML($dom, $options = array()) { $stream = fopen('php://temp', 'wb'); $this->save($dom, $stream, array_merge($this->defaultOptions, $options)); $html = stream_get_contents($stream, -1, 0); fclose($stream); return $html; } } PKZGPDFMerger/PDFMerger.phpnuW+A_rewritepages($pages); } $this->_files[] = array($filepath, $pages, $orientation); } else { throw new Exception("Could not locate PDF on '$filepath'"); } return $this; } /** * Merges your provided PDFs and outputs to specified location. * @param $outputmode * @param $outputname * @param $orientation * @return PDF */ public function merge($outputmode = 'browser', $outputpath = 'newfile.pdf', $orientation = 'A') { if (!isset($this->_files) || !is_array($this->_files)) { throw new Exception("No PDFs to merge."); } $fpdi = new Fpdi(); // merger operations foreach ($this->_files as $file) { $filename = $file[0]; $filepages = $file[1]; $fileorientation = (!is_null($file[2])) ? $file[2] : $orientation; $count = $fpdi->setSourceFile($filename); //add the pages if ($filepages == 'all') { for ($i=1; $i<=$count; $i++) { $template = $fpdi->importPage($i); $size = $fpdi->getTemplateSize($template); $pageOrientation = ($size['width'] > $size['height']) ? 'L' : 'P'; // Determine orientation for this specific page if($fileorientation !== 'A') { // If an orientation was provided for the whole document, use it $pageOrientation = $fileorientation; } $fpdi->AddPage($pageOrientation, array($size['width'], $size['height'])); $fpdi->useTemplate($template); } } else { foreach ($filepages as $page) { if (!$template = $fpdi->importPage($page)) { throw new Exception("Could not load page '$page' in PDF '$filename'. Check that the page exists."); } $size = $fpdi->getTemplateSize($template); $pageOrientation = ($size['width'] > $size['height']) ? 'L' : 'P'; // Determine orientation for this specific page if($fileorientation !== 'A') { // If an orientation was provided for the whole document, use it $pageOrientation = $fileorientation; } $fpdi->AddPage($pageOrientation, array($size['width'], $size['height'])); $fpdi->useTemplate($template); } } } //output operations $mode = $this->_switchmode($outputmode); if ($mode == 'S') { return $fpdi->Output($outputpath, 'S'); } else { if ($fpdi->Output($outputpath, $mode) == '') { return true; } else { throw new Exception("Error outputting PDF to '$outputmode'."); return false; } } } /** * FPDI uses single characters for specifying the output location. Change our more descriptive string into proper format. * @param $mode * @return Character */ private function _switchmode($mode) { switch(strtolower($mode)) { case 'download': return 'D'; break; case 'browser': return 'I'; break; case 'file': return 'F'; break; case 'string': return 'S'; break; default: return 'I'; break; } } /** * Takes our provided pages in the form of 1,3,4,16-50 and creates an array of all pages * @param $pages * @return unknown_type */ private function _rewritepages($pages) { $pages = str_replace(' ', '', $pages); $part = explode(',', $pages); //parse hyphens foreach ($part as $i) { $ind = explode('-', $i); if (count($ind) == 2) { $x = $ind[0]; //start page $y = $ind[1]; //end page if ($x > $y) { throw new Exception("Starting page, '$x' is greater than ending page '$y'."); return false; } //add middle pages while ($x <= $y) { $newpages[] = (int) $x; $x++; } } else { $newpages[] = (int) $ind[0]; } } return $newpages; } } PKZřPDFMerger/sample.phpnuW+AaddPDF('samplepdfs/one.pdf', '1, 3, 4') ->addPDF('samplepdfs/two.pdf', '1-2') ->addPDF('samplepdfs/three.pdf', 'all') ->merge('file', 'samplepdfs/TEST2.pdf'); //REPLACE 'file' WITH 'browser', 'download', 'string', or 'file' for output options //You do not need to give a file path for browser, string, or download - just the name. PKZJ  ClassMethodUnit.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeUnit; /** * @psalm-immutable */ final class ClassMethodUnit extends CodeUnit { /** * @psalm-assert-if-true ClassMethodUnit $this */ public function isClassMethod(): bool { return true; } } PKZΖexceptions/NoTraitException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeUnit; use RuntimeException; final class NoTraitException extends RuntimeException implements Exception { } PKZ6*a'exceptions/InvalidCodeUnitException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeUnit; use RuntimeException; final class InvalidCodeUnitException extends RuntimeException implements Exception { } PKZO"exceptions/ReflectionException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeUnit; use RuntimeException; final class ReflectionException extends RuntimeException implements Exception { } PKZ ֽCodeUnitCollection.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeUnit; use function array_merge; use function count; use Countable; use IteratorAggregate; final class CodeUnitCollection implements Countable, IteratorAggregate { /** * @psalm-var list */ private $codeUnits = []; /** * @psalm-param list $items */ public static function fromArray(array $items): self { $collection = new self; foreach ($items as $item) { $collection->add($item); } return $collection; } public static function fromList(CodeUnit ...$items): self { return self::fromArray($items); } private function __construct() { } /** * @psalm-return list */ public function asArray(): array { return $this->codeUnits; } public function getIterator(): CodeUnitCollectionIterator { return new CodeUnitCollectionIterator($this); } public function count(): int { return count($this->codeUnits); } public function isEmpty(): bool { return empty($this->codeUnits); } public function mergeWith(self $other): self { return self::fromArray( array_merge( $this->asArray(), $other->asArray() ) ); } private function add(CodeUnit $item): void { $this->codeUnits[] = $item; } } PKZ=%tInterfaceUnit.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeUnit; /** * @psalm-immutable */ final class InterfaceUnit extends CodeUnit { /** * @psalm-assert-if-true InterfaceUnit $this */ public function isInterface(): bool { return true; } } PKZx/,, CodeUnit.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeUnit; use function range; use function sprintf; use ReflectionClass; use ReflectionFunction; use ReflectionMethod; /** * @psalm-immutable */ abstract class CodeUnit { /** * @var string */ private $name; /** * @var string */ private $sourceFileName; /** * @var array * @psalm-var list */ private $sourceLines; /** * @psalm-param class-string $className * * @throws InvalidCodeUnitException * @throws ReflectionException */ public static function forClass(string $className): ClassUnit { self::ensureUserDefinedClass($className); $reflector = self::reflectorForClass($className); return new ClassUnit( $className, $reflector->getFileName(), range( $reflector->getStartLine(), $reflector->getEndLine() ) ); } /** * @psalm-param class-string $className * * @throws InvalidCodeUnitException * @throws ReflectionException */ public static function forClassMethod(string $className, string $methodName): ClassMethodUnit { self::ensureUserDefinedClass($className); $reflector = self::reflectorForClassMethod($className, $methodName); return new ClassMethodUnit( $className . '::' . $methodName, $reflector->getFileName(), range( $reflector->getStartLine(), $reflector->getEndLine() ) ); } /** * @psalm-param class-string $interfaceName * * @throws InvalidCodeUnitException * @throws ReflectionException */ public static function forInterface(string $interfaceName): InterfaceUnit { self::ensureUserDefinedInterface($interfaceName); $reflector = self::reflectorForClass($interfaceName); return new InterfaceUnit( $interfaceName, $reflector->getFileName(), range( $reflector->getStartLine(), $reflector->getEndLine() ) ); } /** * @psalm-param class-string $interfaceName * * @throws InvalidCodeUnitException * @throws ReflectionException */ public static function forInterfaceMethod(string $interfaceName, string $methodName): InterfaceMethodUnit { self::ensureUserDefinedInterface($interfaceName); $reflector = self::reflectorForClassMethod($interfaceName, $methodName); return new InterfaceMethodUnit( $interfaceName . '::' . $methodName, $reflector->getFileName(), range( $reflector->getStartLine(), $reflector->getEndLine() ) ); } /** * @psalm-param class-string $traitName * * @throws InvalidCodeUnitException * @throws ReflectionException */ public static function forTrait(string $traitName): TraitUnit { self::ensureUserDefinedTrait($traitName); $reflector = self::reflectorForClass($traitName); return new TraitUnit( $traitName, $reflector->getFileName(), range( $reflector->getStartLine(), $reflector->getEndLine() ) ); } /** * @psalm-param class-string $traitName * * @throws InvalidCodeUnitException * @throws ReflectionException */ public static function forTraitMethod(string $traitName, string $methodName): TraitMethodUnit { self::ensureUserDefinedTrait($traitName); $reflector = self::reflectorForClassMethod($traitName, $methodName); return new TraitMethodUnit( $traitName . '::' . $methodName, $reflector->getFileName(), range( $reflector->getStartLine(), $reflector->getEndLine() ) ); } /** * @psalm-param callable-string $functionName * * @throws InvalidCodeUnitException * @throws ReflectionException */ public static function forFunction(string $functionName): FunctionUnit { $reflector = self::reflectorForFunction($functionName); if (!$reflector->isUserDefined()) { throw new InvalidCodeUnitException( sprintf( '"%s" is not a user-defined function', $functionName ) ); } return new FunctionUnit( $functionName, $reflector->getFileName(), range( $reflector->getStartLine(), $reflector->getEndLine() ) ); } /** * @psalm-param list $sourceLines */ private function __construct(string $name, string $sourceFileName, array $sourceLines) { $this->name = $name; $this->sourceFileName = $sourceFileName; $this->sourceLines = $sourceLines; } public function name(): string { return $this->name; } public function sourceFileName(): string { return $this->sourceFileName; } /** * @psalm-return list */ public function sourceLines(): array { return $this->sourceLines; } public function isClass(): bool { return false; } public function isClassMethod(): bool { return false; } public function isInterface(): bool { return false; } public function isInterfaceMethod(): bool { return false; } public function isTrait(): bool { return false; } public function isTraitMethod(): bool { return false; } public function isFunction(): bool { return false; } /** * @psalm-param class-string $className * * @throws InvalidCodeUnitException */ private static function ensureUserDefinedClass(string $className): void { try { $reflector = new ReflectionClass($className); if ($reflector->isInterface()) { throw new InvalidCodeUnitException( sprintf( '"%s" is an interface and not a class', $className ) ); } if ($reflector->isTrait()) { throw new InvalidCodeUnitException( sprintf( '"%s" is a trait and not a class', $className ) ); } if (!$reflector->isUserDefined()) { throw new InvalidCodeUnitException( sprintf( '"%s" is not a user-defined class', $className ) ); } // @codeCoverageIgnoreStart } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), (int) $e->getCode(), $e ); } // @codeCoverageIgnoreEnd } /** * @psalm-param class-string $interfaceName * * @throws InvalidCodeUnitException */ private static function ensureUserDefinedInterface(string $interfaceName): void { try { $reflector = new ReflectionClass($interfaceName); if (!$reflector->isInterface()) { throw new InvalidCodeUnitException( sprintf( '"%s" is not an interface', $interfaceName ) ); } if (!$reflector->isUserDefined()) { throw new InvalidCodeUnitException( sprintf( '"%s" is not a user-defined interface', $interfaceName ) ); } // @codeCoverageIgnoreStart } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), (int) $e->getCode(), $e ); } // @codeCoverageIgnoreEnd } /** * @psalm-param class-string $traitName * * @throws InvalidCodeUnitException */ private static function ensureUserDefinedTrait(string $traitName): void { try { $reflector = new ReflectionClass($traitName); if (!$reflector->isTrait()) { throw new InvalidCodeUnitException( sprintf( '"%s" is not a trait', $traitName ) ); } // @codeCoverageIgnoreStart if (!$reflector->isUserDefined()) { throw new InvalidCodeUnitException( sprintf( '"%s" is not a user-defined trait', $traitName ) ); } } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), (int) $e->getCode(), $e ); } // @codeCoverageIgnoreEnd } /** * @psalm-param class-string $className * * @throws ReflectionException */ private static function reflectorForClass(string $className): ReflectionClass { try { return new ReflectionClass($className); // @codeCoverageIgnoreStart } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), (int) $e->getCode(), $e ); } // @codeCoverageIgnoreEnd } /** * @psalm-param class-string $className * * @throws ReflectionException */ private static function reflectorForClassMethod(string $className, string $methodName): ReflectionMethod { try { return new ReflectionMethod($className, $methodName); // @codeCoverageIgnoreStart } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), (int) $e->getCode(), $e ); } // @codeCoverageIgnoreEnd } /** * @psalm-param callable-string $functionName * * @throws ReflectionException */ private static function reflectorForFunction(string $functionName): ReflectionFunction { try { return new ReflectionFunction($functionName); // @codeCoverageIgnoreStart } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), (int) $e->getCode(), $e ); } // @codeCoverageIgnoreEnd } } PKZ~{$// Mapper.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeUnit; use function array_keys; use function array_merge; use function array_unique; use function array_values; use function class_exists; use function explode; use function function_exists; use function interface_exists; use function ksort; use function method_exists; use function sort; use function sprintf; use function str_replace; use function strpos; use function trait_exists; use ReflectionClass; use ReflectionFunction; use ReflectionMethod; final class Mapper { /** * @psalm-return array> */ public function codeUnitsToSourceLines(CodeUnitCollection $codeUnits): array { $result = []; foreach ($codeUnits as $codeUnit) { $sourceFileName = $codeUnit->sourceFileName(); if (!isset($result[$sourceFileName])) { $result[$sourceFileName] = []; } $result[$sourceFileName] = array_merge($result[$sourceFileName], $codeUnit->sourceLines()); } foreach (array_keys($result) as $sourceFileName) { $result[$sourceFileName] = array_values(array_unique($result[$sourceFileName])); sort($result[$sourceFileName]); } ksort($result); return $result; } /** * @throws InvalidCodeUnitException * @throws ReflectionException */ public function stringToCodeUnits(string $unit): CodeUnitCollection { if (strpos($unit, '::') !== false) { [$firstPart, $secondPart] = explode('::', $unit); if (empty($firstPart) && $this->isUserDefinedFunction($secondPart)) { return CodeUnitCollection::fromList(CodeUnit::forFunction($secondPart)); } if ($this->isUserDefinedClass($firstPart)) { if ($secondPart === '') { return $this->publicMethodsOfClass($firstPart); } if ($secondPart === '') { return $this->protectedAndPrivateMethodsOfClass($firstPart); } if ($secondPart === '') { return $this->protectedMethodsOfClass($firstPart); } if ($secondPart === '') { return $this->publicAndPrivateMethodsOfClass($firstPart); } if ($secondPart === '') { return $this->privateMethodsOfClass($firstPart); } if ($secondPart === '') { return $this->publicAndProtectedMethodsOfClass($firstPart); } if ($this->isUserDefinedMethod($firstPart, $secondPart)) { return CodeUnitCollection::fromList(CodeUnit::forClassMethod($firstPart, $secondPart)); } } if ($this->isUserDefinedInterface($firstPart)) { return CodeUnitCollection::fromList(CodeUnit::forInterfaceMethod($firstPart, $secondPart)); } if ($this->isUserDefinedTrait($firstPart)) { return CodeUnitCollection::fromList(CodeUnit::forTraitMethod($firstPart, $secondPart)); } } else { if ($this->isUserDefinedClass($unit)) { $units = [CodeUnit::forClass($unit)]; foreach ($this->reflectorForClass($unit)->getTraits() as $trait) { if (!$trait->isUserDefined()) { // @codeCoverageIgnoreStart continue; // @codeCoverageIgnoreEnd } $units[] = CodeUnit::forTrait($trait->getName()); } return CodeUnitCollection::fromArray($units); } if ($this->isUserDefinedInterface($unit)) { return CodeUnitCollection::fromList(CodeUnit::forInterface($unit)); } if ($this->isUserDefinedTrait($unit)) { return CodeUnitCollection::fromList(CodeUnit::forTrait($unit)); } if ($this->isUserDefinedFunction($unit)) { return CodeUnitCollection::fromList(CodeUnit::forFunction($unit)); } $unit = str_replace('', '', $unit); if ($this->isUserDefinedClass($unit)) { return $this->classAndParentClassesAndTraits($unit); } } throw new InvalidCodeUnitException( sprintf( '"%s" is not a valid code unit', $unit ) ); } /** * @psalm-param class-string $className * * @throws ReflectionException */ private function publicMethodsOfClass(string $className): CodeUnitCollection { return $this->methodsOfClass($className, ReflectionMethod::IS_PUBLIC); } /** * @psalm-param class-string $className * * @throws ReflectionException */ private function publicAndProtectedMethodsOfClass(string $className): CodeUnitCollection { return $this->methodsOfClass($className, ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED); } /** * @psalm-param class-string $className * * @throws ReflectionException */ private function publicAndPrivateMethodsOfClass(string $className): CodeUnitCollection { return $this->methodsOfClass($className, ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PRIVATE); } /** * @psalm-param class-string $className * * @throws ReflectionException */ private function protectedMethodsOfClass(string $className): CodeUnitCollection { return $this->methodsOfClass($className, ReflectionMethod::IS_PROTECTED); } /** * @psalm-param class-string $className * * @throws ReflectionException */ private function protectedAndPrivateMethodsOfClass(string $className): CodeUnitCollection { return $this->methodsOfClass($className, ReflectionMethod::IS_PROTECTED | ReflectionMethod::IS_PRIVATE); } /** * @psalm-param class-string $className * * @throws ReflectionException */ private function privateMethodsOfClass(string $className): CodeUnitCollection { return $this->methodsOfClass($className, ReflectionMethod::IS_PRIVATE); } /** * @psalm-param class-string $className * * @throws ReflectionException */ private function methodsOfClass(string $className, int $filter): CodeUnitCollection { $units = []; foreach ($this->reflectorForClass($className)->getMethods($filter) as $method) { if (!$method->isUserDefined()) { continue; } $units[] = CodeUnit::forClassMethod($className, $method->getName()); } return CodeUnitCollection::fromArray($units); } /** * @psalm-param class-string $className * * @throws ReflectionException */ private function classAndParentClassesAndTraits(string $className): CodeUnitCollection { $units = [CodeUnit::forClass($className)]; $reflector = $this->reflectorForClass($className); foreach ($this->reflectorForClass($className)->getTraits() as $trait) { if (!$trait->isUserDefined()) { // @codeCoverageIgnoreStart continue; // @codeCoverageIgnoreEnd } $units[] = CodeUnit::forTrait($trait->getName()); } while ($reflector = $reflector->getParentClass()) { if (!$reflector->isUserDefined()) { break; } $units[] = CodeUnit::forClass($reflector->getName()); foreach ($reflector->getTraits() as $trait) { if (!$trait->isUserDefined()) { // @codeCoverageIgnoreStart continue; // @codeCoverageIgnoreEnd } $units[] = CodeUnit::forTrait($trait->getName()); } } return CodeUnitCollection::fromArray($units); } /** * @psalm-param class-string $className * * @throws ReflectionException */ private function reflectorForClass(string $className): ReflectionClass { try { return new ReflectionClass($className); // @codeCoverageIgnoreStart } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), (int) $e->getCode(), $e ); } // @codeCoverageIgnoreEnd } /** * @throws ReflectionException */ private function isUserDefinedFunction(string $functionName): bool { if (!function_exists($functionName)) { return false; } try { return (new ReflectionFunction($functionName))->isUserDefined(); // @codeCoverageIgnoreStart } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), (int) $e->getCode(), $e ); } // @codeCoverageIgnoreEnd } /** * @throws ReflectionException */ private function isUserDefinedClass(string $className): bool { if (!class_exists($className)) { return false; } try { return (new ReflectionClass($className))->isUserDefined(); // @codeCoverageIgnoreStart } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), (int) $e->getCode(), $e ); } // @codeCoverageIgnoreEnd } /** * @throws ReflectionException */ private function isUserDefinedInterface(string $interfaceName): bool { if (!interface_exists($interfaceName)) { return false; } try { return (new ReflectionClass($interfaceName))->isUserDefined(); // @codeCoverageIgnoreStart } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), (int) $e->getCode(), $e ); } // @codeCoverageIgnoreEnd } /** * @throws ReflectionException */ private function isUserDefinedTrait(string $traitName): bool { if (!trait_exists($traitName)) { return false; } try { return (new ReflectionClass($traitName))->isUserDefined(); // @codeCoverageIgnoreStart } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), (int) $e->getCode(), $e ); } // @codeCoverageIgnoreEnd } /** * @throws ReflectionException */ private function isUserDefinedMethod(string $className, string $methodName): bool { if (!class_exists($className)) { // @codeCoverageIgnoreStart return false; // @codeCoverageIgnoreEnd } if (!method_exists($className, $methodName)) { // @codeCoverageIgnoreStart return false; // @codeCoverageIgnoreEnd } try { return (new ReflectionMethod($className, $methodName))->isUserDefined(); // @codeCoverageIgnoreStart } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), (int) $e->getCode(), $e ); } // @codeCoverageIgnoreEnd } } PKZL wt44CodeUnitCollectionIterator.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeUnit; use Iterator; final class CodeUnitCollectionIterator implements Iterator { /** * @psalm-var list */ private $codeUnits; /** * @var int */ private $position = 0; public function __construct(CodeUnitCollection $collection) { $this->codeUnits = $collection->asArray(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return isset($this->codeUnits[$this->position]); } public function key(): int { return $this->position; } public function current(): CodeUnit { return $this->codeUnits[$this->position]; } public function next(): void { $this->position++; } } PKZTJ˿ TraitUnit.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeUnit; /** * @psalm-immutable */ final class TraitUnit extends CodeUnit { /** * @psalm-assert-if-true TraitUnit $this */ public function isTrait(): bool { return true; } } PKZl`InterfaceMethodUnit.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeUnit; /** * @psalm-immutable */ final class InterfaceMethodUnit extends CodeUnit { /** * @psalm-assert-if-true InterfaceMethod $this */ public function isInterfaceMethod(): bool { return true; } } PKZ 1Z  TraitMethodUnit.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeUnit; /** * @psalm-immutable */ final class TraitMethodUnit extends CodeUnit { /** * @psalm-assert-if-true TraitMethodUnit $this */ public function isTraitMethod(): bool { return true; } } PKZrYFunctionUnit.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeUnit; /** * @psalm-immutable */ final class FunctionUnit extends CodeUnit { /** * @psalm-assert-if-true FunctionUnit $this */ public function isFunction(): bool { return true; } } PKZm= ClassUnit.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeUnit; /** * @psalm-immutable */ final class ClassUnit extends CodeUnit { /** * @psalm-assert-if-true ClassUnit $this */ public function isClass(): bool { return true; } } PKZContainerInterface.phpnuW+A悞NotFoundExceptionInterface.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Webmozart\Assert; class InvalidArgumentException extends \InvalidArgumentException { } PKZObjectReflector.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\ObjectReflector; use function count; use function explode; use function get_class; use function is_object; class ObjectReflector { /** * @param object $object * * @throws InvalidArgumentException */ public function getAttributes($object): array { if (!is_object($object)) { throw new InvalidArgumentException; } $attributes = []; $className = get_class($object); foreach ((array) $object as $name => $value) { $name = explode("\0", (string) $name); if (count($name) === 1) { $name = $name[0]; } else { if ($name[1] !== $className) { $name = $name[1] . '::' . $name[2]; } else { $name = $name[2]; } } $attributes[$name] = $value; } return $attributes; } } PK:ZGww<Doctrine/Instantiator/Exception/UnexpectedValueException.phpnuW+A $reflectionClass * * @template T of object */ public static function fromSerializationTriggeredException( ReflectionClass $reflectionClass, Exception $exception, ): self { return new self( sprintf( 'An exception was raised while trying to instantiate an instance of "%s" via un-serialization', $reflectionClass->getName(), ), 0, $exception, ); } /** * @phpstan-param ReflectionClass $reflectionClass * * @template T of object */ public static function fromUncleanUnSerialization( ReflectionClass $reflectionClass, string $errorString, int $errorCode, string $errorFile, int $errorLine, ): self { return new self( sprintf( 'Could not produce an instance of "%s" via un-serialization, since an error was triggered ' . 'in file "%s" at line "%d"', $reflectionClass->getName(), $errorFile, $errorLine, ), 0, new Exception($errorString, $errorCode), ); } } PK:ZaV<Doctrine/Instantiator/Exception/InvalidArgumentException.phpnuW+A $reflectionClass * * @template T of object */ public static function fromAbstractClass(ReflectionClass $reflectionClass): self { return new self(sprintf( 'The provided class "%s" is abstract, and cannot be instantiated', $reflectionClass->getName(), )); } public static function fromEnum(string $className): self { return new self(sprintf( 'The provided class "%s" is an enum, and cannot be instantiated', $className, )); } } PK:Z8^"6Doctrine/Instantiator/Exception/ExceptionInterface.phpnuW+A $className * * @phpstan-return T * * @throws ExceptionInterface * * @template T of object */ public function instantiate(string $className): object; } PK:Z>w&Doctrine/Instantiator/Instantiator.phpnuW+A $className * * @phpstan-return T * * @throws ExceptionInterface * * @template T of object */ public function instantiate(string $className): object { if (isset(self::$cachedCloneables[$className])) { /** @phpstan-var T */ $cachedCloneable = self::$cachedCloneables[$className]; return clone $cachedCloneable; } if (isset(self::$cachedInstantiators[$className])) { $factory = self::$cachedInstantiators[$className]; return $factory(); } return $this->buildAndCacheFromFactory($className); } /** * Builds the requested object and caches it in static properties for performance * * @phpstan-param class-string $className * * @phpstan-return T * * @template T of object */ private function buildAndCacheFromFactory(string $className): object { $factory = self::$cachedInstantiators[$className] = $this->buildFactory($className); $instance = $factory(); if ($this->isSafeToClone(new ReflectionClass($instance))) { self::$cachedCloneables[$className] = clone $instance; } return $instance; } /** * Builds a callable capable of instantiating the given $className without * invoking its constructor. * * @phpstan-param class-string $className * * @phpstan-return callable(): T * * @throws InvalidArgumentException * @throws UnexpectedValueException * @throws ReflectionException * * @template T of object */ private function buildFactory(string $className): callable { $reflectionClass = $this->getReflectionClass($className); if ($this->isInstantiableViaReflection($reflectionClass)) { return [$reflectionClass, 'newInstanceWithoutConstructor']; } $serializedString = sprintf( '%s:%d:"%s":0:{}', is_subclass_of($className, Serializable::class) ? self::SERIALIZATION_FORMAT_USE_UNSERIALIZER : self::SERIALIZATION_FORMAT_AVOID_UNSERIALIZER, strlen($className), $className, ); $this->checkIfUnSerializationIsSupported($reflectionClass, $serializedString); return static fn () => unserialize($serializedString); } /** * @phpstan-param class-string $className * * @phpstan-return ReflectionClass * * @throws InvalidArgumentException * @throws ReflectionException * * @template T of object */ private function getReflectionClass(string $className): ReflectionClass { if (! class_exists($className)) { throw InvalidArgumentException::fromNonExistingClass($className); } if (enum_exists($className, false)) { throw InvalidArgumentException::fromEnum($className); } $reflection = new ReflectionClass($className); if ($reflection->isAbstract()) { throw InvalidArgumentException::fromAbstractClass($reflection); } return $reflection; } /** * @phpstan-param ReflectionClass $reflectionClass * * @throws UnexpectedValueException * * @template T of object */ private function checkIfUnSerializationIsSupported(ReflectionClass $reflectionClass, string $serializedString): void { set_error_handler(static function (int $code, string $message, string $file, int $line) use ($reflectionClass, &$error): bool { $error = UnexpectedValueException::fromUncleanUnSerialization( $reflectionClass, $message, $code, $file, $line, ); return true; }); try { $this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString); } finally { restore_error_handler(); } if ($error) { throw $error; } } /** * @phpstan-param ReflectionClass $reflectionClass * * @throws UnexpectedValueException * * @template T of object */ private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, string $serializedString): void { try { unserialize($serializedString); } catch (Exception $exception) { throw UnexpectedValueException::fromSerializationTriggeredException($reflectionClass, $exception); } } /** * @phpstan-param ReflectionClass $reflectionClass * * @template T of object */ private function isInstantiableViaReflection(ReflectionClass $reflectionClass): bool { return ! ($this->hasInternalAncestors($reflectionClass) && $reflectionClass->isFinal()); } /** * Verifies whether the given class is to be considered internal * * @phpstan-param ReflectionClass $reflectionClass * * @template T of object */ private function hasInternalAncestors(ReflectionClass $reflectionClass): bool { do { if ($reflectionClass->isInternal()) { return true; } $reflectionClass = $reflectionClass->getParentClass(); } while ($reflectionClass); return false; } /** * Checks if a class is cloneable * * Classes implementing `__clone` cannot be safely cloned, as that may cause side-effects. * * @phpstan-param ReflectionClass $reflectionClass * * @template T of object */ private function isSafeToClone(ReflectionClass $reflectionClass): bool { return $reflectionClass->isCloneable() && ! $reflectionClass->hasMethod('__clone') && ! $reflectionClass->isSubclassOf(ArrayIterator::class); } } PKZzcExtensionToMimeTypeMap.phpnuW+A9vExtensionMimeTypeDetector.phpnuW+Aextensions = $extensions ?: new GeneratedExtensionToMimeTypeMap(); } public function detectMimeType(string $path, $contents): ?string { return $this->detectMimeTypeFromPath($path); } public function detectMimeTypeFromPath(string $path): ?string { $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION)); return $this->extensions->lookupMimeType($extension); } public function detectMimeTypeFromFile(string $path): ?string { return $this->detectMimeTypeFromPath($path); } public function detectMimeTypeFromBuffer(string $contents): ?string { return null; } public function lookupExtension(string $mimetype): ?string { return $this->extensions instanceof ExtensionLookup ? $this->extensions->lookupExtension($mimetype) : null; } public function lookupAllExtensions(string $mimetype): array { return $this->extensions instanceof ExtensionLookup ? $this->extensions->lookupAllExtensions($mimetype) : []; } } PKZU^RRMimeTypeDetector.phpnuW+A * * @internal */ public const MIME_TYPES_FOR_EXTENSIONS = [ '1km' => 'application/vnd.1000minds.decision-model+xml', '3dml' => 'text/vnd.in3d.3dml', '3ds' => 'image/x-3ds', '3g2' => 'video/3gpp2', '3gp' => 'video/3gp', '3gpp' => 'video/3gpp', '3mf' => 'model/3mf', '7z' => 'application/x-7z-compressed', '7zip' => 'application/x-7z-compressed', '123' => 'application/vnd.lotus-1-2-3', 'aab' => 'application/x-authorware-bin', 'aac' => 'audio/acc', 'aam' => 'application/x-authorware-map', 'aas' => 'application/x-authorware-seg', 'abw' => 'application/x-abiword', 'ac' => 'application/vnd.nokia.n-gage.ac+xml', 'ac3' => 'audio/ac3', 'acc' => 'application/vnd.americandynamics.acc', 'ace' => 'application/x-ace-compressed', 'acu' => 'application/vnd.acucobol', 'acutc' => 'application/vnd.acucorp', 'adp' => 'audio/adpcm', 'adts' => 'audio/aac', 'aep' => 'application/vnd.audiograph', 'afm' => 'application/x-font-type1', 'afp' => 'application/vnd.ibm.modcap', 'age' => 'application/vnd.age', 'ahead' => 'application/vnd.ahead.space', 'ai' => 'application/pdf', 'aif' => 'audio/x-aiff', 'aifc' => 'audio/x-aiff', 'aiff' => 'audio/x-aiff', 'air' => 'application/vnd.adobe.air-application-installer-package+zip', 'ait' => 'application/vnd.dvb.ait', 'ami' => 'application/vnd.amiga.ami', 'aml' => 'application/automationml-aml+xml', 'amlx' => 'application/automationml-amlx+zip', 'amr' => 'audio/amr', 'apk' => 'application/vnd.android.package-archive', 'apng' => 'image/apng', 'appcache' => 'text/cache-manifest', 'appinstaller' => 'application/appinstaller', 'application' => 'application/x-ms-application', 'appx' => 'application/appx', 'appxbundle' => 'application/appxbundle', 'apr' => 'application/vnd.lotus-approach', 'arc' => 'application/x-freearc', 'arj' => 'application/x-arj', 'asc' => 'application/pgp-signature', 'asf' => 'video/x-ms-asf', 'asm' => 'text/x-asm', 'aso' => 'application/vnd.accpac.simply.aso', 'asx' => 'video/x-ms-asf', 'atc' => 'application/vnd.acucorp', 'atom' => 'application/atom+xml', 'atomcat' => 'application/atomcat+xml', 'atomdeleted' => 'application/atomdeleted+xml', 'atomsvc' => 'application/atomsvc+xml', 'atx' => 'application/vnd.antix.game-component', 'au' => 'audio/x-au', 'avci' => 'image/avci', 'avcs' => 'image/avcs', 'avi' => 'video/x-msvideo', 'avif' => 'image/avif', 'aw' => 'application/applixware', 'azf' => 'application/vnd.airzip.filesecure.azf', 'azs' => 'application/vnd.airzip.filesecure.azs', 'azv' => 'image/vnd.airzip.accelerator.azv', 'azw' => 'application/vnd.amazon.ebook', 'b16' => 'image/vnd.pco.b16', 'bary' => 'model/vnd.bary', 'bat' => 'application/x-msdownload', 'bcpio' => 'application/x-bcpio', 'bdf' => 'application/x-font-bdf', 'bdm' => 'application/vnd.syncml.dm+wbxml', 'bdo' => 'application/vnd.nato.bindingdataobject+xml', 'bdoc' => 'application/x-bdoc', 'bed' => 'application/vnd.realvnc.bed', 'bh2' => 'application/vnd.fujitsu.oasysprs', 'bin' => 'application/octet-stream', 'blb' => 'application/x-blorb', 'blorb' => 'application/x-blorb', 'bmi' => 'application/vnd.bmi', 'bmml' => 'application/vnd.balsamiq.bmml+xml', 'bmp' => 'image/bmp', 'book' => 'application/vnd.framemaker', 'box' => 'application/vnd.previewsystems.box', 'boz' => 'application/x-bzip2', 'bpk' => 'application/octet-stream', 'bpmn' => 'application/octet-stream', 'brf' => 'application/braille', 'bsp' => 'model/vnd.valve.source.compiled-map', 'btf' => 'image/prs.btif', 'btif' => 'image/prs.btif', 'buffer' => 'application/octet-stream', 'bz' => 'application/x-bzip', 'bz2' => 'application/x-bzip2', 'c' => 'text/x-c', 'c4d' => 'application/vnd.clonk.c4group', 'c4f' => 'application/vnd.clonk.c4group', 'c4g' => 'application/vnd.clonk.c4group', 'c4p' => 'application/vnd.clonk.c4group', 'c4u' => 'application/vnd.clonk.c4group', 'c11amc' => 'application/vnd.cluetrust.cartomobile-config', 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg', 'cab' => 'application/vnd.ms-cab-compressed', 'caf' => 'audio/x-caf', 'cap' => 'application/vnd.tcpdump.pcap', 'car' => 'application/vnd.curl.car', 'cat' => 'application/vnd.ms-pki.seccat', 'cb7' => 'application/x-cbr', 'cba' => 'application/x-cbr', 'cbr' => 'application/x-cbr', 'cbt' => 'application/x-cbr', 'cbz' => 'application/x-cbr', 'cc' => 'text/x-c', 'cco' => 'application/x-cocoa', 'cct' => 'application/x-director', 'ccxml' => 'application/ccxml+xml', 'cdbcmsg' => 'application/vnd.contact.cmsg', 'cdf' => 'application/x-netcdf', 'cdfx' => 'application/cdfx+xml', 'cdkey' => 'application/vnd.mediastation.cdkey', 'cdmia' => 'application/cdmi-capability', 'cdmic' => 'application/cdmi-container', 'cdmid' => 'application/cdmi-domain', 'cdmio' => 'application/cdmi-object', 'cdmiq' => 'application/cdmi-queue', 'cdr' => 'application/cdr', 'cdx' => 'chemical/x-cdx', 'cdxml' => 'application/vnd.chemdraw+xml', 'cdy' => 'application/vnd.cinderella', 'cer' => 'application/pkix-cert', 'cfs' => 'application/x-cfs-compressed', 'cgm' => 'image/cgm', 'chat' => 'application/x-chat', 'chm' => 'application/vnd.ms-htmlhelp', 'chrt' => 'application/vnd.kde.kchart', 'cif' => 'chemical/x-cif', 'cii' => 'application/vnd.anser-web-certificate-issue-initiation', 'cil' => 'application/vnd.ms-artgalry', 'cjs' => 'application/node', 'cla' => 'application/vnd.claymore', 'class' => 'application/octet-stream', 'cld' => 'model/vnd.cld', 'clkk' => 'application/vnd.crick.clicker.keyboard', 'clkp' => 'application/vnd.crick.clicker.palette', 'clkt' => 'application/vnd.crick.clicker.template', 'clkw' => 'application/vnd.crick.clicker.wordbank', 'clkx' => 'application/vnd.crick.clicker', 'clp' => 'application/x-msclip', 'cmc' => 'application/vnd.cosmocaller', 'cmdf' => 'chemical/x-cmdf', 'cml' => 'chemical/x-cml', 'cmp' => 'application/vnd.yellowriver-custom-menu', 'cmx' => 'image/x-cmx', 'cod' => 'application/vnd.rim.cod', 'coffee' => 'text/coffeescript', 'com' => 'application/x-msdownload', 'conf' => 'text/plain', 'cpio' => 'application/x-cpio', 'cpl' => 'application/cpl+xml', 'cpp' => 'text/x-c', 'cpt' => 'application/mac-compactpro', 'crd' => 'application/x-mscardfile', 'crl' => 'application/pkix-crl', 'crt' => 'application/x-x509-ca-cert', 'crx' => 'application/x-chrome-extension', 'cryptonote' => 'application/vnd.rig.cryptonote', 'csh' => 'application/x-csh', 'csl' => 'application/vnd.citationstyles.style+xml', 'csml' => 'chemical/x-csml', 'csp' => 'application/vnd.commonspace', 'csr' => 'application/octet-stream', 'css' => 'text/css', 'cst' => 'application/x-director', 'csv' => 'text/csv', 'cu' => 'application/cu-seeme', 'curl' => 'text/vnd.curl', 'cwl' => 'application/cwl', 'cww' => 'application/prs.cww', 'cxt' => 'application/x-director', 'cxx' => 'text/x-c', 'dae' => 'model/vnd.collada+xml', 'daf' => 'application/vnd.mobius.daf', 'dart' => 'application/vnd.dart', 'dataless' => 'application/vnd.fdsn.seed', 'davmount' => 'application/davmount+xml', 'dbf' => 'application/vnd.dbf', 'dbk' => 'application/docbook+xml', 'dcr' => 'application/x-director', 'dcurl' => 'text/vnd.curl.dcurl', 'dd2' => 'application/vnd.oma.dd2+xml', 'ddd' => 'application/vnd.fujixerox.ddd', 'ddf' => 'application/vnd.syncml.dmddf+xml', 'dds' => 'image/vnd.ms-dds', 'deb' => 'application/x-debian-package', 'def' => 'text/plain', 'deploy' => 'application/octet-stream', 'der' => 'application/x-x509-ca-cert', 'dfac' => 'application/vnd.dreamfactory', 'dgc' => 'application/x-dgc-compressed', 'dib' => 'image/bmp', 'dic' => 'text/x-c', 'dir' => 'application/x-director', 'dis' => 'application/vnd.mobius.dis', 'disposition-notification' => 'message/disposition-notification', 'dist' => 'application/octet-stream', 'distz' => 'application/octet-stream', 'djv' => 'image/vnd.djvu', 'djvu' => 'image/vnd.djvu', 'dll' => 'application/octet-stream', 'dmg' => 'application/x-apple-diskimage', 'dmn' => 'application/octet-stream', 'dmp' => 'application/vnd.tcpdump.pcap', 'dms' => 'application/octet-stream', 'dna' => 'application/vnd.dna', 'doc' => 'application/msword', 'docm' => 'application/vnd.ms-word.template.macroEnabled.12', 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'dot' => 'application/msword', 'dotm' => 'application/vnd.ms-word.template.macroEnabled.12', 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', 'dp' => 'application/vnd.osgi.dp', 'dpg' => 'application/vnd.dpgraph', 'dpx' => 'image/dpx', 'dra' => 'audio/vnd.dra', 'drle' => 'image/dicom-rle', 'dsc' => 'text/prs.lines.tag', 'dssc' => 'application/dssc+der', 'dst' => 'application/octet-stream', 'dtb' => 'application/x-dtbook+xml', 'dtd' => 'application/xml-dtd', 'dts' => 'audio/vnd.dts', 'dtshd' => 'audio/vnd.dts.hd', 'dump' => 'application/octet-stream', 'dvb' => 'video/vnd.dvb.file', 'dvi' => 'application/x-dvi', 'dwd' => 'application/atsc-dwd+xml', 'dwf' => 'model/vnd.dwf', 'dwg' => 'image/vnd.dwg', 'dxf' => 'image/vnd.dxf', 'dxp' => 'application/vnd.spotfire.dxp', 'dxr' => 'application/x-director', 'ear' => 'application/java-archive', 'ecelp4800' => 'audio/vnd.nuera.ecelp4800', 'ecelp7470' => 'audio/vnd.nuera.ecelp7470', 'ecelp9600' => 'audio/vnd.nuera.ecelp9600', 'ecma' => 'application/ecmascript', 'edm' => 'application/vnd.novadigm.edm', 'edx' => 'application/vnd.novadigm.edx', 'efif' => 'application/vnd.picsel', 'ei6' => 'application/vnd.pg.osasli', 'elc' => 'application/octet-stream', 'emf' => 'image/emf', 'eml' => 'message/rfc822', 'emma' => 'application/emma+xml', 'emotionml' => 'application/emotionml+xml', 'emz' => 'application/x-msmetafile', 'eol' => 'audio/vnd.digital-winds', 'eot' => 'application/vnd.ms-fontobject', 'eps' => 'application/postscript', 'epub' => 'application/epub+zip', 'es3' => 'application/vnd.eszigno3+xml', 'esa' => 'application/vnd.osgi.subsystem', 'esf' => 'application/vnd.epson.esf', 'et3' => 'application/vnd.eszigno3+xml', 'etx' => 'text/x-setext', 'eva' => 'application/x-eva', 'evy' => 'application/x-envoy', 'exe' => 'application/octet-stream', 'exi' => 'application/exi', 'exp' => 'application/express', 'exr' => 'image/aces', 'ext' => 'application/vnd.novadigm.ext', 'ez' => 'application/andrew-inset', 'ez2' => 'application/vnd.ezpix-album', 'ez3' => 'application/vnd.ezpix-package', 'f' => 'text/x-fortran', 'f4v' => 'video/mp4', 'f77' => 'text/x-fortran', 'f90' => 'text/x-fortran', 'fbs' => 'image/vnd.fastbidsheet', 'fcdt' => 'application/vnd.adobe.formscentral.fcdt', 'fcs' => 'application/vnd.isac.fcs', 'fdf' => 'application/vnd.fdf', 'fdt' => 'application/fdt+xml', 'fe_launch' => 'application/vnd.denovo.fcselayout-link', 'fg5' => 'application/vnd.fujitsu.oasysgp', 'fgd' => 'application/x-director', 'fh' => 'image/x-freehand', 'fh4' => 'image/x-freehand', 'fh5' => 'image/x-freehand', 'fh7' => 'image/x-freehand', 'fhc' => 'image/x-freehand', 'fig' => 'application/x-xfig', 'fits' => 'image/fits', 'flac' => 'audio/x-flac', 'fli' => 'video/x-fli', 'flo' => 'application/vnd.micrografx.flo', 'flv' => 'video/x-flv', 'flw' => 'application/vnd.kde.kivio', 'flx' => 'text/vnd.fmi.flexstor', 'fly' => 'text/vnd.fly', 'fm' => 'application/vnd.framemaker', 'fnc' => 'application/vnd.frogans.fnc', 'fo' => 'application/vnd.software602.filler.form+xml', 'for' => 'text/x-fortran', 'fpx' => 'image/vnd.fpx', 'frame' => 'application/vnd.framemaker', 'fsc' => 'application/vnd.fsc.weblaunch', 'fst' => 'image/vnd.fst', 'ftc' => 'application/vnd.fluxtime.clip', 'fti' => 'application/vnd.anser-web-funds-transfer-initiation', 'fvt' => 'video/vnd.fvt', 'fxp' => 'application/vnd.adobe.fxp', 'fxpl' => 'application/vnd.adobe.fxp', 'fzs' => 'application/vnd.fuzzysheet', 'g2w' => 'application/vnd.geoplan', 'g3' => 'image/g3fax', 'g3w' => 'application/vnd.geospace', 'gac' => 'application/vnd.groove-account', 'gam' => 'application/x-tads', 'gbr' => 'application/rpki-ghostbusters', 'gca' => 'application/x-gca-compressed', 'gdl' => 'model/vnd.gdl', 'gdoc' => 'application/vnd.google-apps.document', 'ged' => 'text/vnd.familysearch.gedcom', 'geo' => 'application/vnd.dynageo', 'geojson' => 'application/geo+json', 'gex' => 'application/vnd.geometry-explorer', 'ggb' => 'application/vnd.geogebra.file', 'ggs' => 'application/vnd.geogebra.slides', 'ggt' => 'application/vnd.geogebra.tool', 'ghf' => 'application/vnd.groove-help', 'gif' => 'image/gif', 'gim' => 'application/vnd.groove-identity-message', 'glb' => 'model/gltf-binary', 'gltf' => 'model/gltf+json', 'gml' => 'application/gml+xml', 'gmx' => 'application/vnd.gmx', 'gnumeric' => 'application/x-gnumeric', 'gpg' => 'application/gpg-keys', 'gph' => 'application/vnd.flographit', 'gpx' => 'application/gpx+xml', 'gqf' => 'application/vnd.grafeq', 'gqs' => 'application/vnd.grafeq', 'gram' => 'application/srgs', 'gramps' => 'application/x-gramps-xml', 'gre' => 'application/vnd.geometry-explorer', 'grv' => 'application/vnd.groove-injector', 'grxml' => 'application/srgs+xml', 'gsf' => 'application/x-font-ghostscript', 'gsheet' => 'application/vnd.google-apps.spreadsheet', 'gslides' => 'application/vnd.google-apps.presentation', 'gtar' => 'application/x-gtar', 'gtm' => 'application/vnd.groove-tool-message', 'gtw' => 'model/vnd.gtw', 'gv' => 'text/vnd.graphviz', 'gxf' => 'application/gxf', 'gxt' => 'application/vnd.geonext', 'gz' => 'application/gzip', 'gzip' => 'application/gzip', 'h' => 'text/x-c', 'h261' => 'video/h261', 'h263' => 'video/h263', 'h264' => 'video/h264', 'hal' => 'application/vnd.hal+xml', 'hbci' => 'application/vnd.hbci', 'hbs' => 'text/x-handlebars-template', 'hdd' => 'application/x-virtualbox-hdd', 'hdf' => 'application/x-hdf', 'heic' => 'image/heic', 'heics' => 'image/heic-sequence', 'heif' => 'image/heif', 'heifs' => 'image/heif-sequence', 'hej2' => 'image/hej2k', 'held' => 'application/atsc-held+xml', 'hh' => 'text/x-c', 'hjson' => 'application/hjson', 'hlp' => 'application/winhlp', 'hpgl' => 'application/vnd.hp-hpgl', 'hpid' => 'application/vnd.hp-hpid', 'hps' => 'application/vnd.hp-hps', 'hqx' => 'application/mac-binhex40', 'hsj2' => 'image/hsj2', 'htc' => 'text/x-component', 'htke' => 'application/vnd.kenameaapp', 'htm' => 'text/html', 'html' => 'text/html', 'hvd' => 'application/vnd.yamaha.hv-dic', 'hvp' => 'application/vnd.yamaha.hv-voice', 'hvs' => 'application/vnd.yamaha.hv-script', 'i2g' => 'application/vnd.intergeo', 'icc' => 'application/vnd.iccprofile', 'ice' => 'x-conference/x-cooltalk', 'icm' => 'application/vnd.iccprofile', 'ico' => 'image/x-icon', 'ics' => 'text/calendar', 'ief' => 'image/ief', 'ifb' => 'text/calendar', 'ifm' => 'application/vnd.shana.informed.formdata', 'iges' => 'model/iges', 'igl' => 'application/vnd.igloader', 'igm' => 'application/vnd.insors.igm', 'igs' => 'model/iges', 'igx' => 'application/vnd.micrografx.igx', 'iif' => 'application/vnd.shana.informed.interchange', 'img' => 'application/octet-stream', 'imp' => 'application/vnd.accpac.simply.imp', 'ims' => 'application/vnd.ms-ims', 'in' => 'text/plain', 'ini' => 'text/plain', 'ink' => 'application/inkml+xml', 'inkml' => 'application/inkml+xml', 'install' => 'application/x-install-instructions', 'iota' => 'application/vnd.astraea-software.iota', 'ipfix' => 'application/ipfix', 'ipk' => 'application/vnd.shana.informed.package', 'irm' => 'application/vnd.ibm.rights-management', 'irp' => 'application/vnd.irepository.package+xml', 'iso' => 'application/x-iso9660-image', 'itp' => 'application/vnd.shana.informed.formtemplate', 'its' => 'application/its+xml', 'ivp' => 'application/vnd.immervision-ivp', 'ivu' => 'application/vnd.immervision-ivu', 'jad' => 'text/vnd.sun.j2me.app-descriptor', 'jade' => 'text/jade', 'jam' => 'application/vnd.jam', 'jar' => 'application/java-archive', 'jardiff' => 'application/x-java-archive-diff', 'java' => 'text/x-java-source', 'jhc' => 'image/jphc', 'jisp' => 'application/vnd.jisp', 'jls' => 'image/jls', 'jlt' => 'application/vnd.hp-jlyt', 'jng' => 'image/x-jng', 'jnlp' => 'application/x-java-jnlp-file', 'joda' => 'application/vnd.joost.joda-archive', 'jp2' => 'image/jp2', 'jpe' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'jpf' => 'image/jpx', 'jpg' => 'image/jpeg', 'jpg2' => 'image/jp2', 'jpgm' => 'video/jpm', 'jpgv' => 'video/jpeg', 'jph' => 'image/jph', 'jpm' => 'video/jpm', 'jpx' => 'image/jpx', 'js' => 'application/javascript', 'json' => 'application/json', 'json5' => 'application/json5', 'jsonld' => 'application/ld+json', 'jsonml' => 'application/jsonml+json', 'jsx' => 'text/jsx', 'jt' => 'model/jt', 'jxl' => 'image/jxl', 'jxr' => 'image/jxr', 'jxra' => 'image/jxra', 'jxrs' => 'image/jxrs', 'jxs' => 'image/jxs', 'jxsc' => 'image/jxsc', 'jxsi' => 'image/jxsi', 'jxss' => 'image/jxss', 'kar' => 'audio/midi', 'karbon' => 'application/vnd.kde.karbon', 'kdb' => 'application/octet-stream', 'kdbx' => 'application/x-keepass2', 'key' => 'application/x-iwork-keynote-sffkey', 'kfo' => 'application/vnd.kde.kformula', 'kia' => 'application/vnd.kidspiration', 'kml' => 'application/vnd.google-earth.kml+xml', 'kmz' => 'application/vnd.google-earth.kmz', 'kne' => 'application/vnd.kinar', 'knp' => 'application/vnd.kinar', 'kon' => 'application/vnd.kde.kontour', 'kpr' => 'application/vnd.kde.kpresenter', 'kpt' => 'application/vnd.kde.kpresenter', 'kpxx' => 'application/vnd.ds-keypoint', 'ksp' => 'application/vnd.kde.kspread', 'ktr' => 'application/vnd.kahootz', 'ktx' => 'image/ktx', 'ktx2' => 'image/ktx2', 'ktz' => 'application/vnd.kahootz', 'kwd' => 'application/vnd.kde.kword', 'kwt' => 'application/vnd.kde.kword', 'lasxml' => 'application/vnd.las.las+xml', 'latex' => 'application/x-latex', 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop', 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml', 'les' => 'application/vnd.hhe.lesson-player', 'less' => 'text/less', 'lgr' => 'application/lgr+xml', 'lha' => 'application/octet-stream', 'link66' => 'application/vnd.route66.link66+xml', 'list' => 'text/plain', 'list3820' => 'application/vnd.ibm.modcap', 'listafp' => 'application/vnd.ibm.modcap', 'litcoffee' => 'text/coffeescript', 'lnk' => 'application/x-ms-shortcut', 'log' => 'text/plain', 'lostxml' => 'application/lost+xml', 'lrf' => 'application/octet-stream', 'lrm' => 'application/vnd.ms-lrm', 'ltf' => 'application/vnd.frogans.ltf', 'lua' => 'text/x-lua', 'luac' => 'application/x-lua-bytecode', 'lvp' => 'audio/vnd.lucent.voice', 'lwp' => 'application/vnd.lotus-wordpro', 'lzh' => 'application/octet-stream', 'm1v' => 'video/mpeg', 'm2a' => 'audio/mpeg', 'm2t' => 'video/mp2t', 'm2ts' => 'video/mp2t', 'm2v' => 'video/mpeg', 'm3a' => 'audio/mpeg', 'm3u' => 'text/plain', 'm3u8' => 'application/vnd.apple.mpegurl', 'm4a' => 'audio/x-m4a', 'm4p' => 'application/mp4', 'm4s' => 'video/iso.segment', 'm4u' => 'application/vnd.mpegurl', 'm4v' => 'video/x-m4v', 'm13' => 'application/x-msmediaview', 'm14' => 'application/x-msmediaview', 'm21' => 'application/mp21', 'ma' => 'application/mathematica', 'mads' => 'application/mads+xml', 'maei' => 'application/mmt-aei+xml', 'mag' => 'application/vnd.ecowin.chart', 'maker' => 'application/vnd.framemaker', 'man' => 'text/troff', 'manifest' => 'text/cache-manifest', 'map' => 'application/json', 'mar' => 'application/octet-stream', 'markdown' => 'text/markdown', 'mathml' => 'application/mathml+xml', 'mb' => 'application/mathematica', 'mbk' => 'application/vnd.mobius.mbk', 'mbox' => 'application/mbox', 'mc1' => 'application/vnd.medcalcdata', 'mcd' => 'application/vnd.mcd', 'mcurl' => 'text/vnd.curl.mcurl', 'md' => 'text/markdown', 'mdb' => 'application/x-msaccess', 'mdi' => 'image/vnd.ms-modi', 'mdx' => 'text/mdx', 'me' => 'text/troff', 'mesh' => 'model/mesh', 'meta4' => 'application/metalink4+xml', 'metalink' => 'application/metalink+xml', 'mets' => 'application/mets+xml', 'mfm' => 'application/vnd.mfmp', 'mft' => 'application/rpki-manifest', 'mgp' => 'application/vnd.osgeo.mapguide.package', 'mgz' => 'application/vnd.proteus.magazine', 'mid' => 'audio/midi', 'midi' => 'audio/midi', 'mie' => 'application/x-mie', 'mif' => 'application/vnd.mif', 'mime' => 'message/rfc822', 'mj2' => 'video/mj2', 'mjp2' => 'video/mj2', 'mjs' => 'text/javascript', 'mk3d' => 'video/x-matroska', 'mka' => 'audio/x-matroska', 'mkd' => 'text/x-markdown', 'mks' => 'video/x-matroska', 'mkv' => 'video/x-matroska', 'mlp' => 'application/vnd.dolby.mlp', 'mmd' => 'application/vnd.chipnuts.karaoke-mmd', 'mmf' => 'application/vnd.smaf', 'mml' => 'text/mathml', 'mmr' => 'image/vnd.fujixerox.edmics-mmr', 'mng' => 'video/x-mng', 'mny' => 'application/x-msmoney', 'mobi' => 'application/x-mobipocket-ebook', 'mods' => 'application/mods+xml', 'mov' => 'video/quicktime', 'movie' => 'video/x-sgi-movie', 'mp2' => 'audio/mpeg', 'mp2a' => 'audio/mpeg', 'mp3' => 'audio/mpeg', 'mp4' => 'video/mp4', 'mp4a' => 'audio/mp4', 'mp4s' => 'application/mp4', 'mp4v' => 'video/mp4', 'mp21' => 'application/mp21', 'mpc' => 'application/vnd.mophun.certificate', 'mpd' => 'application/dash+xml', 'mpe' => 'video/mpeg', 'mpeg' => 'video/mpeg', 'mpf' => 'application/media-policy-dataset+xml', 'mpg' => 'video/mpeg', 'mpg4' => 'video/mp4', 'mpga' => 'audio/mpeg', 'mpkg' => 'application/vnd.apple.installer+xml', 'mpm' => 'application/vnd.blueice.multipass', 'mpn' => 'application/vnd.mophun.application', 'mpp' => 'application/vnd.ms-project', 'mpt' => 'application/vnd.ms-project', 'mpy' => 'application/vnd.ibm.minipay', 'mqy' => 'application/vnd.mobius.mqy', 'mrc' => 'application/marc', 'mrcx' => 'application/marcxml+xml', 'ms' => 'text/troff', 'mscml' => 'application/mediaservercontrol+xml', 'mseed' => 'application/vnd.fdsn.mseed', 'mseq' => 'application/vnd.mseq', 'msf' => 'application/vnd.epson.msf', 'msg' => 'application/vnd.ms-outlook', 'msh' => 'model/mesh', 'msi' => 'application/x-msdownload', 'msix' => 'application/msix', 'msixbundle' => 'application/msixbundle', 'msl' => 'application/vnd.mobius.msl', 'msm' => 'application/octet-stream', 'msp' => 'application/octet-stream', 'msty' => 'application/vnd.muvee.style', 'mtl' => 'model/mtl', 'mts' => 'video/mp2t', 'mus' => 'application/vnd.musician', 'musd' => 'application/mmt-usd+xml', 'musicxml' => 'application/vnd.recordare.musicxml+xml', 'mvb' => 'application/x-msmediaview', 'mvt' => 'application/vnd.mapbox-vector-tile', 'mwf' => 'application/vnd.mfer', 'mxf' => 'application/mxf', 'mxl' => 'application/vnd.recordare.musicxml', 'mxmf' => 'audio/mobile-xmf', 'mxml' => 'application/xv+xml', 'mxs' => 'application/vnd.triscape.mxs', 'mxu' => 'video/vnd.mpegurl', 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install', 'n3' => 'text/n3', 'nb' => 'application/mathematica', 'nbp' => 'application/vnd.wolfram.player', 'nc' => 'application/x-netcdf', 'ncx' => 'application/x-dtbncx+xml', 'ndjson' => 'application/x-ndjson', 'nfo' => 'text/x-nfo', 'ngdat' => 'application/vnd.nokia.n-gage.data', 'nitf' => 'application/vnd.nitf', 'nlu' => 'application/vnd.neurolanguage.nlu', 'nml' => 'application/vnd.enliven', 'nnd' => 'application/vnd.noblenet-directory', 'nns' => 'application/vnd.noblenet-sealer', 'nnw' => 'application/vnd.noblenet-web', 'npx' => 'image/vnd.net-fpx', 'nq' => 'application/n-quads', 'nsc' => 'application/x-conference', 'nsf' => 'application/vnd.lotus-notes', 'nt' => 'application/n-triples', 'ntf' => 'application/vnd.nitf', 'numbers' => 'application/x-iwork-numbers-sffnumbers', 'nzb' => 'application/x-nzb', 'oa2' => 'application/vnd.fujitsu.oasys2', 'oa3' => 'application/vnd.fujitsu.oasys3', 'oas' => 'application/vnd.fujitsu.oasys', 'obd' => 'application/x-msbinder', 'obgx' => 'application/vnd.openblox.game+xml', 'obj' => 'model/obj', 'oda' => 'application/oda', 'odb' => 'application/vnd.oasis.opendocument.database', 'odc' => 'application/vnd.oasis.opendocument.chart', 'odf' => 'application/vnd.oasis.opendocument.formula', 'odft' => 'application/vnd.oasis.opendocument.formula-template', 'odg' => 'application/vnd.oasis.opendocument.graphics', 'odi' => 'application/vnd.oasis.opendocument.image', 'odm' => 'application/vnd.oasis.opendocument.text-master', 'odp' => 'application/vnd.oasis.opendocument.presentation', 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', 'odt' => 'application/vnd.oasis.opendocument.text', 'oga' => 'audio/ogg', 'ogex' => 'model/vnd.opengex', 'ogg' => 'audio/ogg', 'ogv' => 'video/ogg', 'ogx' => 'application/ogg', 'omdoc' => 'application/omdoc+xml', 'onepkg' => 'application/onenote', 'onetmp' => 'application/onenote', 'onetoc' => 'application/onenote', 'onetoc2' => 'application/onenote', 'opf' => 'application/oebps-package+xml', 'opml' => 'text/x-opml', 'oprc' => 'application/vnd.palm', 'opus' => 'audio/ogg', 'org' => 'text/x-org', 'osf' => 'application/vnd.yamaha.openscoreformat', 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml', 'osm' => 'application/vnd.openstreetmap.data+xml', 'otc' => 'application/vnd.oasis.opendocument.chart-template', 'otf' => 'font/otf', 'otg' => 'application/vnd.oasis.opendocument.graphics-template', 'oth' => 'application/vnd.oasis.opendocument.text-web', 'oti' => 'application/vnd.oasis.opendocument.image-template', 'otp' => 'application/vnd.oasis.opendocument.presentation-template', 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', 'ott' => 'application/vnd.oasis.opendocument.text-template', 'ova' => 'application/x-virtualbox-ova', 'ovf' => 'application/x-virtualbox-ovf', 'owl' => 'application/rdf+xml', 'oxps' => 'application/oxps', 'oxt' => 'application/vnd.openofficeorg.extension', 'p' => 'text/x-pascal', 'p7a' => 'application/x-pkcs7-signature', 'p7b' => 'application/x-pkcs7-certificates', 'p7c' => 'application/pkcs7-mime', 'p7m' => 'application/pkcs7-mime', 'p7r' => 'application/x-pkcs7-certreqresp', 'p7s' => 'application/pkcs7-signature', 'p8' => 'application/pkcs8', 'p10' => 'application/x-pkcs10', 'p12' => 'application/x-pkcs12', 'pac' => 'application/x-ns-proxy-autoconfig', 'pages' => 'application/x-iwork-pages-sffpages', 'pas' => 'text/x-pascal', 'paw' => 'application/vnd.pawaafile', 'pbd' => 'application/vnd.powerbuilder6', 'pbm' => 'image/x-portable-bitmap', 'pcap' => 'application/vnd.tcpdump.pcap', 'pcf' => 'application/x-font-pcf', 'pcl' => 'application/vnd.hp-pcl', 'pclxl' => 'application/vnd.hp-pclxl', 'pct' => 'image/x-pict', 'pcurl' => 'application/vnd.curl.pcurl', 'pcx' => 'image/x-pcx', 'pdb' => 'application/x-pilot', 'pde' => 'text/x-processing', 'pdf' => 'application/pdf', 'pem' => 'application/x-x509-user-cert', 'pfa' => 'application/x-font-type1', 'pfb' => 'application/x-font-type1', 'pfm' => 'application/x-font-type1', 'pfr' => 'application/font-tdpfr', 'pfx' => 'application/x-pkcs12', 'pgm' => 'image/x-portable-graymap', 'pgn' => 'application/x-chess-pgn', 'pgp' => 'application/pgp', 'phar' => 'application/octet-stream', 'php' => 'application/x-httpd-php', 'php3' => 'application/x-httpd-php', 'php4' => 'application/x-httpd-php', 'phps' => 'application/x-httpd-php-source', 'phtml' => 'application/x-httpd-php', 'pic' => 'image/x-pict', 'pkg' => 'application/octet-stream', 'pki' => 'application/pkixcmp', 'pkipath' => 'application/pkix-pkipath', 'pkpass' => 'application/vnd.apple.pkpass', 'pl' => 'application/x-perl', 'plb' => 'application/vnd.3gpp.pic-bw-large', 'plc' => 'application/vnd.mobius.plc', 'plf' => 'application/vnd.pocketlearn', 'pls' => 'application/pls+xml', 'pm' => 'application/x-perl', 'pml' => 'application/vnd.ctc-posml', 'png' => 'image/png', 'pnm' => 'image/x-portable-anymap', 'portpkg' => 'application/vnd.macports.portpkg', 'pot' => 'application/vnd.ms-powerpoint', 'potm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', 'ppa' => 'application/vnd.ms-powerpoint', 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12', 'ppd' => 'application/vnd.cups-ppd', 'ppm' => 'image/x-portable-pixmap', 'pps' => 'application/vnd.ms-powerpoint', 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12', 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', 'ppt' => 'application/powerpoint', 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'pqa' => 'application/vnd.palm', 'prc' => 'model/prc', 'pre' => 'application/vnd.lotus-freelance', 'prf' => 'application/pics-rules', 'provx' => 'application/provenance+xml', 'ps' => 'application/postscript', 'psb' => 'application/vnd.3gpp.pic-bw-small', 'psd' => 'application/x-photoshop', 'psf' => 'application/x-font-linux-psf', 'pskcxml' => 'application/pskc+xml', 'pti' => 'image/prs.pti', 'ptid' => 'application/vnd.pvi.ptid1', 'pub' => 'application/x-mspublisher', 'pv' => 'application/octet-stream', 'pvb' => 'application/vnd.3gpp.pic-bw-var', 'pwn' => 'application/vnd.3m.post-it-notes', 'pxf' => 'application/octet-stream', 'pya' => 'audio/vnd.ms-playready.media.pya', 'pyo' => 'model/vnd.pytha.pyox', 'pyox' => 'model/vnd.pytha.pyox', 'pyv' => 'video/vnd.ms-playready.media.pyv', 'qam' => 'application/vnd.epson.quickanime', 'qbo' => 'application/vnd.intu.qbo', 'qfx' => 'application/vnd.intu.qfx', 'qps' => 'application/vnd.publishare-delta-tree', 'qt' => 'video/quicktime', 'qwd' => 'application/vnd.quark.quarkxpress', 'qwt' => 'application/vnd.quark.quarkxpress', 'qxb' => 'application/vnd.quark.quarkxpress', 'qxd' => 'application/vnd.quark.quarkxpress', 'qxl' => 'application/vnd.quark.quarkxpress', 'qxt' => 'application/vnd.quark.quarkxpress', 'ra' => 'audio/x-realaudio', 'ram' => 'audio/x-pn-realaudio', 'raml' => 'application/raml+yaml', 'rapd' => 'application/route-apd+xml', 'rar' => 'application/x-rar', 'ras' => 'image/x-cmu-raster', 'rcprofile' => 'application/vnd.ipunplugged.rcprofile', 'rdf' => 'application/rdf+xml', 'rdz' => 'application/vnd.data-vision.rdz', 'relo' => 'application/p2p-overlay+xml', 'rep' => 'application/vnd.businessobjects', 'res' => 'application/x-dtbresource+xml', 'rgb' => 'image/x-rgb', 'rif' => 'application/reginfo+xml', 'rip' => 'audio/vnd.rip', 'ris' => 'application/x-research-info-systems', 'rl' => 'application/resource-lists+xml', 'rlc' => 'image/vnd.fujixerox.edmics-rlc', 'rld' => 'application/resource-lists-diff+xml', 'rm' => 'audio/x-pn-realaudio', 'rmi' => 'audio/midi', 'rmp' => 'audio/x-pn-realaudio-plugin', 'rms' => 'application/vnd.jcp.javame.midlet-rms', 'rmvb' => 'application/vnd.rn-realmedia-vbr', 'rnc' => 'application/relax-ng-compact-syntax', 'rng' => 'application/xml', 'roa' => 'application/rpki-roa', 'roff' => 'text/troff', 'rp9' => 'application/vnd.cloanto.rp9', 'rpm' => 'audio/x-pn-realaudio-plugin', 'rpss' => 'application/vnd.nokia.radio-presets', 'rpst' => 'application/vnd.nokia.radio-preset', 'rq' => 'application/sparql-query', 'rs' => 'application/rls-services+xml', 'rsa' => 'application/x-pkcs7', 'rsat' => 'application/atsc-rsat+xml', 'rsd' => 'application/rsd+xml', 'rsheet' => 'application/urc-ressheet+xml', 'rss' => 'application/rss+xml', 'rtf' => 'text/rtf', 'rtx' => 'text/richtext', 'run' => 'application/x-makeself', 'rusd' => 'application/route-usd+xml', 'rv' => 'video/vnd.rn-realvideo', 's' => 'text/x-asm', 's3m' => 'audio/s3m', 'saf' => 'application/vnd.yamaha.smaf-audio', 'sass' => 'text/x-sass', 'sbml' => 'application/sbml+xml', 'sc' => 'application/vnd.ibm.secure-container', 'scd' => 'application/x-msschedule', 'scm' => 'application/vnd.lotus-screencam', 'scq' => 'application/scvp-cv-request', 'scs' => 'application/scvp-cv-response', 'scss' => 'text/x-scss', 'scurl' => 'text/vnd.curl.scurl', 'sda' => 'application/vnd.stardivision.draw', 'sdc' => 'application/vnd.stardivision.calc', 'sdd' => 'application/vnd.stardivision.impress', 'sdkd' => 'application/vnd.solent.sdkm+xml', 'sdkm' => 'application/vnd.solent.sdkm+xml', 'sdp' => 'application/sdp', 'sdw' => 'application/vnd.stardivision.writer', 'sea' => 'application/octet-stream', 'see' => 'application/vnd.seemail', 'seed' => 'application/vnd.fdsn.seed', 'sema' => 'application/vnd.sema', 'semd' => 'application/vnd.semd', 'semf' => 'application/vnd.semf', 'senmlx' => 'application/senml+xml', 'sensmlx' => 'application/sensml+xml', 'ser' => 'application/java-serialized-object', 'setpay' => 'application/set-payment-initiation', 'setreg' => 'application/set-registration-initiation', 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data', 'sfs' => 'application/vnd.spotfire.sfs', 'sfv' => 'text/x-sfv', 'sgi' => 'image/sgi', 'sgl' => 'application/vnd.stardivision.writer-global', 'sgm' => 'text/sgml', 'sgml' => 'text/sgml', 'sh' => 'application/x-sh', 'shar' => 'application/x-shar', 'shex' => 'text/shex', 'shf' => 'application/shf+xml', 'shtml' => 'text/html', 'sid' => 'image/x-mrsid-image', 'sieve' => 'application/sieve', 'sig' => 'application/pgp-signature', 'sil' => 'audio/silk', 'silo' => 'model/mesh', 'sis' => 'application/vnd.symbian.install', 'sisx' => 'application/vnd.symbian.install', 'sit' => 'application/x-stuffit', 'sitx' => 'application/x-stuffitx', 'siv' => 'application/sieve', 'skd' => 'application/vnd.koan', 'skm' => 'application/vnd.koan', 'skp' => 'application/vnd.koan', 'skt' => 'application/vnd.koan', 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12', 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', 'slim' => 'text/slim', 'slm' => 'text/slim', 'sls' => 'application/route-s-tsid+xml', 'slt' => 'application/vnd.epson.salt', 'sm' => 'application/vnd.stepmania.stepchart', 'smf' => 'application/vnd.stardivision.math', 'smi' => 'application/smil', 'smil' => 'application/smil', 'smv' => 'video/x-smv', 'smzip' => 'application/vnd.stepmania.package', 'snd' => 'audio/basic', 'snf' => 'application/x-font-snf', 'so' => 'application/octet-stream', 'spc' => 'application/x-pkcs7-certificates', 'spdx' => 'text/spdx', 'spf' => 'application/vnd.yamaha.smaf-phrase', 'spl' => 'application/x-futuresplash', 'spot' => 'text/vnd.in3d.spot', 'spp' => 'application/scvp-vp-response', 'spq' => 'application/scvp-vp-request', 'spx' => 'audio/ogg', 'sql' => 'application/x-sql', 'src' => 'application/x-wais-source', 'srt' => 'application/x-subrip', 'sru' => 'application/sru+xml', 'srx' => 'application/sparql-results+xml', 'ssdl' => 'application/ssdl+xml', 'sse' => 'application/vnd.kodak-descriptor', 'ssf' => 'application/vnd.epson.ssf', 'ssml' => 'application/ssml+xml', 'sst' => 'application/octet-stream', 'st' => 'application/vnd.sailingtracker.track', 'stc' => 'application/vnd.sun.xml.calc.template', 'std' => 'application/vnd.sun.xml.draw.template', 'step' => 'application/STEP', 'stf' => 'application/vnd.wt.stf', 'sti' => 'application/vnd.sun.xml.impress.template', 'stk' => 'application/hyperstudio', 'stl' => 'model/stl', 'stp' => 'application/STEP', 'stpx' => 'model/step+xml', 'stpxz' => 'model/step-xml+zip', 'stpz' => 'model/step+zip', 'str' => 'application/vnd.pg.format', 'stw' => 'application/vnd.sun.xml.writer.template', 'styl' => 'text/stylus', 'stylus' => 'text/stylus', 'sub' => 'text/vnd.dvb.subtitle', 'sus' => 'application/vnd.sus-calendar', 'susp' => 'application/vnd.sus-calendar', 'sv4cpio' => 'application/x-sv4cpio', 'sv4crc' => 'application/x-sv4crc', 'svc' => 'application/vnd.dvb.service', 'svd' => 'application/vnd.svd', 'svg' => 'image/svg+xml', 'svgz' => 'image/svg+xml', 'swa' => 'application/x-director', 'swf' => 'application/x-shockwave-flash', 'swi' => 'application/vnd.aristanetworks.swi', 'swidtag' => 'application/swid+xml', 'sxc' => 'application/vnd.sun.xml.calc', 'sxd' => 'application/vnd.sun.xml.draw', 'sxg' => 'application/vnd.sun.xml.writer.global', 'sxi' => 'application/vnd.sun.xml.impress', 'sxm' => 'application/vnd.sun.xml.math', 'sxw' => 'application/vnd.sun.xml.writer', 't' => 'text/troff', 't3' => 'application/x-t3vm-image', 't38' => 'image/t38', 'taglet' => 'application/vnd.mynfc', 'tao' => 'application/vnd.tao.intent-module-archive', 'tap' => 'image/vnd.tencent.tap', 'tar' => 'application/x-tar', 'tcap' => 'application/vnd.3gpp2.tcap', 'tcl' => 'application/x-tcl', 'td' => 'application/urc-targetdesc+xml', 'teacher' => 'application/vnd.smart.teacher', 'tei' => 'application/tei+xml', 'teicorpus' => 'application/tei+xml', 'tex' => 'application/x-tex', 'texi' => 'application/x-texinfo', 'texinfo' => 'application/x-texinfo', 'text' => 'text/plain', 'tfi' => 'application/thraud+xml', 'tfm' => 'application/x-tex-tfm', 'tfx' => 'image/tiff-fx', 'tga' => 'image/x-tga', 'tgz' => 'application/x-tar', 'thmx' => 'application/vnd.ms-officetheme', 'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'tk' => 'application/x-tcl', 'tmo' => 'application/vnd.tmobile-livetv', 'toml' => 'application/toml', 'torrent' => 'application/x-bittorrent', 'tpl' => 'application/vnd.groove-tool-template', 'tpt' => 'application/vnd.trid.tpt', 'tr' => 'text/troff', 'tra' => 'application/vnd.trueapp', 'trig' => 'application/trig', 'trm' => 'application/x-msterminal', 'ts' => 'video/mp2t', 'tsd' => 'application/timestamped-data', 'tsv' => 'text/tab-separated-values', 'ttc' => 'font/collection', 'ttf' => 'font/ttf', 'ttl' => 'text/turtle', 'ttml' => 'application/ttml+xml', 'twd' => 'application/vnd.simtech-mindmapper', 'twds' => 'application/vnd.simtech-mindmapper', 'txd' => 'application/vnd.genomatix.tuxedo', 'txf' => 'application/vnd.mobius.txf', 'txt' => 'text/plain', 'u3d' => 'model/u3d', 'u8dsn' => 'message/global-delivery-status', 'u8hdr' => 'message/global-headers', 'u8mdn' => 'message/global-disposition-notification', 'u8msg' => 'message/global', 'u32' => 'application/x-authorware-bin', 'ubj' => 'application/ubjson', 'udeb' => 'application/x-debian-package', 'ufd' => 'application/vnd.ufdl', 'ufdl' => 'application/vnd.ufdl', 'ulx' => 'application/x-glulx', 'umj' => 'application/vnd.umajin', 'unityweb' => 'application/vnd.unity', 'uo' => 'application/vnd.uoml+xml', 'uoml' => 'application/vnd.uoml+xml', 'uri' => 'text/uri-list', 'uris' => 'text/uri-list', 'urls' => 'text/uri-list', 'usda' => 'model/vnd.usda', 'usdz' => 'model/vnd.usdz+zip', 'ustar' => 'application/x-ustar', 'utz' => 'application/vnd.uiq.theme', 'uu' => 'text/x-uuencode', 'uva' => 'audio/vnd.dece.audio', 'uvd' => 'application/vnd.dece.data', 'uvf' => 'application/vnd.dece.data', 'uvg' => 'image/vnd.dece.graphic', 'uvh' => 'video/vnd.dece.hd', 'uvi' => 'image/vnd.dece.graphic', 'uvm' => 'video/vnd.dece.mobile', 'uvp' => 'video/vnd.dece.pd', 'uvs' => 'video/vnd.dece.sd', 'uvt' => 'application/vnd.dece.ttml+xml', 'uvu' => 'video/vnd.uvvu.mp4', 'uvv' => 'video/vnd.dece.video', 'uvva' => 'audio/vnd.dece.audio', 'uvvd' => 'application/vnd.dece.data', 'uvvf' => 'application/vnd.dece.data', 'uvvg' => 'image/vnd.dece.graphic', 'uvvh' => 'video/vnd.dece.hd', 'uvvi' => 'image/vnd.dece.graphic', 'uvvm' => 'video/vnd.dece.mobile', 'uvvp' => 'video/vnd.dece.pd', 'uvvs' => 'video/vnd.dece.sd', 'uvvt' => 'application/vnd.dece.ttml+xml', 'uvvu' => 'video/vnd.uvvu.mp4', 'uvvv' => 'video/vnd.dece.video', 'uvvx' => 'application/vnd.dece.unspecified', 'uvvz' => 'application/vnd.dece.zip', 'uvx' => 'application/vnd.dece.unspecified', 'uvz' => 'application/vnd.dece.zip', 'vbox' => 'application/x-virtualbox-vbox', 'vbox-extpack' => 'application/x-virtualbox-vbox-extpack', 'vcard' => 'text/vcard', 'vcd' => 'application/x-cdlink', 'vcf' => 'text/x-vcard', 'vcg' => 'application/vnd.groove-vcard', 'vcs' => 'text/x-vcalendar', 'vcx' => 'application/vnd.vcx', 'vdi' => 'application/x-virtualbox-vdi', 'vds' => 'model/vnd.sap.vds', 'vhd' => 'application/x-virtualbox-vhd', 'vis' => 'application/vnd.visionary', 'viv' => 'video/vnd.vivo', 'vlc' => 'application/videolan', 'vmdk' => 'application/x-virtualbox-vmdk', 'vob' => 'video/x-ms-vob', 'vor' => 'application/vnd.stardivision.writer', 'vox' => 'application/x-authorware-bin', 'vrml' => 'model/vrml', 'vsd' => 'application/vnd.visio', 'vsf' => 'application/vnd.vsf', 'vss' => 'application/vnd.visio', 'vst' => 'application/vnd.visio', 'vsw' => 'application/vnd.visio', 'vtf' => 'image/vnd.valve.source.texture', 'vtt' => 'text/vtt', 'vtu' => 'model/vnd.vtu', 'vxml' => 'application/voicexml+xml', 'w3d' => 'application/x-director', 'wad' => 'application/x-doom', 'wadl' => 'application/vnd.sun.wadl+xml', 'war' => 'application/java-archive', 'wasm' => 'application/wasm', 'wav' => 'audio/x-wav', 'wax' => 'audio/x-ms-wax', 'wbmp' => 'image/vnd.wap.wbmp', 'wbs' => 'application/vnd.criticaltools.wbs+xml', 'wbxml' => 'application/wbxml', 'wcm' => 'application/vnd.ms-works', 'wdb' => 'application/vnd.ms-works', 'wdp' => 'image/vnd.ms-photo', 'weba' => 'audio/webm', 'webapp' => 'application/x-web-app-manifest+json', 'webm' => 'video/webm', 'webmanifest' => 'application/manifest+json', 'webp' => 'image/webp', 'wg' => 'application/vnd.pmi.widget', 'wgsl' => 'text/wgsl', 'wgt' => 'application/widget', 'wif' => 'application/watcherinfo+xml', 'wks' => 'application/vnd.ms-works', 'wm' => 'video/x-ms-wm', 'wma' => 'audio/x-ms-wma', 'wmd' => 'application/x-ms-wmd', 'wmf' => 'image/wmf', 'wml' => 'text/vnd.wap.wml', 'wmlc' => 'application/wmlc', 'wmls' => 'text/vnd.wap.wmlscript', 'wmlsc' => 'application/vnd.wap.wmlscriptc', 'wmv' => 'video/x-ms-wmv', 'wmx' => 'video/x-ms-wmx', 'wmz' => 'application/x-msmetafile', 'woff' => 'font/woff', 'woff2' => 'font/woff2', 'word' => 'application/msword', 'wpd' => 'application/vnd.wordperfect', 'wpl' => 'application/vnd.ms-wpl', 'wps' => 'application/vnd.ms-works', 'wqd' => 'application/vnd.wqd', 'wri' => 'application/x-mswrite', 'wrl' => 'model/vrml', 'wsc' => 'message/vnd.wfa.wsc', 'wsdl' => 'application/wsdl+xml', 'wspolicy' => 'application/wspolicy+xml', 'wtb' => 'application/vnd.webturbo', 'wvx' => 'video/x-ms-wvx', 'x3d' => 'model/x3d+xml', 'x3db' => 'model/x3d+fastinfoset', 'x3dbz' => 'model/x3d+binary', 'x3dv' => 'model/x3d-vrml', 'x3dvz' => 'model/x3d+vrml', 'x3dz' => 'model/x3d+xml', 'x32' => 'application/x-authorware-bin', 'x_b' => 'model/vnd.parasolid.transmit.binary', 'x_t' => 'model/vnd.parasolid.transmit.text', 'xaml' => 'application/xaml+xml', 'xap' => 'application/x-silverlight-app', 'xar' => 'application/vnd.xara', 'xav' => 'application/xcap-att+xml', 'xbap' => 'application/x-ms-xbap', 'xbd' => 'application/vnd.fujixerox.docuworks.binder', 'xbm' => 'image/x-xbitmap', 'xca' => 'application/xcap-caps+xml', 'xcs' => 'application/calendar+xml', 'xdcf' => 'application/vnd.gov.sk.xmldatacontainer+xml', 'xdf' => 'application/xcap-diff+xml', 'xdm' => 'application/vnd.syncml.dm+xml', 'xdp' => 'application/vnd.adobe.xdp+xml', 'xdssc' => 'application/dssc+xml', 'xdw' => 'application/vnd.fujixerox.docuworks', 'xel' => 'application/xcap-el+xml', 'xenc' => 'application/xenc+xml', 'xer' => 'application/patch-ops-error+xml', 'xfdf' => 'application/xfdf', 'xfdl' => 'application/vnd.xfdl', 'xht' => 'application/xhtml+xml', 'xhtm' => 'application/vnd.pwg-xhtml-print+xml', 'xhtml' => 'application/xhtml+xml', 'xhvml' => 'application/xv+xml', 'xif' => 'image/vnd.xiff', 'xl' => 'application/excel', 'xla' => 'application/vnd.ms-excel', 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', 'xlc' => 'application/vnd.ms-excel', 'xlf' => 'application/xliff+xml', 'xlm' => 'application/vnd.ms-excel', 'xls' => 'application/vnd.ms-excel', 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12', 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'xlt' => 'application/vnd.ms-excel', 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12', 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', 'xlw' => 'application/vnd.ms-excel', 'xm' => 'audio/xm', 'xml' => 'application/xml', 'xns' => 'application/xcap-ns+xml', 'xo' => 'application/vnd.olpc-sugar', 'xop' => 'application/xop+xml', 'xpi' => 'application/x-xpinstall', 'xpl' => 'application/xproc+xml', 'xpm' => 'image/x-xpixmap', 'xpr' => 'application/vnd.is-xpr', 'xps' => 'application/vnd.ms-xpsdocument', 'xpw' => 'application/vnd.intercon.formnet', 'xpx' => 'application/vnd.intercon.formnet', 'xsd' => 'application/xml', 'xsf' => 'application/prs.xsf+xml', 'xsl' => 'application/xml', 'xslt' => 'application/xslt+xml', 'xsm' => 'application/vnd.syncml+xml', 'xspf' => 'application/xspf+xml', 'xul' => 'application/vnd.mozilla.xul+xml', 'xvm' => 'application/xv+xml', 'xvml' => 'application/xv+xml', 'xwd' => 'image/x-xwindowdump', 'xyz' => 'chemical/x-xyz', 'xz' => 'application/x-xz', 'yaml' => 'text/yaml', 'yang' => 'application/yang', 'yin' => 'application/yin+xml', 'yml' => 'text/yaml', 'ymp' => 'text/x-suse-ymp', 'z' => 'application/x-compress', 'z1' => 'application/x-zmachine', 'z2' => 'application/x-zmachine', 'z3' => 'application/x-zmachine', 'z4' => 'application/x-zmachine', 'z5' => 'application/x-zmachine', 'z6' => 'application/x-zmachine', 'z7' => 'application/x-zmachine', 'z8' => 'application/x-zmachine', 'zaz' => 'application/vnd.zzazz.deck+xml', 'zip' => 'application/zip', 'zir' => 'application/vnd.zul', 'zirz' => 'application/vnd.zul', 'zmm' => 'application/vnd.handheld-entertainment+xml', 'zsh' => 'text/x-scriptzsh', ]; /** * @var array * * @internal */ public const EXTENSIONS_FOR_MIME_TIMES = [ 'application/andrew-inset' => ['ez'], 'application/appinstaller' => ['appinstaller'], 'application/applixware' => ['aw'], 'application/appx' => ['appx'], 'application/appxbundle' => ['appxbundle'], 'application/atom+xml' => ['atom'], 'application/atomcat+xml' => ['atomcat'], 'application/atomdeleted+xml' => ['atomdeleted'], 'application/atomsvc+xml' => ['atomsvc'], 'application/atsc-dwd+xml' => ['dwd'], 'application/atsc-held+xml' => ['held'], 'application/atsc-rsat+xml' => ['rsat'], 'application/automationml-aml+xml' => ['aml'], 'application/automationml-amlx+zip' => ['amlx'], 'application/bdoc' => ['bdoc'], 'application/calendar+xml' => ['xcs'], 'application/ccxml+xml' => ['ccxml'], 'application/cdfx+xml' => ['cdfx'], 'application/cdmi-capability' => ['cdmia'], 'application/cdmi-container' => ['cdmic'], 'application/cdmi-domain' => ['cdmid'], 'application/cdmi-object' => ['cdmio'], 'application/cdmi-queue' => ['cdmiq'], 'application/cpl+xml' => ['cpl'], 'application/cu-seeme' => ['cu'], 'application/cwl' => ['cwl'], 'application/dash+xml' => ['mpd'], 'application/dash-patch+xml' => ['mpp'], 'application/davmount+xml' => ['davmount'], 'application/docbook+xml' => ['dbk'], 'application/dssc+der' => ['dssc'], 'application/dssc+xml' => ['xdssc'], 'application/ecmascript' => ['ecma'], 'application/emma+xml' => ['emma'], 'application/emotionml+xml' => ['emotionml'], 'application/epub+zip' => ['epub'], 'application/exi' => ['exi'], 'application/express' => ['exp'], 'application/fdf' => ['fdf'], 'application/fdt+xml' => ['fdt'], 'application/font-tdpfr' => ['pfr'], 'application/geo+json' => ['geojson'], 'application/gml+xml' => ['gml'], 'application/gpx+xml' => ['gpx'], 'application/gxf' => ['gxf'], 'application/gzip' => ['gz', 'gzip'], 'application/hjson' => ['hjson'], 'application/hyperstudio' => ['stk'], 'application/inkml+xml' => ['ink', 'inkml'], 'application/ipfix' => ['ipfix'], 'application/its+xml' => ['its'], 'application/java-archive' => ['jar', 'war', 'ear'], 'application/java-serialized-object' => ['ser'], 'application/java-vm' => ['class'], 'application/javascript' => ['js'], 'application/json' => ['json', 'map'], 'application/json5' => ['json5'], 'application/jsonml+json' => ['jsonml'], 'application/ld+json' => ['jsonld'], 'application/lgr+xml' => ['lgr'], 'application/lost+xml' => ['lostxml'], 'application/mac-binhex40' => ['hqx'], 'application/mac-compactpro' => ['cpt'], 'application/mads+xml' => ['mads'], 'application/manifest+json' => ['webmanifest'], 'application/marc' => ['mrc'], 'application/marcxml+xml' => ['mrcx'], 'application/mathematica' => ['ma', 'nb', 'mb'], 'application/mathml+xml' => ['mathml'], 'application/mbox' => ['mbox'], 'application/media-policy-dataset+xml' => ['mpf'], 'application/mediaservercontrol+xml' => ['mscml'], 'application/metalink+xml' => ['metalink'], 'application/metalink4+xml' => ['meta4'], 'application/mets+xml' => ['mets'], 'application/mmt-aei+xml' => ['maei'], 'application/mmt-usd+xml' => ['musd'], 'application/mods+xml' => ['mods'], 'application/mp21' => ['m21', 'mp21'], 'application/mp4' => ['mp4', 'mpg4', 'mp4s', 'm4p'], 'application/msix' => ['msix'], 'application/msixbundle' => ['msixbundle'], 'application/msword' => ['doc', 'dot', 'word'], 'application/mxf' => ['mxf'], 'application/n-quads' => ['nq'], 'application/n-triples' => ['nt'], 'application/node' => ['cjs'], 'application/octet-stream' => ['bin', 'dms', 'lrf', 'mar', 'so', 'dist', 'distz', 'pkg', 'bpk', 'dump', 'elc', 'deploy', 'exe', 'dll', 'deb', 'dmg', 'iso', 'img', 'msi', 'msp', 'msm', 'buffer', 'phar', 'lha', 'lzh', 'class', 'sea', 'dmn', 'bpmn', 'kdb', 'sst', 'csr', 'dst', 'pv', 'pxf'], 'application/oda' => ['oda'], 'application/oebps-package+xml' => ['opf'], 'application/ogg' => ['ogx'], 'application/omdoc+xml' => ['omdoc'], 'application/onenote' => ['onetoc', 'onetoc2', 'onetmp', 'onepkg'], 'application/oxps' => ['oxps'], 'application/p2p-overlay+xml' => ['relo'], 'application/patch-ops-error+xml' => ['xer'], 'application/pdf' => ['pdf', 'ai'], 'application/pgp-encrypted' => ['pgp'], 'application/pgp-keys' => ['asc'], 'application/pgp-signature' => ['sig', 'asc'], 'application/pics-rules' => ['prf'], 'application/pkcs10' => ['p10'], 'application/pkcs7-mime' => ['p7m', 'p7c'], 'application/pkcs7-signature' => ['p7s'], 'application/pkcs8' => ['p8'], 'application/pkix-attr-cert' => ['ac'], 'application/pkix-cert' => ['cer'], 'application/pkix-crl' => ['crl'], 'application/pkix-pkipath' => ['pkipath'], 'application/pkixcmp' => ['pki'], 'application/pls+xml' => ['pls'], 'application/postscript' => ['ai', 'eps', 'ps'], 'application/provenance+xml' => ['provx'], 'application/prs.cww' => ['cww'], 'application/prs.xsf+xml' => ['xsf'], 'application/pskc+xml' => ['pskcxml'], 'application/raml+yaml' => ['raml'], 'application/rdf+xml' => ['rdf', 'owl'], 'application/reginfo+xml' => ['rif'], 'application/relax-ng-compact-syntax' => ['rnc'], 'application/resource-lists+xml' => ['rl'], 'application/resource-lists-diff+xml' => ['rld'], 'application/rls-services+xml' => ['rs'], 'application/route-apd+xml' => ['rapd'], 'application/route-s-tsid+xml' => ['sls'], 'application/route-usd+xml' => ['rusd'], 'application/rpki-ghostbusters' => ['gbr'], 'application/rpki-manifest' => ['mft'], 'application/rpki-roa' => ['roa'], 'application/rsd+xml' => ['rsd'], 'application/rss+xml' => ['rss'], 'application/rtf' => ['rtf'], 'application/sbml+xml' => ['sbml'], 'application/scvp-cv-request' => ['scq'], 'application/scvp-cv-response' => ['scs'], 'application/scvp-vp-request' => ['spq'], 'application/scvp-vp-response' => ['spp'], 'application/sdp' => ['sdp'], 'application/senml+xml' => ['senmlx'], 'application/sensml+xml' => ['sensmlx'], 'application/set-payment-initiation' => ['setpay'], 'application/set-registration-initiation' => ['setreg'], 'application/shf+xml' => ['shf'], 'application/sieve' => ['siv', 'sieve'], 'application/smil+xml' => ['smi', 'smil'], 'application/sparql-query' => ['rq'], 'application/sparql-results+xml' => ['srx'], 'application/sql' => ['sql'], 'application/srgs' => ['gram'], 'application/srgs+xml' => ['grxml'], 'application/sru+xml' => ['sru'], 'application/ssdl+xml' => ['ssdl'], 'application/ssml+xml' => ['ssml'], 'application/swid+xml' => ['swidtag'], 'application/tei+xml' => ['tei', 'teicorpus'], 'application/thraud+xml' => ['tfi'], 'application/timestamped-data' => ['tsd'], 'application/toml' => ['toml'], 'application/trig' => ['trig'], 'application/ttml+xml' => ['ttml'], 'application/ubjson' => ['ubj'], 'application/urc-ressheet+xml' => ['rsheet'], 'application/urc-targetdesc+xml' => ['td'], 'application/vnd.1000minds.decision-model+xml' => ['1km'], 'application/vnd.3gpp.pic-bw-large' => ['plb'], 'application/vnd.3gpp.pic-bw-small' => ['psb'], 'application/vnd.3gpp.pic-bw-var' => ['pvb'], 'application/vnd.3gpp2.tcap' => ['tcap'], 'application/vnd.3m.post-it-notes' => ['pwn'], 'application/vnd.accpac.simply.aso' => ['aso'], 'application/vnd.accpac.simply.imp' => ['imp'], 'application/vnd.acucobol' => ['acu'], 'application/vnd.acucorp' => ['atc', 'acutc'], 'application/vnd.adobe.air-application-installer-package+zip' => ['air'], 'application/vnd.adobe.formscentral.fcdt' => ['fcdt'], 'application/vnd.adobe.fxp' => ['fxp', 'fxpl'], 'application/vnd.adobe.xdp+xml' => ['xdp'], 'application/vnd.adobe.xfdf' => ['xfdf'], 'application/vnd.age' => ['age'], 'application/vnd.ahead.space' => ['ahead'], 'application/vnd.airzip.filesecure.azf' => ['azf'], 'application/vnd.airzip.filesecure.azs' => ['azs'], 'application/vnd.amazon.ebook' => ['azw'], 'application/vnd.americandynamics.acc' => ['acc'], 'application/vnd.amiga.ami' => ['ami'], 'application/vnd.android.package-archive' => ['apk'], 'application/vnd.anser-web-certificate-issue-initiation' => ['cii'], 'application/vnd.anser-web-funds-transfer-initiation' => ['fti'], 'application/vnd.antix.game-component' => ['atx'], 'application/vnd.apple.installer+xml' => ['mpkg'], 'application/vnd.apple.keynote' => ['key'], 'application/vnd.apple.mpegurl' => ['m3u8'], 'application/vnd.apple.numbers' => ['numbers'], 'application/vnd.apple.pages' => ['pages'], 'application/vnd.apple.pkpass' => ['pkpass'], 'application/vnd.aristanetworks.swi' => ['swi'], 'application/vnd.astraea-software.iota' => ['iota'], 'application/vnd.audiograph' => ['aep'], 'application/vnd.balsamiq.bmml+xml' => ['bmml'], 'application/vnd.blueice.multipass' => ['mpm'], 'application/vnd.bmi' => ['bmi'], 'application/vnd.businessobjects' => ['rep'], 'application/vnd.chemdraw+xml' => ['cdxml'], 'application/vnd.chipnuts.karaoke-mmd' => ['mmd'], 'application/vnd.cinderella' => ['cdy'], 'application/vnd.citationstyles.style+xml' => ['csl'], 'application/vnd.claymore' => ['cla'], 'application/vnd.cloanto.rp9' => ['rp9'], 'application/vnd.clonk.c4group' => ['c4g', 'c4d', 'c4f', 'c4p', 'c4u'], 'application/vnd.cluetrust.cartomobile-config' => ['c11amc'], 'application/vnd.cluetrust.cartomobile-config-pkg' => ['c11amz'], 'application/vnd.commonspace' => ['csp'], 'application/vnd.contact.cmsg' => ['cdbcmsg'], 'application/vnd.cosmocaller' => ['cmc'], 'application/vnd.crick.clicker' => ['clkx'], 'application/vnd.crick.clicker.keyboard' => ['clkk'], 'application/vnd.crick.clicker.palette' => ['clkp'], 'application/vnd.crick.clicker.template' => ['clkt'], 'application/vnd.crick.clicker.wordbank' => ['clkw'], 'application/vnd.criticaltools.wbs+xml' => ['wbs'], 'application/vnd.ctc-posml' => ['pml'], 'application/vnd.cups-ppd' => ['ppd'], 'application/vnd.curl.car' => ['car'], 'application/vnd.curl.pcurl' => ['pcurl'], 'application/vnd.dart' => ['dart'], 'application/vnd.data-vision.rdz' => ['rdz'], 'application/vnd.dbf' => ['dbf'], 'application/vnd.dece.data' => ['uvf', 'uvvf', 'uvd', 'uvvd'], 'application/vnd.dece.ttml+xml' => ['uvt', 'uvvt'], 'application/vnd.dece.unspecified' => ['uvx', 'uvvx'], 'application/vnd.dece.zip' => ['uvz', 'uvvz'], 'application/vnd.denovo.fcselayout-link' => ['fe_launch'], 'application/vnd.dna' => ['dna'], 'application/vnd.dolby.mlp' => ['mlp'], 'application/vnd.dpgraph' => ['dpg'], 'application/vnd.dreamfactory' => ['dfac'], 'application/vnd.ds-keypoint' => ['kpxx'], 'application/vnd.dvb.ait' => ['ait'], 'application/vnd.dvb.service' => ['svc'], 'application/vnd.dynageo' => ['geo'], 'application/vnd.ecowin.chart' => ['mag'], 'application/vnd.enliven' => ['nml'], 'application/vnd.epson.esf' => ['esf'], 'application/vnd.epson.msf' => ['msf'], 'application/vnd.epson.quickanime' => ['qam'], 'application/vnd.epson.salt' => ['slt'], 'application/vnd.epson.ssf' => ['ssf'], 'application/vnd.eszigno3+xml' => ['es3', 'et3'], 'application/vnd.ezpix-album' => ['ez2'], 'application/vnd.ezpix-package' => ['ez3'], 'application/vnd.fdf' => ['fdf'], 'application/vnd.fdsn.mseed' => ['mseed'], 'application/vnd.fdsn.seed' => ['seed', 'dataless'], 'application/vnd.flographit' => ['gph'], 'application/vnd.fluxtime.clip' => ['ftc'], 'application/vnd.framemaker' => ['fm', 'frame', 'maker', 'book'], 'application/vnd.frogans.fnc' => ['fnc'], 'application/vnd.frogans.ltf' => ['ltf'], 'application/vnd.fsc.weblaunch' => ['fsc'], 'application/vnd.fujitsu.oasys' => ['oas'], 'application/vnd.fujitsu.oasys2' => ['oa2'], 'application/vnd.fujitsu.oasys3' => ['oa3'], 'application/vnd.fujitsu.oasysgp' => ['fg5'], 'application/vnd.fujitsu.oasysprs' => ['bh2'], 'application/vnd.fujixerox.ddd' => ['ddd'], 'application/vnd.fujixerox.docuworks' => ['xdw'], 'application/vnd.fujixerox.docuworks.binder' => ['xbd'], 'application/vnd.fuzzysheet' => ['fzs'], 'application/vnd.genomatix.tuxedo' => ['txd'], 'application/vnd.geogebra.file' => ['ggb'], 'application/vnd.geogebra.slides' => ['ggs'], 'application/vnd.geogebra.tool' => ['ggt'], 'application/vnd.geometry-explorer' => ['gex', 'gre'], 'application/vnd.geonext' => ['gxt'], 'application/vnd.geoplan' => ['g2w'], 'application/vnd.geospace' => ['g3w'], 'application/vnd.gmx' => ['gmx'], 'application/vnd.google-apps.document' => ['gdoc'], 'application/vnd.google-apps.presentation' => ['gslides'], 'application/vnd.google-apps.spreadsheet' => ['gsheet'], 'application/vnd.google-earth.kml+xml' => ['kml'], 'application/vnd.google-earth.kmz' => ['kmz'], 'application/vnd.gov.sk.xmldatacontainer+xml' => ['xdcf'], 'application/vnd.grafeq' => ['gqf', 'gqs'], 'application/vnd.groove-account' => ['gac'], 'application/vnd.groove-help' => ['ghf'], 'application/vnd.groove-identity-message' => ['gim'], 'application/vnd.groove-injector' => ['grv'], 'application/vnd.groove-tool-message' => ['gtm'], 'application/vnd.groove-tool-template' => ['tpl'], 'application/vnd.groove-vcard' => ['vcg'], 'application/vnd.hal+xml' => ['hal'], 'application/vnd.handheld-entertainment+xml' => ['zmm'], 'application/vnd.hbci' => ['hbci'], 'application/vnd.hhe.lesson-player' => ['les'], 'application/vnd.hp-hpgl' => ['hpgl'], 'application/vnd.hp-hpid' => ['hpid'], 'application/vnd.hp-hps' => ['hps'], 'application/vnd.hp-jlyt' => ['jlt'], 'application/vnd.hp-pcl' => ['pcl'], 'application/vnd.hp-pclxl' => ['pclxl'], 'application/vnd.hydrostatix.sof-data' => ['sfd-hdstx'], 'application/vnd.ibm.minipay' => ['mpy'], 'application/vnd.ibm.modcap' => ['afp', 'listafp', 'list3820'], 'application/vnd.ibm.rights-management' => ['irm'], 'application/vnd.ibm.secure-container' => ['sc'], 'application/vnd.iccprofile' => ['icc', 'icm'], 'application/vnd.igloader' => ['igl'], 'application/vnd.immervision-ivp' => ['ivp'], 'application/vnd.immervision-ivu' => ['ivu'], 'application/vnd.insors.igm' => ['igm'], 'application/vnd.intercon.formnet' => ['xpw', 'xpx'], 'application/vnd.intergeo' => ['i2g'], 'application/vnd.intu.qbo' => ['qbo'], 'application/vnd.intu.qfx' => ['qfx'], 'application/vnd.ipunplugged.rcprofile' => ['rcprofile'], 'application/vnd.irepository.package+xml' => ['irp'], 'application/vnd.is-xpr' => ['xpr'], 'application/vnd.isac.fcs' => ['fcs'], 'application/vnd.jam' => ['jam'], 'application/vnd.jcp.javame.midlet-rms' => ['rms'], 'application/vnd.jisp' => ['jisp'], 'application/vnd.joost.joda-archive' => ['joda'], 'application/vnd.kahootz' => ['ktz', 'ktr'], 'application/vnd.kde.karbon' => ['karbon'], 'application/vnd.kde.kchart' => ['chrt'], 'application/vnd.kde.kformula' => ['kfo'], 'application/vnd.kde.kivio' => ['flw'], 'application/vnd.kde.kontour' => ['kon'], 'application/vnd.kde.kpresenter' => ['kpr', 'kpt'], 'application/vnd.kde.kspread' => ['ksp'], 'application/vnd.kde.kword' => ['kwd', 'kwt'], 'application/vnd.kenameaapp' => ['htke'], 'application/vnd.kidspiration' => ['kia'], 'application/vnd.kinar' => ['kne', 'knp'], 'application/vnd.koan' => ['skp', 'skd', 'skt', 'skm'], 'application/vnd.kodak-descriptor' => ['sse'], 'application/vnd.las.las+xml' => ['lasxml'], 'application/vnd.llamagraphics.life-balance.desktop' => ['lbd'], 'application/vnd.llamagraphics.life-balance.exchange+xml' => ['lbe'], 'application/vnd.lotus-1-2-3' => ['123'], 'application/vnd.lotus-approach' => ['apr'], 'application/vnd.lotus-freelance' => ['pre'], 'application/vnd.lotus-notes' => ['nsf'], 'application/vnd.lotus-organizer' => ['org'], 'application/vnd.lotus-screencam' => ['scm'], 'application/vnd.lotus-wordpro' => ['lwp'], 'application/vnd.macports.portpkg' => ['portpkg'], 'application/vnd.mapbox-vector-tile' => ['mvt'], 'application/vnd.mcd' => ['mcd'], 'application/vnd.medcalcdata' => ['mc1'], 'application/vnd.mediastation.cdkey' => ['cdkey'], 'application/vnd.mfer' => ['mwf'], 'application/vnd.mfmp' => ['mfm'], 'application/vnd.micrografx.flo' => ['flo'], 'application/vnd.micrografx.igx' => ['igx'], 'application/vnd.mif' => ['mif'], 'application/vnd.mobius.daf' => ['daf'], 'application/vnd.mobius.dis' => ['dis'], 'application/vnd.mobius.mbk' => ['mbk'], 'application/vnd.mobius.mqy' => ['mqy'], 'application/vnd.mobius.msl' => ['msl'], 'application/vnd.mobius.plc' => ['plc'], 'application/vnd.mobius.txf' => ['txf'], 'application/vnd.mophun.application' => ['mpn'], 'application/vnd.mophun.certificate' => ['mpc'], 'application/vnd.mozilla.xul+xml' => ['xul'], 'application/vnd.ms-artgalry' => ['cil'], 'application/vnd.ms-cab-compressed' => ['cab'], 'application/vnd.ms-excel' => ['xls', 'xlm', 'xla', 'xlc', 'xlt', 'xlw'], 'application/vnd.ms-excel.addin.macroenabled.12' => ['xlam'], 'application/vnd.ms-excel.sheet.binary.macroenabled.12' => ['xlsb'], 'application/vnd.ms-excel.sheet.macroenabled.12' => ['xlsm'], 'application/vnd.ms-excel.template.macroenabled.12' => ['xltm'], 'application/vnd.ms-fontobject' => ['eot'], 'application/vnd.ms-htmlhelp' => ['chm'], 'application/vnd.ms-ims' => ['ims'], 'application/vnd.ms-lrm' => ['lrm'], 'application/vnd.ms-officetheme' => ['thmx'], 'application/vnd.ms-outlook' => ['msg'], 'application/vnd.ms-pki.seccat' => ['cat'], 'application/vnd.ms-pki.stl' => ['stl'], 'application/vnd.ms-powerpoint' => ['ppt', 'pps', 'pot', 'ppa'], 'application/vnd.ms-powerpoint.addin.macroenabled.12' => ['ppam'], 'application/vnd.ms-powerpoint.presentation.macroenabled.12' => ['pptm'], 'application/vnd.ms-powerpoint.slide.macroenabled.12' => ['sldm'], 'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => ['ppsm'], 'application/vnd.ms-powerpoint.template.macroenabled.12' => ['potm'], 'application/vnd.ms-project' => ['mpp', 'mpt'], 'application/vnd.ms-word.document.macroenabled.12' => ['docm'], 'application/vnd.ms-word.template.macroenabled.12' => ['dotm'], 'application/vnd.ms-works' => ['wps', 'wks', 'wcm', 'wdb'], 'application/vnd.ms-wpl' => ['wpl'], 'application/vnd.ms-xpsdocument' => ['xps'], 'application/vnd.mseq' => ['mseq'], 'application/vnd.musician' => ['mus'], 'application/vnd.muvee.style' => ['msty'], 'application/vnd.mynfc' => ['taglet'], 'application/vnd.nato.bindingdataobject+xml' => ['bdo'], 'application/vnd.neurolanguage.nlu' => ['nlu'], 'application/vnd.nitf' => ['ntf', 'nitf'], 'application/vnd.noblenet-directory' => ['nnd'], 'application/vnd.noblenet-sealer' => ['nns'], 'application/vnd.noblenet-web' => ['nnw'], 'application/vnd.nokia.n-gage.ac+xml' => ['ac'], 'application/vnd.nokia.n-gage.data' => ['ngdat'], 'application/vnd.nokia.n-gage.symbian.install' => ['n-gage'], 'application/vnd.nokia.radio-preset' => ['rpst'], 'application/vnd.nokia.radio-presets' => ['rpss'], 'application/vnd.novadigm.edm' => ['edm'], 'application/vnd.novadigm.edx' => ['edx'], 'application/vnd.novadigm.ext' => ['ext'], 'application/vnd.oasis.opendocument.chart' => ['odc'], 'application/vnd.oasis.opendocument.chart-template' => ['otc'], 'application/vnd.oasis.opendocument.database' => ['odb'], 'application/vnd.oasis.opendocument.formula' => ['odf'], 'application/vnd.oasis.opendocument.formula-template' => ['odft'], 'application/vnd.oasis.opendocument.graphics' => ['odg'], 'application/vnd.oasis.opendocument.graphics-template' => ['otg'], 'application/vnd.oasis.opendocument.image' => ['odi'], 'application/vnd.oasis.opendocument.image-template' => ['oti'], 'application/vnd.oasis.opendocument.presentation' => ['odp'], 'application/vnd.oasis.opendocument.presentation-template' => ['otp'], 'application/vnd.oasis.opendocument.spreadsheet' => ['ods'], 'application/vnd.oasis.opendocument.spreadsheet-template' => ['ots'], 'application/vnd.oasis.opendocument.text' => ['odt'], 'application/vnd.oasis.opendocument.text-master' => ['odm'], 'application/vnd.oasis.opendocument.text-template' => ['ott'], 'application/vnd.oasis.opendocument.text-web' => ['oth'], 'application/vnd.olpc-sugar' => ['xo'], 'application/vnd.oma.dd2+xml' => ['dd2'], 'application/vnd.openblox.game+xml' => ['obgx'], 'application/vnd.openofficeorg.extension' => ['oxt'], 'application/vnd.openstreetmap.data+xml' => ['osm'], 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => ['pptx'], 'application/vnd.openxmlformats-officedocument.presentationml.slide' => ['sldx'], 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => ['ppsx'], 'application/vnd.openxmlformats-officedocument.presentationml.template' => ['potx'], 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => ['xlsx'], 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => ['xltx'], 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => ['docx'], 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => ['dotx'], 'application/vnd.osgeo.mapguide.package' => ['mgp'], 'application/vnd.osgi.dp' => ['dp'], 'application/vnd.osgi.subsystem' => ['esa'], 'application/vnd.palm' => ['pdb', 'pqa', 'oprc'], 'application/vnd.pawaafile' => ['paw'], 'application/vnd.pg.format' => ['str'], 'application/vnd.pg.osasli' => ['ei6'], 'application/vnd.picsel' => ['efif'], 'application/vnd.pmi.widget' => ['wg'], 'application/vnd.pocketlearn' => ['plf'], 'application/vnd.powerbuilder6' => ['pbd'], 'application/vnd.previewsystems.box' => ['box'], 'application/vnd.proteus.magazine' => ['mgz'], 'application/vnd.publishare-delta-tree' => ['qps'], 'application/vnd.pvi.ptid1' => ['ptid'], 'application/vnd.pwg-xhtml-print+xml' => ['xhtm'], 'application/vnd.quark.quarkxpress' => ['qxd', 'qxt', 'qwd', 'qwt', 'qxl', 'qxb'], 'application/vnd.rar' => ['rar'], 'application/vnd.realvnc.bed' => ['bed'], 'application/vnd.recordare.musicxml' => ['mxl'], 'application/vnd.recordare.musicxml+xml' => ['musicxml'], 'application/vnd.rig.cryptonote' => ['cryptonote'], 'application/vnd.rim.cod' => ['cod'], 'application/vnd.rn-realmedia' => ['rm'], 'application/vnd.rn-realmedia-vbr' => ['rmvb'], 'application/vnd.route66.link66+xml' => ['link66'], 'application/vnd.sailingtracker.track' => ['st'], 'application/vnd.seemail' => ['see'], 'application/vnd.sema' => ['sema'], 'application/vnd.semd' => ['semd'], 'application/vnd.semf' => ['semf'], 'application/vnd.shana.informed.formdata' => ['ifm'], 'application/vnd.shana.informed.formtemplate' => ['itp'], 'application/vnd.shana.informed.interchange' => ['iif'], 'application/vnd.shana.informed.package' => ['ipk'], 'application/vnd.simtech-mindmapper' => ['twd', 'twds'], 'application/vnd.smaf' => ['mmf'], 'application/vnd.smart.teacher' => ['teacher'], 'application/vnd.software602.filler.form+xml' => ['fo'], 'application/vnd.solent.sdkm+xml' => ['sdkm', 'sdkd'], 'application/vnd.spotfire.dxp' => ['dxp'], 'application/vnd.spotfire.sfs' => ['sfs'], 'application/vnd.stardivision.calc' => ['sdc'], 'application/vnd.stardivision.draw' => ['sda'], 'application/vnd.stardivision.impress' => ['sdd'], 'application/vnd.stardivision.math' => ['smf'], 'application/vnd.stardivision.writer' => ['sdw', 'vor'], 'application/vnd.stardivision.writer-global' => ['sgl'], 'application/vnd.stepmania.package' => ['smzip'], 'application/vnd.stepmania.stepchart' => ['sm'], 'application/vnd.sun.wadl+xml' => ['wadl'], 'application/vnd.sun.xml.calc' => ['sxc'], 'application/vnd.sun.xml.calc.template' => ['stc'], 'application/vnd.sun.xml.draw' => ['sxd'], 'application/vnd.sun.xml.draw.template' => ['std'], 'application/vnd.sun.xml.impress' => ['sxi'], 'application/vnd.sun.xml.impress.template' => ['sti'], 'application/vnd.sun.xml.math' => ['sxm'], 'application/vnd.sun.xml.writer' => ['sxw'], 'application/vnd.sun.xml.writer.global' => ['sxg'], 'application/vnd.sun.xml.writer.template' => ['stw'], 'application/vnd.sus-calendar' => ['sus', 'susp'], 'application/vnd.svd' => ['svd'], 'application/vnd.symbian.install' => ['sis', 'sisx'], 'application/vnd.syncml+xml' => ['xsm'], 'application/vnd.syncml.dm+wbxml' => ['bdm'], 'application/vnd.syncml.dm+xml' => ['xdm'], 'application/vnd.syncml.dmddf+xml' => ['ddf'], 'application/vnd.tao.intent-module-archive' => ['tao'], 'application/vnd.tcpdump.pcap' => ['pcap', 'cap', 'dmp'], 'application/vnd.tmobile-livetv' => ['tmo'], 'application/vnd.trid.tpt' => ['tpt'], 'application/vnd.triscape.mxs' => ['mxs'], 'application/vnd.trueapp' => ['tra'], 'application/vnd.ufdl' => ['ufd', 'ufdl'], 'application/vnd.uiq.theme' => ['utz'], 'application/vnd.umajin' => ['umj'], 'application/vnd.unity' => ['unityweb'], 'application/vnd.uoml+xml' => ['uoml', 'uo'], 'application/vnd.vcx' => ['vcx'], 'application/vnd.visio' => ['vsd', 'vst', 'vss', 'vsw'], 'application/vnd.visionary' => ['vis'], 'application/vnd.vsf' => ['vsf'], 'application/vnd.wap.wbxml' => ['wbxml'], 'application/vnd.wap.wmlc' => ['wmlc'], 'application/vnd.wap.wmlscriptc' => ['wmlsc'], 'application/vnd.webturbo' => ['wtb'], 'application/vnd.wolfram.player' => ['nbp'], 'application/vnd.wordperfect' => ['wpd'], 'application/vnd.wqd' => ['wqd'], 'application/vnd.wt.stf' => ['stf'], 'application/vnd.xara' => ['xar'], 'application/vnd.xfdl' => ['xfdl'], 'application/vnd.yamaha.hv-dic' => ['hvd'], 'application/vnd.yamaha.hv-script' => ['hvs'], 'application/vnd.yamaha.hv-voice' => ['hvp'], 'application/vnd.yamaha.openscoreformat' => ['osf'], 'application/vnd.yamaha.openscoreformat.osfpvg+xml' => ['osfpvg'], 'application/vnd.yamaha.smaf-audio' => ['saf'], 'application/vnd.yamaha.smaf-phrase' => ['spf'], 'application/vnd.yellowriver-custom-menu' => ['cmp'], 'application/vnd.zul' => ['zir', 'zirz'], 'application/vnd.zzazz.deck+xml' => ['zaz'], 'application/voicexml+xml' => ['vxml'], 'application/wasm' => ['wasm'], 'application/watcherinfo+xml' => ['wif'], 'application/widget' => ['wgt'], 'application/winhlp' => ['hlp'], 'application/wsdl+xml' => ['wsdl'], 'application/wspolicy+xml' => ['wspolicy'], 'application/x-7z-compressed' => ['7z', '7zip'], 'application/x-abiword' => ['abw'], 'application/x-ace-compressed' => ['ace'], 'application/x-apple-diskimage' => ['dmg'], 'application/x-arj' => ['arj'], 'application/x-authorware-bin' => ['aab', 'x32', 'u32', 'vox'], 'application/x-authorware-map' => ['aam'], 'application/x-authorware-seg' => ['aas'], 'application/x-bcpio' => ['bcpio'], 'application/x-bdoc' => ['bdoc'], 'application/x-bittorrent' => ['torrent'], 'application/x-blorb' => ['blb', 'blorb'], 'application/x-bzip' => ['bz'], 'application/x-bzip2' => ['bz2', 'boz'], 'application/x-cbr' => ['cbr', 'cba', 'cbt', 'cbz', 'cb7'], 'application/x-cdlink' => ['vcd'], 'application/x-cfs-compressed' => ['cfs'], 'application/x-chat' => ['chat'], 'application/x-chess-pgn' => ['pgn'], 'application/x-chrome-extension' => ['crx'], 'application/x-cocoa' => ['cco'], 'application/x-conference' => ['nsc'], 'application/x-cpio' => ['cpio'], 'application/x-csh' => ['csh'], 'application/x-debian-package' => ['deb', 'udeb'], 'application/x-dgc-compressed' => ['dgc'], 'application/x-director' => ['dir', 'dcr', 'dxr', 'cst', 'cct', 'cxt', 'w3d', 'fgd', 'swa'], 'application/x-doom' => ['wad'], 'application/x-dtbncx+xml' => ['ncx'], 'application/x-dtbook+xml' => ['dtb'], 'application/x-dtbresource+xml' => ['res'], 'application/x-dvi' => ['dvi'], 'application/x-envoy' => ['evy'], 'application/x-eva' => ['eva'], 'application/x-font-bdf' => ['bdf'], 'application/x-font-ghostscript' => ['gsf'], 'application/x-font-linux-psf' => ['psf'], 'application/x-font-pcf' => ['pcf'], 'application/x-font-snf' => ['snf'], 'application/x-font-type1' => ['pfa', 'pfb', 'pfm', 'afm'], 'application/x-freearc' => ['arc'], 'application/x-futuresplash' => ['spl'], 'application/x-gca-compressed' => ['gca'], 'application/x-glulx' => ['ulx'], 'application/x-gnumeric' => ['gnumeric'], 'application/x-gramps-xml' => ['gramps'], 'application/x-gtar' => ['gtar'], 'application/x-hdf' => ['hdf'], 'application/x-httpd-php' => ['php', 'php4', 'php3', 'phtml'], 'application/x-install-instructions' => ['install'], 'application/x-iso9660-image' => ['iso'], 'application/x-iwork-keynote-sffkey' => ['key'], 'application/x-iwork-numbers-sffnumbers' => ['numbers'], 'application/x-iwork-pages-sffpages' => ['pages'], 'application/x-java-archive-diff' => ['jardiff'], 'application/x-java-jnlp-file' => ['jnlp'], 'application/x-keepass2' => ['kdbx'], 'application/x-latex' => ['latex'], 'application/x-lua-bytecode' => ['luac'], 'application/x-lzh-compressed' => ['lzh', 'lha'], 'application/x-makeself' => ['run'], 'application/x-mie' => ['mie'], 'application/x-mobipocket-ebook' => ['prc', 'mobi'], 'application/x-ms-application' => ['application'], 'application/x-ms-shortcut' => ['lnk'], 'application/x-ms-wmd' => ['wmd'], 'application/x-ms-wmz' => ['wmz'], 'application/x-ms-xbap' => ['xbap'], 'application/x-msaccess' => ['mdb'], 'application/x-msbinder' => ['obd'], 'application/x-mscardfile' => ['crd'], 'application/x-msclip' => ['clp'], 'application/x-msdos-program' => ['exe'], 'application/x-msdownload' => ['exe', 'dll', 'com', 'bat', 'msi'], 'application/x-msmediaview' => ['mvb', 'm13', 'm14'], 'application/x-msmetafile' => ['wmf', 'wmz', 'emf', 'emz'], 'application/x-msmoney' => ['mny'], 'application/x-mspublisher' => ['pub'], 'application/x-msschedule' => ['scd'], 'application/x-msterminal' => ['trm'], 'application/x-mswrite' => ['wri'], 'application/x-netcdf' => ['nc', 'cdf'], 'application/x-ns-proxy-autoconfig' => ['pac'], 'application/x-nzb' => ['nzb'], 'application/x-perl' => ['pl', 'pm'], 'application/x-pilot' => ['prc', 'pdb'], 'application/x-pkcs12' => ['p12', 'pfx'], 'application/x-pkcs7-certificates' => ['p7b', 'spc'], 'application/x-pkcs7-certreqresp' => ['p7r'], 'application/x-rar-compressed' => ['rar'], 'application/x-redhat-package-manager' => ['rpm'], 'application/x-research-info-systems' => ['ris'], 'application/x-sea' => ['sea'], 'application/x-sh' => ['sh'], 'application/x-shar' => ['shar'], 'application/x-shockwave-flash' => ['swf'], 'application/x-silverlight-app' => ['xap'], 'application/x-sql' => ['sql'], 'application/x-stuffit' => ['sit'], 'application/x-stuffitx' => ['sitx'], 'application/x-subrip' => ['srt'], 'application/x-sv4cpio' => ['sv4cpio'], 'application/x-sv4crc' => ['sv4crc'], 'application/x-t3vm-image' => ['t3'], 'application/x-tads' => ['gam'], 'application/x-tar' => ['tar', 'tgz'], 'application/x-tcl' => ['tcl', 'tk'], 'application/x-tex' => ['tex'], 'application/x-tex-tfm' => ['tfm'], 'application/x-texinfo' => ['texinfo', 'texi'], 'application/x-tgif' => ['obj'], 'application/x-ustar' => ['ustar'], 'application/x-virtualbox-hdd' => ['hdd'], 'application/x-virtualbox-ova' => ['ova'], 'application/x-virtualbox-ovf' => ['ovf'], 'application/x-virtualbox-vbox' => ['vbox'], 'application/x-virtualbox-vbox-extpack' => ['vbox-extpack'], 'application/x-virtualbox-vdi' => ['vdi'], 'application/x-virtualbox-vhd' => ['vhd'], 'application/x-virtualbox-vmdk' => ['vmdk'], 'application/x-wais-source' => ['src'], 'application/x-web-app-manifest+json' => ['webapp'], 'application/x-x509-ca-cert' => ['der', 'crt', 'pem'], 'application/x-xfig' => ['fig'], 'application/x-xliff+xml' => ['xlf'], 'application/x-xpinstall' => ['xpi'], 'application/x-xz' => ['xz'], 'application/x-zmachine' => ['z1', 'z2', 'z3', 'z4', 'z5', 'z6', 'z7', 'z8'], 'application/xaml+xml' => ['xaml'], 'application/xcap-att+xml' => ['xav'], 'application/xcap-caps+xml' => ['xca'], 'application/xcap-diff+xml' => ['xdf'], 'application/xcap-el+xml' => ['xel'], 'application/xcap-ns+xml' => ['xns'], 'application/xenc+xml' => ['xenc'], 'application/xfdf' => ['xfdf'], 'application/xhtml+xml' => ['xhtml', 'xht'], 'application/xliff+xml' => ['xlf'], 'application/xml' => ['xml', 'xsl', 'xsd', 'rng'], 'application/xml-dtd' => ['dtd'], 'application/xop+xml' => ['xop'], 'application/xproc+xml' => ['xpl'], 'application/xslt+xml' => ['xsl', 'xslt'], 'application/xspf+xml' => ['xspf'], 'application/xv+xml' => ['mxml', 'xhvml', 'xvml', 'xvm'], 'application/yang' => ['yang'], 'application/yin+xml' => ['yin'], 'application/zip' => ['zip'], 'audio/3gpp' => ['3gpp'], 'audio/aac' => ['adts', 'aac'], 'audio/adpcm' => ['adp'], 'audio/amr' => ['amr'], 'audio/basic' => ['au', 'snd'], 'audio/midi' => ['mid', 'midi', 'kar', 'rmi'], 'audio/mobile-xmf' => ['mxmf'], 'audio/mp3' => ['mp3'], 'audio/mp4' => ['m4a', 'mp4a'], 'audio/mpeg' => ['mpga', 'mp2', 'mp2a', 'mp3', 'm2a', 'm3a'], 'audio/ogg' => ['oga', 'ogg', 'spx', 'opus'], 'audio/s3m' => ['s3m'], 'audio/silk' => ['sil'], 'audio/vnd.dece.audio' => ['uva', 'uvva'], 'audio/vnd.digital-winds' => ['eol'], 'audio/vnd.dra' => ['dra'], 'audio/vnd.dts' => ['dts'], 'audio/vnd.dts.hd' => ['dtshd'], 'audio/vnd.lucent.voice' => ['lvp'], 'audio/vnd.ms-playready.media.pya' => ['pya'], 'audio/vnd.nuera.ecelp4800' => ['ecelp4800'], 'audio/vnd.nuera.ecelp7470' => ['ecelp7470'], 'audio/vnd.nuera.ecelp9600' => ['ecelp9600'], 'audio/vnd.rip' => ['rip'], 'audio/wav' => ['wav'], 'audio/wave' => ['wav'], 'audio/webm' => ['weba'], 'audio/x-aac' => ['aac'], 'audio/x-aiff' => ['aif', 'aiff', 'aifc'], 'audio/x-caf' => ['caf'], 'audio/x-flac' => ['flac'], 'audio/x-m4a' => ['m4a'], 'audio/x-matroska' => ['mka'], 'audio/x-mpegurl' => ['m3u'], 'audio/x-ms-wax' => ['wax'], 'audio/x-ms-wma' => ['wma'], 'audio/x-pn-realaudio' => ['ram', 'ra', 'rm'], 'audio/x-pn-realaudio-plugin' => ['rmp', 'rpm'], 'audio/x-realaudio' => ['ra'], 'audio/x-wav' => ['wav'], 'audio/xm' => ['xm'], 'chemical/x-cdx' => ['cdx'], 'chemical/x-cif' => ['cif'], 'chemical/x-cmdf' => ['cmdf'], 'chemical/x-cml' => ['cml'], 'chemical/x-csml' => ['csml'], 'chemical/x-xyz' => ['xyz'], 'font/collection' => ['ttc'], 'font/otf' => ['otf'], 'font/ttf' => ['ttf'], 'font/woff' => ['woff'], 'font/woff2' => ['woff2'], 'image/aces' => ['exr'], 'image/apng' => ['apng'], 'image/avci' => ['avci'], 'image/avcs' => ['avcs'], 'image/avif' => ['avif'], 'image/bmp' => ['bmp', 'dib'], 'image/cgm' => ['cgm'], 'image/dicom-rle' => ['drle'], 'image/dpx' => ['dpx'], 'image/emf' => ['emf'], 'image/fits' => ['fits'], 'image/g3fax' => ['g3'], 'image/gif' => ['gif'], 'image/heic' => ['heic'], 'image/heic-sequence' => ['heics'], 'image/heif' => ['heif'], 'image/heif-sequence' => ['heifs'], 'image/hej2k' => ['hej2'], 'image/hsj2' => ['hsj2'], 'image/ief' => ['ief'], 'image/jls' => ['jls'], 'image/jp2' => ['jp2', 'jpg2'], 'image/jpeg' => ['jpeg', 'jpg', 'jpe'], 'image/jph' => ['jph'], 'image/jphc' => ['jhc'], 'image/jpm' => ['jpm', 'jpgm'], 'image/jpx' => ['jpx', 'jpf'], 'image/jxl' => ['jxl'], 'image/jxr' => ['jxr'], 'image/jxra' => ['jxra'], 'image/jxrs' => ['jxrs'], 'image/jxs' => ['jxs'], 'image/jxsc' => ['jxsc'], 'image/jxsi' => ['jxsi'], 'image/jxss' => ['jxss'], 'image/ktx' => ['ktx'], 'image/ktx2' => ['ktx2'], 'image/png' => ['png'], 'image/prs.btif' => ['btif', 'btf'], 'image/prs.pti' => ['pti'], 'image/sgi' => ['sgi'], 'image/svg+xml' => ['svg', 'svgz'], 'image/t38' => ['t38'], 'image/tiff' => ['tif', 'tiff'], 'image/tiff-fx' => ['tfx'], 'image/vnd.adobe.photoshop' => ['psd'], 'image/vnd.airzip.accelerator.azv' => ['azv'], 'image/vnd.dece.graphic' => ['uvi', 'uvvi', 'uvg', 'uvvg'], 'image/vnd.djvu' => ['djvu', 'djv'], 'image/vnd.dvb.subtitle' => ['sub'], 'image/vnd.dwg' => ['dwg'], 'image/vnd.dxf' => ['dxf'], 'image/vnd.fastbidsheet' => ['fbs'], 'image/vnd.fpx' => ['fpx'], 'image/vnd.fst' => ['fst'], 'image/vnd.fujixerox.edmics-mmr' => ['mmr'], 'image/vnd.fujixerox.edmics-rlc' => ['rlc'], 'image/vnd.microsoft.icon' => ['ico'], 'image/vnd.ms-dds' => ['dds'], 'image/vnd.ms-modi' => ['mdi'], 'image/vnd.ms-photo' => ['wdp'], 'image/vnd.net-fpx' => ['npx'], 'image/vnd.pco.b16' => ['b16'], 'image/vnd.tencent.tap' => ['tap'], 'image/vnd.valve.source.texture' => ['vtf'], 'image/vnd.wap.wbmp' => ['wbmp'], 'image/vnd.xiff' => ['xif'], 'image/vnd.zbrush.pcx' => ['pcx'], 'image/webp' => ['webp'], 'image/wmf' => ['wmf'], 'image/x-3ds' => ['3ds'], 'image/x-cmu-raster' => ['ras'], 'image/x-cmx' => ['cmx'], 'image/x-freehand' => ['fh', 'fhc', 'fh4', 'fh5', 'fh7'], 'image/x-icon' => ['ico'], 'image/x-jng' => ['jng'], 'image/x-mrsid-image' => ['sid'], 'image/x-ms-bmp' => ['bmp'], 'image/x-pcx' => ['pcx'], 'image/x-pict' => ['pic', 'pct'], 'image/x-portable-anymap' => ['pnm'], 'image/x-portable-bitmap' => ['pbm'], 'image/x-portable-graymap' => ['pgm'], 'image/x-portable-pixmap' => ['ppm'], 'image/x-rgb' => ['rgb'], 'image/x-tga' => ['tga'], 'image/x-xbitmap' => ['xbm'], 'image/x-xpixmap' => ['xpm'], 'image/x-xwindowdump' => ['xwd'], 'message/disposition-notification' => ['disposition-notification'], 'message/global' => ['u8msg'], 'message/global-delivery-status' => ['u8dsn'], 'message/global-disposition-notification' => ['u8mdn'], 'message/global-headers' => ['u8hdr'], 'message/rfc822' => ['eml', 'mime'], 'message/vnd.wfa.wsc' => ['wsc'], 'model/3mf' => ['3mf'], 'model/gltf+json' => ['gltf'], 'model/gltf-binary' => ['glb'], 'model/iges' => ['igs', 'iges'], 'model/jt' => ['jt'], 'model/mesh' => ['msh', 'mesh', 'silo'], 'model/mtl' => ['mtl'], 'model/obj' => ['obj'], 'model/prc' => ['prc'], 'model/step+xml' => ['stpx'], 'model/step+zip' => ['stpz'], 'model/step-xml+zip' => ['stpxz'], 'model/stl' => ['stl'], 'model/u3d' => ['u3d'], 'model/vnd.bary' => ['bary'], 'model/vnd.cld' => ['cld'], 'model/vnd.collada+xml' => ['dae'], 'model/vnd.dwf' => ['dwf'], 'model/vnd.gdl' => ['gdl'], 'model/vnd.gtw' => ['gtw'], 'model/vnd.mts' => ['mts'], 'model/vnd.opengex' => ['ogex'], 'model/vnd.parasolid.transmit.binary' => ['x_b'], 'model/vnd.parasolid.transmit.text' => ['x_t'], 'model/vnd.pytha.pyox' => ['pyo', 'pyox'], 'model/vnd.sap.vds' => ['vds'], 'model/vnd.usda' => ['usda'], 'model/vnd.usdz+zip' => ['usdz'], 'model/vnd.valve.source.compiled-map' => ['bsp'], 'model/vnd.vtu' => ['vtu'], 'model/vrml' => ['wrl', 'vrml'], 'model/x3d+binary' => ['x3db', 'x3dbz'], 'model/x3d+fastinfoset' => ['x3db'], 'model/x3d+vrml' => ['x3dv', 'x3dvz'], 'model/x3d+xml' => ['x3d', 'x3dz'], 'model/x3d-vrml' => ['x3dv'], 'text/cache-manifest' => ['appcache', 'manifest'], 'text/calendar' => ['ics', 'ifb'], 'text/coffeescript' => ['coffee', 'litcoffee'], 'text/css' => ['css'], 'text/csv' => ['csv'], 'text/html' => ['html', 'htm', 'shtml'], 'text/jade' => ['jade'], 'text/javascript' => ['js', 'mjs'], 'text/jsx' => ['jsx'], 'text/less' => ['less'], 'text/markdown' => ['md', 'markdown'], 'text/mathml' => ['mml'], 'text/mdx' => ['mdx'], 'text/n3' => ['n3'], 'text/plain' => ['txt', 'text', 'conf', 'def', 'list', 'log', 'in', 'ini', 'm3u'], 'text/prs.lines.tag' => ['dsc'], 'text/richtext' => ['rtx'], 'text/rtf' => ['rtf'], 'text/sgml' => ['sgml', 'sgm'], 'text/shex' => ['shex'], 'text/slim' => ['slim', 'slm'], 'text/spdx' => ['spdx'], 'text/stylus' => ['stylus', 'styl'], 'text/tab-separated-values' => ['tsv'], 'text/troff' => ['t', 'tr', 'roff', 'man', 'me', 'ms'], 'text/turtle' => ['ttl'], 'text/uri-list' => ['uri', 'uris', 'urls'], 'text/vcard' => ['vcard'], 'text/vnd.curl' => ['curl'], 'text/vnd.curl.dcurl' => ['dcurl'], 'text/vnd.curl.mcurl' => ['mcurl'], 'text/vnd.curl.scurl' => ['scurl'], 'text/vnd.dvb.subtitle' => ['sub'], 'text/vnd.familysearch.gedcom' => ['ged'], 'text/vnd.fly' => ['fly'], 'text/vnd.fmi.flexstor' => ['flx'], 'text/vnd.graphviz' => ['gv'], 'text/vnd.in3d.3dml' => ['3dml'], 'text/vnd.in3d.spot' => ['spot'], 'text/vnd.sun.j2me.app-descriptor' => ['jad'], 'text/vnd.wap.wml' => ['wml'], 'text/vnd.wap.wmlscript' => ['wmls'], 'text/vtt' => ['vtt'], 'text/wgsl' => ['wgsl'], 'text/x-asm' => ['s', 'asm'], 'text/x-c' => ['c', 'cc', 'cxx', 'cpp', 'h', 'hh', 'dic'], 'text/x-component' => ['htc'], 'text/x-fortran' => ['f', 'for', 'f77', 'f90'], 'text/x-handlebars-template' => ['hbs'], 'text/x-java-source' => ['java'], 'text/x-lua' => ['lua'], 'text/x-markdown' => ['mkd'], 'text/x-nfo' => ['nfo'], 'text/x-opml' => ['opml'], 'text/x-org' => ['org'], 'text/x-pascal' => ['p', 'pas'], 'text/x-processing' => ['pde'], 'text/x-sass' => ['sass'], 'text/x-scss' => ['scss'], 'text/x-setext' => ['etx'], 'text/x-sfv' => ['sfv'], 'text/x-suse-ymp' => ['ymp'], 'text/x-uuencode' => ['uu'], 'text/x-vcalendar' => ['vcs'], 'text/x-vcard' => ['vcf'], 'text/xml' => ['xml'], 'text/yaml' => ['yaml', 'yml'], 'video/3gpp' => ['3gp', '3gpp'], 'video/3gpp2' => ['3g2'], 'video/h261' => ['h261'], 'video/h263' => ['h263'], 'video/h264' => ['h264'], 'video/iso.segment' => ['m4s'], 'video/jpeg' => ['jpgv'], 'video/jpm' => ['jpm', 'jpgm'], 'video/mj2' => ['mj2', 'mjp2'], 'video/mp2t' => ['ts', 'm2t', 'm2ts', 'mts'], 'video/mp4' => ['mp4', 'mp4v', 'mpg4', 'f4v'], 'video/mpeg' => ['mpeg', 'mpg', 'mpe', 'm1v', 'm2v'], 'video/ogg' => ['ogv'], 'video/quicktime' => ['qt', 'mov'], 'video/vnd.dece.hd' => ['uvh', 'uvvh'], 'video/vnd.dece.mobile' => ['uvm', 'uvvm'], 'video/vnd.dece.pd' => ['uvp', 'uvvp'], 'video/vnd.dece.sd' => ['uvs', 'uvvs'], 'video/vnd.dece.video' => ['uvv', 'uvvv'], 'video/vnd.dvb.file' => ['dvb'], 'video/vnd.fvt' => ['fvt'], 'video/vnd.mpegurl' => ['mxu', 'm4u'], 'video/vnd.ms-playready.media.pyv' => ['pyv'], 'video/vnd.uvvu.mp4' => ['uvu', 'uvvu'], 'video/vnd.vivo' => ['viv'], 'video/webm' => ['webm'], 'video/x-f4v' => ['f4v'], 'video/x-fli' => ['fli'], 'video/x-flv' => ['flv'], 'video/x-m4v' => ['m4v'], 'video/x-matroska' => ['mkv', 'mk3d', 'mks'], 'video/x-mng' => ['mng'], 'video/x-ms-asf' => ['asf', 'asx'], 'video/x-ms-vob' => ['vob'], 'video/x-ms-wm' => ['wm'], 'video/x-ms-wmv' => ['wmv'], 'video/x-ms-wmx' => ['wmx'], 'video/x-ms-wvx' => ['wvx'], 'video/x-msvideo' => ['avi'], 'video/x-sgi-movie' => ['movie'], 'video/x-smv' => ['smv'], 'x-conference/x-cooltalk' => ['ice'], 'application/x-photoshop' => ['psd'], 'application/smil' => ['smi', 'smil'], 'application/powerpoint' => ['ppt'], 'application/vnd.ms-powerpoint.addin.macroEnabled.12' => ['ppam'], 'application/vnd.ms-powerpoint.presentation.macroEnabled.12' => ['pptm', 'potm'], 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12' => ['ppsm'], 'application/wbxml' => ['wbxml'], 'application/wmlc' => ['wmlc'], 'application/x-httpd-php-source' => ['phps'], 'application/x-compress' => ['z'], 'application/x-rar' => ['rar'], 'video/vnd.rn-realvideo' => ['rv'], 'application/vnd.ms-word.template.macroEnabled.12' => ['docm', 'dotm'], 'application/vnd.ms-excel.sheet.macroEnabled.12' => ['xlsm'], 'application/vnd.ms-excel.template.macroEnabled.12' => ['xltm'], 'application/vnd.ms-excel.addin.macroEnabled.12' => ['xlam'], 'application/vnd.ms-excel.sheet.binary.macroEnabled.12' => ['xlsb'], 'application/excel' => ['xl'], 'application/x-x509-user-cert' => ['pem'], 'application/x-pkcs10' => ['p10'], 'application/x-pkcs7-signature' => ['p7a'], 'application/pgp' => ['pgp'], 'application/gpg-keys' => ['gpg'], 'application/x-pkcs7' => ['rsa'], 'video/3gp' => ['3gp'], 'audio/acc' => ['aac'], 'application/vnd.mpegurl' => ['m4u'], 'application/videolan' => ['vlc'], 'audio/x-au' => ['au'], 'audio/ac3' => ['ac3'], 'text/x-scriptzsh' => ['zsh'], 'application/cdr' => ['cdr'], 'application/STEP' => ['step', 'stp'], 'application/x-ndjson' => ['ndjson'], 'application/braille' => ['brf'], ]; public function lookupMimeType(string $extension): ?string { return self::MIME_TYPES_FOR_EXTENSIONS[$extension] ?? null; } public function lookupExtension(string $mimetype): ?string { return self::EXTENSIONS_FOR_MIME_TIMES[$mimetype][0] ?? null; } /** * @return string[] */ public function lookupAllExtensions(string $mimetype): array { return self::EXTENSIONS_FOR_MIME_TIMES[$mimetype] ?? []; } } PKZ 2EmptyExtensionToMimeTypeMap.phpnuW+A $overrides */ public function __construct(ExtensionToMimeTypeMap $innerMap, array $overrides) { $this->innerMap = $innerMap; $this->overrides = $overrides; } public function lookupMimeType(string $extension): ?string { return $this->overrides[$extension] ?? $this->innerMap->lookupMimeType($extension); } } PKZ!% FinfoMimeTypeDetector.phpnuW+A */ private $inconclusiveMimetypes; public function __construct( string $magicFile = '', ?ExtensionToMimeTypeMap $extensionMap = null, ?int $bufferSampleSize = null, array $inconclusiveMimetypes = self::INCONCLUSIVE_MIME_TYPES ) { $this->finfo = new finfo(FILEINFO_MIME_TYPE, $magicFile); $this->extensionMap = $extensionMap ?: new GeneratedExtensionToMimeTypeMap(); $this->bufferSampleSize = $bufferSampleSize; $this->inconclusiveMimetypes = $inconclusiveMimetypes; } public function detectMimeType(string $path, $contents): ?string { $mimeType = is_string($contents) ? (@$this->finfo->buffer($this->takeSample($contents)) ?: null) : null; if ($mimeType !== null && ! in_array($mimeType, $this->inconclusiveMimetypes)) { return $mimeType; } return $this->detectMimeTypeFromPath($path); } public function detectMimeTypeFromPath(string $path): ?string { $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION)); return $this->extensionMap->lookupMimeType($extension); } public function detectMimeTypeFromFile(string $path): ?string { return @$this->finfo->file($path) ?: null; } public function detectMimeTypeFromBuffer(string $contents): ?string { return @$this->finfo->buffer($this->takeSample($contents)) ?: null; } private function takeSample(string $contents): string { if ($this->bufferSampleSize === null) { return $contents; } return (string) substr($contents, 0, $this->bufferSampleSize); } public function lookupExtension(string $mimetype): ?string { return $this->extensionMap instanceof ExtensionLookup ? $this->extensionMap->lookupExtension($mimetype) : null; } public function lookupAllExtensions(string $mimetype): array { return $this->extensionMap instanceof ExtensionLookup ? $this->extensionMap->lookupAllExtensions($mimetype) : []; } } PKZLKKInternal/Calculator.phpnuW+Ainit($a, $b); if ($aNeg && ! $bNeg) { return -1; } if ($bNeg && ! $aNeg) { return 1; } $aLen = \strlen($aDig); $bLen = \strlen($bDig); if ($aLen < $bLen) { $result = -1; } elseif ($aLen > $bLen) { $result = 1; } else { $result = $aDig <=> $bDig; } return $aNeg ? -$result : $result; } /** * Adds two numbers. */ abstract public function add(string $a, string $b) : string; /** * Subtracts two numbers. */ abstract public function sub(string $a, string $b) : string; /** * Multiplies two numbers. */ abstract public function mul(string $a, string $b) : string; /** * Returns the quotient of the division of two numbers. * * @param string $a The dividend. * @param string $b The divisor, must not be zero. * * @return string The quotient. */ abstract public function divQ(string $a, string $b) : string; /** * Returns the remainder of the division of two numbers. * * @param string $a The dividend. * @param string $b The divisor, must not be zero. * * @return string The remainder. */ abstract public function divR(string $a, string $b) : string; /** * Returns the quotient and remainder of the division of two numbers. * * @param string $a The dividend. * @param string $b The divisor, must not be zero. * * @return array{string, string} An array containing the quotient and remainder. */ abstract public function divQR(string $a, string $b) : array; /** * Exponentiates a number. * * @param string $a The base number. * @param int $e The exponent, validated as an integer between 0 and MAX_POWER. * * @return string The power. */ abstract public function pow(string $a, int $e) : string; /** * @param string $b The modulus; must not be zero. */ public function mod(string $a, string $b) : string { return $this->divR($this->add($this->divR($a, $b), $b), $b); } /** * Returns the modular multiplicative inverse of $x modulo $m. * * If $x has no multiplicative inverse mod m, this method must return null. * * This method can be overridden by the concrete implementation if the underlying library has built-in support. * * @param string $m The modulus; must not be negative or zero. */ public function modInverse(string $x, string $m) : ?string { if ($m === '1') { return '0'; } $modVal = $x; if ($x[0] === '-' || ($this->cmp($this->abs($x), $m) >= 0)) { $modVal = $this->mod($x, $m); } [$g, $x] = $this->gcdExtended($modVal, $m); if ($g !== '1') { return null; } return $this->mod($this->add($this->mod($x, $m), $m), $m); } /** * Raises a number into power with modulo. * * @param string $base The base number; must be positive or zero. * @param string $exp The exponent; must be positive or zero. * @param string $mod The modulus; must be strictly positive. */ abstract public function modPow(string $base, string $exp, string $mod) : string; /** * Returns the greatest common divisor of the two numbers. * * This method can be overridden by the concrete implementation if the underlying library * has built-in support for GCD calculations. * * @return string The GCD, always positive, or zero if both arguments are zero. */ public function gcd(string $a, string $b) : string { if ($a === '0') { return $this->abs($b); } if ($b === '0') { return $this->abs($a); } return $this->gcd($b, $this->divR($a, $b)); } /** * @return array{string, string, string} GCD, X, Y */ private function gcdExtended(string $a, string $b) : array { if ($a === '0') { return [$b, '0', '1']; } [$gcd, $x1, $y1] = $this->gcdExtended($this->mod($b, $a), $a); $x = $this->sub($y1, $this->mul($this->divQ($b, $a), $x1)); $y = $x1; return [$gcd, $x, $y]; } /** * Returns the square root of the given number, rounded down. * * The result is the largest x such that x² ≤ n. * The input MUST NOT be negative. */ abstract public function sqrt(string $n) : string; /** * Converts a number from an arbitrary base. * * This method can be overridden by the concrete implementation if the underlying library * has built-in support for base conversion. * * @param string $number The number, positive or zero, non-empty, case-insensitively validated for the given base. * @param int $base The base of the number, validated from 2 to 36. * * @return string The converted number, following the Calculator conventions. */ public function fromBase(string $number, int $base) : string { return $this->fromArbitraryBase(\strtolower($number), self::ALPHABET, $base); } /** * Converts a number to an arbitrary base. * * This method can be overridden by the concrete implementation if the underlying library * has built-in support for base conversion. * * @param string $number The number to convert, following the Calculator conventions. * @param int $base The base to convert to, validated from 2 to 36. * * @return string The converted number, lowercase. */ public function toBase(string $number, int $base) : string { $negative = ($number[0] === '-'); if ($negative) { $number = \substr($number, 1); } $number = $this->toArbitraryBase($number, self::ALPHABET, $base); if ($negative) { return '-' . $number; } return $number; } /** * Converts a non-negative number in an arbitrary base using a custom alphabet, to base 10. * * @param string $number The number to convert, validated as a non-empty string, * containing only chars in the given alphabet/base. * @param string $alphabet The alphabet that contains every digit, validated as 2 chars minimum. * @param int $base The base of the number, validated from 2 to alphabet length. * * @return string The number in base 10, following the Calculator conventions. */ final public function fromArbitraryBase(string $number, string $alphabet, int $base) : string { // remove leading "zeros" $number = \ltrim($number, $alphabet[0]); if ($number === '') { return '0'; } // optimize for "one" if ($number === $alphabet[1]) { return '1'; } $result = '0'; $power = '1'; $base = (string) $base; for ($i = \strlen($number) - 1; $i >= 0; $i--) { $index = \strpos($alphabet, $number[$i]); if ($index !== 0) { $result = $this->add($result, ($index === 1) ? $power : $this->mul($power, (string) $index) ); } if ($i !== 0) { $power = $this->mul($power, $base); } } return $result; } /** * Converts a non-negative number to an arbitrary base using a custom alphabet. * * @param string $number The number to convert, positive or zero, following the Calculator conventions. * @param string $alphabet The alphabet that contains every digit, validated as 2 chars minimum. * @param int $base The base to convert to, validated from 2 to alphabet length. * * @return string The converted number in the given alphabet. */ final public function toArbitraryBase(string $number, string $alphabet, int $base) : string { if ($number === '0') { return $alphabet[0]; } $base = (string) $base; $result = ''; while ($number !== '0') { [$number, $remainder] = $this->divQR($number, $base); $remainder = (int) $remainder; $result .= $alphabet[$remainder]; } return \strrev($result); } /** * Performs a rounded division. * * Rounding is performed when the remainder of the division is not zero. * * @param string $a The dividend. * @param string $b The divisor, must not be zero. * @param int $roundingMode The rounding mode. * * @throws \InvalidArgumentException If the rounding mode is invalid. * @throws RoundingNecessaryException If RoundingMode::UNNECESSARY is provided but rounding is necessary. * * @psalm-suppress ImpureFunctionCall */ final public function divRound(string $a, string $b, int $roundingMode) : string { [$quotient, $remainder] = $this->divQR($a, $b); $hasDiscardedFraction = ($remainder !== '0'); $isPositiveOrZero = ($a[0] === '-') === ($b[0] === '-'); $discardedFractionSign = function() use ($remainder, $b) : int { $r = $this->abs($this->mul($remainder, '2')); $b = $this->abs($b); return $this->cmp($r, $b); }; $increment = false; switch ($roundingMode) { case RoundingMode::UNNECESSARY: if ($hasDiscardedFraction) { throw RoundingNecessaryException::roundingNecessary(); } break; case RoundingMode::UP: $increment = $hasDiscardedFraction; break; case RoundingMode::DOWN: break; case RoundingMode::CEILING: $increment = $hasDiscardedFraction && $isPositiveOrZero; break; case RoundingMode::FLOOR: $increment = $hasDiscardedFraction && ! $isPositiveOrZero; break; case RoundingMode::HALF_UP: $increment = $discardedFractionSign() >= 0; break; case RoundingMode::HALF_DOWN: $increment = $discardedFractionSign() > 0; break; case RoundingMode::HALF_CEILING: $increment = $isPositiveOrZero ? $discardedFractionSign() >= 0 : $discardedFractionSign() > 0; break; case RoundingMode::HALF_FLOOR: $increment = $isPositiveOrZero ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0; break; case RoundingMode::HALF_EVEN: $lastDigit = (int) $quotient[-1]; $lastDigitIsEven = ($lastDigit % 2 === 0); $increment = $lastDigitIsEven ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0; break; default: throw new \InvalidArgumentException('Invalid rounding mode.'); } if ($increment) { return $this->add($quotient, $isPositiveOrZero ? '1' : '-1'); } return $quotient; } /** * Calculates bitwise AND of two numbers. * * This method can be overridden by the concrete implementation if the underlying library * has built-in support for bitwise operations. */ public function and(string $a, string $b) : string { return $this->bitwise('and', $a, $b); } /** * Calculates bitwise OR of two numbers. * * This method can be overridden by the concrete implementation if the underlying library * has built-in support for bitwise operations. */ public function or(string $a, string $b) : string { return $this->bitwise('or', $a, $b); } /** * Calculates bitwise XOR of two numbers. * * This method can be overridden by the concrete implementation if the underlying library * has built-in support for bitwise operations. */ public function xor(string $a, string $b) : string { return $this->bitwise('xor', $a, $b); } /** * Performs a bitwise operation on a decimal number. * * @param 'and'|'or'|'xor' $operator The operator to use. * @param string $a The left operand. * @param string $b The right operand. */ private function bitwise(string $operator, string $a, string $b) : string { [$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b); $aBin = $this->toBinary($aDig); $bBin = $this->toBinary($bDig); $aLen = \strlen($aBin); $bLen = \strlen($bBin); if ($aLen > $bLen) { $bBin = \str_repeat("\x00", $aLen - $bLen) . $bBin; } elseif ($bLen > $aLen) { $aBin = \str_repeat("\x00", $bLen - $aLen) . $aBin; } if ($aNeg) { $aBin = $this->twosComplement($aBin); } if ($bNeg) { $bBin = $this->twosComplement($bBin); } switch ($operator) { case 'and': $value = $aBin & $bBin; $negative = ($aNeg and $bNeg); break; case 'or': $value = $aBin | $bBin; $negative = ($aNeg or $bNeg); break; case 'xor': $value = $aBin ^ $bBin; $negative = ($aNeg xor $bNeg); break; // @codeCoverageIgnoreStart default: throw new \InvalidArgumentException('Invalid bitwise operator.'); // @codeCoverageIgnoreEnd } if ($negative) { $value = $this->twosComplement($value); } $result = $this->toDecimal($value); return $negative ? $this->neg($result) : $result; } /** * @param string $number A positive, binary number. */ private function twosComplement(string $number) : string { $xor = \str_repeat("\xff", \strlen($number)); $number ^= $xor; for ($i = \strlen($number) - 1; $i >= 0; $i--) { $byte = \ord($number[$i]); if (++$byte !== 256) { $number[$i] = \chr($byte); break; } $number[$i] = "\x00"; if ($i === 0) { $number = "\x01" . $number; } } return $number; } /** * Converts a decimal number to a binary string. * * @param string $number The number to convert, positive or zero, only digits. */ private function toBinary(string $number) : string { $result = ''; while ($number !== '0') { [$number, $remainder] = $this->divQR($number, '256'); $result .= \chr((int) $remainder); } return \strrev($result); } /** * Returns the positive decimal representation of a binary number. * * @param string $bytes The bytes representing the number. */ private function toDecimal(string $bytes) : string { $result = '0'; $power = '1'; for ($i = \strlen($bytes) - 1; $i >= 0; $i--) { $index = \ord($bytes[$i]); if ($index !== 0) { $result = $this->add($result, ($index === 1) ? $power : $this->mul($power, (string) $index) ); } if ($i !== 0) { $power = $this->mul($power, '256'); } } return $result; } } PKZmK~L  %Internal/Calculator/GmpCalculator.phpnuW+AmaxDigits = 9; break; case 8: $this->maxDigits = 18; break; default: throw new \RuntimeException('The platform is not 32-bit or 64-bit as expected.'); } } public function add(string $a, string $b) : string { /** * @psalm-var numeric-string $a * @psalm-var numeric-string $b */ $result = $a + $b; if (is_int($result)) { return (string) $result; } if ($a === '0') { return $b; } if ($b === '0') { return $a; } [$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b); $result = $aNeg === $bNeg ? $this->doAdd($aDig, $bDig) : $this->doSub($aDig, $bDig); if ($aNeg) { $result = $this->neg($result); } return $result; } public function sub(string $a, string $b) : string { return $this->add($a, $this->neg($b)); } public function mul(string $a, string $b) : string { /** * @psalm-var numeric-string $a * @psalm-var numeric-string $b */ $result = $a * $b; if (is_int($result)) { return (string) $result; } if ($a === '0' || $b === '0') { return '0'; } if ($a === '1') { return $b; } if ($b === '1') { return $a; } if ($a === '-1') { return $this->neg($b); } if ($b === '-1') { return $this->neg($a); } [$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b); $result = $this->doMul($aDig, $bDig); if ($aNeg !== $bNeg) { $result = $this->neg($result); } return $result; } public function divQ(string $a, string $b) : string { return $this->divQR($a, $b)[0]; } public function divR(string $a, string $b): string { return $this->divQR($a, $b)[1]; } public function divQR(string $a, string $b) : array { if ($a === '0') { return ['0', '0']; } if ($a === $b) { return ['1', '0']; } if ($b === '1') { return [$a, '0']; } if ($b === '-1') { return [$this->neg($a), '0']; } /** @psalm-var numeric-string $a */ $na = $a * 1; // cast to number if (is_int($na)) { /** @psalm-var numeric-string $b */ $nb = $b * 1; if (is_int($nb)) { // the only division that may overflow is PHP_INT_MIN / -1, // which cannot happen here as we've already handled a divisor of -1 above. $r = $na % $nb; $q = ($na - $r) / $nb; assert(is_int($q)); return [ (string) $q, (string) $r ]; } } [$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b); [$q, $r] = $this->doDiv($aDig, $bDig); if ($aNeg !== $bNeg) { $q = $this->neg($q); } if ($aNeg) { $r = $this->neg($r); } return [$q, $r]; } public function pow(string $a, int $e) : string { if ($e === 0) { return '1'; } if ($e === 1) { return $a; } $odd = $e % 2; $e -= $odd; $aa = $this->mul($a, $a); /** @psalm-suppress PossiblyInvalidArgument We're sure that $e / 2 is an int now */ $result = $this->pow($aa, $e / 2); if ($odd === 1) { $result = $this->mul($result, $a); } return $result; } /** * Algorithm from: https://www.geeksforgeeks.org/modular-exponentiation-power-in-modular-arithmetic/ */ public function modPow(string $base, string $exp, string $mod) : string { // special case: the algorithm below fails with 0 power 0 mod 1 (returns 1 instead of 0) if ($base === '0' && $exp === '0' && $mod === '1') { return '0'; } // special case: the algorithm below fails with power 0 mod 1 (returns 1 instead of 0) if ($exp === '0' && $mod === '1') { return '0'; } $x = $base; $res = '1'; // numbers are positive, so we can use remainder instead of modulo $x = $this->divR($x, $mod); while ($exp !== '0') { if (in_array($exp[-1], ['1', '3', '5', '7', '9'])) { // odd $res = $this->divR($this->mul($res, $x), $mod); } $exp = $this->divQ($exp, '2'); $x = $this->divR($this->mul($x, $x), $mod); } return $res; } /** * Adapted from https://cp-algorithms.com/num_methods/roots_newton.html */ public function sqrt(string $n) : string { if ($n === '0') { return '0'; } // initial approximation $x = \str_repeat('9', \intdiv(\strlen($n), 2) ?: 1); $decreased = false; for (;;) { $nx = $this->divQ($this->add($x, $this->divQ($n, $x)), '2'); if ($x === $nx || $this->cmp($nx, $x) > 0 && $decreased) { break; } $decreased = $this->cmp($nx, $x) < 0; $x = $nx; } return $x; } /** * Performs the addition of two non-signed large integers. */ private function doAdd(string $a, string $b) : string { [$a, $b, $length] = $this->pad($a, $b); $carry = 0; $result = ''; for ($i = $length - $this->maxDigits;; $i -= $this->maxDigits) { $blockLength = $this->maxDigits; if ($i < 0) { $blockLength += $i; /** @psalm-suppress LoopInvalidation */ $i = 0; } /** @psalm-var numeric-string $blockA */ $blockA = \substr($a, $i, $blockLength); /** @psalm-var numeric-string $blockB */ $blockB = \substr($b, $i, $blockLength); $sum = (string) ($blockA + $blockB + $carry); $sumLength = \strlen($sum); if ($sumLength > $blockLength) { $sum = \substr($sum, 1); $carry = 1; } else { if ($sumLength < $blockLength) { $sum = \str_repeat('0', $blockLength - $sumLength) . $sum; } $carry = 0; } $result = $sum . $result; if ($i === 0) { break; } } if ($carry === 1) { $result = '1' . $result; } return $result; } /** * Performs the subtraction of two non-signed large integers. */ private function doSub(string $a, string $b) : string { if ($a === $b) { return '0'; } // Ensure that we always subtract to a positive result: biggest minus smallest. $cmp = $this->doCmp($a, $b); $invert = ($cmp === -1); if ($invert) { $c = $a; $a = $b; $b = $c; } [$a, $b, $length] = $this->pad($a, $b); $carry = 0; $result = ''; $complement = 10 ** $this->maxDigits; for ($i = $length - $this->maxDigits;; $i -= $this->maxDigits) { $blockLength = $this->maxDigits; if ($i < 0) { $blockLength += $i; /** @psalm-suppress LoopInvalidation */ $i = 0; } /** @psalm-var numeric-string $blockA */ $blockA = \substr($a, $i, $blockLength); /** @psalm-var numeric-string $blockB */ $blockB = \substr($b, $i, $blockLength); $sum = $blockA - $blockB - $carry; if ($sum < 0) { $sum += $complement; $carry = 1; } else { $carry = 0; } $sum = (string) $sum; $sumLength = \strlen($sum); if ($sumLength < $blockLength) { $sum = \str_repeat('0', $blockLength - $sumLength) . $sum; } $result = $sum . $result; if ($i === 0) { break; } } // Carry cannot be 1 when the loop ends, as a > b assert($carry === 0); $result = \ltrim($result, '0'); if ($invert) { $result = $this->neg($result); } return $result; } /** * Performs the multiplication of two non-signed large integers. */ private function doMul(string $a, string $b) : string { $x = \strlen($a); $y = \strlen($b); $maxDigits = \intdiv($this->maxDigits, 2); $complement = 10 ** $maxDigits; $result = '0'; for ($i = $x - $maxDigits;; $i -= $maxDigits) { $blockALength = $maxDigits; if ($i < 0) { $blockALength += $i; /** @psalm-suppress LoopInvalidation */ $i = 0; } $blockA = (int) \substr($a, $i, $blockALength); $line = ''; $carry = 0; for ($j = $y - $maxDigits;; $j -= $maxDigits) { $blockBLength = $maxDigits; if ($j < 0) { $blockBLength += $j; /** @psalm-suppress LoopInvalidation */ $j = 0; } $blockB = (int) \substr($b, $j, $blockBLength); $mul = $blockA * $blockB + $carry; $value = $mul % $complement; $carry = ($mul - $value) / $complement; $value = (string) $value; $value = \str_pad($value, $maxDigits, '0', STR_PAD_LEFT); $line = $value . $line; if ($j === 0) { break; } } if ($carry !== 0) { $line = $carry . $line; } $line = \ltrim($line, '0'); if ($line !== '') { $line .= \str_repeat('0', $x - $blockALength - $i); $result = $this->add($result, $line); } if ($i === 0) { break; } } return $result; } /** * Performs the division of two non-signed large integers. * * @return string[] The quotient and remainder. */ private function doDiv(string $a, string $b) : array { $cmp = $this->doCmp($a, $b); if ($cmp === -1) { return ['0', $a]; } $x = \strlen($a); $y = \strlen($b); // we now know that a >= b && x >= y $q = '0'; // quotient $r = $a; // remainder $z = $y; // focus length, always $y or $y+1 for (;;) { $focus = \substr($a, 0, $z); $cmp = $this->doCmp($focus, $b); if ($cmp === -1) { if ($z === $x) { // remainder < dividend break; } $z++; } $zeros = \str_repeat('0', $x - $z); $q = $this->add($q, '1' . $zeros); $a = $this->sub($a, $b . $zeros); $r = $a; if ($r === '0') { // remainder == 0 break; } $x = \strlen($a); if ($x < $y) { // remainder < dividend break; } $z = $y; } return [$q, $r]; } /** * Compares two non-signed large numbers. * * @return int [-1, 0, 1] */ private function doCmp(string $a, string $b) : int { $x = \strlen($a); $y = \strlen($b); $cmp = $x <=> $y; if ($cmp !== 0) { return $cmp; } return \strcmp($a, $b) <=> 0; // enforce [-1, 0, 1] } /** * Pads the left of one of the given numbers with zeros if necessary to make both numbers the same length. * * The numbers must only consist of digits, without leading minus sign. * * @return array{string, string, int} */ private function pad(string $a, string $b) : array { $x = \strlen($a); $y = \strlen($b); if ($x > $y) { $b = \str_repeat('0', $x - $y) . $b; return [$a, $b, $x]; } if ($x < $y) { $a = \str_repeat('0', $y - $x) . $a; return [$a, $b, $y]; } return [$a, $b, $x]; } } PKZ1>(Exception/RoundingNecessaryException.phpnuW+A 126) { $char = \strtoupper(\dechex($ord)); if ($ord < 10) { $char = '0' . $char; } } else { $char = '"' . $char . '"'; } return new self(sprintf('Char %s is not a valid character in the given alphabet.', $char)); } } PKZəb%Exception/DivisionByZeroException.phpnuW+AisZero()) { throw DivisionByZeroException::denominatorMustNotBeZero(); } if ($denominator->isNegative()) { $numerator = $numerator->negated(); $denominator = $denominator->negated(); } } $this->numerator = $numerator; $this->denominator = $denominator; } /** * Creates a BigRational of the given value. * * @throws MathException If the value cannot be converted to a BigRational. * * @psalm-pure */ public static function of(BigNumber|int|float|string $value) : BigRational { return parent::of($value)->toBigRational(); } /** * Creates a BigRational out of a numerator and a denominator. * * If the denominator is negative, the signs of both the numerator and the denominator * will be inverted to ensure that the denominator is always positive. * * @param BigNumber|int|float|string $numerator The numerator. Must be convertible to a BigInteger. * @param BigNumber|int|float|string $denominator The denominator. Must be convertible to a BigInteger. * * @throws NumberFormatException If an argument does not represent a valid number. * @throws RoundingNecessaryException If an argument represents a non-integer number. * @throws DivisionByZeroException If the denominator is zero. * * @psalm-pure */ public static function nd( BigNumber|int|float|string $numerator, BigNumber|int|float|string $denominator, ) : BigRational { $numerator = BigInteger::of($numerator); $denominator = BigInteger::of($denominator); return new BigRational($numerator, $denominator, true); } /** * Returns a BigRational representing zero. * * @psalm-pure */ public static function zero() : BigRational { /** * @psalm-suppress ImpureStaticVariable * @var BigRational|null $zero */ static $zero; if ($zero === null) { $zero = new BigRational(BigInteger::zero(), BigInteger::one(), false); } return $zero; } /** * Returns a BigRational representing one. * * @psalm-pure */ public static function one() : BigRational { /** * @psalm-suppress ImpureStaticVariable * @var BigRational|null $one */ static $one; if ($one === null) { $one = new BigRational(BigInteger::one(), BigInteger::one(), false); } return $one; } /** * Returns a BigRational representing ten. * * @psalm-pure */ public static function ten() : BigRational { /** * @psalm-suppress ImpureStaticVariable * @var BigRational|null $ten */ static $ten; if ($ten === null) { $ten = new BigRational(BigInteger::ten(), BigInteger::one(), false); } return $ten; } public function getNumerator() : BigInteger { return $this->numerator; } public function getDenominator() : BigInteger { return $this->denominator; } /** * Returns the quotient of the division of the numerator by the denominator. */ public function quotient() : BigInteger { return $this->numerator->quotient($this->denominator); } /** * Returns the remainder of the division of the numerator by the denominator. */ public function remainder() : BigInteger { return $this->numerator->remainder($this->denominator); } /** * Returns the quotient and remainder of the division of the numerator by the denominator. * * @return BigInteger[] */ public function quotientAndRemainder() : array { return $this->numerator->quotientAndRemainder($this->denominator); } /** * Returns the sum of this number and the given one. * * @param BigNumber|int|float|string $that The number to add. * * @throws MathException If the number is not valid. */ public function plus(BigNumber|int|float|string $that) : BigRational { $that = BigRational::of($that); $numerator = $this->numerator->multipliedBy($that->denominator); $numerator = $numerator->plus($that->numerator->multipliedBy($this->denominator)); $denominator = $this->denominator->multipliedBy($that->denominator); return new BigRational($numerator, $denominator, false); } /** * Returns the difference of this number and the given one. * * @param BigNumber|int|float|string $that The number to subtract. * * @throws MathException If the number is not valid. */ public function minus(BigNumber|int|float|string $that) : BigRational { $that = BigRational::of($that); $numerator = $this->numerator->multipliedBy($that->denominator); $numerator = $numerator->minus($that->numerator->multipliedBy($this->denominator)); $denominator = $this->denominator->multipliedBy($that->denominator); return new BigRational($numerator, $denominator, false); } /** * Returns the product of this number and the given one. * * @param BigNumber|int|float|string $that The multiplier. * * @throws MathException If the multiplier is not a valid number. */ public function multipliedBy(BigNumber|int|float|string $that) : BigRational { $that = BigRational::of($that); $numerator = $this->numerator->multipliedBy($that->numerator); $denominator = $this->denominator->multipliedBy($that->denominator); return new BigRational($numerator, $denominator, false); } /** * Returns the result of the division of this number by the given one. * * @param BigNumber|int|float|string $that The divisor. * * @throws MathException If the divisor is not a valid number, or is zero. */ public function dividedBy(BigNumber|int|float|string $that) : BigRational { $that = BigRational::of($that); $numerator = $this->numerator->multipliedBy($that->denominator); $denominator = $this->denominator->multipliedBy($that->numerator); return new BigRational($numerator, $denominator, true); } /** * Returns this number exponentiated to the given value. * * @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000. */ public function power(int $exponent) : BigRational { if ($exponent === 0) { $one = BigInteger::one(); return new BigRational($one, $one, false); } if ($exponent === 1) { return $this; } return new BigRational( $this->numerator->power($exponent), $this->denominator->power($exponent), false ); } /** * Returns the reciprocal of this BigRational. * * The reciprocal has the numerator and denominator swapped. * * @throws DivisionByZeroException If the numerator is zero. */ public function reciprocal() : BigRational { return new BigRational($this->denominator, $this->numerator, true); } /** * Returns the absolute value of this BigRational. */ public function abs() : BigRational { return new BigRational($this->numerator->abs(), $this->denominator, false); } /** * Returns the negated value of this BigRational. */ public function negated() : BigRational { return new BigRational($this->numerator->negated(), $this->denominator, false); } /** * Returns the simplified value of this BigRational. */ public function simplified() : BigRational { $gcd = $this->numerator->gcd($this->denominator); $numerator = $this->numerator->quotient($gcd); $denominator = $this->denominator->quotient($gcd); return new BigRational($numerator, $denominator, false); } public function compareTo(BigNumber|int|float|string $that) : int { return $this->minus($that)->getSign(); } public function getSign() : int { return $this->numerator->getSign(); } public function toBigInteger() : BigInteger { $simplified = $this->simplified(); if (! $simplified->denominator->isEqualTo(1)) { throw new RoundingNecessaryException('This rational number cannot be represented as an integer value without rounding.'); } return $simplified->numerator; } public function toBigDecimal() : BigDecimal { return $this->numerator->toBigDecimal()->exactlyDividedBy($this->denominator); } public function toBigRational() : BigRational { return $this; } public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal { return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode); } public function toInt() : int { return $this->toBigInteger()->toInt(); } public function toFloat() : float { $simplified = $this->simplified(); return $simplified->numerator->toFloat() / $simplified->denominator->toFloat(); } public function __toString() : string { $numerator = (string) $this->numerator; $denominator = (string) $this->denominator; if ($denominator === '1') { return $numerator; } return $this->numerator . '/' . $this->denominator; } /** * This method is required for serializing the object and SHOULD NOT be accessed directly. * * @internal * * @return array{numerator: BigInteger, denominator: BigInteger} */ public function __serialize(): array { return ['numerator' => $this->numerator, 'denominator' => $this->denominator]; } /** * This method is only here to allow unserializing the object and cannot be accessed directly. * * @internal * @psalm-suppress RedundantPropertyInitializationCheck * * @param array{numerator: BigInteger, denominator: BigInteger} $data * * @throws \LogicException */ public function __unserialize(array $data): void { if (isset($this->numerator)) { throw new \LogicException('__unserialize() is an internal function, it must not be called directly.'); } $this->numerator = $data['numerator']; $this->denominator = $data['denominator']; } /** * This method is required by interface Serializable and SHOULD NOT be accessed directly. * * @internal */ public function serialize() : string { return $this->numerator . '/' . $this->denominator; } /** * This method is only here to implement interface Serializable and cannot be accessed directly. * * @internal * @psalm-suppress RedundantPropertyInitializationCheck * * @throws \LogicException */ public function unserialize($value) : void { if (isset($this->numerator)) { throw new \LogicException('unserialize() is an internal function, it must not be called directly.'); } [$numerator, $denominator] = \explode('/', $value); $this->numerator = BigInteger::of($numerator); $this->denominator = BigInteger::of($denominator); } } PKZ\BigInteger.phpnuW+Avalue = $value; } /** * Creates a BigInteger of the given value. * * @throws MathException If the value cannot be converted to a BigInteger. * * @psalm-pure */ public static function of(BigNumber|int|float|string $value) : BigInteger { return parent::of($value)->toBigInteger(); } /** * Creates a number from a string in a given base. * * The string can optionally be prefixed with the `+` or `-` sign. * * Bases greater than 36 are not supported by this method, as there is no clear consensus on which of the lowercase * or uppercase characters should come first. Instead, this method accepts any base up to 36, and does not * differentiate lowercase and uppercase characters, which are considered equal. * * For bases greater than 36, and/or custom alphabets, use the fromArbitraryBase() method. * * @param string $number The number to convert, in the given base. * @param int $base The base of the number, between 2 and 36. * * @throws NumberFormatException If the number is empty, or contains invalid chars for the given base. * @throws \InvalidArgumentException If the base is out of range. * * @psalm-pure */ public static function fromBase(string $number, int $base) : BigInteger { if ($number === '') { throw new NumberFormatException('The number cannot be empty.'); } if ($base < 2 || $base > 36) { throw new \InvalidArgumentException(\sprintf('Base %d is not in range 2 to 36.', $base)); } if ($number[0] === '-') { $sign = '-'; $number = \substr($number, 1); } elseif ($number[0] === '+') { $sign = ''; $number = \substr($number, 1); } else { $sign = ''; } if ($number === '') { throw new NumberFormatException('The number cannot be empty.'); } $number = \ltrim($number, '0'); if ($number === '') { // The result will be the same in any base, avoid further calculation. return BigInteger::zero(); } if ($number === '1') { // The result will be the same in any base, avoid further calculation. return new BigInteger($sign . '1'); } $pattern = '/[^' . \substr(Calculator::ALPHABET, 0, $base) . ']/'; if (\preg_match($pattern, \strtolower($number), $matches) === 1) { throw new NumberFormatException(\sprintf('"%s" is not a valid character in base %d.', $matches[0], $base)); } if ($base === 10) { // The number is usable as is, avoid further calculation. return new BigInteger($sign . $number); } $result = Calculator::get()->fromBase($number, $base); return new BigInteger($sign . $result); } /** * Parses a string containing an integer in an arbitrary base, using a custom alphabet. * * Because this method accepts an alphabet with any character, including dash, it does not handle negative numbers. * * @param string $number The number to parse. * @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8. * * @throws NumberFormatException If the given number is empty or contains invalid chars for the given alphabet. * @throws \InvalidArgumentException If the alphabet does not contain at least 2 chars. * * @psalm-pure */ public static function fromArbitraryBase(string $number, string $alphabet) : BigInteger { if ($number === '') { throw new NumberFormatException('The number cannot be empty.'); } $base = \strlen($alphabet); if ($base < 2) { throw new \InvalidArgumentException('The alphabet must contain at least 2 chars.'); } $pattern = '/[^' . \preg_quote($alphabet, '/') . ']/'; if (\preg_match($pattern, $number, $matches) === 1) { throw NumberFormatException::charNotInAlphabet($matches[0]); } $number = Calculator::get()->fromArbitraryBase($number, $alphabet, $base); return new BigInteger($number); } /** * Translates a string of bytes containing the binary representation of a BigInteger into a BigInteger. * * The input string is assumed to be in big-endian byte-order: the most significant byte is in the zeroth element. * * If `$signed` is true, the input is assumed to be in two's-complement representation, and the leading bit is * interpreted as a sign bit. If `$signed` is false, the input is interpreted as an unsigned number, and the * resulting BigInteger will always be positive or zero. * * This method can be used to retrieve a number exported by `toBytes()`, as long as the `$signed` flags match. * * @param string $value The byte string. * @param bool $signed Whether to interpret as a signed number in two's-complement representation with a leading * sign bit. * * @throws NumberFormatException If the string is empty. */ public static function fromBytes(string $value, bool $signed = true) : BigInteger { if ($value === '') { throw new NumberFormatException('The byte string must not be empty.'); } $twosComplement = false; if ($signed) { $x = \ord($value[0]); if (($twosComplement = ($x >= 0x80))) { $value = ~$value; } } $number = self::fromBase(\bin2hex($value), 16); if ($twosComplement) { return $number->plus(1)->negated(); } return $number; } /** * Generates a pseudo-random number in the range 0 to 2^numBits - 1. * * Using the default random bytes generator, this method is suitable for cryptographic use. * * @psalm-param (callable(int): string)|null $randomBytesGenerator * * @param int $numBits The number of bits. * @param callable|null $randomBytesGenerator A function that accepts a number of bytes as an integer, and returns a * string of random bytes of the given length. Defaults to the * `random_bytes()` function. * * @throws \InvalidArgumentException If $numBits is negative. */ public static function randomBits(int $numBits, ?callable $randomBytesGenerator = null) : BigInteger { if ($numBits < 0) { throw new \InvalidArgumentException('The number of bits cannot be negative.'); } if ($numBits === 0) { return BigInteger::zero(); } if ($randomBytesGenerator === null) { $randomBytesGenerator = 'random_bytes'; } $byteLength = \intdiv($numBits - 1, 8) + 1; $extraBits = ($byteLength * 8 - $numBits); $bitmask = \chr(0xFF >> $extraBits); $randomBytes = $randomBytesGenerator($byteLength); $randomBytes[0] = $randomBytes[0] & $bitmask; return self::fromBytes($randomBytes, false); } /** * Generates a pseudo-random number between `$min` and `$max`. * * Using the default random bytes generator, this method is suitable for cryptographic use. * * @psalm-param (callable(int): string)|null $randomBytesGenerator * * @param BigNumber|int|float|string $min The lower bound. Must be convertible to a BigInteger. * @param BigNumber|int|float|string $max The upper bound. Must be convertible to a BigInteger. * @param callable|null $randomBytesGenerator A function that accepts a number of bytes as an integer, * and returns a string of random bytes of the given length. * Defaults to the `random_bytes()` function. * * @throws MathException If one of the parameters cannot be converted to a BigInteger, * or `$min` is greater than `$max`. */ public static function randomRange( BigNumber|int|float|string $min, BigNumber|int|float|string $max, ?callable $randomBytesGenerator = null ) : BigInteger { $min = BigInteger::of($min); $max = BigInteger::of($max); if ($min->isGreaterThan($max)) { throw new MathException('$min cannot be greater than $max.'); } if ($min->isEqualTo($max)) { return $min; } $diff = $max->minus($min); $bitLength = $diff->getBitLength(); // try until the number is in range (50% to 100% chance of success) do { $randomNumber = self::randomBits($bitLength, $randomBytesGenerator); } while ($randomNumber->isGreaterThan($diff)); return $randomNumber->plus($min); } /** * Returns a BigInteger representing zero. * * @psalm-pure */ public static function zero() : BigInteger { /** * @psalm-suppress ImpureStaticVariable * @var BigInteger|null $zero */ static $zero; if ($zero === null) { $zero = new BigInteger('0'); } return $zero; } /** * Returns a BigInteger representing one. * * @psalm-pure */ public static function one() : BigInteger { /** * @psalm-suppress ImpureStaticVariable * @var BigInteger|null $one */ static $one; if ($one === null) { $one = new BigInteger('1'); } return $one; } /** * Returns a BigInteger representing ten. * * @psalm-pure */ public static function ten() : BigInteger { /** * @psalm-suppress ImpureStaticVariable * @var BigInteger|null $ten */ static $ten; if ($ten === null) { $ten = new BigInteger('10'); } return $ten; } public static function gcdMultiple(BigInteger $a, BigInteger ...$n): BigInteger { $result = $a; foreach ($n as $next) { $result = $result->gcd($next); if ($result->isEqualTo(1)) { return $result; } } return $result; } /** * Returns the sum of this number and the given one. * * @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigInteger. * * @throws MathException If the number is not valid, or is not convertible to a BigInteger. */ public function plus(BigNumber|int|float|string $that) : BigInteger { $that = BigInteger::of($that); if ($that->value === '0') { return $this; } if ($this->value === '0') { return $that; } $value = Calculator::get()->add($this->value, $that->value); return new BigInteger($value); } /** * Returns the difference of this number and the given one. * * @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigInteger. * * @throws MathException If the number is not valid, or is not convertible to a BigInteger. */ public function minus(BigNumber|int|float|string $that) : BigInteger { $that = BigInteger::of($that); if ($that->value === '0') { return $this; } $value = Calculator::get()->sub($this->value, $that->value); return new BigInteger($value); } /** * Returns the product of this number and the given one. * * @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigInteger. * * @throws MathException If the multiplier is not a valid number, or is not convertible to a BigInteger. */ public function multipliedBy(BigNumber|int|float|string $that) : BigInteger { $that = BigInteger::of($that); if ($that->value === '1') { return $this; } if ($this->value === '1') { return $that; } $value = Calculator::get()->mul($this->value, $that->value); return new BigInteger($value); } /** * Returns the result of the division of this number by the given one. * * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. * @param int $roundingMode An optional rounding mode. * * @throws MathException If the divisor is not a valid number, is not convertible to a BigInteger, is zero, * or RoundingMode::UNNECESSARY is used and the remainder is not zero. */ public function dividedBy(BigNumber|int|float|string $that, int $roundingMode = RoundingMode::UNNECESSARY) : BigInteger { $that = BigInteger::of($that); if ($that->value === '1') { return $this; } if ($that->value === '0') { throw DivisionByZeroException::divisionByZero(); } $result = Calculator::get()->divRound($this->value, $that->value, $roundingMode); return new BigInteger($result); } /** * Returns this number exponentiated to the given value. * * @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000. */ public function power(int $exponent) : BigInteger { if ($exponent === 0) { return BigInteger::one(); } if ($exponent === 1) { return $this; } if ($exponent < 0 || $exponent > Calculator::MAX_POWER) { throw new \InvalidArgumentException(\sprintf( 'The exponent %d is not in the range 0 to %d.', $exponent, Calculator::MAX_POWER )); } return new BigInteger(Calculator::get()->pow($this->value, $exponent)); } /** * Returns the quotient of the division of this number by the given one. * * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. * * @throws DivisionByZeroException If the divisor is zero. */ public function quotient(BigNumber|int|float|string $that) : BigInteger { $that = BigInteger::of($that); if ($that->value === '1') { return $this; } if ($that->value === '0') { throw DivisionByZeroException::divisionByZero(); } $quotient = Calculator::get()->divQ($this->value, $that->value); return new BigInteger($quotient); } /** * Returns the remainder of the division of this number by the given one. * * The remainder, when non-zero, has the same sign as the dividend. * * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. * * @throws DivisionByZeroException If the divisor is zero. */ public function remainder(BigNumber|int|float|string $that) : BigInteger { $that = BigInteger::of($that); if ($that->value === '1') { return BigInteger::zero(); } if ($that->value === '0') { throw DivisionByZeroException::divisionByZero(); } $remainder = Calculator::get()->divR($this->value, $that->value); return new BigInteger($remainder); } /** * Returns the quotient and remainder of the division of this number by the given one. * * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. * * @return BigInteger[] An array containing the quotient and the remainder. * * @throws DivisionByZeroException If the divisor is zero. */ public function quotientAndRemainder(BigNumber|int|float|string $that) : array { $that = BigInteger::of($that); if ($that->value === '0') { throw DivisionByZeroException::divisionByZero(); } [$quotient, $remainder] = Calculator::get()->divQR($this->value, $that->value); return [ new BigInteger($quotient), new BigInteger($remainder) ]; } /** * Returns the modulo of this number and the given one. * * The modulo operation yields the same result as the remainder operation when both operands are of the same sign, * and may differ when signs are different. * * The result of the modulo operation, when non-zero, has the same sign as the divisor. * * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger. * * @throws DivisionByZeroException If the divisor is zero. */ public function mod(BigNumber|int|float|string $that) : BigInteger { $that = BigInteger::of($that); if ($that->value === '0') { throw DivisionByZeroException::modulusMustNotBeZero(); } $value = Calculator::get()->mod($this->value, $that->value); return new BigInteger($value); } /** * Returns the modular multiplicative inverse of this BigInteger modulo $m. * * @throws DivisionByZeroException If $m is zero. * @throws NegativeNumberException If $m is negative. * @throws MathException If this BigInteger has no multiplicative inverse mod m (that is, this BigInteger * is not relatively prime to m). */ public function modInverse(BigInteger $m) : BigInteger { if ($m->value === '0') { throw DivisionByZeroException::modulusMustNotBeZero(); } if ($m->isNegative()) { throw new NegativeNumberException('Modulus must not be negative.'); } if ($m->value === '1') { return BigInteger::zero(); } $value = Calculator::get()->modInverse($this->value, $m->value); if ($value === null) { throw new MathException('Unable to compute the modInverse for the given modulus.'); } return new BigInteger($value); } /** * Returns this number raised into power with modulo. * * This operation only works on positive numbers. * * @param BigNumber|int|float|string $exp The exponent. Must be positive or zero. * @param BigNumber|int|float|string $mod The modulus. Must be strictly positive. * * @throws NegativeNumberException If any of the operands is negative. * @throws DivisionByZeroException If the modulus is zero. */ public function modPow(BigNumber|int|float|string $exp, BigNumber|int|float|string $mod) : BigInteger { $exp = BigInteger::of($exp); $mod = BigInteger::of($mod); if ($this->isNegative() || $exp->isNegative() || $mod->isNegative()) { throw new NegativeNumberException('The operands cannot be negative.'); } if ($mod->isZero()) { throw DivisionByZeroException::modulusMustNotBeZero(); } $result = Calculator::get()->modPow($this->value, $exp->value, $mod->value); return new BigInteger($result); } /** * Returns the greatest common divisor of this number and the given one. * * The GCD is always positive, unless both operands are zero, in which case it is zero. * * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number. */ public function gcd(BigNumber|int|float|string $that) : BigInteger { $that = BigInteger::of($that); if ($that->value === '0' && $this->value[0] !== '-') { return $this; } if ($this->value === '0' && $that->value[0] !== '-') { return $that; } $value = Calculator::get()->gcd($this->value, $that->value); return new BigInteger($value); } /** * Returns the integer square root number of this number, rounded down. * * The result is the largest x such that x² ≤ n. * * @throws NegativeNumberException If this number is negative. */ public function sqrt() : BigInteger { if ($this->value[0] === '-') { throw new NegativeNumberException('Cannot calculate the square root of a negative number.'); } $value = Calculator::get()->sqrt($this->value); return new BigInteger($value); } /** * Returns the absolute value of this number. */ public function abs() : BigInteger { return $this->isNegative() ? $this->negated() : $this; } /** * Returns the inverse of this number. */ public function negated() : BigInteger { return new BigInteger(Calculator::get()->neg($this->value)); } /** * Returns the integer bitwise-and combined with another integer. * * This method returns a negative BigInteger if and only if both operands are negative. * * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number. */ public function and(BigNumber|int|float|string $that) : BigInteger { $that = BigInteger::of($that); return new BigInteger(Calculator::get()->and($this->value, $that->value)); } /** * Returns the integer bitwise-or combined with another integer. * * This method returns a negative BigInteger if and only if either of the operands is negative. * * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number. */ public function or(BigNumber|int|float|string $that) : BigInteger { $that = BigInteger::of($that); return new BigInteger(Calculator::get()->or($this->value, $that->value)); } /** * Returns the integer bitwise-xor combined with another integer. * * This method returns a negative BigInteger if and only if exactly one of the operands is negative. * * @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number. */ public function xor(BigNumber|int|float|string $that) : BigInteger { $that = BigInteger::of($that); return new BigInteger(Calculator::get()->xor($this->value, $that->value)); } /** * Returns the bitwise-not of this BigInteger. */ public function not() : BigInteger { return $this->negated()->minus(1); } /** * Returns the integer left shifted by a given number of bits. */ public function shiftedLeft(int $distance) : BigInteger { if ($distance === 0) { return $this; } if ($distance < 0) { return $this->shiftedRight(- $distance); } return $this->multipliedBy(BigInteger::of(2)->power($distance)); } /** * Returns the integer right shifted by a given number of bits. */ public function shiftedRight(int $distance) : BigInteger { if ($distance === 0) { return $this; } if ($distance < 0) { return $this->shiftedLeft(- $distance); } $operand = BigInteger::of(2)->power($distance); if ($this->isPositiveOrZero()) { return $this->quotient($operand); } return $this->dividedBy($operand, RoundingMode::UP); } /** * Returns the number of bits in the minimal two's-complement representation of this BigInteger, excluding a sign bit. * * For positive BigIntegers, this is equivalent to the number of bits in the ordinary binary representation. * Computes (ceil(log2(this < 0 ? -this : this+1))). */ public function getBitLength() : int { if ($this->value === '0') { return 0; } if ($this->isNegative()) { return $this->abs()->minus(1)->getBitLength(); } return \strlen($this->toBase(2)); } /** * Returns the index of the rightmost (lowest-order) one bit in this BigInteger. * * Returns -1 if this BigInteger contains no one bits. */ public function getLowestSetBit() : int { $n = $this; $bitLength = $this->getBitLength(); for ($i = 0; $i <= $bitLength; $i++) { if ($n->isOdd()) { return $i; } $n = $n->shiftedRight(1); } return -1; } /** * Returns whether this number is even. */ public function isEven() : bool { return \in_array($this->value[-1], ['0', '2', '4', '6', '8'], true); } /** * Returns whether this number is odd. */ public function isOdd() : bool { return \in_array($this->value[-1], ['1', '3', '5', '7', '9'], true); } /** * Returns true if and only if the designated bit is set. * * Computes ((this & (1<shiftedRight($n)->isOdd(); } public function compareTo(BigNumber|int|float|string $that) : int { $that = BigNumber::of($that); if ($that instanceof BigInteger) { return Calculator::get()->cmp($this->value, $that->value); } return - $that->compareTo($this); } public function getSign() : int { return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1); } public function toBigInteger() : BigInteger { return $this; } public function toBigDecimal() : BigDecimal { return self::newBigDecimal($this->value); } public function toBigRational() : BigRational { return self::newBigRational($this, BigInteger::one(), false); } public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal { return $this->toBigDecimal()->toScale($scale, $roundingMode); } public function toInt() : int { $intValue = (int) $this->value; if ($this->value !== (string) $intValue) { throw IntegerOverflowException::toIntOverflow($this); } return $intValue; } public function toFloat() : float { return (float) $this->value; } /** * Returns a string representation of this number in the given base. * * The output will always be lowercase for bases greater than 10. * * @throws \InvalidArgumentException If the base is out of range. */ public function toBase(int $base) : string { if ($base === 10) { return $this->value; } if ($base < 2 || $base > 36) { throw new \InvalidArgumentException(\sprintf('Base %d is out of range [2, 36]', $base)); } return Calculator::get()->toBase($this->value, $base); } /** * Returns a string representation of this number in an arbitrary base with a custom alphabet. * * Because this method accepts an alphabet with any character, including dash, it does not handle negative numbers; * a NegativeNumberException will be thrown when attempting to call this method on a negative number. * * @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8. * * @throws NegativeNumberException If this number is negative. * @throws \InvalidArgumentException If the given alphabet does not contain at least 2 chars. */ public function toArbitraryBase(string $alphabet) : string { $base = \strlen($alphabet); if ($base < 2) { throw new \InvalidArgumentException('The alphabet must contain at least 2 chars.'); } if ($this->value[0] === '-') { throw new NegativeNumberException(__FUNCTION__ . '() does not support negative numbers.'); } return Calculator::get()->toArbitraryBase($this->value, $alphabet, $base); } /** * Returns a string of bytes containing the binary representation of this BigInteger. * * The string is in big-endian byte-order: the most significant byte is in the zeroth element. * * If `$signed` is true, the output will be in two's-complement representation, and a sign bit will be prepended to * the output. If `$signed` is false, no sign bit will be prepended, and this method will throw an exception if the * number is negative. * * The string will contain the minimum number of bytes required to represent this BigInteger, including a sign bit * if `$signed` is true. * * This representation is compatible with the `fromBytes()` factory method, as long as the `$signed` flags match. * * @param bool $signed Whether to output a signed number in two's-complement representation with a leading sign bit. * * @throws NegativeNumberException If $signed is false, and the number is negative. */ public function toBytes(bool $signed = true) : string { if (! $signed && $this->isNegative()) { throw new NegativeNumberException('Cannot convert a negative number to a byte string when $signed is false.'); } $hex = $this->abs()->toBase(16); if (\strlen($hex) % 2 !== 0) { $hex = '0' . $hex; } $baseHexLength = \strlen($hex); if ($signed) { if ($this->isNegative()) { $bin = \hex2bin($hex); assert($bin !== false); $hex = \bin2hex(~$bin); $hex = self::fromBase($hex, 16)->plus(1)->toBase(16); $hexLength = \strlen($hex); if ($hexLength < $baseHexLength) { $hex = \str_repeat('0', $baseHexLength - $hexLength) . $hex; } if ($hex[0] < '8') { $hex = 'FF' . $hex; } } else { if ($hex[0] >= '8') { $hex = '00' . $hex; } } } return \hex2bin($hex); } public function __toString() : string { return $this->value; } /** * This method is required for serializing the object and SHOULD NOT be accessed directly. * * @internal * * @return array{value: string} */ public function __serialize(): array { return ['value' => $this->value]; } /** * This method is only here to allow unserializing the object and cannot be accessed directly. * * @internal * @psalm-suppress RedundantPropertyInitializationCheck * * @param array{value: string} $data * * @throws \LogicException */ public function __unserialize(array $data): void { if (isset($this->value)) { throw new \LogicException('__unserialize() is an internal function, it must not be called directly.'); } $this->value = $data['value']; } /** * This method is required by interface Serializable and SHOULD NOT be accessed directly. * * @internal */ public function serialize() : string { return $this->value; } /** * This method is only here to implement interface Serializable and cannot be accessed directly. * * @internal * @psalm-suppress RedundantPropertyInitializationCheck * * @throws \LogicException */ public function unserialize($value) : void { if (isset($this->value)) { throw new \LogicException('unserialize() is an internal function, it must not be called directly.'); } $this->value = $value; } } PKZSRoundingMode.phpnuW+A= 0.5; otherwise, behaves as for DOWN. * Note that this is the rounding mode commonly taught at school. */ public const HALF_UP = 5; /** * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round down. * * Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves as for DOWN. */ public const HALF_DOWN = 6; /** * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards positive infinity. * * If the result is positive, behaves as for HALF_UP; if negative, behaves as for HALF_DOWN. */ public const HALF_CEILING = 7; /** * Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards negative infinity. * * If the result is positive, behaves as for HALF_DOWN; if negative, behaves as for HALF_UP. */ public const HALF_FLOOR = 8; /** * Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case rounds towards the even neighbor. * * Behaves as for HALF_UP if the digit to the left of the discarded fraction is odd; * behaves as for HALF_DOWN if it's even. * * Note that this is the rounding mode that statistically minimizes * cumulative error when applied repeatedly over a sequence of calculations. * It is sometimes known as "Banker's rounding", and is chiefly used in the USA. */ public const HALF_EVEN = 9; } PKZ nEWEWBigDecimal.phpnuW+Avalue = $value; $this->scale = $scale; } /** * Creates a BigDecimal of the given value. * * @throws MathException If the value cannot be converted to a BigDecimal. * * @psalm-pure */ public static function of(BigNumber|int|float|string $value) : BigDecimal { return parent::of($value)->toBigDecimal(); } /** * Creates a BigDecimal from an unscaled value and a scale. * * Example: `(12345, 3)` will result in the BigDecimal `12.345`. * * @param BigNumber|int|float|string $value The unscaled value. Must be convertible to a BigInteger. * @param int $scale The scale of the number, positive or zero. * * @throws \InvalidArgumentException If the scale is negative. * * @psalm-pure */ public static function ofUnscaledValue(BigNumber|int|float|string $value, int $scale = 0) : BigDecimal { if ($scale < 0) { throw new \InvalidArgumentException('The scale cannot be negative.'); } return new BigDecimal((string) BigInteger::of($value), $scale); } /** * Returns a BigDecimal representing zero, with a scale of zero. * * @psalm-pure */ public static function zero() : BigDecimal { /** * @psalm-suppress ImpureStaticVariable * @var BigDecimal|null $zero */ static $zero; if ($zero === null) { $zero = new BigDecimal('0'); } return $zero; } /** * Returns a BigDecimal representing one, with a scale of zero. * * @psalm-pure */ public static function one() : BigDecimal { /** * @psalm-suppress ImpureStaticVariable * @var BigDecimal|null $one */ static $one; if ($one === null) { $one = new BigDecimal('1'); } return $one; } /** * Returns a BigDecimal representing ten, with a scale of zero. * * @psalm-pure */ public static function ten() : BigDecimal { /** * @psalm-suppress ImpureStaticVariable * @var BigDecimal|null $ten */ static $ten; if ($ten === null) { $ten = new BigDecimal('10'); } return $ten; } /** * Returns the sum of this number and the given one. * * The result has a scale of `max($this->scale, $that->scale)`. * * @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigDecimal. * * @throws MathException If the number is not valid, or is not convertible to a BigDecimal. */ public function plus(BigNumber|int|float|string $that) : BigDecimal { $that = BigDecimal::of($that); if ($that->value === '0' && $that->scale <= $this->scale) { return $this; } if ($this->value === '0' && $this->scale <= $that->scale) { return $that; } [$a, $b] = $this->scaleValues($this, $that); $value = Calculator::get()->add($a, $b); $scale = $this->scale > $that->scale ? $this->scale : $that->scale; return new BigDecimal($value, $scale); } /** * Returns the difference of this number and the given one. * * The result has a scale of `max($this->scale, $that->scale)`. * * @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigDecimal. * * @throws MathException If the number is not valid, or is not convertible to a BigDecimal. */ public function minus(BigNumber|int|float|string $that) : BigDecimal { $that = BigDecimal::of($that); if ($that->value === '0' && $that->scale <= $this->scale) { return $this; } [$a, $b] = $this->scaleValues($this, $that); $value = Calculator::get()->sub($a, $b); $scale = $this->scale > $that->scale ? $this->scale : $that->scale; return new BigDecimal($value, $scale); } /** * Returns the product of this number and the given one. * * The result has a scale of `$this->scale + $that->scale`. * * @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigDecimal. * * @throws MathException If the multiplier is not a valid number, or is not convertible to a BigDecimal. */ public function multipliedBy(BigNumber|int|float|string $that) : BigDecimal { $that = BigDecimal::of($that); if ($that->value === '1' && $that->scale === 0) { return $this; } if ($this->value === '1' && $this->scale === 0) { return $that; } $value = Calculator::get()->mul($this->value, $that->value); $scale = $this->scale + $that->scale; return new BigDecimal($value, $scale); } /** * Returns the result of the division of this number by the given one, at the given scale. * * @param BigNumber|int|float|string $that The divisor. * @param int|null $scale The desired scale, or null to use the scale of this number. * @param int $roundingMode An optional rounding mode. * * @throws \InvalidArgumentException If the scale or rounding mode is invalid. * @throws MathException If the number is invalid, is zero, or rounding was necessary. */ public function dividedBy(BigNumber|int|float|string $that, ?int $scale = null, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal { $that = BigDecimal::of($that); if ($that->isZero()) { throw DivisionByZeroException::divisionByZero(); } if ($scale === null) { $scale = $this->scale; } elseif ($scale < 0) { throw new \InvalidArgumentException('Scale cannot be negative.'); } if ($that->value === '1' && $that->scale === 0 && $scale === $this->scale) { return $this; } $p = $this->valueWithMinScale($that->scale + $scale); $q = $that->valueWithMinScale($this->scale - $scale); $result = Calculator::get()->divRound($p, $q, $roundingMode); return new BigDecimal($result, $scale); } /** * Returns the exact result of the division of this number by the given one. * * The scale of the result is automatically calculated to fit all the fraction digits. * * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal. * * @throws MathException If the divisor is not a valid number, is not convertible to a BigDecimal, is zero, * or the result yields an infinite number of digits. */ public function exactlyDividedBy(BigNumber|int|float|string $that) : BigDecimal { $that = BigDecimal::of($that); if ($that->value === '0') { throw DivisionByZeroException::divisionByZero(); } [, $b] = $this->scaleValues($this, $that); $d = \rtrim($b, '0'); $scale = \strlen($b) - \strlen($d); $calculator = Calculator::get(); foreach ([5, 2] as $prime) { for (;;) { $lastDigit = (int) $d[-1]; if ($lastDigit % $prime !== 0) { break; } $d = $calculator->divQ($d, (string) $prime); $scale++; } } return $this->dividedBy($that, $scale)->stripTrailingZeros(); } /** * Returns this number exponentiated to the given value. * * The result has a scale of `$this->scale * $exponent`. * * @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000. */ public function power(int $exponent) : BigDecimal { if ($exponent === 0) { return BigDecimal::one(); } if ($exponent === 1) { return $this; } if ($exponent < 0 || $exponent > Calculator::MAX_POWER) { throw new \InvalidArgumentException(\sprintf( 'The exponent %d is not in the range 0 to %d.', $exponent, Calculator::MAX_POWER )); } return new BigDecimal(Calculator::get()->pow($this->value, $exponent), $this->scale * $exponent); } /** * Returns the quotient of the division of this number by this given one. * * The quotient has a scale of `0`. * * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal. * * @throws MathException If the divisor is not a valid decimal number, or is zero. */ public function quotient(BigNumber|int|float|string $that) : BigDecimal { $that = BigDecimal::of($that); if ($that->isZero()) { throw DivisionByZeroException::divisionByZero(); } $p = $this->valueWithMinScale($that->scale); $q = $that->valueWithMinScale($this->scale); $quotient = Calculator::get()->divQ($p, $q); return new BigDecimal($quotient, 0); } /** * Returns the remainder of the division of this number by this given one. * * The remainder has a scale of `max($this->scale, $that->scale)`. * * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal. * * @throws MathException If the divisor is not a valid decimal number, or is zero. */ public function remainder(BigNumber|int|float|string $that) : BigDecimal { $that = BigDecimal::of($that); if ($that->isZero()) { throw DivisionByZeroException::divisionByZero(); } $p = $this->valueWithMinScale($that->scale); $q = $that->valueWithMinScale($this->scale); $remainder = Calculator::get()->divR($p, $q); $scale = $this->scale > $that->scale ? $this->scale : $that->scale; return new BigDecimal($remainder, $scale); } /** * Returns the quotient and remainder of the division of this number by the given one. * * The quotient has a scale of `0`, and the remainder has a scale of `max($this->scale, $that->scale)`. * * @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal. * * @return BigDecimal[] An array containing the quotient and the remainder. * * @throws MathException If the divisor is not a valid decimal number, or is zero. */ public function quotientAndRemainder(BigNumber|int|float|string $that) : array { $that = BigDecimal::of($that); if ($that->isZero()) { throw DivisionByZeroException::divisionByZero(); } $p = $this->valueWithMinScale($that->scale); $q = $that->valueWithMinScale($this->scale); [$quotient, $remainder] = Calculator::get()->divQR($p, $q); $scale = $this->scale > $that->scale ? $this->scale : $that->scale; $quotient = new BigDecimal($quotient, 0); $remainder = new BigDecimal($remainder, $scale); return [$quotient, $remainder]; } /** * Returns the square root of this number, rounded down to the given number of decimals. * * @throws \InvalidArgumentException If the scale is negative. * @throws NegativeNumberException If this number is negative. */ public function sqrt(int $scale) : BigDecimal { if ($scale < 0) { throw new \InvalidArgumentException('Scale cannot be negative.'); } if ($this->value === '0') { return new BigDecimal('0', $scale); } if ($this->value[0] === '-') { throw new NegativeNumberException('Cannot calculate the square root of a negative number.'); } $value = $this->value; $addDigits = 2 * $scale - $this->scale; if ($addDigits > 0) { // add zeros $value .= \str_repeat('0', $addDigits); } elseif ($addDigits < 0) { // trim digits if (-$addDigits >= \strlen($this->value)) { // requesting a scale too low, will always yield a zero result return new BigDecimal('0', $scale); } $value = \substr($value, 0, $addDigits); } $value = Calculator::get()->sqrt($value); return new BigDecimal($value, $scale); } /** * Returns a copy of this BigDecimal with the decimal point moved $n places to the left. */ public function withPointMovedLeft(int $n) : BigDecimal { if ($n === 0) { return $this; } if ($n < 0) { return $this->withPointMovedRight(-$n); } return new BigDecimal($this->value, $this->scale + $n); } /** * Returns a copy of this BigDecimal with the decimal point moved $n places to the right. */ public function withPointMovedRight(int $n) : BigDecimal { if ($n === 0) { return $this; } if ($n < 0) { return $this->withPointMovedLeft(-$n); } $value = $this->value; $scale = $this->scale - $n; if ($scale < 0) { if ($value !== '0') { $value .= \str_repeat('0', -$scale); } $scale = 0; } return new BigDecimal($value, $scale); } /** * Returns a copy of this BigDecimal with any trailing zeros removed from the fractional part. */ public function stripTrailingZeros() : BigDecimal { if ($this->scale === 0) { return $this; } $trimmedValue = \rtrim($this->value, '0'); if ($trimmedValue === '') { return BigDecimal::zero(); } $trimmableZeros = \strlen($this->value) - \strlen($trimmedValue); if ($trimmableZeros === 0) { return $this; } if ($trimmableZeros > $this->scale) { $trimmableZeros = $this->scale; } $value = \substr($this->value, 0, -$trimmableZeros); $scale = $this->scale - $trimmableZeros; return new BigDecimal($value, $scale); } /** * Returns the absolute value of this number. */ public function abs() : BigDecimal { return $this->isNegative() ? $this->negated() : $this; } /** * Returns the negated value of this number. */ public function negated() : BigDecimal { return new BigDecimal(Calculator::get()->neg($this->value), $this->scale); } public function compareTo(BigNumber|int|float|string $that) : int { $that = BigNumber::of($that); if ($that instanceof BigInteger) { $that = $that->toBigDecimal(); } if ($that instanceof BigDecimal) { [$a, $b] = $this->scaleValues($this, $that); return Calculator::get()->cmp($a, $b); } return - $that->compareTo($this); } public function getSign() : int { return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1); } public function getUnscaledValue() : BigInteger { return self::newBigInteger($this->value); } public function getScale() : int { return $this->scale; } /** * Returns a string representing the integral part of this decimal number. * * Example: `-123.456` => `-123`. */ public function getIntegralPart() : string { if ($this->scale === 0) { return $this->value; } $value = $this->getUnscaledValueWithLeadingZeros(); return \substr($value, 0, -$this->scale); } /** * Returns a string representing the fractional part of this decimal number. * * If the scale is zero, an empty string is returned. * * Examples: `-123.456` => '456', `123` => ''. */ public function getFractionalPart() : string { if ($this->scale === 0) { return ''; } $value = $this->getUnscaledValueWithLeadingZeros(); return \substr($value, -$this->scale); } /** * Returns whether this decimal number has a non-zero fractional part. */ public function hasNonZeroFractionalPart() : bool { return $this->getFractionalPart() !== \str_repeat('0', $this->scale); } public function toBigInteger() : BigInteger { $zeroScaleDecimal = $this->scale === 0 ? $this : $this->dividedBy(1, 0); return self::newBigInteger($zeroScaleDecimal->value); } public function toBigDecimal() : BigDecimal { return $this; } public function toBigRational() : BigRational { $numerator = self::newBigInteger($this->value); $denominator = self::newBigInteger('1' . \str_repeat('0', $this->scale)); return self::newBigRational($numerator, $denominator, false); } public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal { if ($scale === $this->scale) { return $this; } return $this->dividedBy(BigDecimal::one(), $scale, $roundingMode); } public function toInt() : int { return $this->toBigInteger()->toInt(); } public function toFloat() : float { return (float) (string) $this; } public function __toString() : string { if ($this->scale === 0) { return $this->value; } $value = $this->getUnscaledValueWithLeadingZeros(); return \substr($value, 0, -$this->scale) . '.' . \substr($value, -$this->scale); } /** * This method is required for serializing the object and SHOULD NOT be accessed directly. * * @internal * * @return array{value: string, scale: int} */ public function __serialize(): array { return ['value' => $this->value, 'scale' => $this->scale]; } /** * This method is only here to allow unserializing the object and cannot be accessed directly. * * @internal * @psalm-suppress RedundantPropertyInitializationCheck * * @param array{value: string, scale: int} $data * * @throws \LogicException */ public function __unserialize(array $data): void { if (isset($this->value)) { throw new \LogicException('__unserialize() is an internal function, it must not be called directly.'); } $this->value = $data['value']; $this->scale = $data['scale']; } /** * This method is required by interface Serializable and SHOULD NOT be accessed directly. * * @internal */ public function serialize() : string { return $this->value . ':' . $this->scale; } /** * This method is only here to implement interface Serializable and cannot be accessed directly. * * @internal * @psalm-suppress RedundantPropertyInitializationCheck * * @throws \LogicException */ public function unserialize($value) : void { if (isset($this->value)) { throw new \LogicException('unserialize() is an internal function, it must not be called directly.'); } [$value, $scale] = \explode(':', $value); $this->value = $value; $this->scale = (int) $scale; } /** * Puts the internal values of the given decimal numbers on the same scale. * * @return array{string, string} The scaled integer values of $x and $y. */ private function scaleValues(BigDecimal $x, BigDecimal $y) : array { $a = $x->value; $b = $y->value; if ($b !== '0' && $x->scale > $y->scale) { $b .= \str_repeat('0', $x->scale - $y->scale); } elseif ($a !== '0' && $x->scale < $y->scale) { $a .= \str_repeat('0', $y->scale - $x->scale); } return [$a, $b]; } private function valueWithMinScale(int $scale) : string { $value = $this->value; if ($this->value !== '0' && $scale > $this->scale) { $value .= \str_repeat('0', $scale - $this->scale); } return $value; } /** * Adds leading zeros if necessary to the unscaled value to represent the full decimal number. */ private function getUnscaledValueWithLeadingZeros() : string { $value = $this->value; $targetLength = $this->scale + 1; $negative = ($value[0] === '-'); $length = \strlen($value); if ($negative) { $length--; } if ($length >= $targetLength) { return $this->value; } if ($negative) { $value = \substr($value, 1); } $value = \str_pad($value, $targetLength, '0', STR_PAD_LEFT); if ($negative) { $value = '-' . $value; } return $value; } } PKZ<< BigNumber.phpnuW+A[\-\+])?' . '(?:' . '(?:' . '(?[0-9]+)?' . '(?\.)?' . '(?[0-9]+)?' . '(?:[eE](?[\-\+]?[0-9]+))?' . ')|(?:' . '(?[0-9]+)' . '\/?' . '(?[0-9]+)' . ')' . ')' . '$/'; /** * Creates a BigNumber of the given value. * * The concrete return type is dependent on the given value, with the following rules: * * - BigNumber instances are returned as is * - integer numbers are returned as BigInteger * - floating point numbers are converted to a string then parsed as such * - strings containing a `/` character are returned as BigRational * - strings containing a `.` character or using an exponential notation are returned as BigDecimal * - strings containing only digits with an optional leading `+` or `-` sign are returned as BigInteger * * @throws NumberFormatException If the format of the number is not valid. * @throws DivisionByZeroException If the value represents a rational number with a denominator of zero. * * @psalm-pure */ public static function of(BigNumber|int|float|string $value) : BigNumber { if ($value instanceof BigNumber) { return $value; } if (\is_int($value)) { return new BigInteger((string) $value); } $value = \is_float($value) ? self::floatToString($value) : $value; $throw = static function() use ($value) : void { throw new NumberFormatException(\sprintf( 'The given value "%s" does not represent a valid number.', $value )); }; if (\preg_match(self::PARSE_REGEXP, $value, $matches) !== 1) { $throw(); } $getMatch = static fn(string $value): ?string => (($matches[$value] ?? '') !== '') ? $matches[$value] : null; $sign = $getMatch('sign'); $numerator = $getMatch('numerator'); $denominator = $getMatch('denominator'); if ($numerator !== null) { assert($denominator !== null); if ($sign !== null) { $numerator = $sign . $numerator; } $numerator = self::cleanUp($numerator); $denominator = self::cleanUp($denominator); if ($denominator === '0') { throw DivisionByZeroException::denominatorMustNotBeZero(); } return new BigRational( new BigInteger($numerator), new BigInteger($denominator), false ); } $point = $getMatch('point'); $integral = $getMatch('integral'); $fractional = $getMatch('fractional'); $exponent = $getMatch('exponent'); if ($integral === null && $fractional === null) { $throw(); } if ($integral === null) { $integral = '0'; } if ($point !== null || $exponent !== null) { $fractional = ($fractional ?? ''); $exponent = ($exponent !== null) ? (int) $exponent : 0; if ($exponent === PHP_INT_MIN || $exponent === PHP_INT_MAX) { throw new NumberFormatException('Exponent too large.'); } $unscaledValue = self::cleanUp(($sign ?? ''). $integral . $fractional); $scale = \strlen($fractional) - $exponent; if ($scale < 0) { if ($unscaledValue !== '0') { $unscaledValue .= \str_repeat('0', - $scale); } $scale = 0; } return new BigDecimal($unscaledValue, $scale); } $integral = self::cleanUp(($sign ?? '') . $integral); return new BigInteger($integral); } /** * Safely converts float to string, avoiding locale-dependent issues. * * @see https://github.com/brick/math/pull/20 * * @psalm-pure * @psalm-suppress ImpureFunctionCall */ private static function floatToString(float $float) : string { $currentLocale = \setlocale(LC_NUMERIC, '0'); \setlocale(LC_NUMERIC, 'C'); $result = (string) $float; \setlocale(LC_NUMERIC, $currentLocale); return $result; } /** * Proxy method to access BigInteger's protected constructor from sibling classes. * * @internal * @psalm-pure */ protected function newBigInteger(string $value) : BigInteger { return new BigInteger($value); } /** * Proxy method to access BigDecimal's protected constructor from sibling classes. * * @internal * @psalm-pure */ protected function newBigDecimal(string $value, int $scale = 0) : BigDecimal { return new BigDecimal($value, $scale); } /** * Proxy method to access BigRational's protected constructor from sibling classes. * * @internal * @psalm-pure */ protected function newBigRational(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator) : BigRational { return new BigRational($numerator, $denominator, $checkDenominator); } /** * Returns the minimum of the given values. * * @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible * to an instance of the class this method is called on. * * @throws \InvalidArgumentException If no values are given. * @throws MathException If an argument is not valid. * * @psalm-suppress LessSpecificReturnStatement * @psalm-suppress MoreSpecificReturnType * @psalm-pure */ public static function min(BigNumber|int|float|string ...$values) : static { $min = null; foreach ($values as $value) { $value = static::of($value); if ($min === null || $value->isLessThan($min)) { $min = $value; } } if ($min === null) { throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.'); } return $min; } /** * Returns the maximum of the given values. * * @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible * to an instance of the class this method is called on. * * @throws \InvalidArgumentException If no values are given. * @throws MathException If an argument is not valid. * * @psalm-suppress LessSpecificReturnStatement * @psalm-suppress MoreSpecificReturnType * @psalm-pure */ public static function max(BigNumber|int|float|string ...$values) : static { $max = null; foreach ($values as $value) { $value = static::of($value); if ($max === null || $value->isGreaterThan($max)) { $max = $value; } } if ($max === null) { throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.'); } return $max; } /** * Returns the sum of the given values. * * @param BigNumber|int|float|string ...$values The numbers to add. All the numbers need to be convertible * to an instance of the class this method is called on. * * @throws \InvalidArgumentException If no values are given. * @throws MathException If an argument is not valid. * * @psalm-pure */ public static function sum(BigNumber|int|float|string ...$values) : static { /** @var static|null $sum */ $sum = null; foreach ($values as $value) { $value = static::of($value); $sum = $sum === null ? $value : self::add($sum, $value); } if ($sum === null) { throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.'); } return $sum; } /** * Adds two BigNumber instances in the correct order to avoid a RoundingNecessaryException. * * @todo This could be better resolved by creating an abstract protected method in BigNumber, and leaving to * concrete classes the responsibility to perform the addition themselves or delegate it to the given number, * depending on their ability to perform the operation. This will also require a version bump because we're * potentially breaking custom BigNumber implementations (if any...) * * @psalm-pure */ private static function add(BigNumber $a, BigNumber $b) : BigNumber { if ($a instanceof BigRational) { return $a->plus($b); } if ($b instanceof BigRational) { return $b->plus($a); } if ($a instanceof BigDecimal) { return $a->plus($b); } if ($b instanceof BigDecimal) { return $b->plus($a); } /** @var BigInteger $a */ return $a->plus($b); } /** * Removes optional leading zeros and + sign from the given number. * * @param string $number The number, validated as a non-empty string of digits with optional leading sign. * * @psalm-pure */ private static function cleanUp(string $number) : string { $firstChar = $number[0]; if ($firstChar === '+' || $firstChar === '-') { $number = \substr($number, 1); } $number = \ltrim($number, '0'); if ($number === '') { return '0'; } if ($firstChar === '-') { return '-' . $number; } return $number; } /** * Checks if this number is equal to the given one. */ public function isEqualTo(BigNumber|int|float|string $that) : bool { return $this->compareTo($that) === 0; } /** * Checks if this number is strictly lower than the given one. */ public function isLessThan(BigNumber|int|float|string $that) : bool { return $this->compareTo($that) < 0; } /** * Checks if this number is lower than or equal to the given one. */ public function isLessThanOrEqualTo(BigNumber|int|float|string $that) : bool { return $this->compareTo($that) <= 0; } /** * Checks if this number is strictly greater than the given one. */ public function isGreaterThan(BigNumber|int|float|string $that) : bool { return $this->compareTo($that) > 0; } /** * Checks if this number is greater than or equal to the given one. */ public function isGreaterThanOrEqualTo(BigNumber|int|float|string $that) : bool { return $this->compareTo($that) >= 0; } /** * Checks if this number equals zero. */ public function isZero() : bool { return $this->getSign() === 0; } /** * Checks if this number is strictly negative. */ public function isNegative() : bool { return $this->getSign() < 0; } /** * Checks if this number is negative or zero. */ public function isNegativeOrZero() : bool { return $this->getSign() <= 0; } /** * Checks if this number is strictly positive. */ public function isPositive() : bool { return $this->getSign() > 0; } /** * Checks if this number is positive or zero. */ public function isPositiveOrZero() : bool { return $this->getSign() >= 0; } /** * Returns the sign of this number. * * @return int -1 if the number is negative, 0 if zero, 1 if positive. */ abstract public function getSign() : int; /** * Compares this number to the given one. * * @return int [-1,0,1] If `$this` is lower than, equal to, or greater than `$that`. * * @throws MathException If the number is not valid. */ abstract public function compareTo(BigNumber|int|float|string $that) : int; /** * Converts this number to a BigInteger. * * @throws RoundingNecessaryException If this number cannot be converted to a BigInteger without rounding. */ abstract public function toBigInteger() : BigInteger; /** * Converts this number to a BigDecimal. * * @throws RoundingNecessaryException If this number cannot be converted to a BigDecimal without rounding. */ abstract public function toBigDecimal() : BigDecimal; /** * Converts this number to a BigRational. */ abstract public function toBigRational() : BigRational; /** * Converts this number to a BigDecimal with the given scale, using rounding if necessary. * * @param int $scale The scale of the resulting `BigDecimal`. * @param int $roundingMode A `RoundingMode` constant. * * @throws RoundingNecessaryException If this number cannot be converted to the given scale without rounding. * This only applies when RoundingMode::UNNECESSARY is used. */ abstract public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal; /** * Returns the exact value of this number as a native integer. * * If this number cannot be converted to a native integer without losing precision, an exception is thrown. * Note that the acceptable range for an integer depends on the platform and differs for 32-bit and 64-bit. * * @throws MathException If this number cannot be exactly converted to a native integer. */ abstract public function toInt() : int; /** * Returns an approximation of this number as a floating-point value. * * Note that this method can discard information as the precision of a floating-point value * is inherently limited. * * If the number is greater than the largest representable floating point number, positive infinity is returned. * If the number is less than the smallest representable floating point number, negative infinity is returned. */ abstract public function toFloat() : float; /** * Returns a string representation of this number. * * The output of this method can be parsed by the `of()` factory method; * this will yield an object equal to this one, without any information loss. */ abstract public function __toString() : string; public function jsonSerialize() : string { return $this->__toString(); } } PKZ7ConfigurationAwareInterface.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\Config; /** * Implement this class to facilitate setter injection of the configuration where needed */ interface ConfigurationAwareInterface { public function setConfiguration(ConfigurationInterface $configuration): void; } PKZ+Exception/InvalidConfigurationException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\Config\Exception; class InvalidConfigurationException extends \UnexpectedValueException implements ConfigurationExceptionInterface { /** * @param string $option Name/path of the option * @param mixed $valueGiven The invalid option that was provided * @param ?string $description Additional text describing the issue (optional) */ public static function forConfigOption(string $option, $valueGiven, ?string $description = null): self { $message = \sprintf('Invalid config option for "%s": %s', $option, self::getDebugValue($valueGiven)); if ($description !== null) { $message .= \sprintf(' (%s)', $description); } return new self($message); } /** * @param mixed $value * * @psalm-pure */ private static function getDebugValue($value): string { if (\is_object($value)) { return \get_class($value); } return \print_r($value, true); } } PKZ߈C$Exception/UnknownOptionException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\Config\Exception; use Throwable; final class UnknownOptionException extends \InvalidArgumentException implements ConfigurationExceptionInterface { private string $path; public function __construct(string $message, string $path, int $code = 0, ?Throwable $previous = null) { parent::__construct($message, $code, $previous); $this->path = $path; } public function getPath(): string { return $this->path; } } PKZĖ-Exception/ConfigurationExceptionInterface.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\Config\Exception; /** * Marker interface for any/all exceptions thrown by this library */ interface ConfigurationExceptionInterface extends \Throwable { } PKZ v/^^!Exception/ValidationException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\Config\Exception; use Nette\Schema\ValidationException as NetteException; final class ValidationException extends InvalidConfigurationException { /** @var string[] */ private array $messages; public function __construct(NetteException $innerException) { parent::__construct($innerException->getMessage(), (int) $innerException->getCode(), $innerException); $this->messages = $innerException->getMessages(); } /** * @return string[] */ public function getMessages(): array { return $this->messages; } } PKZWVTTConfiguration.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\Config; use Dflydev\DotAccessData\Data; use Dflydev\DotAccessData\DataInterface; use Dflydev\DotAccessData\Exception\DataException; use Dflydev\DotAccessData\Exception\InvalidPathException; use Dflydev\DotAccessData\Exception\MissingPathException; use League\Config\Exception\UnknownOptionException; use League\Config\Exception\ValidationException; use Nette\Schema\Expect; use Nette\Schema\Processor; use Nette\Schema\Schema; use Nette\Schema\ValidationException as NetteValidationException; final class Configuration implements ConfigurationBuilderInterface, ConfigurationInterface { /** @psalm-readonly */ private Data $userConfig; /** * @var array * * @psalm-allow-private-mutation */ private array $configSchemas = []; /** @psalm-allow-private-mutation */ private Data $finalConfig; /** * @var array * * @psalm-allow-private-mutation */ private array $cache = []; /** @psalm-readonly */ private ConfigurationInterface $reader; /** * @param array $baseSchemas */ public function __construct(array $baseSchemas = []) { $this->configSchemas = $baseSchemas; $this->userConfig = new Data(); $this->finalConfig = new Data(); $this->reader = new ReadOnlyConfiguration($this); } /** * Registers a new configuration schema at the given top-level key * * @psalm-allow-private-mutation */ public function addSchema(string $key, Schema $schema): void { $this->invalidate(); $this->configSchemas[$key] = $schema; } /** * {@inheritDoc} * * @psalm-allow-private-mutation */ public function merge(array $config = []): void { $this->invalidate(); $this->userConfig->import($config, DataInterface::REPLACE); } /** * {@inheritDoc} * * @psalm-allow-private-mutation */ public function set(string $key, $value): void { $this->invalidate(); try { $this->userConfig->set($key, $value); } catch (DataException $ex) { throw new UnknownOptionException($ex->getMessage(), $key, (int) $ex->getCode(), $ex); } } /** * {@inheritDoc} * * @psalm-external-mutation-free */ public function get(string $key) { if (\array_key_exists($key, $this->cache)) { return $this->cache[$key]; } try { $this->build(self::getTopLevelKey($key)); return $this->cache[$key] = $this->finalConfig->get($key); } catch (InvalidPathException | MissingPathException $ex) { throw new UnknownOptionException($ex->getMessage(), $key, (int) $ex->getCode(), $ex); } } /** * {@inheritDoc} * * @psalm-external-mutation-free */ public function exists(string $key): bool { if (\array_key_exists($key, $this->cache)) { return true; } try { $this->build(self::getTopLevelKey($key)); return $this->finalConfig->has($key); } catch (InvalidPathException | UnknownOptionException $ex) { return false; } } /** * @psalm-mutation-free */ public function reader(): ConfigurationInterface { return $this->reader; } /** * @psalm-external-mutation-free */ private function invalidate(): void { $this->cache = []; $this->finalConfig = new Data(); } /** * Applies the schema against the configuration to return the final configuration * * @throws ValidationException|UnknownOptionException|InvalidPathException * * @psalm-allow-private-mutation */ private function build(string $topLevelKey): void { if ($this->finalConfig->has($topLevelKey)) { return; } if (! isset($this->configSchemas[$topLevelKey])) { throw new UnknownOptionException(\sprintf('Missing config schema for "%s"', $topLevelKey), $topLevelKey); } try { $userData = [$topLevelKey => $this->userConfig->get($topLevelKey)]; } catch (DataException $ex) { $userData = []; } try { $schema = $this->configSchemas[$topLevelKey]; $processor = new Processor(); $processed = $processor->process(Expect::structure([$topLevelKey => $schema]), $userData); $this->raiseAnyDeprecationNotices($processor->getWarnings()); $this->finalConfig->import((array) self::convertStdClassesToArrays($processed)); } catch (NetteValidationException $ex) { throw new ValidationException($ex); } } /** * Recursively converts stdClass instances to arrays * * @phpstan-template T * * @param T $data * * @return mixed * * @phpstan-return ($data is \stdClass ? array : T) * * @psalm-pure */ private static function convertStdClassesToArrays($data) { if ($data instanceof \stdClass) { $data = (array) $data; } if (\is_array($data)) { foreach ($data as $k => $v) { $data[$k] = self::convertStdClassesToArrays($v); } } return $data; } /** * @param string[] $warnings */ private function raiseAnyDeprecationNotices(array $warnings): void { foreach ($warnings as $warning) { @\trigger_error($warning, \E_USER_DEPRECATED); } } /** * @throws InvalidPathException */ private static function getTopLevelKey(string $path): string { if (\strlen($path) === 0) { throw new InvalidPathException('Path cannot be an empty string'); } $path = \str_replace(['.', '/'], '.', $path); $firstDelimiter = \strpos($path, '.'); if ($firstDelimiter === false) { return $path; } return \substr($path, 0, $firstDelimiter); } } PKZN""ReadOnlyConfiguration.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\Config; /** * Provides read-only access to a given Configuration object */ final class ReadOnlyConfiguration implements ConfigurationInterface { private Configuration $config; public function __construct(Configuration $config) { $this->config = $config; } /** * {@inheritDoc} */ public function get(string $key) { return $this->config->get($key); } public function exists(string $key): bool { return $this->config->exists($key); } } PKZA[eo22!MutableConfigurationInterface.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\Config; use League\Config\Exception\UnknownOptionException; /** * Interface for setting/merging user-defined configuration values into the configuration object */ interface MutableConfigurationInterface { /** * @param mixed $value * * @throws UnknownOptionException if $key contains a nested path which doesn't point to an array value */ public function set(string $key, $value): void; /** * @param array $config */ public function merge(array $config = []): void; } PKZK"!ConfigurationBuilderInterface.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\Config; /** * An interface that provides the ability to set both the schema and configuration values */ interface ConfigurationBuilderInterface extends MutableConfigurationInterface, SchemaBuilderInterface { } PKZ JJSchemaBuilderInterface.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\Config; use Nette\Schema\Schema; /** * Interface that allows new schemas to be added to a configuration */ interface SchemaBuilderInterface { /** * Registers a new configuration schema at the given top-level key */ public function addSchema(string $key, Schema $schema): void; } PKZ_WConfigurationInterface.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\Config; use League\Config\Exception\UnknownOptionException; use League\Config\Exception\ValidationException; /** * Interface for reading configuration values */ interface ConfigurationInterface { /** * @param string $key Configuration option path/key * * @psalm-param non-empty-string $key * * @return mixed * * @throws ValidationException if the schema failed to validate the given input * @throws UnknownOptionException if the requested key does not exist or is malformed */ public function get(string $key); /** * @param string $key Configuration option path/key * * @psalm-param non-empty-string $key * * @return bool Whether the given option exists * * @throws ValidationException if the schema failed to validate the given input */ public function exists(string $key): bool; } PKZ1A7"ConfigurationProviderInterface.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\Config; /** * Interface for a service which provides a readable configuration object */ interface ConfigurationProviderInterface { public function getConfiguration(): ConfigurationInterface; } PK+ Z.A Mixin.phpnuW+A $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allString($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::string($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrString($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::string($entry, $message); } } /** * @psalm-pure * @psalm-assert non-empty-string|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrStringNotEmpty($value, $message = '') { null === $value || static::stringNotEmpty($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allStringNotEmpty($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::stringNotEmpty($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrStringNotEmpty($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::stringNotEmpty($entry, $message); } } /** * @psalm-pure * @psalm-assert int|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrInteger($value, $message = '') { null === $value || static::integer($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allInteger($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::integer($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrInteger($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::integer($entry, $message); } } /** * @psalm-pure * @psalm-assert numeric|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIntegerish($value, $message = '') { null === $value || static::integerish($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIntegerish($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::integerish($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIntegerish($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::integerish($entry, $message); } } /** * @psalm-pure * @psalm-assert positive-int|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrPositiveInteger($value, $message = '') { null === $value || static::positiveInteger($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allPositiveInteger($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::positiveInteger($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrPositiveInteger($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::positiveInteger($entry, $message); } } /** * @psalm-pure * @psalm-assert float|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrFloat($value, $message = '') { null === $value || static::float($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allFloat($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::float($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrFloat($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::float($entry, $message); } } /** * @psalm-pure * @psalm-assert numeric|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrNumeric($value, $message = '') { null === $value || static::numeric($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNumeric($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::numeric($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrNumeric($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::numeric($entry, $message); } } /** * @psalm-pure * @psalm-assert positive-int|0|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrNatural($value, $message = '') { null === $value || static::natural($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNatural($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::natural($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrNatural($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::natural($entry, $message); } } /** * @psalm-pure * @psalm-assert bool|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrBoolean($value, $message = '') { null === $value || static::boolean($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allBoolean($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::boolean($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrBoolean($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::boolean($entry, $message); } } /** * @psalm-pure * @psalm-assert scalar|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrScalar($value, $message = '') { null === $value || static::scalar($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allScalar($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::scalar($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrScalar($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::scalar($entry, $message); } } /** * @psalm-pure * @psalm-assert object|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrObject($value, $message = '') { null === $value || static::object($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allObject($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::object($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrObject($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::object($entry, $message); } } /** * @psalm-pure * @psalm-assert resource|null $value * * @param mixed $value * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrResource($value, $type = null, $message = '') { null === $value || static::resource($value, $type, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allResource($value, $type = null, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::resource($entry, $type, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrResource($value, $type = null, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::resource($entry, $type, $message); } } /** * @psalm-pure * @psalm-assert callable|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIsCallable($value, $message = '') { null === $value || static::isCallable($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIsCallable($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::isCallable($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIsCallable($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::isCallable($entry, $message); } } /** * @psalm-pure * @psalm-assert array|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIsArray($value, $message = '') { null === $value || static::isArray($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIsArray($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::isArray($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIsArray($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::isArray($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable|null $value * * @deprecated use "isIterable" or "isInstanceOf" instead * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIsTraversable($value, $message = '') { null === $value || static::isTraversable($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @deprecated use "isIterable" or "isInstanceOf" instead * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIsTraversable($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::isTraversable($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @deprecated use "isIterable" or "isInstanceOf" instead * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIsTraversable($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::isTraversable($entry, $message); } } /** * @psalm-pure * @psalm-assert array|ArrayAccess|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIsArrayAccessible($value, $message = '') { null === $value || static::isArrayAccessible($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIsArrayAccessible($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::isArrayAccessible($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIsArrayAccessible($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::isArrayAccessible($entry, $message); } } /** * @psalm-pure * @psalm-assert countable|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIsCountable($value, $message = '') { null === $value || static::isCountable($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIsCountable($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::isCountable($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIsCountable($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::isCountable($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIsIterable($value, $message = '') { null === $value || static::isIterable($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIsIterable($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::isIterable($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIsIterable($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::isIterable($entry, $message); } } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert ExpectedType|null $value * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIsInstanceOf($value, $class, $message = '') { null === $value || static::isInstanceOf($value, $class, $message); } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert iterable $value * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIsInstanceOf($value, $class, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::isInstanceOf($entry, $class, $message); } } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert iterable $value * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIsInstanceOf($value, $class, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::isInstanceOf($entry, $class, $message); } } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrNotInstanceOf($value, $class, $message = '') { null === $value || static::notInstanceOf($value, $class, $message); } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNotInstanceOf($value, $class, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::notInstanceOf($entry, $class, $message); } } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert iterable $value * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrNotInstanceOf($value, $class, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::notInstanceOf($entry, $class, $message); } } /** * @psalm-pure * @psalm-param array $classes * * @param mixed $value * @param array $classes * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIsInstanceOfAny($value, $classes, $message = '') { null === $value || static::isInstanceOfAny($value, $classes, $message); } /** * @psalm-pure * @psalm-param array $classes * * @param mixed $value * @param array $classes * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIsInstanceOfAny($value, $classes, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::isInstanceOfAny($entry, $classes, $message); } } /** * @psalm-pure * @psalm-param array $classes * * @param mixed $value * @param array $classes * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIsInstanceOfAny($value, $classes, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::isInstanceOfAny($entry, $classes, $message); } } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert ExpectedType|class-string|null $value * * @param object|string|null $value * @param string $class * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIsAOf($value, $class, $message = '') { null === $value || static::isAOf($value, $class, $message); } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert iterable> $value * * @param iterable $value * @param string $class * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIsAOf($value, $class, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::isAOf($entry, $class, $message); } } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert iterable|null> $value * * @param iterable $value * @param string $class * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIsAOf($value, $class, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::isAOf($entry, $class, $message); } } /** * @psalm-pure * @psalm-template UnexpectedType of object * @psalm-param class-string $class * * @param object|string|null $value * @param string $class * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIsNotA($value, $class, $message = '') { null === $value || static::isNotA($value, $class, $message); } /** * @psalm-pure * @psalm-template UnexpectedType of object * @psalm-param class-string $class * * @param iterable $value * @param string $class * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIsNotA($value, $class, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::isNotA($entry, $class, $message); } } /** * @psalm-pure * @psalm-template UnexpectedType of object * @psalm-param class-string $class * @psalm-assert iterable $value * @psalm-assert iterable|null> $value * * @param iterable $value * @param string $class * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIsNotA($value, $class, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::isNotA($entry, $class, $message); } } /** * @psalm-pure * @psalm-param array $classes * * @param object|string|null $value * @param string[] $classes * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIsAnyOf($value, $classes, $message = '') { null === $value || static::isAnyOf($value, $classes, $message); } /** * @psalm-pure * @psalm-param array $classes * * @param iterable $value * @param string[] $classes * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIsAnyOf($value, $classes, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::isAnyOf($entry, $classes, $message); } } /** * @psalm-pure * @psalm-param array $classes * * @param iterable $value * @param string[] $classes * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIsAnyOf($value, $classes, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::isAnyOf($entry, $classes, $message); } } /** * @psalm-pure * @psalm-assert empty $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIsEmpty($value, $message = '') { null === $value || static::isEmpty($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIsEmpty($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::isEmpty($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIsEmpty($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::isEmpty($entry, $message); } } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrNotEmpty($value, $message = '') { null === $value || static::notEmpty($value, $message); } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNotEmpty($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::notEmpty($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrNotEmpty($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::notEmpty($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNull($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::null($entry, $message); } } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNotNull($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::notNull($entry, $message); } } /** * @psalm-pure * @psalm-assert true|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrTrue($value, $message = '') { null === $value || static::true($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allTrue($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::true($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrTrue($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::true($entry, $message); } } /** * @psalm-pure * @psalm-assert false|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrFalse($value, $message = '') { null === $value || static::false($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allFalse($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::false($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrFalse($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::false($entry, $message); } } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrNotFalse($value, $message = '') { null === $value || static::notFalse($value, $message); } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNotFalse($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::notFalse($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrNotFalse($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::notFalse($entry, $message); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIp($value, $message = '') { null === $value || static::ip($value, $message); } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIp($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::ip($entry, $message); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIp($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::ip($entry, $message); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIpv4($value, $message = '') { null === $value || static::ipv4($value, $message); } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIpv4($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::ipv4($entry, $message); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIpv4($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::ipv4($entry, $message); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIpv6($value, $message = '') { null === $value || static::ipv6($value, $message); } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIpv6($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::ipv6($entry, $message); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIpv6($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::ipv6($entry, $message); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrEmail($value, $message = '') { null === $value || static::email($value, $message); } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allEmail($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::email($entry, $message); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrEmail($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::email($entry, $message); } } /** * @param array|null $values * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrUniqueValues($values, $message = '') { null === $values || static::uniqueValues($values, $message); } /** * @param iterable $values * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allUniqueValues($values, $message = '') { static::isIterable($values); foreach ($values as $entry) { static::uniqueValues($entry, $message); } } /** * @param iterable $values * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrUniqueValues($values, $message = '') { static::isIterable($values); foreach ($values as $entry) { null === $entry || static::uniqueValues($entry, $message); } } /** * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrEq($value, $expect, $message = '') { null === $value || static::eq($value, $expect, $message); } /** * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allEq($value, $expect, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::eq($entry, $expect, $message); } } /** * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrEq($value, $expect, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::eq($entry, $expect, $message); } } /** * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrNotEq($value, $expect, $message = '') { null === $value || static::notEq($value, $expect, $message); } /** * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNotEq($value, $expect, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::notEq($entry, $expect, $message); } } /** * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrNotEq($value, $expect, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::notEq($entry, $expect, $message); } } /** * @psalm-pure * * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrSame($value, $expect, $message = '') { null === $value || static::same($value, $expect, $message); } /** * @psalm-pure * * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allSame($value, $expect, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::same($entry, $expect, $message); } } /** * @psalm-pure * * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrSame($value, $expect, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::same($entry, $expect, $message); } } /** * @psalm-pure * * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrNotSame($value, $expect, $message = '') { null === $value || static::notSame($value, $expect, $message); } /** * @psalm-pure * * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNotSame($value, $expect, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::notSame($entry, $expect, $message); } } /** * @psalm-pure * * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrNotSame($value, $expect, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::notSame($entry, $expect, $message); } } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrGreaterThan($value, $limit, $message = '') { null === $value || static::greaterThan($value, $limit, $message); } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allGreaterThan($value, $limit, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::greaterThan($entry, $limit, $message); } } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrGreaterThan($value, $limit, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::greaterThan($entry, $limit, $message); } } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrGreaterThanEq($value, $limit, $message = '') { null === $value || static::greaterThanEq($value, $limit, $message); } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allGreaterThanEq($value, $limit, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::greaterThanEq($entry, $limit, $message); } } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrGreaterThanEq($value, $limit, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::greaterThanEq($entry, $limit, $message); } } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrLessThan($value, $limit, $message = '') { null === $value || static::lessThan($value, $limit, $message); } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allLessThan($value, $limit, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::lessThan($entry, $limit, $message); } } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrLessThan($value, $limit, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::lessThan($entry, $limit, $message); } } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrLessThanEq($value, $limit, $message = '') { null === $value || static::lessThanEq($value, $limit, $message); } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allLessThanEq($value, $limit, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::lessThanEq($entry, $limit, $message); } } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrLessThanEq($value, $limit, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::lessThanEq($entry, $limit, $message); } } /** * @psalm-pure * * @param mixed $value * @param mixed $min * @param mixed $max * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrRange($value, $min, $max, $message = '') { null === $value || static::range($value, $min, $max, $message); } /** * @psalm-pure * * @param mixed $value * @param mixed $min * @param mixed $max * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allRange($value, $min, $max, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::range($entry, $min, $max, $message); } } /** * @psalm-pure * * @param mixed $value * @param mixed $min * @param mixed $max * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrRange($value, $min, $max, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::range($entry, $min, $max, $message); } } /** * @psalm-pure * * @param mixed $value * @param array $values * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrOneOf($value, $values, $message = '') { null === $value || static::oneOf($value, $values, $message); } /** * @psalm-pure * * @param mixed $value * @param array $values * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allOneOf($value, $values, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::oneOf($entry, $values, $message); } } /** * @psalm-pure * * @param mixed $value * @param array $values * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrOneOf($value, $values, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::oneOf($entry, $values, $message); } } /** * @psalm-pure * * @param mixed $value * @param array $values * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrInArray($value, $values, $message = '') { null === $value || static::inArray($value, $values, $message); } /** * @psalm-pure * * @param mixed $value * @param array $values * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allInArray($value, $values, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::inArray($entry, $values, $message); } } /** * @psalm-pure * * @param mixed $value * @param array $values * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrInArray($value, $values, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::inArray($entry, $values, $message); } } /** * @psalm-pure * * @param string|null $value * @param string $subString * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrContains($value, $subString, $message = '') { null === $value || static::contains($value, $subString, $message); } /** * @psalm-pure * * @param iterable $value * @param string $subString * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allContains($value, $subString, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::contains($entry, $subString, $message); } } /** * @psalm-pure * * @param iterable $value * @param string $subString * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrContains($value, $subString, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::contains($entry, $subString, $message); } } /** * @psalm-pure * * @param string|null $value * @param string $subString * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrNotContains($value, $subString, $message = '') { null === $value || static::notContains($value, $subString, $message); } /** * @psalm-pure * * @param iterable $value * @param string $subString * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNotContains($value, $subString, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::notContains($entry, $subString, $message); } } /** * @psalm-pure * * @param iterable $value * @param string $subString * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrNotContains($value, $subString, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::notContains($entry, $subString, $message); } } /** * @psalm-pure * * @param string|null $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrNotWhitespaceOnly($value, $message = '') { null === $value || static::notWhitespaceOnly($value, $message); } /** * @psalm-pure * * @param iterable $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNotWhitespaceOnly($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::notWhitespaceOnly($entry, $message); } } /** * @psalm-pure * * @param iterable $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrNotWhitespaceOnly($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::notWhitespaceOnly($entry, $message); } } /** * @psalm-pure * * @param string|null $value * @param string $prefix * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrStartsWith($value, $prefix, $message = '') { null === $value || static::startsWith($value, $prefix, $message); } /** * @psalm-pure * * @param iterable $value * @param string $prefix * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allStartsWith($value, $prefix, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::startsWith($entry, $prefix, $message); } } /** * @psalm-pure * * @param iterable $value * @param string $prefix * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrStartsWith($value, $prefix, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::startsWith($entry, $prefix, $message); } } /** * @psalm-pure * * @param string|null $value * @param string $prefix * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrNotStartsWith($value, $prefix, $message = '') { null === $value || static::notStartsWith($value, $prefix, $message); } /** * @psalm-pure * * @param iterable $value * @param string $prefix * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNotStartsWith($value, $prefix, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::notStartsWith($entry, $prefix, $message); } } /** * @psalm-pure * * @param iterable $value * @param string $prefix * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrNotStartsWith($value, $prefix, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::notStartsWith($entry, $prefix, $message); } } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrStartsWithLetter($value, $message = '') { null === $value || static::startsWithLetter($value, $message); } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allStartsWithLetter($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::startsWithLetter($entry, $message); } } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrStartsWithLetter($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::startsWithLetter($entry, $message); } } /** * @psalm-pure * * @param string|null $value * @param string $suffix * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrEndsWith($value, $suffix, $message = '') { null === $value || static::endsWith($value, $suffix, $message); } /** * @psalm-pure * * @param iterable $value * @param string $suffix * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allEndsWith($value, $suffix, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::endsWith($entry, $suffix, $message); } } /** * @psalm-pure * * @param iterable $value * @param string $suffix * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrEndsWith($value, $suffix, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::endsWith($entry, $suffix, $message); } } /** * @psalm-pure * * @param string|null $value * @param string $suffix * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrNotEndsWith($value, $suffix, $message = '') { null === $value || static::notEndsWith($value, $suffix, $message); } /** * @psalm-pure * * @param iterable $value * @param string $suffix * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNotEndsWith($value, $suffix, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::notEndsWith($entry, $suffix, $message); } } /** * @psalm-pure * * @param iterable $value * @param string $suffix * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrNotEndsWith($value, $suffix, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::notEndsWith($entry, $suffix, $message); } } /** * @psalm-pure * * @param string|null $value * @param string $pattern * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrRegex($value, $pattern, $message = '') { null === $value || static::regex($value, $pattern, $message); } /** * @psalm-pure * * @param iterable $value * @param string $pattern * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allRegex($value, $pattern, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::regex($entry, $pattern, $message); } } /** * @psalm-pure * * @param iterable $value * @param string $pattern * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrRegex($value, $pattern, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::regex($entry, $pattern, $message); } } /** * @psalm-pure * * @param string|null $value * @param string $pattern * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrNotRegex($value, $pattern, $message = '') { null === $value || static::notRegex($value, $pattern, $message); } /** * @psalm-pure * * @param iterable $value * @param string $pattern * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNotRegex($value, $pattern, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::notRegex($entry, $pattern, $message); } } /** * @psalm-pure * * @param iterable $value * @param string $pattern * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrNotRegex($value, $pattern, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::notRegex($entry, $pattern, $message); } } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrUnicodeLetters($value, $message = '') { null === $value || static::unicodeLetters($value, $message); } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allUnicodeLetters($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::unicodeLetters($entry, $message); } } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrUnicodeLetters($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::unicodeLetters($entry, $message); } } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrAlpha($value, $message = '') { null === $value || static::alpha($value, $message); } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allAlpha($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::alpha($entry, $message); } } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrAlpha($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::alpha($entry, $message); } } /** * @psalm-pure * * @param string|null $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrDigits($value, $message = '') { null === $value || static::digits($value, $message); } /** * @psalm-pure * * @param iterable $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allDigits($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::digits($entry, $message); } } /** * @psalm-pure * * @param iterable $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrDigits($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::digits($entry, $message); } } /** * @psalm-pure * * @param string|null $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrAlnum($value, $message = '') { null === $value || static::alnum($value, $message); } /** * @psalm-pure * * @param iterable $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allAlnum($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::alnum($entry, $message); } } /** * @psalm-pure * * @param iterable $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrAlnum($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::alnum($entry, $message); } } /** * @psalm-pure * @psalm-assert lowercase-string|null $value * * @param string|null $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrLower($value, $message = '') { null === $value || static::lower($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param iterable $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allLower($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::lower($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param iterable $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrLower($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::lower($entry, $message); } } /** * @psalm-pure * * @param string|null $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrUpper($value, $message = '') { null === $value || static::upper($value, $message); } /** * @psalm-pure * * @param iterable $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allUpper($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::upper($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param iterable $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrUpper($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::upper($entry, $message); } } /** * @psalm-pure * * @param string|null $value * @param int $length * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrLength($value, $length, $message = '') { null === $value || static::length($value, $length, $message); } /** * @psalm-pure * * @param iterable $value * @param int $length * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allLength($value, $length, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::length($entry, $length, $message); } } /** * @psalm-pure * * @param iterable $value * @param int $length * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrLength($value, $length, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::length($entry, $length, $message); } } /** * @psalm-pure * * @param string|null $value * @param int|float $min * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrMinLength($value, $min, $message = '') { null === $value || static::minLength($value, $min, $message); } /** * @psalm-pure * * @param iterable $value * @param int|float $min * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allMinLength($value, $min, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::minLength($entry, $min, $message); } } /** * @psalm-pure * * @param iterable $value * @param int|float $min * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrMinLength($value, $min, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::minLength($entry, $min, $message); } } /** * @psalm-pure * * @param string|null $value * @param int|float $max * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrMaxLength($value, $max, $message = '') { null === $value || static::maxLength($value, $max, $message); } /** * @psalm-pure * * @param iterable $value * @param int|float $max * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allMaxLength($value, $max, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::maxLength($entry, $max, $message); } } /** * @psalm-pure * * @param iterable $value * @param int|float $max * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrMaxLength($value, $max, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::maxLength($entry, $max, $message); } } /** * @psalm-pure * * @param string|null $value * @param int|float $min * @param int|float $max * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrLengthBetween($value, $min, $max, $message = '') { null === $value || static::lengthBetween($value, $min, $max, $message); } /** * @psalm-pure * * @param iterable $value * @param int|float $min * @param int|float $max * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allLengthBetween($value, $min, $max, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::lengthBetween($entry, $min, $max, $message); } } /** * @psalm-pure * * @param iterable $value * @param int|float $min * @param int|float $max * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrLengthBetween($value, $min, $max, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::lengthBetween($entry, $min, $max, $message); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrFileExists($value, $message = '') { null === $value || static::fileExists($value, $message); } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allFileExists($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::fileExists($entry, $message); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrFileExists($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::fileExists($entry, $message); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrFile($value, $message = '') { null === $value || static::file($value, $message); } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allFile($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::file($entry, $message); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrFile($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::file($entry, $message); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrDirectory($value, $message = '') { null === $value || static::directory($value, $message); } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allDirectory($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::directory($entry, $message); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrDirectory($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::directory($entry, $message); } } /** * @param string|null $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrReadable($value, $message = '') { null === $value || static::readable($value, $message); } /** * @param iterable $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allReadable($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::readable($entry, $message); } } /** * @param iterable $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrReadable($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::readable($entry, $message); } } /** * @param string|null $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrWritable($value, $message = '') { null === $value || static::writable($value, $message); } /** * @param iterable $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allWritable($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::writable($entry, $message); } } /** * @param iterable $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrWritable($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::writable($entry, $message); } } /** * @psalm-assert class-string|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrClassExists($value, $message = '') { null === $value || static::classExists($value, $message); } /** * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allClassExists($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::classExists($entry, $message); } } /** * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrClassExists($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::classExists($entry, $message); } } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert class-string|ExpectedType|null $value * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrSubclassOf($value, $class, $message = '') { null === $value || static::subclassOf($value, $class, $message); } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert iterable|ExpectedType> $value * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allSubclassOf($value, $class, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::subclassOf($entry, $class, $message); } } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert iterable|ExpectedType|null> $value * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrSubclassOf($value, $class, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::subclassOf($entry, $class, $message); } } /** * @psalm-assert class-string|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrInterfaceExists($value, $message = '') { null === $value || static::interfaceExists($value, $message); } /** * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allInterfaceExists($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::interfaceExists($entry, $message); } } /** * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrInterfaceExists($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::interfaceExists($entry, $message); } } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $interface * @psalm-assert class-string|null $value * * @param mixed $value * @param mixed $interface * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrImplementsInterface($value, $interface, $message = '') { null === $value || static::implementsInterface($value, $interface, $message); } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $interface * @psalm-assert iterable> $value * * @param mixed $value * @param mixed $interface * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allImplementsInterface($value, $interface, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::implementsInterface($entry, $interface, $message); } } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $interface * @psalm-assert iterable|null> $value * * @param mixed $value * @param mixed $interface * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrImplementsInterface($value, $interface, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::implementsInterface($entry, $interface, $message); } } /** * @psalm-pure * @psalm-param class-string|object|null $classOrObject * * @param string|object|null $classOrObject * @param mixed $property * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrPropertyExists($classOrObject, $property, $message = '') { null === $classOrObject || static::propertyExists($classOrObject, $property, $message); } /** * @psalm-pure * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $property * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allPropertyExists($classOrObject, $property, $message = '') { static::isIterable($classOrObject); foreach ($classOrObject as $entry) { static::propertyExists($entry, $property, $message); } } /** * @psalm-pure * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $property * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrPropertyExists($classOrObject, $property, $message = '') { static::isIterable($classOrObject); foreach ($classOrObject as $entry) { null === $entry || static::propertyExists($entry, $property, $message); } } /** * @psalm-pure * @psalm-param class-string|object|null $classOrObject * * @param string|object|null $classOrObject * @param mixed $property * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrPropertyNotExists($classOrObject, $property, $message = '') { null === $classOrObject || static::propertyNotExists($classOrObject, $property, $message); } /** * @psalm-pure * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $property * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allPropertyNotExists($classOrObject, $property, $message = '') { static::isIterable($classOrObject); foreach ($classOrObject as $entry) { static::propertyNotExists($entry, $property, $message); } } /** * @psalm-pure * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $property * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrPropertyNotExists($classOrObject, $property, $message = '') { static::isIterable($classOrObject); foreach ($classOrObject as $entry) { null === $entry || static::propertyNotExists($entry, $property, $message); } } /** * @psalm-pure * @psalm-param class-string|object|null $classOrObject * * @param string|object|null $classOrObject * @param mixed $method * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrMethodExists($classOrObject, $method, $message = '') { null === $classOrObject || static::methodExists($classOrObject, $method, $message); } /** * @psalm-pure * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $method * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allMethodExists($classOrObject, $method, $message = '') { static::isIterable($classOrObject); foreach ($classOrObject as $entry) { static::methodExists($entry, $method, $message); } } /** * @psalm-pure * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $method * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrMethodExists($classOrObject, $method, $message = '') { static::isIterable($classOrObject); foreach ($classOrObject as $entry) { null === $entry || static::methodExists($entry, $method, $message); } } /** * @psalm-pure * @psalm-param class-string|object|null $classOrObject * * @param string|object|null $classOrObject * @param mixed $method * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrMethodNotExists($classOrObject, $method, $message = '') { null === $classOrObject || static::methodNotExists($classOrObject, $method, $message); } /** * @psalm-pure * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $method * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allMethodNotExists($classOrObject, $method, $message = '') { static::isIterable($classOrObject); foreach ($classOrObject as $entry) { static::methodNotExists($entry, $method, $message); } } /** * @psalm-pure * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $method * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrMethodNotExists($classOrObject, $method, $message = '') { static::isIterable($classOrObject); foreach ($classOrObject as $entry) { null === $entry || static::methodNotExists($entry, $method, $message); } } /** * @psalm-pure * * @param array|null $array * @param string|int $key * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrKeyExists($array, $key, $message = '') { null === $array || static::keyExists($array, $key, $message); } /** * @psalm-pure * * @param iterable $array * @param string|int $key * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allKeyExists($array, $key, $message = '') { static::isIterable($array); foreach ($array as $entry) { static::keyExists($entry, $key, $message); } } /** * @psalm-pure * * @param iterable $array * @param string|int $key * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrKeyExists($array, $key, $message = '') { static::isIterable($array); foreach ($array as $entry) { null === $entry || static::keyExists($entry, $key, $message); } } /** * @psalm-pure * * @param array|null $array * @param string|int $key * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrKeyNotExists($array, $key, $message = '') { null === $array || static::keyNotExists($array, $key, $message); } /** * @psalm-pure * * @param iterable $array * @param string|int $key * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allKeyNotExists($array, $key, $message = '') { static::isIterable($array); foreach ($array as $entry) { static::keyNotExists($entry, $key, $message); } } /** * @psalm-pure * * @param iterable $array * @param string|int $key * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrKeyNotExists($array, $key, $message = '') { static::isIterable($array); foreach ($array as $entry) { null === $entry || static::keyNotExists($entry, $key, $message); } } /** * @psalm-pure * @psalm-assert array-key|null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrValidArrayKey($value, $message = '') { null === $value || static::validArrayKey($value, $message); } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allValidArrayKey($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::validArrayKey($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrValidArrayKey($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::validArrayKey($entry, $message); } } /** * @param Countable|array|null $array * @param int $number * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrCount($array, $number, $message = '') { null === $array || static::count($array, $number, $message); } /** * @param iterable $array * @param int $number * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allCount($array, $number, $message = '') { static::isIterable($array); foreach ($array as $entry) { static::count($entry, $number, $message); } } /** * @param iterable $array * @param int $number * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrCount($array, $number, $message = '') { static::isIterable($array); foreach ($array as $entry) { null === $entry || static::count($entry, $number, $message); } } /** * @param Countable|array|null $array * @param int|float $min * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrMinCount($array, $min, $message = '') { null === $array || static::minCount($array, $min, $message); } /** * @param iterable $array * @param int|float $min * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allMinCount($array, $min, $message = '') { static::isIterable($array); foreach ($array as $entry) { static::minCount($entry, $min, $message); } } /** * @param iterable $array * @param int|float $min * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrMinCount($array, $min, $message = '') { static::isIterable($array); foreach ($array as $entry) { null === $entry || static::minCount($entry, $min, $message); } } /** * @param Countable|array|null $array * @param int|float $max * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrMaxCount($array, $max, $message = '') { null === $array || static::maxCount($array, $max, $message); } /** * @param iterable $array * @param int|float $max * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allMaxCount($array, $max, $message = '') { static::isIterable($array); foreach ($array as $entry) { static::maxCount($entry, $max, $message); } } /** * @param iterable $array * @param int|float $max * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrMaxCount($array, $max, $message = '') { static::isIterable($array); foreach ($array as $entry) { null === $entry || static::maxCount($entry, $max, $message); } } /** * @param Countable|array|null $array * @param int|float $min * @param int|float $max * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrCountBetween($array, $min, $max, $message = '') { null === $array || static::countBetween($array, $min, $max, $message); } /** * @param iterable $array * @param int|float $min * @param int|float $max * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allCountBetween($array, $min, $max, $message = '') { static::isIterable($array); foreach ($array as $entry) { static::countBetween($entry, $min, $max, $message); } } /** * @param iterable $array * @param int|float $min * @param int|float $max * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrCountBetween($array, $min, $max, $message = '') { static::isIterable($array); foreach ($array as $entry) { null === $entry || static::countBetween($entry, $min, $max, $message); } } /** * @psalm-pure * @psalm-assert list|null $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIsList($array, $message = '') { null === $array || static::isList($array, $message); } /** * @psalm-pure * @psalm-assert iterable $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIsList($array, $message = '') { static::isIterable($array); foreach ($array as $entry) { static::isList($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIsList($array, $message = '') { static::isIterable($array); foreach ($array as $entry) { null === $entry || static::isList($entry, $message); } } /** * @psalm-pure * @psalm-assert non-empty-list|null $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIsNonEmptyList($array, $message = '') { null === $array || static::isNonEmptyList($array, $message); } /** * @psalm-pure * @psalm-assert iterable $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIsNonEmptyList($array, $message = '') { static::isIterable($array); foreach ($array as $entry) { static::isNonEmptyList($entry, $message); } } /** * @psalm-pure * @psalm-assert iterable $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIsNonEmptyList($array, $message = '') { static::isIterable($array); foreach ($array as $entry) { null === $entry || static::isNonEmptyList($entry, $message); } } /** * @psalm-pure * @psalm-template T * @psalm-param mixed|array|null $array * @psalm-assert array|null $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIsMap($array, $message = '') { null === $array || static::isMap($array, $message); } /** * @psalm-pure * @psalm-template T * @psalm-param iterable> $array * @psalm-assert iterable> $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIsMap($array, $message = '') { static::isIterable($array); foreach ($array as $entry) { static::isMap($entry, $message); } } /** * @psalm-pure * @psalm-template T * @psalm-param iterable|null> $array * @psalm-assert iterable|null> $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIsMap($array, $message = '') { static::isIterable($array); foreach ($array as $entry) { null === $entry || static::isMap($entry, $message); } } /** * @psalm-pure * @psalm-template T * @psalm-param mixed|array|null $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrIsNonEmptyMap($array, $message = '') { null === $array || static::isNonEmptyMap($array, $message); } /** * @psalm-pure * @psalm-template T * @psalm-param iterable> $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allIsNonEmptyMap($array, $message = '') { static::isIterable($array); foreach ($array as $entry) { static::isNonEmptyMap($entry, $message); } } /** * @psalm-pure * @psalm-template T * @psalm-param iterable|null> $array * @psalm-assert iterable|null> $array * @psalm-assert iterable $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrIsNonEmptyMap($array, $message = '') { static::isIterable($array); foreach ($array as $entry) { null === $entry || static::isNonEmptyMap($entry, $message); } } /** * @psalm-pure * * @param string|null $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrUuid($value, $message = '') { null === $value || static::uuid($value, $message); } /** * @psalm-pure * * @param iterable $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allUuid($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { static::uuid($entry, $message); } } /** * @psalm-pure * * @param iterable $value * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrUuid($value, $message = '') { static::isIterable($value); foreach ($value as $entry) { null === $entry || static::uuid($entry, $message); } } /** * @psalm-param class-string $class * * @param Closure|null $expression * @param string $class * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function nullOrThrows($expression, $class = 'Exception', $message = '') { null === $expression || static::throws($expression, $class, $message); } /** * @psalm-param class-string $class * * @param iterable $expression * @param string $class * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allThrows($expression, $class = 'Exception', $message = '') { static::isIterable($expression); foreach ($expression as $entry) { static::throws($entry, $class, $message); } } /** * @psalm-param class-string $class * * @param iterable $expression * @param string $class * @param string $message * * @throws InvalidArgumentException * * @return void */ public static function allNullOrThrows($expression, $class = 'Exception', $message = '') { static::isIterable($expression); foreach ($expression as $entry) { null === $entry || static::throws($entry, $class, $message); } } } PK+ Z\166 Assert.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Webmozart\Assert; use ArrayAccess; use BadMethodCallException; use Closure; use Countable; use DateTime; use DateTimeImmutable; use Exception; use ResourceBundle; use SimpleXMLElement; use Throwable; use Traversable; /** * Efficient assertions to validate the input/output of your methods. * * @since 1.0 * * @author Bernhard Schussek */ class Assert { use Mixin; /** * @psalm-pure * @psalm-assert string $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function string($value, $message = '') { if (!\is_string($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a string. Got: %s', static::typeToString($value) )); } } /** * @psalm-pure * @psalm-assert non-empty-string $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function stringNotEmpty($value, $message = '') { static::string($value, $message); static::notEq($value, '', $message); } /** * @psalm-pure * @psalm-assert int $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function integer($value, $message = '') { if (!\is_int($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected an integer. Got: %s', static::typeToString($value) )); } } /** * @psalm-pure * @psalm-assert numeric $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function integerish($value, $message = '') { if (!\is_numeric($value) || $value != (int) $value) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected an integerish value. Got: %s', static::typeToString($value) )); } } /** * @psalm-pure * @psalm-assert positive-int $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function positiveInteger($value, $message = '') { if (!(\is_int($value) && $value > 0)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a positive integer. Got: %s', static::valueToString($value) )); } } /** * @psalm-pure * @psalm-assert float $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function float($value, $message = '') { if (!\is_float($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a float. Got: %s', static::typeToString($value) )); } } /** * @psalm-pure * @psalm-assert numeric $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function numeric($value, $message = '') { if (!\is_numeric($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a numeric. Got: %s', static::typeToString($value) )); } } /** * @psalm-pure * @psalm-assert positive-int|0 $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function natural($value, $message = '') { if (!\is_int($value) || $value < 0) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a non-negative integer. Got: %s', static::valueToString($value) )); } } /** * @psalm-pure * @psalm-assert bool $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function boolean($value, $message = '') { if (!\is_bool($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a boolean. Got: %s', static::typeToString($value) )); } } /** * @psalm-pure * @psalm-assert scalar $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function scalar($value, $message = '') { if (!\is_scalar($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a scalar. Got: %s', static::typeToString($value) )); } } /** * @psalm-pure * @psalm-assert object $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function object($value, $message = '') { if (!\is_object($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected an object. Got: %s', static::typeToString($value) )); } } /** * @psalm-pure * @psalm-assert resource $value * * @param mixed $value * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php * @param string $message * * @throws InvalidArgumentException */ public static function resource($value, $type = null, $message = '') { if (!\is_resource($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a resource. Got: %s', static::typeToString($value) )); } if ($type && $type !== \get_resource_type($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a resource of type %2$s. Got: %s', static::typeToString($value), $type )); } } /** * @psalm-pure * @psalm-assert callable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function isCallable($value, $message = '') { if (!\is_callable($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a callable. Got: %s', static::typeToString($value) )); } } /** * @psalm-pure * @psalm-assert array $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function isArray($value, $message = '') { if (!\is_array($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected an array. Got: %s', static::typeToString($value) )); } } /** * @psalm-pure * @psalm-assert iterable $value * * @deprecated use "isIterable" or "isInstanceOf" instead * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function isTraversable($value, $message = '') { @\trigger_error( \sprintf( 'The "%s" assertion is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use "isIterable" or "isInstanceOf" instead.', __METHOD__ ), \E_USER_DEPRECATED ); if (!\is_array($value) && !($value instanceof Traversable)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a traversable. Got: %s', static::typeToString($value) )); } } /** * @psalm-pure * @psalm-assert array|ArrayAccess $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function isArrayAccessible($value, $message = '') { if (!\is_array($value) && !($value instanceof ArrayAccess)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected an array accessible. Got: %s', static::typeToString($value) )); } } /** * @psalm-pure * @psalm-assert countable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function isCountable($value, $message = '') { if ( !\is_array($value) && !($value instanceof Countable) && !($value instanceof ResourceBundle) && !($value instanceof SimpleXMLElement) ) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a countable. Got: %s', static::typeToString($value) )); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function isIterable($value, $message = '') { if (!\is_array($value) && !($value instanceof Traversable)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected an iterable. Got: %s', static::typeToString($value) )); } } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert ExpectedType $value * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException */ public static function isInstanceOf($value, $class, $message = '') { if (!($value instanceof $class)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected an instance of %2$s. Got: %s', static::typeToString($value), $class )); } } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert !ExpectedType $value * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException */ public static function notInstanceOf($value, $class, $message = '') { if ($value instanceof $class) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected an instance other than %2$s. Got: %s', static::typeToString($value), $class )); } } /** * @psalm-pure * @psalm-param array $classes * * @param mixed $value * @param array $classes * @param string $message * * @throws InvalidArgumentException */ public static function isInstanceOfAny($value, array $classes, $message = '') { foreach ($classes as $class) { if ($value instanceof $class) { return; } } static::reportInvalidArgument(\sprintf( $message ?: 'Expected an instance of any of %2$s. Got: %s', static::typeToString($value), \implode(', ', \array_map(array(static::class, 'valueToString'), $classes)) )); } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert ExpectedType|class-string $value * * @param object|string $value * @param string $class * @param string $message * * @throws InvalidArgumentException */ public static function isAOf($value, $class, $message = '') { static::string($class, 'Expected class as a string. Got: %s'); if (!\is_a($value, $class, \is_string($value))) { static::reportInvalidArgument(sprintf( $message ?: 'Expected an instance of this class or to this class among its parents "%2$s". Got: %s', static::valueToString($value), $class )); } } /** * @psalm-pure * @psalm-template UnexpectedType of object * @psalm-param class-string $class * @psalm-assert !UnexpectedType $value * @psalm-assert !class-string $value * * @param object|string $value * @param string $class * @param string $message * * @throws InvalidArgumentException */ public static function isNotA($value, $class, $message = '') { static::string($class, 'Expected class as a string. Got: %s'); if (\is_a($value, $class, \is_string($value))) { static::reportInvalidArgument(sprintf( $message ?: 'Expected an instance of this class or to this class among its parents other than "%2$s". Got: %s', static::valueToString($value), $class )); } } /** * @psalm-pure * @psalm-param array $classes * * @param object|string $value * @param string[] $classes * @param string $message * * @throws InvalidArgumentException */ public static function isAnyOf($value, array $classes, $message = '') { foreach ($classes as $class) { static::string($class, 'Expected class as a string. Got: %s'); if (\is_a($value, $class, \is_string($value))) { return; } } static::reportInvalidArgument(sprintf( $message ?: 'Expected an instance of any of this classes or any of those classes among their parents "%2$s". Got: %s', static::valueToString($value), \implode(', ', $classes) )); } /** * @psalm-pure * @psalm-assert empty $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function isEmpty($value, $message = '') { if (!empty($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected an empty value. Got: %s', static::valueToString($value) )); } } /** * @psalm-pure * @psalm-assert !empty $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function notEmpty($value, $message = '') { if (empty($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a non-empty value. Got: %s', static::valueToString($value) )); } } /** * @psalm-pure * @psalm-assert null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function null($value, $message = '') { if (null !== $value) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected null. Got: %s', static::valueToString($value) )); } } /** * @psalm-pure * @psalm-assert !null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function notNull($value, $message = '') { if (null === $value) { static::reportInvalidArgument( $message ?: 'Expected a value other than null.' ); } } /** * @psalm-pure * @psalm-assert true $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function true($value, $message = '') { if (true !== $value) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to be true. Got: %s', static::valueToString($value) )); } } /** * @psalm-pure * @psalm-assert false $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function false($value, $message = '') { if (false !== $value) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to be false. Got: %s', static::valueToString($value) )); } } /** * @psalm-pure * @psalm-assert !false $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function notFalse($value, $message = '') { if (false === $value) { static::reportInvalidArgument( $message ?: 'Expected a value other than false.' ); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function ip($value, $message = '') { if (false === \filter_var($value, \FILTER_VALIDATE_IP)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to be an IP. Got: %s', static::valueToString($value) )); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function ipv4($value, $message = '') { if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to be an IPv4. Got: %s', static::valueToString($value) )); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function ipv6($value, $message = '') { if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to be an IPv6. Got: %s', static::valueToString($value) )); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function email($value, $message = '') { if (false === \filter_var($value, FILTER_VALIDATE_EMAIL)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to be a valid e-mail address. Got: %s', static::valueToString($value) )); } } /** * Does non strict comparisons on the items, so ['3', 3] will not pass the assertion. * * @param array $values * @param string $message * * @throws InvalidArgumentException */ public static function uniqueValues(array $values, $message = '') { $allValues = \count($values); $uniqueValues = \count(\array_unique($values)); if ($allValues !== $uniqueValues) { $difference = $allValues - $uniqueValues; static::reportInvalidArgument(\sprintf( $message ?: 'Expected an array of unique values, but %s of them %s duplicated', $difference, (1 === $difference ? 'is' : 'are') )); } } /** * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException */ public static function eq($value, $expect, $message = '') { if ($expect != $value) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value equal to %2$s. Got: %s', static::valueToString($value), static::valueToString($expect) )); } } /** * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException */ public static function notEq($value, $expect, $message = '') { if ($expect == $value) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a different value than %s.', static::valueToString($expect) )); } } /** * @psalm-pure * * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException */ public static function same($value, $expect, $message = '') { if ($expect !== $value) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value identical to %2$s. Got: %s', static::valueToString($value), static::valueToString($expect) )); } } /** * @psalm-pure * * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException */ public static function notSame($value, $expect, $message = '') { if ($expect === $value) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value not identical to %s.', static::valueToString($expect) )); } } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException */ public static function greaterThan($value, $limit, $message = '') { if ($value <= $limit) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value greater than %2$s. Got: %s', static::valueToString($value), static::valueToString($limit) )); } } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException */ public static function greaterThanEq($value, $limit, $message = '') { if ($value < $limit) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value greater than or equal to %2$s. Got: %s', static::valueToString($value), static::valueToString($limit) )); } } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException */ public static function lessThan($value, $limit, $message = '') { if ($value >= $limit) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value less than %2$s. Got: %s', static::valueToString($value), static::valueToString($limit) )); } } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException */ public static function lessThanEq($value, $limit, $message = '') { if ($value > $limit) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value less than or equal to %2$s. Got: %s', static::valueToString($value), static::valueToString($limit) )); } } /** * Inclusive range, so Assert::(3, 3, 5) passes. * * @psalm-pure * * @param mixed $value * @param mixed $min * @param mixed $max * @param string $message * * @throws InvalidArgumentException */ public static function range($value, $min, $max, $message = '') { if ($value < $min || $value > $max) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value between %2$s and %3$s. Got: %s', static::valueToString($value), static::valueToString($min), static::valueToString($max) )); } } /** * A more human-readable alias of Assert::inArray(). * * @psalm-pure * * @param mixed $value * @param array $values * @param string $message * * @throws InvalidArgumentException */ public static function oneOf($value, array $values, $message = '') { static::inArray($value, $values, $message); } /** * Does strict comparison, so Assert::inArray(3, ['3']) does not pass the assertion. * * @psalm-pure * * @param mixed $value * @param array $values * @param string $message * * @throws InvalidArgumentException */ public static function inArray($value, array $values, $message = '') { if (!\in_array($value, $values, true)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected one of: %2$s. Got: %s', static::valueToString($value), \implode(', ', \array_map(array(static::class, 'valueToString'), $values)) )); } } /** * @psalm-pure * * @param string $value * @param string $subString * @param string $message * * @throws InvalidArgumentException */ public static function contains($value, $subString, $message = '') { if (false === \strpos($value, $subString)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain %2$s. Got: %s', static::valueToString($value), static::valueToString($subString) )); } } /** * @psalm-pure * * @param string $value * @param string $subString * @param string $message * * @throws InvalidArgumentException */ public static function notContains($value, $subString, $message = '') { if (false !== \strpos($value, $subString)) { static::reportInvalidArgument(\sprintf( $message ?: '%2$s was not expected to be contained in a value. Got: %s', static::valueToString($value), static::valueToString($subString) )); } } /** * @psalm-pure * * @param string $value * @param string $message * * @throws InvalidArgumentException */ public static function notWhitespaceOnly($value, $message = '') { if (\preg_match('/^\s*$/', $value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a non-whitespace string. Got: %s', static::valueToString($value) )); } } /** * @psalm-pure * * @param string $value * @param string $prefix * @param string $message * * @throws InvalidArgumentException */ public static function startsWith($value, $prefix, $message = '') { if (0 !== \strpos($value, $prefix)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to start with %2$s. Got: %s', static::valueToString($value), static::valueToString($prefix) )); } } /** * @psalm-pure * * @param string $value * @param string $prefix * @param string $message * * @throws InvalidArgumentException */ public static function notStartsWith($value, $prefix, $message = '') { if (0 === \strpos($value, $prefix)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value not to start with %2$s. Got: %s', static::valueToString($value), static::valueToString($prefix) )); } } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function startsWithLetter($value, $message = '') { static::string($value); $valid = isset($value[0]); if ($valid) { $locale = \setlocale(LC_CTYPE, 0); \setlocale(LC_CTYPE, 'C'); $valid = \ctype_alpha($value[0]); \setlocale(LC_CTYPE, $locale); } if (!$valid) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to start with a letter. Got: %s', static::valueToString($value) )); } } /** * @psalm-pure * * @param string $value * @param string $suffix * @param string $message * * @throws InvalidArgumentException */ public static function endsWith($value, $suffix, $message = '') { if ($suffix !== \substr($value, -\strlen($suffix))) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to end with %2$s. Got: %s', static::valueToString($value), static::valueToString($suffix) )); } } /** * @psalm-pure * * @param string $value * @param string $suffix * @param string $message * * @throws InvalidArgumentException */ public static function notEndsWith($value, $suffix, $message = '') { if ($suffix === \substr($value, -\strlen($suffix))) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value not to end with %2$s. Got: %s', static::valueToString($value), static::valueToString($suffix) )); } } /** * @psalm-pure * * @param string $value * @param string $pattern * @param string $message * * @throws InvalidArgumentException */ public static function regex($value, $pattern, $message = '') { if (!\preg_match($pattern, $value)) { static::reportInvalidArgument(\sprintf( $message ?: 'The value %s does not match the expected pattern.', static::valueToString($value) )); } } /** * @psalm-pure * * @param string $value * @param string $pattern * @param string $message * * @throws InvalidArgumentException */ public static function notRegex($value, $pattern, $message = '') { if (\preg_match($pattern, $value, $matches, PREG_OFFSET_CAPTURE)) { static::reportInvalidArgument(\sprintf( $message ?: 'The value %s matches the pattern %s (at offset %d).', static::valueToString($value), static::valueToString($pattern), $matches[0][1] )); } } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function unicodeLetters($value, $message = '') { static::string($value); if (!\preg_match('/^\p{L}+$/u', $value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain only Unicode letters. Got: %s', static::valueToString($value) )); } } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function alpha($value, $message = '') { static::string($value); $locale = \setlocale(LC_CTYPE, 0); \setlocale(LC_CTYPE, 'C'); $valid = !\ctype_alpha($value); \setlocale(LC_CTYPE, $locale); if ($valid) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain only letters. Got: %s', static::valueToString($value) )); } } /** * @psalm-pure * * @param string $value * @param string $message * * @throws InvalidArgumentException */ public static function digits($value, $message = '') { $locale = \setlocale(LC_CTYPE, 0); \setlocale(LC_CTYPE, 'C'); $valid = !\ctype_digit($value); \setlocale(LC_CTYPE, $locale); if ($valid) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain digits only. Got: %s', static::valueToString($value) )); } } /** * @psalm-pure * * @param string $value * @param string $message * * @throws InvalidArgumentException */ public static function alnum($value, $message = '') { $locale = \setlocale(LC_CTYPE, 0); \setlocale(LC_CTYPE, 'C'); $valid = !\ctype_alnum($value); \setlocale(LC_CTYPE, $locale); if ($valid) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain letters and digits only. Got: %s', static::valueToString($value) )); } } /** * @psalm-pure * @psalm-assert lowercase-string $value * * @param string $value * @param string $message * * @throws InvalidArgumentException */ public static function lower($value, $message = '') { $locale = \setlocale(LC_CTYPE, 0); \setlocale(LC_CTYPE, 'C'); $valid = !\ctype_lower($value); \setlocale(LC_CTYPE, $locale); if ($valid) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain lowercase characters only. Got: %s', static::valueToString($value) )); } } /** * @psalm-pure * @psalm-assert !lowercase-string $value * * @param string $value * @param string $message * * @throws InvalidArgumentException */ public static function upper($value, $message = '') { $locale = \setlocale(LC_CTYPE, 0); \setlocale(LC_CTYPE, 'C'); $valid = !\ctype_upper($value); \setlocale(LC_CTYPE, $locale); if ($valid) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain uppercase characters only. Got: %s', static::valueToString($value) )); } } /** * @psalm-pure * * @param string $value * @param int $length * @param string $message * * @throws InvalidArgumentException */ public static function length($value, $length, $message = '') { if ($length !== static::strlen($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain %2$s characters. Got: %s', static::valueToString($value), $length )); } } /** * Inclusive min. * * @psalm-pure * * @param string $value * @param int|float $min * @param string $message * * @throws InvalidArgumentException */ public static function minLength($value, $min, $message = '') { if (static::strlen($value) < $min) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain at least %2$s characters. Got: %s', static::valueToString($value), $min )); } } /** * Inclusive max. * * @psalm-pure * * @param string $value * @param int|float $max * @param string $message * * @throws InvalidArgumentException */ public static function maxLength($value, $max, $message = '') { if (static::strlen($value) > $max) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain at most %2$s characters. Got: %s', static::valueToString($value), $max )); } } /** * Inclusive , so Assert::lengthBetween('asd', 3, 5); passes the assertion. * * @psalm-pure * * @param string $value * @param int|float $min * @param int|float $max * @param string $message * * @throws InvalidArgumentException */ public static function lengthBetween($value, $min, $max, $message = '') { $length = static::strlen($value); if ($length < $min || $length > $max) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain between %2$s and %3$s characters. Got: %s', static::valueToString($value), $min, $max )); } } /** * Will also pass if $value is a directory, use Assert::file() instead if you need to be sure it is a file. * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function fileExists($value, $message = '') { static::string($value); if (!\file_exists($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'The file %s does not exist.', static::valueToString($value) )); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function file($value, $message = '') { static::fileExists($value, $message); if (!\is_file($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'The path %s is not a file.', static::valueToString($value) )); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function directory($value, $message = '') { static::fileExists($value, $message); if (!\is_dir($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'The path %s is no directory.', static::valueToString($value) )); } } /** * @param string $value * @param string $message * * @throws InvalidArgumentException */ public static function readable($value, $message = '') { if (!\is_readable($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'The path %s is not readable.', static::valueToString($value) )); } } /** * @param string $value * @param string $message * * @throws InvalidArgumentException */ public static function writable($value, $message = '') { if (!\is_writable($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'The path %s is not writable.', static::valueToString($value) )); } } /** * @psalm-assert class-string $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function classExists($value, $message = '') { if (!\class_exists($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected an existing class name. Got: %s', static::valueToString($value) )); } } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert class-string|ExpectedType $value * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException */ public static function subclassOf($value, $class, $message = '') { if (!\is_subclass_of($value, $class)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected a sub-class of %2$s. Got: %s', static::valueToString($value), static::valueToString($class) )); } } /** * @psalm-assert class-string $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function interfaceExists($value, $message = '') { if (!\interface_exists($value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected an existing interface name. got %s', static::valueToString($value) )); } } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $interface * @psalm-assert class-string $value * * @param mixed $value * @param mixed $interface * @param string $message * * @throws InvalidArgumentException */ public static function implementsInterface($value, $interface, $message = '') { if (!\in_array($interface, \class_implements($value))) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected an implementation of %2$s. Got: %s', static::valueToString($value), static::valueToString($interface) )); } } /** * @psalm-pure * @psalm-param class-string|object $classOrObject * * @param string|object $classOrObject * @param mixed $property * @param string $message * * @throws InvalidArgumentException */ public static function propertyExists($classOrObject, $property, $message = '') { if (!\property_exists($classOrObject, $property)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected the property %s to exist.', static::valueToString($property) )); } } /** * @psalm-pure * @psalm-param class-string|object $classOrObject * * @param string|object $classOrObject * @param mixed $property * @param string $message * * @throws InvalidArgumentException */ public static function propertyNotExists($classOrObject, $property, $message = '') { if (\property_exists($classOrObject, $property)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected the property %s to not exist.', static::valueToString($property) )); } } /** * @psalm-pure * @psalm-param class-string|object $classOrObject * * @param string|object $classOrObject * @param mixed $method * @param string $message * * @throws InvalidArgumentException */ public static function methodExists($classOrObject, $method, $message = '') { if (!(\is_string($classOrObject) || \is_object($classOrObject)) || !\method_exists($classOrObject, $method)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected the method %s to exist.', static::valueToString($method) )); } } /** * @psalm-pure * @psalm-param class-string|object $classOrObject * * @param string|object $classOrObject * @param mixed $method * @param string $message * * @throws InvalidArgumentException */ public static function methodNotExists($classOrObject, $method, $message = '') { if ((\is_string($classOrObject) || \is_object($classOrObject)) && \method_exists($classOrObject, $method)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected the method %s to not exist.', static::valueToString($method) )); } } /** * @psalm-pure * * @param array $array * @param string|int $key * @param string $message * * @throws InvalidArgumentException */ public static function keyExists($array, $key, $message = '') { if (!(isset($array[$key]) || \array_key_exists($key, $array))) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected the key %s to exist.', static::valueToString($key) )); } } /** * @psalm-pure * * @param array $array * @param string|int $key * @param string $message * * @throws InvalidArgumentException */ public static function keyNotExists($array, $key, $message = '') { if (isset($array[$key]) || \array_key_exists($key, $array)) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected the key %s to not exist.', static::valueToString($key) )); } } /** * Checks if a value is a valid array key (int or string). * * @psalm-pure * @psalm-assert array-key $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function validArrayKey($value, $message = '') { if (!(\is_int($value) || \is_string($value))) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected string or integer. Got: %s', static::typeToString($value) )); } } /** * Does not check if $array is countable, this can generate a warning on php versions after 7.2. * * @param Countable|array $array * @param int $number * @param string $message * * @throws InvalidArgumentException */ public static function count($array, $number, $message = '') { static::eq( \count($array), $number, \sprintf( $message ?: 'Expected an array to contain %d elements. Got: %d.', $number, \count($array) ) ); } /** * Does not check if $array is countable, this can generate a warning on php versions after 7.2. * * @param Countable|array $array * @param int|float $min * @param string $message * * @throws InvalidArgumentException */ public static function minCount($array, $min, $message = '') { if (\count($array) < $min) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected an array to contain at least %2$d elements. Got: %d', \count($array), $min )); } } /** * Does not check if $array is countable, this can generate a warning on php versions after 7.2. * * @param Countable|array $array * @param int|float $max * @param string $message * * @throws InvalidArgumentException */ public static function maxCount($array, $max, $message = '') { if (\count($array) > $max) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected an array to contain at most %2$d elements. Got: %d', \count($array), $max )); } } /** * Does not check if $array is countable, this can generate a warning on php versions after 7.2. * * @param Countable|array $array * @param int|float $min * @param int|float $max * @param string $message * * @throws InvalidArgumentException */ public static function countBetween($array, $min, $max, $message = '') { $count = \count($array); if ($count < $min || $count > $max) { static::reportInvalidArgument(\sprintf( $message ?: 'Expected an array to contain between %2$d and %3$d elements. Got: %d', $count, $min, $max )); } } /** * @psalm-pure * @psalm-assert list $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException */ public static function isList($array, $message = '') { if (!\is_array($array)) { static::reportInvalidArgument( $message ?: 'Expected list - non-associative array.' ); } if ($array === \array_values($array)) { return; } $nextKey = -1; foreach ($array as $k => $v) { if ($k !== ++$nextKey) { static::reportInvalidArgument( $message ?: 'Expected list - non-associative array.' ); } } } /** * @psalm-pure * @psalm-assert non-empty-list $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException */ public static function isNonEmptyList($array, $message = '') { static::isList($array, $message); static::notEmpty($array, $message); } /** * @psalm-pure * @psalm-template T * @psalm-param mixed|array $array * @psalm-assert array $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException */ public static function isMap($array, $message = '') { if ( !\is_array($array) || \array_keys($array) !== \array_filter(\array_keys($array), '\is_string') ) { static::reportInvalidArgument( $message ?: 'Expected map - associative array with string keys.' ); } } /** * @psalm-pure * @psalm-template T * @psalm-param mixed|array $array * @psalm-assert array $array * @psalm-assert !empty $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException */ public static function isNonEmptyMap($array, $message = '') { static::isMap($array, $message); static::notEmpty($array, $message); } /** * @psalm-pure * * @param string $value * @param string $message * * @throws InvalidArgumentException */ public static function uuid($value, $message = '') { $value = \str_replace(array('urn:', 'uuid:', '{', '}'), '', $value); // The nil UUID is special form of UUID that is specified to have all // 128 bits set to zero. if ('00000000-0000-0000-0000-000000000000' === $value) { return; } if (!\preg_match('/^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/', $value)) { static::reportInvalidArgument(\sprintf( $message ?: 'Value %s is not a valid UUID.', static::valueToString($value) )); } } /** * @psalm-param class-string $class * * @param Closure $expression * @param string $class * @param string $message * * @throws InvalidArgumentException */ public static function throws(Closure $expression, $class = 'Exception', $message = '') { static::string($class); $actual = 'none'; try { $expression(); } catch (Exception $e) { $actual = \get_class($e); if ($e instanceof $class) { return; } } catch (Throwable $e) { $actual = \get_class($e); if ($e instanceof $class) { return; } } static::reportInvalidArgument($message ?: \sprintf( 'Expected to throw "%s", got "%s"', $class, $actual )); } /** * @throws BadMethodCallException */ public static function __callStatic($name, $arguments) { if ('nullOr' === \substr($name, 0, 6)) { if (null !== $arguments[0]) { $method = \lcfirst(\substr($name, 6)); \call_user_func_array(array(static::class, $method), $arguments); } return; } if ('all' === \substr($name, 0, 3)) { static::isIterable($arguments[0]); $method = \lcfirst(\substr($name, 3)); $args = $arguments; foreach ($arguments[0] as $entry) { $args[0] = $entry; \call_user_func_array(array(static::class, $method), $args); } return; } throw new BadMethodCallException('No such method: '.$name); } /** * @param mixed $value * * @return string */ protected static function valueToString($value) { if (null === $value) { return 'null'; } if (true === $value) { return 'true'; } if (false === $value) { return 'false'; } if (\is_array($value)) { return 'array'; } if (\is_object($value)) { if (\method_exists($value, '__toString')) { return \get_class($value).': '.self::valueToString($value->__toString()); } if ($value instanceof DateTime || $value instanceof DateTimeImmutable) { return \get_class($value).': '.self::valueToString($value->format('c')); } return \get_class($value); } if (\is_resource($value)) { return 'resource'; } if (\is_string($value)) { return '"'.$value.'"'; } return (string) $value; } /** * @param mixed $value * * @return string */ protected static function typeToString($value) { return \is_object($value) ? \get_class($value) : \gettype($value); } protected static function strlen($value) { if (!\function_exists('mb_detect_encoding')) { return \strlen($value); } if (false === $encoding = \mb_detect_encoding($value)) { return \strlen($value); } return \mb_strlen($value, $encoding); } /** * @param string $message * * @throws InvalidArgumentException * * @psalm-pure this method is not supposed to perform side-effects * @psalm-return never */ protected static function reportInvalidArgument($message) { throw new InvalidArgumentException($message); } private function __construct() { } } PK$ZvCClassAliasAutoloader.phpnuW+Ashell = $shell; $this->vendorPath = dirname(dirname($classMapPath)); $this->includedAliases = collect($includedAliases); $this->excludedAliases = collect($excludedAliases); $classes = require $classMapPath; foreach ($classes as $class => $path) { if (! $this->isAliasable($class, $path)) { continue; } $name = class_basename($class); if (! isset($this->classes[$name])) { $this->classes[$name] = $class; } } } /** * Find the closest class by name. * * @param string $class * @return void */ public function aliasClass($class) { if (Str::contains($class, '\\')) { return; } $fullName = $this->classes[$class] ?? false; if ($fullName) { $this->shell->writeStdout("[!] Aliasing '{$class}' to '{$fullName}' for this Tinker session.\n"); class_alias($fullName, $class); } } /** * Unregister the alias loader instance. * * @return void */ public function unregister() { spl_autoload_unregister([$this, 'aliasClass']); } /** * Handle the destruction of the instance. * * @return void */ public function __destruct() { $this->unregister(); } /** * Whether a class may be aliased. * * @param string $class * @param string $path */ public function isAliasable($class, $path) { if (! Str::contains($class, '\\')) { return false; } if (! $this->includedAliases->filter(function ($alias) use ($class) { return Str::startsWith($class, $alias); })->isEmpty()) { return true; } if (Str::startsWith($path, $this->vendorPath)) { return false; } if (! $this->excludedAliases->filter(function ($alias) use ($class) { return Str::startsWith($class, $alias); })->isEmpty()) { return false; } return true; } } PK$Zp7Console/TinkerCommand.phpnuW+AgetApplication()->setCatchExceptions(false); $config = Configuration::fromInput($this->input); $config->setUpdateCheck(Checker::NEVER); $config->getPresenter()->addCasters( $this->getCasters() ); if ($this->option('execute')) { $config->setRawOutput(true); } $shell = new Shell($config); $shell->addCommands($this->getCommands()); $shell->setIncludes($this->argument('include')); $path = Env::get('COMPOSER_VENDOR_DIR', $this->getLaravel()->basePath().DIRECTORY_SEPARATOR.'vendor'); $path .= '/composer/autoload_classmap.php'; $config = $this->getLaravel()->make('config'); $loader = ClassAliasAutoloader::register( $shell, $path, $config->get('tinker.alias', []), $config->get('tinker.dont_alias', []) ); if ($code = $this->option('execute')) { try { $shell->setOutput($this->output); $shell->execute($code); } finally { $loader->unregister(); } return 0; } try { return $shell->run(); } finally { $loader->unregister(); } } /** * Get artisan commands to pass through to PsySH. * * @return array */ protected function getCommands() { $commands = []; foreach ($this->getApplication()->all() as $name => $command) { if (in_array($name, $this->commandWhitelist)) { $commands[] = $command; } } $config = $this->getLaravel()->make('config'); foreach ($config->get('tinker.commands', []) as $command) { $commands[] = $this->getApplication()->add( $this->getLaravel()->make($command) ); } return $commands; } /** * Get an array of Laravel tailored casters. * * @return array */ protected function getCasters() { $casters = [ 'Illuminate\Support\Collection' => 'Laravel\Tinker\TinkerCaster::castCollection', 'Illuminate\Support\HtmlString' => 'Laravel\Tinker\TinkerCaster::castHtmlString', 'Illuminate\Support\Stringable' => 'Laravel\Tinker\TinkerCaster::castStringable', ]; if (class_exists('Illuminate\Database\Eloquent\Model')) { $casters['Illuminate\Database\Eloquent\Model'] = 'Laravel\Tinker\TinkerCaster::castModel'; } if (class_exists('Illuminate\Process\ProcessResult')) { $casters['Illuminate\Process\ProcessResult'] = 'Laravel\Tinker\TinkerCaster::castProcessResult'; } if (class_exists('Illuminate\Foundation\Application')) { $casters['Illuminate\Foundation\Application'] = 'Laravel\Tinker\TinkerCaster::castApplication'; } $config = $this->getLaravel()->make('config'); return array_merge($casters, (array) $config->get('tinker.casters', [])); } /** * Get the console command arguments. * * @return array */ protected function getArguments() { return [ ['include', InputArgument::IS_ARRAY, 'Include file(s) before starting tinker'], ]; } /** * Get the console command options. * * @return array */ protected function getOptions() { return [ ['execute', null, InputOption::VALUE_OPTIONAL, 'Execute the given code using Tinker'], ]; } } PK$Z7jRRTinkerCaster.phpnuW+A$property(); if (! is_null($val)) { $results[Caster::PREFIX_VIRTUAL.$property] = $val; } } catch (Exception $e) { // } } return $results; } /** * Get an array representing the properties of a collection. * * @param \Illuminate\Support\Collection $collection * @return array */ public static function castCollection($collection) { return [ Caster::PREFIX_VIRTUAL.'all' => $collection->all(), ]; } /** * Get an array representing the properties of an html string. * * @param \Illuminate\Support\HtmlString $htmlString * @return array */ public static function castHtmlString($htmlString) { return [ Caster::PREFIX_VIRTUAL.'html' => $htmlString->toHtml(), ]; } /** * Get an array representing the properties of a fluent string. * * @param \Illuminate\Support\Stringable $stringable * @return array */ public static function castStringable($stringable) { return [ Caster::PREFIX_VIRTUAL.'value' => (string) $stringable, ]; } /** * Get an array representing the properties of a process result. * * @param \Illuminate\Process\ProcessResult $result * @return array */ public static function castProcessResult($result) { return [ Caster::PREFIX_VIRTUAL.'output' => $result->output(), Caster::PREFIX_VIRTUAL.'errorOutput' => $result->errorOutput(), Caster::PREFIX_VIRTUAL.'exitCode' => $result->exitCode(), Caster::PREFIX_VIRTUAL.'successful' => $result->successful(), ]; } /** * Get an array representing the properties of a model. * * @param \Illuminate\Database\Eloquent\Model $model * @return array */ public static function castModel($model) { $attributes = array_merge( $model->getAttributes(), $model->getRelations() ); $visible = array_flip( $model->getVisible() ?: array_diff(array_keys($attributes), $model->getHidden()) ); $hidden = array_flip($model->getHidden()); $appends = (function () { return array_combine($this->appends, $this->appends); })->bindTo($model, $model)(); foreach ($appends as $appended) { $attributes[$appended] = $model->{$appended}; } $results = []; foreach ($attributes as $key => $value) { $prefix = ''; if (isset($visible[$key])) { $prefix = Caster::PREFIX_VIRTUAL; } if (isset($hidden[$key])) { $prefix = Caster::PREFIX_PROTECTED; } $results[$prefix.$key] = $value; } return $results; } } PK$Z-@@TinkerServiceProvider.phpnuW+Aapp instanceof LaravelApplication && $this->app->runningInConsole()) { $this->publishes([$source => config_path('tinker.php')]); } elseif ($this->app instanceof LumenApplication) { $this->app->configure('tinker'); } $this->mergeConfigFrom($source, 'tinker'); } /** * Register the service provider. * * @return void */ public function register() { $this->app->singleton('command.tinker', function () { return new TinkerCommand; }); $this->commands(['command.tinker']); } /** * Get the services provided by the provider. * * @return array */ public function provides() { return ['command.tinker']; } } PK*%ZL9'9' Exporter.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Exporter; use function bin2hex; use function count; use function function_exists; use function get_class; use function get_resource_type; use function gettype; use function implode; use function ini_get; use function ini_set; use function is_array; use function is_float; use function is_object; use function is_resource; use function is_string; use function mb_strlen; use function mb_substr; use function preg_match; use function spl_object_hash; use function sprintf; use function str_repeat; use function str_replace; use function strlen; use function substr; use function var_export; use SebastianBergmann\RecursionContext\Context; use SplObjectStorage; /** * A nifty utility for visualizing PHP variables. * * * export(new Exception); * */ class Exporter { /** * Exports a value as a string. * * The output of this method is similar to the output of print_r(), but * improved in various aspects: * * - NULL is rendered as "null" (instead of "") * - TRUE is rendered as "true" (instead of "1") * - FALSE is rendered as "false" (instead of "") * - Strings are always quoted with single quotes * - Carriage returns and newlines are normalized to \n * - Recursion and repeated rendering is treated properly * * @param int $indentation The indentation level of the 2nd+ line * * @return string */ public function export($value, $indentation = 0) { return $this->recursiveExport($value, $indentation); } /** * @param array $data * @param Context $context * * @return string */ public function shortenedRecursiveExport(&$data, ?Context $context = null) { $result = []; $exporter = new self(); if (!$context) { $context = new Context; } $array = $data; $context->add($data); foreach ($array as $key => $value) { if (is_array($value)) { if ($context->contains($data[$key]) !== false) { $result[] = '*RECURSION*'; } else { $result[] = sprintf( 'array(%s)', $this->shortenedRecursiveExport($data[$key], $context) ); } } else { $result[] = $exporter->shortenedExport($value); } } return implode(', ', $result); } /** * Exports a value into a single-line string. * * The output of this method is similar to the output of * SebastianBergmann\Exporter\Exporter::export(). * * Newlines are replaced by the visible string '\n'. * Contents of arrays and objects (if any) are replaced by '...'. * * @return string * * @see SebastianBergmann\Exporter\Exporter::export */ public function shortenedExport($value) { if (is_string($value)) { $string = str_replace("\n", '', $this->export($value)); if (function_exists('mb_strlen')) { if (mb_strlen($string) > 40) { $string = mb_substr($string, 0, 30) . '...' . mb_substr($string, -7); } } else { if (strlen($string) > 40) { $string = substr($string, 0, 30) . '...' . substr($string, -7); } } return $string; } if (is_object($value)) { return sprintf( '%s Object (%s)', get_class($value), count($this->toArray($value)) > 0 ? '...' : '' ); } if (is_array($value)) { return sprintf( 'Array (%s)', count($value) > 0 ? '...' : '' ); } return $this->export($value); } /** * Converts an object to an array containing all of its private, protected * and public properties. * * @return array */ public function toArray($value) { if (!is_object($value)) { return (array) $value; } $array = []; foreach ((array) $value as $key => $val) { // Exception traces commonly reference hundreds to thousands of // objects currently loaded in memory. Including them in the result // has a severe negative performance impact. if ("\0Error\0trace" === $key || "\0Exception\0trace" === $key) { continue; } // properties are transformed to keys in the following way: // private $property => "\0Classname\0property" // protected $property => "\0*\0property" // public $property => "property" if (preg_match('/^\0.+\0(.+)$/', (string) $key, $matches)) { $key = $matches[1]; } // See https://github.com/php/php-src/commit/5721132 if ($key === "\0gcdata") { continue; } $array[$key] = $val; } // Some internal classes like SplObjectStorage don't work with the // above (fast) mechanism nor with reflection in Zend. // Format the output similarly to print_r() in this case if ($value instanceof SplObjectStorage) { foreach ($value as $key => $val) { $array[spl_object_hash($val)] = [ 'obj' => $val, 'inf' => $value->getInfo(), ]; } } return $array; } /** * Recursive implementation of export. * * @param mixed $value The value to export * @param int $indentation The indentation level of the 2nd+ line * @param \SebastianBergmann\RecursionContext\Context $processed Previously processed objects * * @return string * * @see SebastianBergmann\Exporter\Exporter::export */ protected function recursiveExport(&$value, $indentation, $processed = null) { if ($value === null) { return 'null'; } if ($value === true) { return 'true'; } if ($value === false) { return 'false'; } if (is_float($value)) { $precisionBackup = ini_get('precision'); ini_set('precision', '-1'); try { $valueStr = (string) $value; if ((string) (int) $value === $valueStr) { return $valueStr . '.0'; } return $valueStr; } finally { ini_set('precision', $precisionBackup); } } if (gettype($value) === 'resource (closed)') { return 'resource (closed)'; } if (is_resource($value)) { return sprintf( 'resource(%d) of type (%s)', $value, get_resource_type($value) ); } if (is_string($value)) { // Match for most non printable chars somewhat taking multibyte chars into account if (preg_match('/[^\x09-\x0d\x1b\x20-\xff]/', $value)) { return 'Binary String: 0x' . bin2hex($value); } return "'" . str_replace( '', "\n", str_replace( ["\r\n", "\n\r", "\r", "\n"], ['\r\n', '\n\r', '\r', '\n'], $value ) ) . "'"; } $whitespace = str_repeat(' ', 4 * $indentation); if (!$processed) { $processed = new Context; } if (is_array($value)) { if (($key = $processed->contains($value)) !== false) { return 'Array &' . $key; } $array = $value; $key = $processed->add($value); $values = ''; if (count($array) > 0) { foreach ($array as $k => $v) { $values .= sprintf( '%s %s => %s' . "\n", $whitespace, $this->recursiveExport($k, $indentation), $this->recursiveExport($value[$k], $indentation + 1, $processed) ); } $values = "\n" . $values . $whitespace; } return sprintf('Array &%s (%s)', $key, $values); } if (is_object($value)) { $class = get_class($value); if ($hash = $processed->contains($value)) { return sprintf('%s Object &%s', $class, $hash); } $hash = $processed->add($value); $values = ''; $array = $this->toArray($value); if (count($array) > 0) { foreach ($array as $k => $v) { $values .= sprintf( '%s %s => %s' . "\n", $whitespace, $this->recursiveExport($k, $indentation), $this->recursiveExport($v, $indentation + 1, $processed) ); } $values = "\n" . $values . $whitespace; } return sprintf('%s Object &%s (%s)', $class, $hash, $values); } return var_export($value, true); } } PK&Z L Backtrace.phpnuW+AforThrowable($throwable); } protected function forThrowable(Throwable $throwable): self { $this->throwable = $throwable; return $this; } public function withArguments(bool $withArguments = true): self { $this->withArguments = $withArguments; return $this; } public function withObject(): self { $this->withObject = true; return $this; } public function applicationPath(string $applicationPath): self { $this->applicationPath = rtrim($applicationPath, '/'); return $this; } public function offset(int $offset): self { $this->offset = $offset; return $this; } public function limit(int $limit): self { $this->limit = $limit; return $this; } public function startingFromFrame(Closure $startingFromFrameClosure) { $this->startingFromFrameClosure = $startingFromFrameClosure; return $this; } /** * @return \Spatie\Backtrace\Frame[] */ public function frames(): array { $rawFrames = $this->getRawFrames(); return $this->toFrameObjects($rawFrames); } public function firstApplicationFrameIndex(): ?int { foreach ($this->frames() as $index => $frame) { if ($frame->applicationFrame) { return $index; } } return null; } protected function getRawFrames(): array { if ($this->throwable) { return $this->throwable->getTrace(); } $options = null; if (! $this->withArguments) { $options = $options | DEBUG_BACKTRACE_IGNORE_ARGS; } if ($this->withObject()) { $options = $options | DEBUG_BACKTRACE_PROVIDE_OBJECT; } $limit = $this->limit; if ($limit !== 0) { $limit += 3; } return debug_backtrace($options, $limit); } /** * @return \Spatie\Backtrace\Frame[] */ protected function toFrameObjects(array $rawFrames): array { $currentFile = $this->throwable ? $this->throwable->getFile() : ''; $currentLine = $this->throwable ? $this->throwable->getLine() : 0; $frames = []; foreach ($rawFrames as $rawFrame) { $frames[] = new Frame( $currentFile, $currentLine, $rawFrame['args'] ?? null, $rawFrame['function'] ?? null, $rawFrame['class'] ?? null, $this->isApplicationFrame($currentFile) ); $currentFile = $rawFrame['file'] ?? 'unknown'; $currentLine = $rawFrame['line'] ?? 0; } $frames[] = new Frame( $currentFile, $currentLine, [], '[top]' ); $frames = $this->removeBacktracePackageFrames($frames); if ($closure = $this->startingFromFrameClosure) { $frames = $this->startAtFrameFromClosure($frames, $closure); } $frames = array_slice($frames, $this->offset, $this->limit === 0 ? PHP_INT_MAX : $this->limit); return array_values($frames); } protected function isApplicationFrame(string $frameFilename): bool { $relativeFile = str_replace('\\', DIRECTORY_SEPARATOR, $frameFilename); if (! empty($this->applicationPath)) { $relativeFile = array_reverse(explode($this->applicationPath ?? '', $frameFilename, 2))[0]; } if (strpos($relativeFile, DIRECTORY_SEPARATOR . 'vendor') === 0) { return false; } return true; } protected function removeBacktracePackageFrames(array $frames): array { return $this->startAtFrameFromClosure($frames, function (Frame $frame) { return $frame->class !== static::class; }); } /** * @param \Spatie\Backtrace\Frame[] $frames * @param \Closure $closure * * @return array */ protected function startAtFrameFromClosure(array $frames, Closure $closure): array { foreach ($frames as $i => $frame) { $foundStartingFrame = $closure($frame); if ($foundStartingFrame) { return $frames; } unset($frames[$i]); } return $frames; } } PK&ZrǶ)Arguments/ReduceArgumentPayloadAction.phpnuW+AargumentReducers = $argumentReducers; } public function reduce($argument, bool $includeObjectType = false): ReducedArgument { foreach ($this->argumentReducers->argumentReducers as $reducer) { $reduced = $reducer->execute($argument); if ($reduced instanceof ReducedArgument) { return $reduced; } } if (gettype($argument) === 'object' && $includeObjectType) { return new ReducedArgument( 'object ('.get_class($argument).')', get_debug_type($argument), ); } if (gettype($argument) === 'object') { return new ReducedArgument('object', get_debug_type($argument), ); } return new ReducedArgument( $argument, get_debug_type($argument), ); } } PK&Z،'ee5Arguments/ReducedArgument/ReducedArgumentContract.phpnuW+AoriginalType = $originalType; $this->value = $value; } } PK&Z1E5Arguments/ReducedArgument/VariadicReducedArgument.phpnuW+A $item) { if (! $item instanceof ReducedArgument) { throw new Exception('VariadicReducedArgument must be an array of ReducedArgument'); } $value[$key] = $item->value; } parent::__construct($value, 'array'); } } PK&ZKΉzz6Arguments/ReducedArgument/TruncatedReducedArgument.phpnuW+A */ public $argumentReducers = []; /** * @param array> $argumentReducers */ public static function create(array $argumentReducers): self { return new self(array_map( function ($argumentReducer) { /** @var $argumentReducer ArgumentReducer|class-string */ return $argumentReducer instanceof ArgumentReducer ? $argumentReducer : new $argumentReducer(); }, $argumentReducers )); } public static function default(array $extra = []): self { return new self(static::defaultReducers($extra)); } public static function minimal(array $extra = []): self { return new self(static::minimalReducers($extra)); } /** * @param array $argumentReducers */ protected function __construct(array $argumentReducers) { $this->argumentReducers = $argumentReducers; } protected static function defaultReducers(array $extra = []): array { return array_merge($extra, [ new BaseTypeArgumentReducer(), new ArrayArgumentReducer(), new StdClassArgumentReducer(), new EnumArgumentReducer(), new ClosureArgumentReducer(), new SensitiveParameterArrayReducer(), new DateTimeArgumentReducer(), new DateTimeZoneArgumentReducer(), new SymphonyRequestArgumentReducer(), new StringableArgumentReducer(), ]); } protected static function minimalReducers(array $extra = []): array { return array_merge($extra, [ new BaseTypeArgumentReducer(), new MinimalArrayArgumentReducer(), new EnumArgumentReducer(), new ClosureArgumentReducer(), new SensitiveParameterArrayReducer(), ]); } } PK&ZXR-Arguments/Reducers/ClosureArgumentReducer.phpnuW+AgetFileName() && $reflection->getStartLine() && $reflection->getEndLine()) { return new ReducedArgument( "{$reflection->getFileName()}:{$reflection->getStartLine()}-{$reflection->getEndLine()}", 'Closure' ); } return new ReducedArgument("{$reflection->getFileName()}", 'Closure'); } } PK&Z95Arguments/Reducers/SymphonyRequestArgumentReducer.phpnuW+AgetMethod()} {$argument->getUri()}", get_class($argument), ); } } PK&Z2Arguments/Reducers/DateTimeZoneArgumentReducer.phpnuW+AgetName(), get_class($argument), ); } } PK&Z''lzz0Arguments/Reducers/StringableArgumentReducer.phpnuW+Aformat('d M Y H:i:s e'), get_class($argument), ); } } PK&Z D5Arguments/Reducers/SensitiveParameterArrayReducer.phpnuW+AgetValue()).')', get_class($argument) ); } } PK&Zs+*Arguments/Reducers/EnumArgumentReducer.phpnuW+Aname, get_class($argument), ); } } PK&Z&EKcc2Arguments/Reducers/MinimalArrayArgumentReducer.phpnuW+AreduceArgumentPayloadAction = new ReduceArgumentPayloadAction(ArgumentReducers::minimal()); } public function execute($argument): ReducedArgumentContract { if (! is_array($argument)) { return UnReducedArgument::create(); } return $this->reduceArgument($argument, 'array'); } protected function reduceArgument(array $argument, string $originalType): ReducedArgumentContract { foreach ($argument as $key => $value) { $argument[$key] = $this->reduceArgumentPayloadAction->reduce( $value, true )->value; } if (count($argument) > $this->maxArraySize) { return new TruncatedReducedArgument( array_slice($argument, 0, $this->maxArraySize), 'array' ); } return new ReducedArgument($argument, $originalType); } } PK&ZR  &Arguments/Reducers/ArgumentReducer.phpnuW+AargumentReducers = $argumentReducers; $this->reduceArgumentPayloadAction = new ReduceArgumentPayloadAction($argumentReducers); } public function execute( ?string $class, ?string $method, ?array $frameArguments ): ?array { try { if ($frameArguments === null) { return null; } $parameters = $this->getParameters($class, $method); if ($parameters === null) { $arguments = []; foreach ($frameArguments as $index => $argument) { $arguments[$index] = ProvidedArgument::fromNonReflectableParameter($index) ->setReducedArgument($this->reduceArgumentPayloadAction->reduce($argument)) ->toArray(); } return $arguments; } $arguments = array_map( function ($argument) { return $this->reduceArgumentPayloadAction->reduce($argument); }, $frameArguments, ); $argumentsCount = count($arguments); $hasVariadicParameter = false; foreach ($parameters as $index => $parameter) { if ($index + 1 > $argumentsCount) { $parameter->defaultValueUsed(); } elseif ($parameter->isVariadic) { $parameter->setReducedArgument(new VariadicReducedArgument(array_slice($arguments, $index))); $hasVariadicParameter = true; } else { $parameter->setReducedArgument($arguments[$index]); } $parameters[$index] = $parameter->toArray(); } if ($this->moreArgumentsProvidedThanParameters($arguments, $parameters, $hasVariadicParameter)) { for ($i = count($parameters); $i < count($arguments); $i++) { $parameters[$i] = ProvidedArgument::fromNonReflectableParameter(count($parameters)) ->setReducedArgument($arguments[$i]) ->toArray(); } } return $parameters; } catch (Throwable $e) { return null; } } /** @return null|Array<\Spatie\Backtrace\Arguments\ProvidedArgument> */ protected function getParameters( ?string $class, ?string $method ): ?array { try { $reflection = $class !== null ? new ReflectionMethod($class, $method) : new ReflectionFunction($method); } catch (ReflectionException $e) { return null; } return array_map( function (ReflectionParameter $reflectionParameter) { return ProvidedArgument::fromReflectionParameter($reflectionParameter); }, $reflection->getParameters(), ); } protected function moreArgumentsProvidedThanParameters( array $arguments, array $parameters, bool $hasVariadicParameter ): bool { return count($arguments) > count($parameters) && ! $hasVariadicParameter; } } PK&Z=bxI I Arguments/ProvidedArgument.phpnuW+AgetName(), $parameter->isPassedByReference(), $parameter->isVariadic(), $parameter->isDefaultValueAvailable(), $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : null, ); } public static function fromNonReflectableParameter( int $index ): self { return new self( "arg{$index}", false, ); } public function __construct( string $name, bool $passedByReference = false, bool $isVariadic = false, bool $hasDefaultValue = false, $defaultValue = null, bool $defaultValueUsed = false, bool $truncated = false, $reducedValue = null, ?string $originalType = null ) { $this->originalType = $originalType; $this->reducedValue = $reducedValue; $this->truncated = $truncated; $this->defaultValueUsed = $defaultValueUsed; $this->defaultValue = $defaultValue; $this->hasDefaultValue = $hasDefaultValue; $this->isVariadic = $isVariadic; $this->passedByReference = $passedByReference; $this->name = $name; if ($this->isVariadic) { $this->defaultValue = []; } } public function setReducedArgument( ReducedArgument $reducedArgument ): self { $this->reducedValue = $reducedArgument->value; $this->originalType = $reducedArgument->originalType; if ($reducedArgument instanceof TruncatedReducedArgument) { $this->truncated = true; } return $this; } public function defaultValueUsed(): self { $this->defaultValueUsed = true; $this->originalType = get_debug_type($this->defaultValue); return $this; } public function toArray(): array { return [ 'name' => $this->name, 'value' => $this->defaultValueUsed ? $this->defaultValue : $this->reducedValue, 'original_type' => $this->originalType, 'passed_by_reference' => $this->passedByReference, 'is_variadic' => $this->isVariadic, 'truncated' => $this->truncated, ]; } } PK&Z`$CodeSnippets/NullSnippetProvider.phpnuW+AgetNextLine(); } public function getNextLine(): string { return "File not found for code snippet"; } } PK&ZF}ʻCodeSnippets/CodeSnippet.phpnuW+AsurroundingLine = $surroundingLine; return $this; } public function snippetLineCount(int $snippetLineCount): self { $this->snippetLineCount = $snippetLineCount; return $this; } public function get(SnippetProvider $provider): array { try { [$startLineNumber, $endLineNumber] = $this->getBounds($provider->numberOfLines()); $code = []; $line = $provider->getLine($startLineNumber); $currentLineNumber = $startLineNumber; while ($currentLineNumber <= $endLineNumber) { $code[$currentLineNumber] = rtrim(substr($line, 0, 250)); $line = $provider->getNextLine(); $currentLineNumber++; } return $code; } catch (RuntimeException $exception) { return []; } } public function getAsString(SnippetProvider $provider): string { $snippet = $this->get($provider); $snippetStrings = array_map(function (string $line, string $number) { return "{$number} {$line}"; }, $snippet, array_keys($snippet)); return implode(PHP_EOL, $snippetStrings); } protected function getBounds(int $totalNumberOfLineInFile): array { $startLine = max($this->surroundingLine - floor($this->snippetLineCount / 2), 1); $endLine = $startLine + ($this->snippetLineCount - 1); if ($endLine > $totalNumberOfLineInFile) { $endLine = $totalNumberOfLineInFile; $startLine = max($endLine - ($this->snippetLineCount - 1), 1); } return [$startLine, $endLine]; } } PK&Z ` CodeSnippets/SnippetProvider.phpnuW+A */ protected $lines; /** @var int */ protected $counter = 0; public function __construct(string $snippet) { $this->lines = preg_split("/\r\n|\n|\r/", $snippet); $this->cleanupLines(); } public function numberOfLines(): int { return count($this->lines); } public function getLine(?int $lineNumber = null): string { if (is_null($lineNumber)) { return $this->getNextLine(); } $this->counter = $lineNumber - 1; return $this->lines[$lineNumber - 1]; } public function getNextLine(): string { $this->counter++; if ($this->counter >= count($this->lines)) { return ''; } return $this->lines[$this->counter]; } protected function cleanupLines(): void { $spacesOrTabsToRemove = PHP_INT_MAX; for ($i = 1; $i < count($this->lines); $i++) { if (empty($this->lines[$i])) { continue; } $spacesOrTabsToRemove = min(strspn($this->lines[$i], " \t"), $spacesOrTabsToRemove); } if ($spacesOrTabsToRemove === PHP_INT_MAX) { $spacesOrTabsToRemove = 0; } for ($i = 1; $i < count($this->lines); $i++) { $this->lines[$i] = substr($this->lines[$i], $spacesOrTabsToRemove); } } } PK&Z8ƙX$CodeSnippets/FileSnippetProvider.phpnuW+Afile = new SplFileObject($path); } public function numberOfLines(): int { $this->file->seek(PHP_INT_MAX); return $this->file->key() + 1; } public function getLine(?int $lineNumber = null): string { if (is_null($lineNumber)) { return $this->getNextLine(); } $this->file->seek($lineNumber - 1); return $this->file->current(); } public function getNextLine(): string { $this->file->next(); return $this->file->current(); } } PK&Z Frame.phpnuW+Aframe = $frame; } public function toArray(): array { return [ 'file' => $this->frame->file, 'line_number' => $this->frame->lineNumber, 'method' => $this->frame->method, 'class' => $this->frame->class, 'code_snippet' => $this->frame->getSnippet(30), 'application_frame' => $this->frame->applicationFrame, ]; } } PK*Z VersionUpdater/Checker.phpnuW+AgetLatest(), '>='); } public function getLatest(): string { if (!isset($this->latest)) { $this->setLatest($this->getVersionFromTag()); } return $this->latest; } public function setLatest(string $version) { $this->latest = $version; } private function getVersionFromTag(): ?string { $contents = $this->fetchLatestRelease(); if (!$contents || !isset($contents->tag_name)) { throw new \InvalidArgumentException('Unable to check for updates'); } $this->setLatest($contents->tag_name); return $this->getLatest(); } /** * Set to public to make testing easier. * * @return mixed */ public function fetchLatestRelease() { $context = \stream_context_create([ 'http' => [ 'user_agent' => 'PsySH/'.Shell::VERSION, 'timeout' => 1.0, ], ]); \set_error_handler(function () { // Just ignore all errors with this. The checker will throw an exception // if it doesn't work :) }); $result = @\file_get_contents(self::URL, false, $context); \restore_error_handler(); return \json_decode($result); } } PK*Z!2&VersionUpdater/SelfUpdate.phpnuW+Achecker = $checker; $this->installer = $installer; } /** * Allow the downloader to be injected for testing. * * @return void */ public function setDownloader(Downloader $downloader) { $this->downloader = $downloader; } /** * Get the currently set Downloader or create one based on the capabilities of the php environment. * * @throws ErrorException if a downloader cannot be created for the php environment */ private function getDownloader(): Downloader { if (!isset($this->downloader)) { return Downloader\Factory::getDownloader(); } return $this->downloader; } /** * Build the download URL for the latest release. * * The file name used in the URL will include the flavour postfix extracted from the current version * if it's present */ private function getAssetUrl(string $latestVersion): string { $versionPostfix = ''; if (\strpos(Shell::VERSION, '+')) { $versionPostfix = '-'.\substr(Shell::VERSION, \strpos(Shell::VERSION, '+') + 1); } $downloadFilename = \sprintf('psysh-%s%s.tar.gz', $latestVersion, $versionPostfix); // check if latest release data contains an asset matching the filename? return \sprintf('%s/%s/%s', self::URL_PREFIX, $latestVersion, $downloadFilename); } /** * Execute the self-update process. * * @throws ErrorException if the current version is not restored when installation fails */ public function run(InputInterface $input, OutputInterface $output): int { $currentVersion = Shell::VERSION; // already have the latest version? if ($this->checker->isLatest()) { // current version is latest version... $output->writeln('Current version is up-to-date.'); return self::SUCCESS; } // can overwrite current version? if (!$this->installer->isInstallLocationWritable()) { $output->writeln('Installed version is not writable.'); return self::FAILURE; } // can download to, and create a backup in the temp directory? if (!$this->installer->isTempDirectoryWritable()) { $output->writeln('Temporary directory is not writable.'); return self::FAILURE; } $latestVersion = $this->checker->getLatest(); $downloadUrl = $this->getAssetUrl($latestVersion); $output->write("Downloading PsySH $latestVersion ..."); try { $downloader = $this->getDownloader(); $downloader->setTempDir($this->installer->getTempDirectory()); $downloaded = $downloader->download($downloadUrl); } catch (ErrorException $e) { $output->write(' Failed.'); $output->writeln(\sprintf('%s', $e->getMessage())); return self::FAILURE; } if (!$downloaded) { $output->writeln('Download failed.'); $downloader->cleanup(); return self::FAILURE; } else { $output->write(' OK'.\PHP_EOL); } $downloadedFile = $downloader->getFilename(); if (!$this->installer->isValidSource($downloadedFile)) { $downloader->cleanup(); $output->writeln('Downloaded file is not a valid archive.'); return self::FAILURE; } // create backup as bin.old-version in the temporary directory $backupCreated = $this->installer->createBackup($currentVersion); if (!$backupCreated) { $downloader->cleanup(); $output->writeln('Failed to create a backup of the current version.'); return self::FAILURE; } elseif ($input->getOption('verbose')) { $backupFilename = $this->installer->getBackupFilename($currentVersion); $output->writeln('Created backup of current version: '.$backupFilename); } if (!$this->installer->install($downloadedFile)) { $this->installer->restoreFromBackup($currentVersion); $downloader->cleanup(); $output->writeln("Failed to install new PsySH version $latestVersion."); return self::FAILURE; } // Remove the downloaded archive file from the temporary directory $downloader->cleanup(); $output->writeln("Updated PsySH from $currentVersion to $latestVersion"); return self::SUCCESS; } } PK*Zdk"VersionUpdater/IntervalChecker.phpnuW+AcacheFile = $cacheFile; $this->interval = $interval; } public function fetchLatestRelease() { // Read the cached file $cached = \json_decode(@\file_get_contents($this->cacheFile, false)); if ($cached && isset($cached->last_check) && isset($cached->release)) { $now = new \DateTime(); $lastCheck = new \DateTime($cached->last_check); if ($lastCheck >= $now->sub($this->getDateInterval())) { return $cached->release; } } // Fall back to fetching from GitHub $release = parent::fetchLatestRelease(); if ($release && isset($release->tag_name)) { $this->updateCache($release); } return $release; } /** * @throws \RuntimeException if interval passed to constructor is not supported */ private function getDateInterval(): \DateInterval { switch ($this->interval) { case Checker::DAILY: return new \DateInterval('P1D'); case Checker::WEEKLY: return new \DateInterval('P1W'); case Checker::MONTHLY: return new \DateInterval('P1M'); } throw new \RuntimeException('Invalid interval configured'); } private function updateCache($release) { $data = [ 'last_check' => \date(\DATE_ATOM), 'release' => $release, ]; \file_put_contents($this->cacheFile, \json_encode($data)); } } PK*ZO""VersionUpdater/NoopChecker.phpnuW+AtempDir = $tempDir; } /** {@inheritDoc} */ public function download(string $url): bool { $tempDir = $this->tempDir ?: \sys_get_temp_dir(); $this->outputFile = \tempnam($tempDir, 'psysh-archive-'); $targetName = $this->outputFile.'.tar.gz'; if (!\rename($this->outputFile, $targetName)) { return false; } $this->outputFile = $targetName; $outputHandle = \fopen($this->outputFile, 'w'); if (!$outputHandle) { return false; } $curl = \curl_init(); \curl_setopt_array($curl, [ \CURLOPT_FAILONERROR => true, \CURLOPT_HEADER => 0, \CURLOPT_FOLLOWLOCATION => true, \CURLOPT_TIMEOUT => 10, \CURLOPT_FILE => $outputHandle, \CURLOPT_HTTPHEADER => [ 'User-Agent' => 'PsySH/'.Shell::VERSION, ], ]); \curl_setopt($curl, \CURLOPT_URL, $url); $result = \curl_exec($curl); $error = \curl_error($curl); \curl_close($curl); \fclose($outputHandle); if (!$result) { throw new ErrorException('cURL Error: '.$error); } return (bool) $result; } /** {@inheritDoc} */ public function getFilename(): string { if ($this->outputFile === null) { throw new RuntimeException('Call download() first'); } return $this->outputFile; } /** {@inheritDoc} */ public function cleanup() { if ($this->outputFile !== null && \file_exists($this->outputFile)) { \unlink($this->outputFile); } } } PK*ZS,VersionUpdater/Downloader/FileDownloader.phpnuW+AtempDir = $tempDir; } /** {@inheritDoc} */ public function download(string $url): bool { $tempDir = $this->tempDir ?: \sys_get_temp_dir(); $this->outputFile = \tempnam($tempDir, 'psysh-archive-'); $targetName = $this->outputFile.'.tar.gz'; if (!\rename($this->outputFile, $targetName)) { return false; } $this->outputFile = $targetName; return (bool) \file_put_contents($this->outputFile, \file_get_contents($url)); } /** {@inheritDoc} */ public function getFilename(): string { if ($this->outputFile === null) { throw new RuntimeException('Call download() first'); } return $this->outputFile; } /** {@inheritDoc} */ public function cleanup() { if ($this->outputFile !== null && \file_exists($this->outputFile)) { \unlink($this->outputFile); } } } PK*Z4g^^VersionUpdater/Installer.phpnuW+AtempDirectory = $tempDirectory ?: \sys_get_temp_dir(); $this->installLocation = \Phar::running(false); } /** * Public to allow the Downloader to use the temporary directory if it's been set. */ public function getTempDirectory(): string { return $this->tempDirectory; } /** * Verify the currently installed PsySH phar is writable so it can be replaced. */ public function isInstallLocationWritable(): bool { return \is_writable($this->installLocation); } /** * Verify the temporary directory is writable so downloads and backups can be saved there. */ public function isTempDirectoryWritable(): bool { return \is_writable($this->tempDirectory); } /** * Verifies the downloaded archive can be extracted with \PharData. */ public function isValidSource(string $sourceArchive): bool { if (!\class_exists('\PharData')) { return false; } $pharArchive = new \PharData($sourceArchive); return $pharArchive->valid(); } /** * Extract the "psysh" phar from the archive and move it, replacing the currently installed phar. */ public function install(string $sourceArchive): bool { $pharArchive = new \PharData($sourceArchive); $outputDirectory = \tempnam($this->tempDirectory, 'psysh-'); // remove the temp file, and replace it with a sub-directory if (!\unlink($outputDirectory) || !\mkdir($outputDirectory, 0700)) { return false; } $pharArchive->extractTo($outputDirectory, ['psysh'], true); $renamed = \rename($outputDirectory.'/psysh', $this->installLocation); // Remove the sub-directory created to extract the psysh binary/phar \rmdir($outputDirectory); return $renamed; } /** * Create a backup of the currently installed PsySH phar in the temporary directory with a version number postfix. */ public function createBackup(string $version): bool { $backupFilename = $this->getBackupFilename($version); if (\file_exists($backupFilename) && !\is_writable($backupFilename)) { return false; } return \rename($this->installLocation, $backupFilename); } /** * Restore the backup file to the original PsySH install location. * * @throws ErrorException If the backup file could not be found */ public function restoreFromBackup(string $version): bool { $backupFilename = $this->getBackupFilename($version); if (!\file_exists($backupFilename)) { throw new ErrorException("Cannot restore from backup. File not found! [{$backupFilename}]"); } return \rename($backupFilename, $this->installLocation); } /** * Get the full path for the backup target file location. */ public function getBackupFilename(string $version): string { $installFilename = \basename($this->installLocation); return \sprintf('%s/%s.%s', $this->tempDirectory, $installFilename, $version); } } PK*ZlM~~!Exception/DeprecatedException.phpnuW+Atarget = $target; parent::__construct($message, $code, $previous); } /** * @return mixed */ public function getTarget() { return $this->target; } } PK*ZT!Exception/ParseErrorException.phpnuW+A $attributes]; } parent::__construct($message, $attributes); } /** * Create a ParseErrorException from a PhpParser Error. * * @param \PhpParser\Error $e */ public static function fromParseError(\PhpParser\Error $e): self { return new self($e->getRawMessage(), $e->getAttributes()); } } PK*ZwC C Exception/ErrorException.phpnuW+ArawMessage = $message; if (!empty($filename) && \preg_match('{Psy[/\\\\]ExecutionLoop}', $filename)) { $filename = ''; } switch ($severity) { case \E_NOTICE: case \E_USER_NOTICE: $type = 'Notice'; break; case \E_WARNING: case \E_CORE_WARNING: case \E_COMPILE_WARNING: case \E_USER_WARNING: $type = 'Warning'; break; case \E_DEPRECATED: case \E_USER_DEPRECATED: $type = 'Deprecated'; break; case \E_RECOVERABLE_ERROR: $type = 'Recoverable fatal error'; break; default: if (\PHP_VERSION_ID < 80400 && $severity === \E_STRICT) { $type = 'Strict error'; break; } $type = 'Error'; break; } $message = \sprintf('PHP %s: %s%s on line %d', $type, $message, $filename ? ' in '.$filename : '', $lineno); parent::__construct($message, $code, $severity, $filename, $lineno, $previous); } /** * Get the raw (unformatted) message for this error. */ public function getRawMessage(): string { return $this->rawMessage; } /** * Helper for throwing an ErrorException. * * This allows us to: * * set_error_handler([ErrorException::class, 'throwException']); * * @throws self * * @param int $errno Error type * @param string $errstr Message * @param string $errfile Filename * @param int $errline Line number */ public static function throwException($errno, $errstr, $errfile, $errline) { throw new self($errstr, 0, $errno, $errfile, $errline); } /** * Create an ErrorException from an Error. * * @deprecated PsySH no longer wraps Errors * * @param \Error $e */ public static function fromError(\Error $e) { @\trigger_error('PsySH no longer wraps Errors', \E_USER_DEPRECATED); } } PK*Z0+qqException/Exception.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\LinesOfCode; use Throwable; interface Exception extends Throwable { } PK*Z<Exception/ThrowUpException.phpnuW+AgetMessage()); parent::__construct($message, $throwable->getCode(), $throwable); } /** * Return a raw (unformatted) version of the error message. */ public function getRawMessage(): string { return $this->getPrevious()->getMessage(); } /** * Create a ThrowUpException from a Throwable. * * @deprecated PsySH no longer wraps Throwables * * @param \Throwable $throwable */ public static function fromThrowable($throwable) { @\trigger_error('PsySH no longer wraps Throwables', \E_USER_DEPRECATED); } } PK*Z/Exception/RuntimeException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\LinesOfCode; final class RuntimeException extends \RuntimeException implements Exception { } PK*ZzNNException/BreakException.phpnuW+ArawMessage = $message; parent::__construct(\sprintf('Exit: %s', $message), $code, $previous); } /** * Return a raw (unformatted) version of the error message. */ public function getRawMessage(): string { return $this->rawMessage; } /** * Throws BreakException. * * Since `throw` can not be inserted into arbitrary expressions, it wraps with function call. * * @throws BreakException */ public static function exitShell() { throw new self('Goodbye'); } } PK*ZJ/!Exception/FatalErrorException.phpnuW+ArawMessage = $message; $message = \sprintf('PHP Fatal error: %s in %s on line %d', $message, $filename ?: "eval()'d code", $lineno); parent::__construct($message, $code, $severity, $filename, $lineno, $previous); } /** * Return a raw (unformatted) version of the error message. */ public function getRawMessage(): string { return $this->rawMessage; } } PK*ZmjSudo.phpnuW+Aproperty */ public static function fetchProperty($object, string $property) { $prop = self::getProperty(new \ReflectionObject($object), $property); return $prop->getValue($object); } /** * Assign the value of a property of an object, bypassing visibility restrictions. * * @param object $object * @param string $property property name * @param mixed $value * * @return mixed Value of $object->property */ public static function assignProperty($object, string $property, $value) { $prop = self::getProperty(new \ReflectionObject($object), $property); $prop->setValue($object, $value); return $value; } /** * Call a method on an object, bypassing visibility restrictions. * * @param object $object * @param string $method method name * @param mixed $args... * * @return mixed */ public static function callMethod($object, string $method, ...$args) { $refl = new \ReflectionObject($object); $reflMethod = $refl->getMethod($method); $reflMethod->setAccessible(true); return $reflMethod->invokeArgs($object, $args); } /** * Fetch a property of a class, bypassing visibility restrictions. * * @param string|object $class class name or instance * @param string $property property name * * @return mixed Value of $class::$property */ public static function fetchStaticProperty($class, string $property) { $prop = self::getProperty(new \ReflectionClass($class), $property); $prop->setAccessible(true); return $prop->getValue(); } /** * Assign the value of a static property of a class, bypassing visibility restrictions. * * @param string|object $class class name or instance * @param string $property property name * @param mixed $value * * @return mixed Value of $class::$property */ public static function assignStaticProperty($class, string $property, $value) { $prop = self::getProperty(new \ReflectionClass($class), $property); $refl = $prop->getDeclaringClass(); if (\method_exists($refl, 'setStaticPropertyValue')) { $refl->setStaticPropertyValue($property, $value); } else { $prop->setValue($value); } return $value; } /** * Call a static method on a class, bypassing visibility restrictions. * * @param string|object $class class name or instance * @param string $method method name * @param mixed $args... * * @return mixed */ public static function callStatic($class, string $method, ...$args) { $refl = new \ReflectionClass($class); $reflMethod = $refl->getMethod($method); $reflMethod->setAccessible(true); return $reflMethod->invokeArgs(null, $args); } /** * Fetch a class constant, bypassing visibility restrictions. * * @param string|object $class class name or instance * @param string $const constant name * * @return mixed */ public static function fetchClassConst($class, string $const) { $refl = new \ReflectionClass($class); // Special case the ::class magic constant, because `getConstant` does the wrong thing here. if ($const === 'class') { return $refl->getName(); } do { if ($refl->hasConstant($const)) { return $refl->getConstant($const); } $refl = $refl->getParentClass(); } while ($refl !== false); return false; } /** * Construct an instance of a class, bypassing private constructors. * * @param string $class class name * @param mixed $args... */ public static function newInstance(string $class, ...$args) { $refl = new \ReflectionClass($class); $instance = $refl->newInstanceWithoutConstructor(); $constructor = $refl->getConstructor(); $constructor->setAccessible(true); $constructor->invokeArgs($instance, $args); return $instance; } /** * Get a ReflectionProperty from an object (or its parent classes). * * @throws \ReflectionException if neither the object nor any of its parents has this property * * @param \ReflectionClass $refl * @param string $property property name * * @return \ReflectionProperty */ private static function getProperty(\ReflectionClass $refl, string $property): \ReflectionProperty { $firstException = null; do { try { $prop = $refl->getProperty($property); $prop->setAccessible(true); return $prop; } catch (\ReflectionException $e) { if ($firstException === null) { $firstException = $e; } $refl = $refl->getParentClass(); } } while ($refl !== false); throw $firstException; } } PK*ZuG  ExecutionClosure.phpnuW+AsetClosure($__psysh__, function () use ($__psysh__) { try { // Restore execution scope variables \extract($__psysh__->getScopeVariables(false)); // Buffer stdout; we'll need it later \ob_start([$__psysh__, 'writeStdout'], 1); // Convert all errors to exceptions \set_error_handler([$__psysh__, 'handleError']); // Evaluate the current code buffer $_ = eval($__psysh__->onExecute($__psysh__->flushCode() ?: self::NOOP_INPUT)); } catch (\Throwable $_e) { // Clean up on our way out. if (\ob_get_level() > 0) { \ob_end_clean(); } throw $_e; } finally { // Won't be needing this anymore \restore_error_handler(); } // Flush stdout (write to shell output, plus save to magic variable) \ob_end_flush(); // Save execution scope variables for next time $__psysh__->setScopeVariables(\get_defined_vars()); return $_; }); } /** * Set the closure instance. * * @param Shell $shell * @param \Closure $closure */ protected function setClosure(Shell $shell, \Closure $closure) { $that = $shell->getBoundObject(); if (\is_object($that)) { $this->closure = $closure->bindTo($that, \get_class($that)); } else { $this->closure = $closure->bindTo(null, $shell->getBoundClass()); } } /** * Go go gadget closure. * * @return mixed */ public function execute() { $closure = $this->closure; return $closure(); } } PK*Z}c"ExecutionLoop/AbstractListener.phpnuW+Aparser = (new ParserFactory())->createParser(); } /** * Reload code on input. * * @param Shell $shell * @param string $input */ public function onInput(Shell $shell, string $input) { $this->reload($shell); } /** * Look through included files and update anything with a new timestamp. * * @param Shell $shell */ private function reload(Shell $shell) { \clearstatcache(); $modified = []; foreach (\get_included_files() as $file) { $timestamp = \filemtime($file); if (!isset($this->timestamps[$file])) { $this->timestamps[$file] = $timestamp; continue; } if ($this->timestamps[$file] === $timestamp) { continue; } if (!$this->lintFile($file)) { $msg = \sprintf('Modified file "%s" could not be reloaded', $file); $shell->writeException(new ParseErrorException($msg)); continue; } $modified[] = $file; $this->timestamps[$file] = $timestamp; } // switch (count($modified)) { // case 0: // return; // case 1: // printf("Reloading modified file: \"%s\"\n", str_replace(getcwd(), '.', $file)); // break; // default: // printf("Reloading %d modified files\n", count($modified)); // break; // } foreach ($modified as $file) { $flags = ( RUNKIT_IMPORT_FUNCTIONS | RUNKIT_IMPORT_CLASSES | RUNKIT_IMPORT_CLASS_METHODS | RUNKIT_IMPORT_CLASS_CONSTS | RUNKIT_IMPORT_CLASS_PROPS | RUNKIT_IMPORT_OVERRIDE ); // these two const cannot be used with RUNKIT_IMPORT_OVERRIDE in runkit7 if (\extension_loaded('runkit7')) { $flags &= ~RUNKIT_IMPORT_CLASS_PROPS & ~RUNKIT_IMPORT_CLASS_STATIC_PROPS; runkit7_import($file, $flags); } else { runkit_import($file, $flags); } } } /** * Should this file be re-imported? * * Use PHP-Parser to ensure that the file is valid PHP. * * @param string $file */ private function lintFile(string $file): bool { // first try to parse it try { $this->parser->parse(\file_get_contents($file)); } catch (\Throwable $e) { return false; } return true; } } PK*Z0^^!^!ExecutionLoop/ProcessForker.phpnuW+A 0) { // This is the main thread. We'll just wait for a while. // We won't be needing this one. \fclose($up); // Wait for a return value from the loop process. $read = [$down]; $write = null; $except = null; do { $n = @\stream_select($read, $write, $except, null); if ($n === 0) { throw new \RuntimeException('Process timed out waiting for execution loop'); } if ($n === false) { $err = \error_get_last(); if (!isset($err['message']) || \stripos($err['message'], 'interrupted system call') === false) { $msg = $err['message'] ? \sprintf('Error waiting for execution loop: %s', $err['message']) : 'Error waiting for execution loop'; throw new \RuntimeException($msg); } } } while ($n < 1); $content = \stream_get_contents($down); \fclose($down); if ($content) { $shell->setScopeVariables(@\unserialize($content)); } throw new BreakException('Exiting main thread'); } // This is the child process. It's going to do all the work. if (!@\cli_set_process_title('psysh (loop)')) { // Fall back to `setproctitle` if that wasn't succesful. if (\function_exists('setproctitle')) { @\setproctitle('psysh (loop)'); } } // We won't be needing this one. \fclose($down); // Save this; we'll need to close it in `afterRun` $this->up = $up; } /** * Create a savegame at the start of each loop iteration. * * @param Shell $shell */ public function beforeLoop(Shell $shell) { $this->createSavegame(); } /** * Clean up old savegames at the end of each loop iteration. * * @param Shell $shell */ public function afterLoop(Shell $shell) { // if there's an old savegame hanging around, let's kill it. if (isset($this->savegame)) { \posix_kill($this->savegame, \SIGKILL); \pcntl_signal_dispatch(); } } /** * After the REPL session ends, send the scope variables back up to the main * thread (if this is a child thread). * * @param Shell $shell */ public function afterRun(Shell $shell) { // We're a child thread. Send the scope variables back up to the main thread. if (isset($this->up)) { \fwrite($this->up, $this->serializeReturn($shell->getScopeVariables(false))); \fclose($this->up); \posix_kill(\posix_getpid(), \SIGKILL); } } /** * Create a savegame fork. * * The savegame contains the current execution state, and can be resumed in * the event that the worker dies unexpectedly (for example, by encountering * a PHP fatal error). */ private function createSavegame() { // the current process will become the savegame $this->savegame = \posix_getpid(); $pid = \pcntl_fork(); if ($pid < 0) { throw new \RuntimeException('Unable to create savegame fork'); } elseif ($pid > 0) { // we're the savegame now... let's wait and see what happens \pcntl_waitpid($pid, $status); // worker exited cleanly, let's bail if (!\pcntl_wexitstatus($status)) { \posix_kill(\posix_getpid(), \SIGKILL); } // worker didn't exit cleanly, we'll need to have another go $this->createSavegame(); } } /** * Serialize all serializable return values. * * A naïve serialization will run into issues if there is a Closure or * SimpleXMLElement (among other things) in scope when exiting the execution * loop. We'll just ignore these unserializable classes, and serialize what * we can. * * @param array $return */ private function serializeReturn(array $return): string { $serializable = []; foreach ($return as $key => $value) { // No need to return magic variables if (Context::isSpecialVariableName($key)) { continue; } // Resources and Closures don't error, but they don't serialize well either. if (\is_resource($value) || $value instanceof \Closure) { continue; } if (\version_compare(\PHP_VERSION, '8.1', '>=') && $value instanceof \UnitEnum) { // Enums defined in the REPL session can't be unserialized. $ref = new \ReflectionObject($value); if (\strpos($ref->getFileName(), ": eval()'d code") !== false) { continue; } } try { @\serialize($value); $serializable[$key] = $value; } catch (\Throwable $e) { // we'll just ignore this one... } } return @\serialize($serializable); } } PK*ZO,**ExecutionLoop/Listener.phpnuW+AhistoryFile === false) { return []; } $history = \file_get_contents($this->historyFile); if (!$history) { return []; } // libedit doesn't seem to support non-unix line separators. $history = \explode("\n", $history); // remove history signature if it exists if ($history[0] === '_HiStOrY_V2_') { \array_shift($history); } // decode the line $history = \array_map([$this, 'parseHistoryLine'], $history); // filter empty lines & comments return \array_values(\array_filter($history)); } /** * {@inheritdoc} */ public function writeHistory(): bool { $res = parent::writeHistory(); // Libedit apparently refuses to save history if the history file is not // owned by the user, even if it is writable. Warn when this happens. // // See https://github.com/bobthecow/psysh/issues/552 if ($res === false && !$this->hasWarnedOwnership) { if (\is_file($this->historyFile) && \is_writable($this->historyFile)) { $this->hasWarnedOwnership = true; $msg = \sprintf('Error writing history file, check file ownership: %s', $this->historyFile); \trigger_error($msg, \E_USER_NOTICE); } } return $res; } /** * From GNUReadline (readline/histfile.c & readline/histexpand.c): * lines starting with "\0" are comments or timestamps; * if "\0" is found in an entry, * everything from it until the next line is a comment. * * @param string $line The history line to parse * * @return string|null */ protected function parseHistoryLine(string $line) { // empty line, comment or timestamp if (!$line || $line[0] === "\0") { return; } // if "\0" is found in an entry, then // everything from it until the end of line is a comment. if (($pos = \strpos($line, "\0")) !== false) { $line = \substr($line, 0, $pos); } return ($line !== '') ? Str::unvis($line) : null; } } PK*Z1&((Readline/GNUReadline.phpnuW+AhistoryFile = ($historyFile !== null) ? $historyFile : false; $this->historySize = $historySize; $this->eraseDups = $eraseDups; \readline_info('readline_name', 'psysh'); } /** * {@inheritdoc} */ public function addHistory(string $line): bool { if ($res = \readline_add_history($line)) { $this->writeHistory(); } return $res; } /** * {@inheritdoc} */ public function clearHistory(): bool { if ($res = \readline_clear_history()) { $this->writeHistory(); } return $res; } /** * {@inheritdoc} */ public function listHistory(): array { return \readline_list_history(); } /** * {@inheritdoc} */ public function readHistory(): bool { \readline_read_history(); \readline_clear_history(); return \readline_read_history($this->historyFile); } /** * {@inheritdoc} */ public function readline(?string $prompt = null) { return \readline($prompt); } /** * {@inheritdoc} */ public function redisplay() { \readline_redisplay(); } /** * {@inheritdoc} */ public function writeHistory(): bool { // We have to write history first, since it is used // by Libedit to list history if ($this->historyFile !== false) { $res = \readline_write_history($this->historyFile); } else { $res = true; } if (!$res || !$this->eraseDups && !$this->historySize > 0) { return $res; } $hist = $this->listHistory(); if (!$hist) { return true; } if ($this->eraseDups) { // flip-flip technique: removes duplicates, latest entries win. $hist = \array_flip(\array_flip($hist)); // sort on keys to get the order back \ksort($hist); } if ($this->historySize > 0) { $histsize = \count($hist); if ($histsize > $this->historySize) { $hist = \array_slice($hist, $histsize - $this->historySize); } } \readline_clear_history(); foreach ($hist as $line) { \readline_add_history($line); } if ($this->historyFile !== false) { return \readline_write_history($this->historyFile); } return true; } } PK*Z#g((Readline/Readline.phpnuW+A_input = $input; return; } /** * Get underlying stream. */ public function getStream(): StreamIn { return $this->_input; } /** * Test for end-of-file. */ public function eof(): bool { return $this->_input->eof(); } /** * Read n characters. */ public function read(int $length) { return $this->_input->read($length); } /** * Alias of $this->read(). */ public function readString(int $length) { return $this->_input->readString($length); } /** * Read a character. */ public function readCharacter() { return $this->_input->readCharacter(); } /** * Read a boolean. */ public function readBoolean() { return $this->_input->readBoolean(); } /** * Read an integer. */ public function readInteger(int $length = 1) { return $this->_input->readInteger($length); } /** * Read a float. */ public function readFloat(int $length = 1) { return $this->_input->readFloat($length); } /** * Read an array. * Alias of the $this->scanf() method. */ public function readArray($argument = null) { return $this->_input->readArray($argument); } /** * Read a line. */ public function readLine() { return $this->_input->readLine(); } /** * Read all, i.e. read as much as possible. */ public function readAll(int $offset = 0) { return $this->_input->readAll($offset); } /** * Parse input from a stream according to a format. */ public function scanf(string $format): array { return $this->_input->scanf($format); } } PK*Z:]QQ!Readline/Hoa/ConsoleProcessus.phpnuW+A value, or input). */ protected $_options = []; /** * Current working directory. */ protected $_cwd = null; /** * Environment. */ protected $_environment = null; /** * Timeout. */ protected $_timeout = 30; /** * Descriptor. */ protected $_descriptors = [ 0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w'], ]; /** * Pipe descriptors of the processus. */ protected $_pipes = null; /** * Seekability of pipes. */ protected $_seekable = []; /** * Start a processus. */ public function __construct( string $command, ?array $options = null, ?array $descriptors = null, ?string $cwd = null, ?array $environment = null, int $timeout = 30 ) { $this->setCommand($command); if (null !== $options) { $this->setOptions($options); } if (null !== $descriptors) { $this->_descriptors = []; foreach ($descriptors as $descriptor => $nature) { if (isset($this->_descriptors[$descriptor])) { throw new ConsoleException('Pipe descriptor %d already exists, cannot '.'redefine it.', 0, $descriptor); } $this->_descriptors[$descriptor] = $nature; } } $this->setCwd($cwd ?: \getcwd()); if (null !== $environment) { $this->setEnvironment($environment); } $this->setTimeout($timeout); parent::__construct($this->getCommandLine(), null, true); $this->getListener()->addIds(['input', 'output', 'timeout', 'start', 'stop']); return; } /** * Open the stream and return the associated resource. */ protected function &_open(string $streamName, ?StreamContext $context = null) { $out = @\proc_open( $streamName, $this->_descriptors, $this->_pipes, $this->getCwd(), $this->getEnvironment() ); if (false === $out) { throw new ConsoleException('Something wrong happen when running %s.', 1, $streamName); } return $out; } /** * Close the current stream. */ protected function _close(): bool { foreach ($this->_pipes as $pipe) { @\fclose($pipe); } return (bool) @\proc_close($this->getStream()); } /** * Run the process and fire events (amongst start, stop, input, output and * timeout). * If an event returns false, it will close the current pipe. * For a simple run without firing events, use the $this->open() method. */ public function run() { if (false === $this->isOpened()) { $this->open(); } else { $this->_close(); $this->_setStream($this->_open( $this->getStreamName(), $this->getStreamContext() )); } $this->getListener()->fire('start', new EventBucket()); $_read = []; $_write = []; $_except = []; foreach ($this->_pipes as $p => $pipe) { switch ($this->_descriptors[$p][1]) { case 'r': \stream_set_blocking($pipe, false); $_write[] = $pipe; break; case 'w': case 'a': \stream_set_blocking($pipe, true); $_read[] = $pipe; break; } } while (true) { foreach ($_read as $i => $r) { if (false === \is_resource($r)) { unset($_read[$i]); } } foreach ($_write as $i => $w) { if (false === \is_resource($w)) { unset($_write[$i]); } } foreach ($_except as $i => $e) { if (false === \is_resource($e)) { unset($_except[$i]); } } if (empty($_read) && empty($_write) && empty($_except)) { break; } $read = $_read; $write = $_write; $except = $_except; $select = \stream_select($read, $write, $except, $this->getTimeout()); if (0 === $select) { $this->getListener()->fire('timeout', new EventBucket()); break; } foreach ($read as $i => $_r) { $pipe = \array_search($_r, $this->_pipes); $line = $this->readLine($pipe); if (false === $line) { $result = [false]; } else { $result = $this->getListener()->fire( 'output', new EventBucket([ 'pipe' => $pipe, 'line' => $line, ]) ); } if (true === \feof($_r) || \in_array(false, $result, true)) { \fclose($_r); unset($_read[$i]); break; } } foreach ($write as $j => $_w) { $result = $this->getListener()->fire( 'input', new EventBucket([ 'pipe' => \array_search($_w, $this->_pipes), ]) ); if (true === \feof($_w) || \in_array(false, $result, true)) { \fclose($_w); unset($_write[$j]); } } if (empty($_read)) { break; } } $this->getListener()->fire('stop', new EventBucket()); return; } /** * Get pipe resource. */ protected function getPipe(int $pipe) { if (!isset($this->_pipes[$pipe])) { throw new ConsoleException('Pipe descriptor %d does not exist, cannot read from it.', 2, $pipe); } return $this->_pipes[$pipe]; } /** * Check if a pipe is seekable or not. */ protected function isPipeSeekable(int $pipe): bool { if (!isset($this->_seekable[$pipe])) { $_pipe = $this->getPipe($pipe); $data = \stream_get_meta_data($_pipe); $this->_seekable[$pipe] = $data['seekable']; } return $this->_seekable[$pipe]; } /** * Test for end-of-file. */ public function eof(int $pipe = 1): bool { return \feof($this->getPipe($pipe)); } /** * Read n characters. */ public function read(int $length, int $pipe = 1) { if (0 > $length) { throw new ConsoleException('Length must be greater than 0, given %d.', 3, $length); } return \fread($this->getPipe($pipe), $length); } /** * Alias of $this->read(). */ public function readString(int $length, int $pipe = 1) { return $this->read($length, $pipe); } /** * Read a character. */ public function readCharacter(int $pipe = 1) { return \fgetc($this->getPipe($pipe)); } /** * Read a boolean. */ public function readBoolean(int $pipe = 1) { return (bool) $this->read(1, $pipe); } /** * Read an integer. */ public function readInteger(int $length = 1, int $pipe = 1) { return (int) $this->read($length, $pipe); } /** * Read a float. */ public function readFloat(int $length = 1, int $pipe = 1) { return (float) $this->read($length, $pipe); } /** * Read an array. * Alias of the $this->scanf() method. */ public function readArray(?string $format = null, int $pipe = 1) { return $this->scanf($format, $pipe); } /** * Read a line. */ public function readLine(int $pipe = 1) { return \stream_get_line($this->getPipe($pipe), 1 << 15, "\n"); } /** * Read all, i.e. read as much as possible. */ public function readAll(int $offset = -1, int $pipe = 1) { $_pipe = $this->getPipe($pipe); if (true === $this->isPipeSeekable($pipe)) { $offset += \ftell($_pipe); } else { $offset = -1; } return \stream_get_contents($_pipe, -1, $offset); } /** * Parse input from a stream according to a format. */ public function scanf(string $format, int $pipe = 1): array { return \fscanf($this->getPipe($pipe), $format); } /** * Write n characters. */ public function write(string $string, int $length, int $pipe = 0) { if (0 > $length) { throw new ConsoleException('Length must be greater than 0, given %d.', 4, $length); } return \fwrite($this->getPipe($pipe), $string, $length); } /** * Write a string. */ public function writeString(string $string, int $pipe = 0) { $string = (string) $string; return $this->write($string, \strlen($string), $pipe); } /** * Write a character. */ public function writeCharacter(string $char, int $pipe = 0) { return $this->write((string) $char[0], 1, $pipe); } /** * Write a boolean. */ public function writeBoolean(bool $boolean, int $pipe = 0) { return $this->write((string) (bool) $boolean, 1, $pipe); } /** * Write an integer. */ public function writeInteger(int $integer, int $pipe = 0) { $integer = (string) (int) $integer; return $this->write($integer, \strlen($integer), $pipe); } /** * Write a float. */ public function writeFloat(float $float, int $pipe = 0) { $float = (string) (float) $float; return $this->write($float, \strlen($float), $pipe); } /** * Write an array. */ public function writeArray(array $array, int $pipe = 0) { $array = \var_export($array, true); return $this->write($array, \strlen($array), $pipe); } /** * Write a line. */ public function writeLine(string $line, int $pipe = 0) { if (false === $n = \strpos($line, "\n")) { return $this->write($line."\n", \strlen($line) + 1, $pipe); } ++$n; return $this->write(\substr($line, 0, $n), $n, $pipe); } /** * Write all, i.e. as much as possible. */ public function writeAll(string $string, int $pipe = 0) { return $this->write($string, \strlen($string), $pipe); } /** * Truncate a file to a given length. */ public function truncate(int $size, int $pipe = 0): bool { return \ftruncate($this->getPipe($pipe), $size); } /** * Get filename component of path. */ public function getBasename(): string { return \basename($this->getCommand()); } /** * Get directory name component of path. */ public function getDirname(): string { return \dirname($this->getCommand()); } /** * Get status. */ public function getStatus(): array { return \proc_get_status($this->getStream()); } /** * Get exit code (alias of $this->getStatus()['exitcode']);. */ public function getExitCode(): int { $handle = $this->getStatus(); return $handle['exitcode']; } /** * Whether the processus have ended successfully. * * @return bool */ public function isSuccessful(): bool { return 0 === $this->getExitCode(); } /** * Terminate the process. * * Valid signals are self::SIGHUP, SIGINT, SIGQUIT, SIGABRT, SIGKILL, * SIGALRM and SIGTERM. */ public function terminate(int $signal = self::SIGTERM): bool { return \proc_terminate($this->getStream(), $signal); } /** * Set command name. */ protected function setCommand(string $command) { $old = $this->_command; $this->_command = \escapeshellcmd($command); return $old; } /** * Get command name. */ public function getCommand() { return $this->_command; } /** * Set command options. */ protected function setOptions(array $options): array { foreach ($options as &$option) { $option = \escapeshellarg($option); } $old = $this->_options; $this->_options = $options; return $old; } /** * Get options. */ public function getOptions(): array { return $this->_options; } /** * Get command-line. */ public function getCommandLine(): string { $out = $this->getCommand(); foreach ($this->getOptions() as $key => $value) { if (!\is_int($key)) { $out .= ' '.$key.'='.$value; } else { $out .= ' '.$value; } } return $out; } /** * Set current working directory of the process. */ protected function setCwd(string $cwd) { $old = $this->_cwd; $this->_cwd = $cwd; return $old; } /** * Get current working directory of the process. */ public function getCwd(): string { return $this->_cwd; } /** * Set environment of the process. */ protected function setEnvironment(array $environment) { $old = $this->_environment; $this->_environment = $environment; return $old; } /** * Get environment of the process. */ public function getEnvironment() { return $this->_environment; } /** * Set timeout of the process. */ public function setTimeout(int $timeout) { $old = $this->_timeout; $this->_timeout = $timeout; return $old; } /** * Get timeout of the process. */ public function getTimeout(): int { return $this->_timeout; } /** * Set process title. */ public static function setTitle(string $title) { \cli_set_process_title($title); } /** * Get process title. */ public static function getTitle() { return \cli_get_process_title(); } /** * Found the place of a binary. */ public static function locate(string $binary) { if (isset($_ENV['PATH'])) { $separator = ':'; $path = &$_ENV['PATH']; } elseif (isset($_SERVER['PATH'])) { $separator = ':'; $path = &$_SERVER['PATH']; } elseif (isset($_SERVER['Path'])) { $separator = ';'; $path = &$_SERVER['Path']; } else { return null; } foreach (\explode($separator, $path) as $directory) { if (true === \file_exists($out = $directory.\DIRECTORY_SEPARATOR.$binary)) { return $out; } } return null; } /** * Quick process execution. * Returns only the STDOUT. */ public static function execute(string $commandLine, bool $escape = true): string { if (true === $escape) { $commandLine = \escapeshellcmd($commandLine); } return \rtrim(\shell_exec($commandLine) ?? ''); } } PK*Z;)Readline/Hoa/Event.phpnuW+A new self(), self::KEY_SOURCE => null, ]; } return self::$_register[$eventId][self::KEY_EVENT]; } /** * Declares a new object in the observable collection. * Note: Hoa's libraries use `hoa://Event/anID` for their observable objects. */ public static function register(string $eventId, /* Source|string */ $source) { if (true === self::eventExists($eventId)) { throw new EventException('Cannot redeclare an event with the same ID, i.e. the event '.'ID %s already exists.', 0, $eventId); } if (\is_object($source) && !($source instanceof EventSource)) { throw new EventException('The source must implement \Hoa\Event\Source '.'interface; given %s.', 1, \get_class($source)); } else { $reflection = new \ReflectionClass($source); if (false === $reflection->implementsInterface('\Psy\Readline\Hoa\EventSource')) { throw new EventException('The source must implement \Hoa\Event\Source '.'interface; given %s.', 2, $source); } } if (!isset(self::$_register[$eventId][self::KEY_EVENT])) { self::$_register[$eventId][self::KEY_EVENT] = new self(); } self::$_register[$eventId][self::KEY_SOURCE] = $source; } /** * Undeclares an object in the observable collection. * * If `$hard` is set to `true, then the source and its attached callables * will be deleted. */ public static function unregister(string $eventId, bool $hard = false) { if (false !== $hard) { unset(self::$_register[$eventId]); } else { self::$_register[$eventId][self::KEY_SOURCE] = null; } } /** * Attach an object to an event. * * It can be a callable or an accepted callable form (please, see the * `Hoa\Consistency\Xcallable` class). */ public function attach($callable): self { $callable = Xcallable::from($callable); $this->_callable[$callable->getHash()] = $callable; return $this; } /** * Detaches an object to an event. * * Please see `self::attach` method. */ public function detach($callable): self { unset($this->_callable[Xcallable::from($callable)->getHash()]); return $this; } /** * Checks if at least one callable is attached to an event. */ public function isListened(): bool { return !empty($this->_callable); } /** * Notifies, i.e. send data to observers. */ public static function notify(string $eventId, EventSource $source, EventBucket $data) { if (false === self::eventExists($eventId)) { throw new EventException('Event ID %s does not exist, cannot send notification.', 3, $eventId); } $data->setSource($source); $event = self::getEvent($eventId); foreach ($event->_callable as $callable) { $callable($data); } } /** * Checks whether an event exists. */ public static function eventExists(string $eventId): bool { return \array_key_exists($eventId, self::$_register) && self::$_register[$eventId][self::KEY_SOURCE] !== null; } } PK*Zl+H+ Readline/Hoa/EventListenable.phpnuW+A_source = $source; $this->addIds($ids); return; } /** * Adds acceptable ID (or reset). */ public function addIds(array $ids) { foreach ($ids as $id) { $this->_callables[$id] = []; } } /** * Attaches a callable to a listenable component. */ public function attach(string $listenerId, $callable): self { if (false === $this->listenerExists($listenerId)) { throw new EventException('Cannot listen %s because it is not defined.', 0, $listenerId); } $callable = Xcallable::from($callable); $this->_callables[$listenerId][$callable->getHash()] = $callable; return $this; } /** * Detaches a callable from a listenable component. */ public function detach(string $listenerId, $callable): self { unset($this->_callables[$listenerId][Xcallable::from($callable)->getHash()]); return $this; } /** * Detaches all callables from a listenable component. */ public function detachAll(string $listenerId): self { unset($this->_callables[$listenerId]); return $this; } /** * Checks if a listener exists. */ public function listenerExists(string $listenerId): bool { return \array_key_exists($listenerId, $this->_callables); } /** * Sends/fires a bucket to a listener. */ public function fire(string $listenerId, EventBucket $data): array { if (false === $this->listenerExists($listenerId)) { throw new EventException('Cannot fire on %s because it is not defined.', 1, $listenerId); } $data->setSource($this->_source); $out = []; foreach ($this->_callables[$listenerId] as $callable) { $out[] = $callable($data); } return $out; } } PK*Zu--Readline/Hoa/StreamContext.phpnuW+A_id = $id; $this->_context = \stream_context_create(); return; } /** * Multiton. */ public static function getInstance(string $id): self { if (false === static::contextExists($id)) { static::$_instances[$id] = new self($id); } return static::$_instances[$id]; } /** * Get context ID. */ public function getId(): string { return $this->_id; } /** * Check if a context exists. */ public static function contextExists(string $id): bool { return \array_key_exists($id, static::$_instances); } /** * Set options. * Please, see http://php.net/context. */ public function setOptions(array $options): bool { return \stream_context_set_option($this->getContext(), $options); } /** * Set parameters. * Please, see http://php.net/context.params. */ public function setParameters(array $parameters): bool { return \stream_context_set_params($this->getContext(), $parameters); } /** * Get options. */ public function getOptions(): array { return \stream_context_get_options($this->getContext()); } /** * Get parameters. */ public function getParameters(): array { return \stream_context_get_params($this->getContext()); } /** * Get context as a resource. */ public function getContext() { return $this->_context; } } PK*Z\) 55Readline/Hoa/FileException.phpnuW+A $repeat) { return; } elseif (1 === $repeat) { $handle = \explode(' ', $steps); } else { $handle = \explode(' ', $steps, 1); } $tput = Console::getTput(); $output = Console::getOutput(); foreach ($handle as $step) { switch ($step) { case 'u': case 'up': case '↑': $output->writeAll( \str_replace( '%p1%d', $repeat, $tput->get('parm_up_cursor') ) ); break; case 'U': case 'UP': static::moveTo(null, 1); break; case 'r': case 'right': case '→': $output->writeAll( \str_replace( '%p1%d', $repeat, $tput->get('parm_right_cursor') ) ); break; case 'R': case 'RIGHT': static::moveTo(9999); break; case 'd': case 'down': case '↓': $output->writeAll( \str_replace( '%p1%d', $repeat, $tput->get('parm_down_cursor') ) ); break; case 'D': case 'DOWN': static::moveTo(null, 9999); break; case 'l': case 'left': case '←': $output->writeAll( \str_replace( '%p1%d', $repeat, $tput->get('parm_left_cursor') ) ); break; case 'L': case 'LEFT': static::moveTo(1); break; } } } /** * Move to the line X and the column Y. * If null, use the current coordinate. */ public static function moveTo(?int $x = null, ?int $y = null) { if (null === $x || null === $y) { $position = static::getPosition(); if (null === $x) { $x = $position['x']; } if (null === $y) { $y = $position['y']; } } Console::getOutput()->writeAll( \str_replace( ['%i%p1%d', '%p2%d'], [$y, $x], Console::getTput()->get('cursor_address') ) ); } /** * Get current position (x and y) of the cursor. */ public static function getPosition(): array { $tput = Console::getTput(); $user7 = $tput->get('user7'); if (null === $user7) { return [ 'x' => 0, 'y' => 0, ]; } Console::getOutput()->writeAll($user7); $input = Console::getInput(); // Read $tput->get('user6'). $input->read(2); // skip \033 and [. $x = null; $y = null; $handle = &$y; while (true) { $char = $input->readCharacter(); switch ($char) { case ';': $handle = &$x; break; case 'R': break 2; default: $handle .= $char; } } return [ 'x' => (int) $x, 'y' => (int) $y, ]; } /** * Save current position. */ public static function save() { Console::getOutput()->writeAll( Console::getTput()->get('save_cursor') ); } /** * Restore cursor to the last saved position. */ public static function restore() { Console::getOutput()->writeAll( Console::getTput()->get('restore_cursor') ); } /** * Clear the screen. * Part can be: * • a, all, ↕ : clear entire screen and static::move(1, 1); * • u, up, ↑ : clear from cursor to beginning of the screen; * • r, right, → : clear from cursor to the end of the line; * • d, down, ↓ : clear from cursor to end of the screen; * • l, left, ← : clear from cursor to beginning of the screen; * • line, ↔ : clear all the line and static::move(1). * Parts can be concatenated by a single space. */ public static function clear(string $parts = 'all') { $tput = Console::getTput(); $output = Console::getOutput(); foreach (\explode(' ', $parts) as $part) { switch ($part) { case 'a': case 'all': case '↕': $output->writeAll($tput->get('clear_screen')); static::moveTo(1, 1); break; case 'u': case 'up': case '↑': $output->writeAll("\033[1J"); break; case 'r': case 'right': case '→': $output->writeAll($tput->get('clr_eol')); break; case 'd': case 'down': case '↓': $output->writeAll($tput->get('clr_eos')); break; case 'l': case 'left': case '←': $output->writeAll($tput->get('clr_bol')); break; case 'line': case '↔': $output->writeAll("\r".$tput->get('clr_eol')); break; } } } /** * Hide the cursor. */ public static function hide() { Console::getOutput()->writeAll( Console::getTput()->get('cursor_invisible') ); } /** * Show the cursor. */ public static function show() { Console::getOutput()->writeAll( Console::getTput()->get('cursor_visible') ); } /** * Colorize cursor. * Attributes can be: * • n, normal : normal; * • b, bold : bold; * • u, underlined : underlined; * • bl, blink : blink; * • i, inverse : inverse; * • !b, !bold : normal weight; * • !u, !underlined : not underlined; * • !bl, !blink : steady; * • !i, !inverse : positive; * • fg(color), foreground(color) : set foreground to “color”; * • bg(color), background(color) : set background to “color”. * “color” can be: * • default; * • black; * • red; * • green; * • yellow; * • blue; * • magenta; * • cyan; * • white; * • 0-256 (classic palette); * • #hexa. * Attributes can be concatenated by a single space. */ public static function colorize(string $attributes) { static $_rgbTo256 = null; if (null === $_rgbTo256) { $_rgbTo256 = [ '000000', '800000', '008000', '808000', '000080', '800080', '008080', 'c0c0c0', '808080', 'ff0000', '00ff00', 'ffff00', '0000ff', 'ff00ff', '00ffff', 'ffffff', '000000', '00005f', '000087', '0000af', '0000d7', '0000ff', '005f00', '005f5f', '005f87', '005faf', '005fd7', '005fff', '008700', '00875f', '008787', '0087af', '0087d7', '0087ff', '00af00', '00af5f', '00af87', '00afaf', '00afd7', '00afff', '00d700', '00d75f', '00d787', '00d7af', '00d7d7', '00d7ff', '00ff00', '00ff5f', '00ff87', '00ffaf', '00ffd7', '00ffff', '5f0000', '5f005f', '5f0087', '5f00af', '5f00d7', '5f00ff', '5f5f00', '5f5f5f', '5f5f87', '5f5faf', '5f5fd7', '5f5fff', '5f8700', '5f875f', '5f8787', '5f87af', '5f87d7', '5f87ff', '5faf00', '5faf5f', '5faf87', '5fafaf', '5fafd7', '5fafff', '5fd700', '5fd75f', '5fd787', '5fd7af', '5fd7d7', '5fd7ff', '5fff00', '5fff5f', '5fff87', '5fffaf', '5fffd7', '5fffff', '870000', '87005f', '870087', '8700af', '8700d7', '8700ff', '875f00', '875f5f', '875f87', '875faf', '875fd7', '875fff', '878700', '87875f', '878787', '8787af', '8787d7', '8787ff', '87af00', '87af5f', '87af87', '87afaf', '87afd7', '87afff', '87d700', '87d75f', '87d787', '87d7af', '87d7d7', '87d7ff', '87ff00', '87ff5f', '87ff87', '87ffaf', '87ffd7', '87ffff', 'af0000', 'af005f', 'af0087', 'af00af', 'af00d7', 'af00ff', 'af5f00', 'af5f5f', 'af5f87', 'af5faf', 'af5fd7', 'af5fff', 'af8700', 'af875f', 'af8787', 'af87af', 'af87d7', 'af87ff', 'afaf00', 'afaf5f', 'afaf87', 'afafaf', 'afafd7', 'afafff', 'afd700', 'afd75f', 'afd787', 'afd7af', 'afd7d7', 'afd7ff', 'afff00', 'afff5f', 'afff87', 'afffaf', 'afffd7', 'afffff', 'd70000', 'd7005f', 'd70087', 'd700af', 'd700d7', 'd700ff', 'd75f00', 'd75f5f', 'd75f87', 'd75faf', 'd75fd7', 'd75fff', 'd78700', 'd7875f', 'd78787', 'd787af', 'd787d7', 'd787ff', 'd7af00', 'd7af5f', 'd7af87', 'd7afaf', 'd7afd7', 'd7afff', 'd7d700', 'd7d75f', 'd7d787', 'd7d7af', 'd7d7d7', 'd7d7ff', 'd7ff00', 'd7ff5f', 'd7ff87', 'd7ffaf', 'd7ffd7', 'd7ffff', 'ff0000', 'ff005f', 'ff0087', 'ff00af', 'ff00d7', 'ff00ff', 'ff5f00', 'ff5f5f', 'ff5f87', 'ff5faf', 'ff5fd7', 'ff5fff', 'ff8700', 'ff875f', 'ff8787', 'ff87af', 'ff87d7', 'ff87ff', 'ffaf00', 'ffaf5f', 'ffaf87', 'ffafaf', 'ffafd7', 'ffafff', 'ffd700', 'ffd75f', 'ffd787', 'ffd7af', 'ffd7d7', 'ffd7ff', 'ffff00', 'ffff5f', 'ffff87', 'ffffaf', 'ffffd7', 'ffffff', '080808', '121212', '1c1c1c', '262626', '303030', '3a3a3a', '444444', '4e4e4e', '585858', '606060', '666666', '767676', '808080', '8a8a8a', '949494', '9e9e9e', 'a8a8a8', 'b2b2b2', 'bcbcbc', 'c6c6c6', 'd0d0d0', 'dadada', 'e4e4e4', 'eeeeee', ]; } $tput = Console::getTput(); if (1 >= $tput->count('max_colors')) { return; } $handle = []; foreach (\explode(' ', $attributes) as $attribute) { switch ($attribute) { case 'n': case 'normal': $handle[] = 0; break; case 'b': case 'bold': $handle[] = 1; break; case 'u': case 'underlined': $handle[] = 4; break; case 'bl': case 'blink': $handle[] = 5; break; case 'i': case 'inverse': $handle[] = 7; break; case '!b': case '!bold': $handle[] = 22; break; case '!u': case '!underlined': $handle[] = 24; break; case '!bl': case '!blink': $handle[] = 25; break; case '!i': case '!inverse': $handle[] = 27; break; default: if (0 === \preg_match('#^([^\(]+)\(([^\)]+)\)$#', $attribute, $m)) { break; } $shift = 0; switch ($m[1]) { case 'fg': case 'foreground': $shift = 0; break; case 'bg': case 'background': $shift = 10; break; default: break 2; } $_handle = 0; $_keyword = true; switch ($m[2]) { case 'black': $_handle = 30; break; case 'red': $_handle = 31; break; case 'green': $_handle = 32; break; case 'yellow': $_handle = 33; break; case 'blue': $_handle = 34; break; case 'magenta': $_handle = 35; break; case 'cyan': $_handle = 36; break; case 'white': $_handle = 37; break; case 'default': $_handle = 39; break; default: $_keyword = false; if (256 <= $tput->count('max_colors') && '#' === $m[2][0]) { $rgb = \hexdec(\substr($m[2], 1)); $r = ($rgb >> 16) & 255; $g = ($rgb >> 8) & 255; $b = $rgb & 255; $distance = null; foreach ($_rgbTo256 as $i => $_rgb) { $_rgb = \hexdec($_rgb); $_r = ($_rgb >> 16) & 255; $_g = ($_rgb >> 8) & 255; $_b = $_rgb & 255; $d = \sqrt( ($_r - $r) ** 2 + ($_g - $g) ** 2 + ($_b - $b) ** 2 ); if (null === $distance || $d <= $distance) { $distance = $d; $_handle = $i; } } } else { $_handle = (int) ($m[2]); } } if (true === $_keyword) { $handle[] = $_handle + $shift; } else { $handle[] = (38 + $shift).';5;'.$_handle; } } } Console::getOutput()->writeAll("\033[".\implode(';', $handle).'m'); return; } /** * Change color number to a specific RGB color. */ public static function changeColor(int $fromCode, int $toColor) { $tput = Console::getTput(); if (true !== $tput->has('can_change')) { return; } $r = ($toColor >> 16) & 255; $g = ($toColor >> 8) & 255; $b = $toColor & 255; Console::getOutput()->writeAll( \str_replace( [ '%p1%d', 'rgb:', '%p2%{255}%*%{1000}%/%2.2X/', '%p3%{255}%*%{1000}%/%2.2X/', '%p4%{255}%*%{1000}%/%2.2X', ], [ $fromCode, '', \sprintf('%02x', $r), \sprintf('%02x', $g), \sprintf('%02x', $b), ], $tput->get('initialize_color') ) ); return; } /** * Set cursor style. * Style can be: * • b, block, ▋: block; * • u, underline, _: underline; * • v, vertical, |: vertical. */ public static function setStyle(string $style, bool $blink = true) { if (\defined('PHP_WINDOWS_VERSION_PLATFORM')) { return; } switch ($style) { case 'u': case 'underline': case '_': $_style = 2; break; case 'v': case 'vertical': case '|': $_style = 5; break; case 'b': case 'block': case '▋': default: $_style = 1; break; } if (false === $blink) { ++$_style; } // Not sure what tput entry we can use here… Console::getOutput()->writeAll("\033[".$_style.' q'); return; } /** * Make a stupid “bip”. */ public static function bip() { Console::getOutput()->writeAll( Console::getTput()->get('bell') ); } } /* * Advanced interaction. */ Console::advancedInteraction(); PK*Zz $Readline/Hoa/IteratorSplFileInfo.phpnuW+AgetMTime()) { $this->_hash = \md5($this->getPathname().$mtime); } $this->_relativePath = $relativePath; return; } /** * Get the hash. */ public function getHash(): string { return $this->_hash; } /** * Get the MTime. */ public function getMTime(): int { try { return parent::getMTime(); } catch (\RuntimeException $e) { return -1; } } /** * Set relative path. */ public function setRelativePath(string $relativePath) { $old = $this->_relativePath; $this->_relativePath = $relativePath; return $old; } /** * Get relative path (if given). */ public function getRelativePath() { return $this->_relativePath; } /** * Get relative pathname (if possible). */ public function getRelativePathname(): string { if (null === $relative = $this->getRelativePath()) { return $this->getPathname(); } return \substr($this->getPathname(), \strlen($relative)); } } PK*Zxk k "Readline/Hoa/AutocompleterWord.phpnuW+AsetWords($words); } /** * Complete a word. * Returns null for no word, a full-word or an array of full-words. * * @param string &$prefix Prefix to autocomplete * * @return mixed */ public function complete(&$prefix) { $out = []; $length = \mb_strlen($prefix); foreach ($this->getWords() as $word) { if (\mb_substr($word, 0, $length) === $prefix) { $out[] = $word; } } if (empty($out)) { return null; } if (1 === \count($out)) { return $out[0]; } return $out; } /** * Get definition of a word. */ public function getWordDefinition(): string { return '\b\w+'; } /** * Set list of words. * * @param array $words words * * @return array */ public function setWords(array $words) { $old = $this->_words; $this->_words = $words; return $old; } /** * Get list of words. */ public function getWords(): array { return $this->_words; } } PK*Z-5 Readline/Hoa/StreamOut.phpnuW+A_tmpArguments = $arguments; parent::__construct($message, $code, $previous); $this->_rawMessage = $message; $this->message = @\vsprintf($message, $this->getArguments()); return; } /** * Returns the backtrace. * * Do not use `Exception::getTrace` any more. */ public function getBacktrace() { if (null === $this->_trace) { $this->_trace = $this->getTrace(); } return $this->_trace; } /** * Returns the previous exception if any. * * Do not use `Exception::getPrevious` any more. */ public function getPreviousThrow() { if (null === $this->_previous) { $this->_previous = $this->getPrevious(); } return $this->_previous; } /** * Returns the arguments of the message. */ public function getArguments() { if (null === $this->_arguments) { $arguments = $this->_tmpArguments; if (!\is_array($arguments)) { $arguments = [$arguments]; } foreach ($arguments as &$value) { if (null === $value) { $value = '(null)'; } } $this->_arguments = $arguments; unset($this->_tmpArguments); } return $this->_arguments; } /** * Returns the raw message. */ public function getRawMessage(): string { return $this->_rawMessage; } /** * Returns the message already formatted. */ public function getFormattedMessage(): string { return $this->getMessage(); } /** * Returns the source of the exception (class, method, function, main etc.). */ public function getFrom(): string { $trace = $this->getBacktrace(); $from = '{main}'; if (!empty($trace)) { $t = $trace[0]; $from = ''; if (isset($t['class'])) { $from .= $t['class'].'::'; } if (isset($t['function'])) { $from .= $t['function'].'()'; } } return $from; } /** * Raises an exception as a string. */ public function raise(bool $includePrevious = false): string { $message = $this->getFormattedMessage(); $trace = $this->getBacktrace(); $file = '/dev/null'; $line = -1; $pre = $this->getFrom(); if (!empty($trace)) { $file = $trace['file'] ?? null; $line = $trace['line'] ?? null; } $pre .= ': '; try { $out = $pre.'('.$this->getCode().') '.$message."\n". 'in '.$this->getFile().' at line '. $this->getLine().'.'; } catch (\Exception $e) { $out = $pre.'('.$this->getCode().') '.$message."\n". 'in '.$file.' around line '.$line.'.'; } if (true === $includePrevious && null !== $previous = $this->getPreviousThrow()) { $out .= "\n\n".' ⬇'."\n\n". 'Nested exception ('.\get_class($previous).'):'."\n". ($previous instanceof self ? $previous->raise(true) : $previous->getMessage()); } return $out; } /** * Catches uncaught exception (only `Hoa\Exception\Idle` and children). */ public static function uncaught(\Throwable $exception) { if (!($exception instanceof self)) { throw $exception; } while (0 < \ob_get_level()) { \ob_end_flush(); } echo 'Uncaught exception ('.\get_class($exception).'):'."\n". $exception->raise(true); } /** * String representation of object. */ public function __toString(): string { return $this->raise(); } /** * Enables uncaught exception handler. * * This is restricted to Hoa's exceptions only. */ public static function enableUncaughtHandler(bool $enable = true) { if (false === $enable) { return \restore_exception_handler(); } return \set_exception_handler(function ($exception) { return self::uncaught($exception); }); } } PK*ZK Readline/Hoa/Exception.phpnuW+Asend(); return; } /** * Sends the exception on `hoa://Event/Exception`. */ public function send() { Event::notify( 'hoa://Event/Exception', $this, new EventBucket($this) ); } } PK*ZԪ}ziziReadline/Hoa/Readline.phpnuW+A_mapping["\033[A"] = [$this, '_bindArrowUp']; $this->_mapping["\033[B"] = [$this, '_bindArrowDown']; $this->_mapping["\033[C"] = [$this, '_bindArrowRight']; $this->_mapping["\033[D"] = [$this, '_bindArrowLeft']; $this->_mapping["\001"] = [$this, '_bindControlA']; $this->_mapping["\002"] = [$this, '_bindControlB']; $this->_mapping["\005"] = [$this, '_bindControlE']; $this->_mapping["\006"] = [$this, '_bindControlF']; $this->_mapping["\010"] = $this->_mapping["\177"] = [$this, '_bindBackspace']; $this->_mapping["\027"] = [$this, '_bindControlW']; $this->_mapping["\n"] = [$this, '_bindNewline']; $this->_mapping["\t"] = [$this, '_bindTab']; return; } /** * Read a line from the input. */ public function readLine(?string $prefix = null) { $input = Console::getInput(); if (true === $input->eof()) { return false; } $direct = Console::isDirect($input->getStream()->getStream()); $output = Console::getOutput(); if (false === $direct || \defined('PHP_WINDOWS_VERSION_PLATFORM')) { $out = $input->readLine(); if (false === $out) { return false; } $out = \substr($out, 0, -1); if (true === $direct) { $output->writeAll($prefix); } else { $output->writeAll($prefix.$out."\n"); } return $out; } $this->resetLine(); $this->setPrefix($prefix); $read = [$input->getStream()->getStream()]; $write = $except = []; $output->writeAll($prefix); while (true) { @\stream_select($read, $write, $except, 30, 0); if (empty($read)) { $read = [$input->getStream()->getStream()]; continue; } $char = $this->_read(); $this->_buffer = $char; $return = $this->_readLine($char); if (0 === ($return & self::STATE_NO_ECHO)) { $output->writeAll($this->_buffer); } if (0 !== ($return & self::STATE_BREAK)) { break; } } return $this->getLine(); } /** * Readline core. */ public function _readLine(string $char) { if (isset($this->_mapping[$char]) && \is_callable($this->_mapping[$char])) { $mapping = $this->_mapping[$char]; return $mapping($this); } if (isset($this->_mapping[$char])) { $this->_buffer = $this->_mapping[$char]; } elseif (false === Ustring::isCharPrintable($char)) { ConsoleCursor::bip(); return static::STATE_CONTINUE | static::STATE_NO_ECHO; } if ($this->getLineLength() === $this->getLineCurrent()) { $this->appendLine($this->_buffer); return static::STATE_CONTINUE; } $this->insertLine($this->_buffer); $tail = \mb_substr( $this->getLine(), $this->getLineCurrent() - 1 ); $this->_buffer = "\033[K".$tail.\str_repeat( "\033[D", \mb_strlen($tail) - 1 ); return static::STATE_CONTINUE; } /** * Add mappings. */ public function addMappings(array $mappings) { foreach ($mappings as $key => $mapping) { $this->addMapping($key, $mapping); } } /** * Add a mapping. * Supported key: * • \e[… for \033[…; * • \C-… for Ctrl-…; * • abc for a simple mapping. * A mapping is a callable that has only one parameter of type * Hoa\Console\Readline and that returns a self::STATE_* constant. */ public function addMapping(string $key, $mapping) { if ('\e[' === \substr($key, 0, 3)) { $this->_mapping["\033[".\substr($key, 3)] = $mapping; } elseif ('\C-' === \substr($key, 0, 3)) { $_key = \ord(\strtolower(\substr($key, 3))) - 96; $this->_mapping[\chr($_key)] = $mapping; } else { $this->_mapping[$key] = $mapping; } } /** * Add an entry in the history. */ public function addHistory(?string $line = null) { if (empty($line)) { return; } $this->_history[] = $line; $this->_historyCurrent = $this->_historySize++; } /** * Clear history. */ public function clearHistory() { unset($this->_history); $this->_history = []; $this->_historyCurrent = 0; $this->_historySize = 1; } /** * Get an entry in the history. */ public function getHistory(?int $i = null) { if (null === $i) { $i = $this->_historyCurrent; } if (!isset($this->_history[$i])) { return null; } return $this->_history[$i]; } /** * Go backward in the history. */ public function previousHistory() { if (0 >= $this->_historyCurrent) { return $this->getHistory(0); } return $this->getHistory($this->_historyCurrent--); } /** * Go forward in the history. */ public function nextHistory() { if ($this->_historyCurrent + 1 >= $this->_historySize) { return $this->getLine(); } return $this->getHistory(++$this->_historyCurrent); } /** * Get current line. */ public function getLine() { return $this->_line; } /** * Append to current line. */ public function appendLine(string $append) { $this->_line .= $append; $this->_lineLength = \mb_strlen($this->_line); $this->_lineCurrent = $this->_lineLength; } /** * Insert into current line at the current seek. */ public function insertLine(string $insert) { if ($this->_lineLength === $this->_lineCurrent) { return $this->appendLine($insert); } $this->_line = \mb_substr($this->_line, 0, $this->_lineCurrent). $insert. \mb_substr($this->_line, $this->_lineCurrent); $this->_lineLength = \mb_strlen($this->_line); $this->_lineCurrent += \mb_strlen($insert); return; } /** * Reset current line. */ protected function resetLine() { $this->_line = null; $this->_lineCurrent = 0; $this->_lineLength = 0; } /** * Get current line seek. */ public function getLineCurrent(): int { return $this->_lineCurrent; } /** * Get current line length. * * @return int */ public function getLineLength(): int { return $this->_lineLength; } /** * Set prefix. */ public function setPrefix(string $prefix) { $this->_prefix = $prefix; } /** * Get prefix. */ public function getPrefix() { return $this->_prefix; } /** * Get buffer. Not for user. */ public function getBuffer() { return $this->_buffer; } /** * Set an autocompleter. */ public function setAutocompleter(Autocompleter $autocompleter) { $old = $this->_autocompleter; $this->_autocompleter = $autocompleter; return $old; } /** * Get the autocompleter. * * @return ?Autocompleter */ public function getAutocompleter() { return $this->_autocompleter; } /** * Read on input. Not for user. */ public function _read(int $length = 512): string { return Console::getInput()->read($length); } /** * Set current line. Not for user. */ public function setLine(string $line) { $this->_line = $line; $this->_lineLength = \mb_strlen($this->_line ?: ''); $this->_lineCurrent = $this->_lineLength; } /** * Set current line seek. Not for user. */ public function setLineCurrent(int $current) { $this->_lineCurrent = $current; } /** * Set line length. Not for user. */ public function setLineLength(int $length) { $this->_lineLength = $length; } /** * Set buffer. Not for user. */ public function setBuffer(string $buffer) { $this->_buffer = $buffer; } /** * Up arrow binding. * Go backward in the history. */ public function _bindArrowUp(self $self): int { if (0 === (static::STATE_CONTINUE & static::STATE_NO_ECHO)) { ConsoleCursor::clear('↔'); Console::getOutput()->writeAll($self->getPrefix()); } $buffer = $self->previousHistory() ?? ''; $self->setBuffer($buffer); $self->setLine($buffer); return static::STATE_CONTINUE; } /** * Down arrow binding. * Go forward in the history. */ public function _bindArrowDown(self $self): int { if (0 === (static::STATE_CONTINUE & static::STATE_NO_ECHO)) { ConsoleCursor::clear('↔'); Console::getOutput()->writeAll($self->getPrefix()); } $self->setBuffer($buffer = $self->nextHistory()); $self->setLine($buffer); return static::STATE_CONTINUE; } /** * Right arrow binding. * Move cursor to the right. */ public function _bindArrowRight(self $self): int { if ($self->getLineLength() > $self->getLineCurrent()) { if (0 === (static::STATE_CONTINUE & static::STATE_NO_ECHO)) { ConsoleCursor::move('→'); } $self->setLineCurrent($self->getLineCurrent() + 1); } $self->setBuffer(''); return static::STATE_CONTINUE; } /** * Left arrow binding. * Move cursor to the left. */ public function _bindArrowLeft(self $self): int { if (0 < $self->getLineCurrent()) { if (0 === (static::STATE_CONTINUE & static::STATE_NO_ECHO)) { ConsoleCursor::move('←'); } $self->setLineCurrent($self->getLineCurrent() - 1); } $self->setBuffer(''); return static::STATE_CONTINUE; } /** * Backspace and Control-H binding. * Delete the first character at the right of the cursor. */ public function _bindBackspace(self $self): int { $buffer = ''; if (0 < $self->getLineCurrent()) { if (0 === (static::STATE_CONTINUE & static::STATE_NO_ECHO)) { ConsoleCursor::move('←'); ConsoleCursor::clear('→'); } if ($self->getLineLength() === $current = $self->getLineCurrent()) { $self->setLine(\mb_substr($self->getLine(), 0, -1)); } else { $line = $self->getLine(); $current = $self->getLineCurrent(); $tail = \mb_substr($line, $current); $buffer = $tail.\str_repeat("\033[D", \mb_strlen($tail)); $self->setLine(\mb_substr($line, 0, $current - 1).$tail); $self->setLineCurrent($current - 1); } } $self->setBuffer($buffer); return static::STATE_CONTINUE; } /** * Control-A binding. * Move cursor to beginning of line. */ public function _bindControlA(self $self): int { for ($i = $self->getLineCurrent() - 1; 0 <= $i; --$i) { $self->_bindArrowLeft($self); } return static::STATE_CONTINUE; } /** * Control-B binding. * Move cursor backward one word. */ public function _bindControlB(self $self): int { $current = $self->getLineCurrent(); if (0 === $current) { return static::STATE_CONTINUE; } $words = \preg_split( '#\b#u', $self->getLine(), -1, \PREG_SPLIT_OFFSET_CAPTURE | \PREG_SPLIT_NO_EMPTY ); for ( $i = 0, $max = \count($words) - 1; $i < $max && $words[$i + 1][1] < $current; ++$i ) { } for ($j = $words[$i][1] + 1; $current >= $j; ++$j) { $self->_bindArrowLeft($self); } return static::STATE_CONTINUE; } /** * Control-E binding. * Move cursor to end of line. */ public function _bindControlE(self $self): int { for ( $i = $self->getLineCurrent(), $max = $self->getLineLength(); $i < $max; ++$i ) { $self->_bindArrowRight($self); } return static::STATE_CONTINUE; } /** * Control-F binding. * Move cursor forward one word. */ public function _bindControlF(self $self): int { $current = $self->getLineCurrent(); if ($self->getLineLength() === $current) { return static::STATE_CONTINUE; } $words = \preg_split( '#\b#u', $self->getLine(), -1, \PREG_SPLIT_OFFSET_CAPTURE | \PREG_SPLIT_NO_EMPTY ); for ( $i = 0, $max = \count($words) - 1; $i < $max && $words[$i][1] < $current; ++$i ) { } if (!isset($words[$i + 1])) { $words[$i + 1] = [1 => $self->getLineLength()]; } for ($j = $words[$i + 1][1]; $j > $current; --$j) { $self->_bindArrowRight($self); } return static::STATE_CONTINUE; } /** * Control-W binding. * Delete first backward word. */ public function _bindControlW(self $self): int { $current = $self->getLineCurrent(); if (0 === $current) { return static::STATE_CONTINUE; } $words = \preg_split( '#\b#u', $self->getLine(), -1, \PREG_SPLIT_OFFSET_CAPTURE | \PREG_SPLIT_NO_EMPTY ); for ( $i = 0, $max = \count($words) - 1; $i < $max && $words[$i + 1][1] < $current; ++$i ) { } for ($j = $words[$i][1] + 1; $current >= $j; ++$j) { $self->_bindBackspace($self); } return static::STATE_CONTINUE; } /** * Newline binding. */ public function _bindNewline(self $self): int { $self->addHistory($self->getLine()); return static::STATE_BREAK; } /** * Tab binding. */ public function _bindTab(self $self): int { $output = Console::getOutput(); $autocompleter = $self->getAutocompleter(); $state = static::STATE_CONTINUE | static::STATE_NO_ECHO; if (null === $autocompleter) { return $state; } $current = $self->getLineCurrent(); $line = $self->getLine(); if (0 === $current) { return $state; } $matches = \preg_match_all( '#'.$autocompleter->getWordDefinition().'$#u', \mb_substr($line, 0, $current), $words ); if (0 === $matches) { return $state; } $word = $words[0][0]; if ('' === \trim($word)) { return $state; } $solution = $autocompleter->complete($word); $length = \mb_strlen($word); if (null === $solution) { return $state; } if (\is_array($solution)) { $_solution = $solution; $count = \count($_solution) - 1; $cWidth = 0; $window = ConsoleWindow::getSize(); $wWidth = $window['x']; $cursor = ConsoleCursor::getPosition(); \array_walk($_solution, function (&$value) use (&$cWidth) { $handle = \mb_strlen($value); if ($handle > $cWidth) { $cWidth = $handle; } return; }); \array_walk($_solution, function (&$value) use (&$cWidth) { $handle = \mb_strlen($value); if ($handle >= $cWidth) { return; } $value .= \str_repeat(' ', $cWidth - $handle); return; }); $mColumns = (int) \floor($wWidth / ($cWidth + 2)); $mLines = (int) \ceil(($count + 1) / $mColumns); --$mColumns; $i = 0; if (0 > $window['y'] - $cursor['y'] - $mLines) { ConsoleWindow::scroll('↑', $mLines); ConsoleCursor::move('↑', $mLines); } ConsoleCursor::save(); ConsoleCursor::hide(); ConsoleCursor::move('↓ LEFT'); ConsoleCursor::clear('↓'); foreach ($_solution as $j => $s) { $output->writeAll("\033[0m".$s."\033[0m"); if ($i++ < $mColumns) { $output->writeAll(' '); } else { $i = 0; if (isset($_solution[$j + 1])) { $output->writeAll("\n"); } } } ConsoleCursor::restore(); ConsoleCursor::show(); ++$mColumns; $input = Console::getInput(); $read = [$input->getStream()->getStream()]; $write = $except = []; $mColumn = -1; $mLine = -1; $coord = -1; $unselect = function () use ( &$mColumn, &$mLine, &$coord, &$_solution, &$cWidth, $output ) { ConsoleCursor::save(); ConsoleCursor::hide(); ConsoleCursor::move('↓ LEFT'); ConsoleCursor::move('→', $mColumn * ($cWidth + 2)); ConsoleCursor::move('↓', $mLine); $output->writeAll("\033[0m".$_solution[$coord]."\033[0m"); ConsoleCursor::restore(); ConsoleCursor::show(); return; }; $select = function () use ( &$mColumn, &$mLine, &$coord, &$_solution, &$cWidth, $output ) { ConsoleCursor::save(); ConsoleCursor::hide(); ConsoleCursor::move('↓ LEFT'); ConsoleCursor::move('→', $mColumn * ($cWidth + 2)); ConsoleCursor::move('↓', $mLine); $output->writeAll("\033[7m".$_solution[$coord]."\033[0m"); ConsoleCursor::restore(); ConsoleCursor::show(); return; }; $init = function () use ( &$mColumn, &$mLine, &$coord, &$select ) { $mColumn = 0; $mLine = 0; $coord = 0; $select(); return; }; while (true) { @\stream_select($read, $write, $except, 30, 0); if (empty($read)) { $read = [$input->getStream()->getStream()]; continue; } switch ($char = $self->_read()) { case "\033[A": if (-1 === $mColumn && -1 === $mLine) { $init(); break; } $unselect(); $coord = \max(0, $coord - $mColumns); $mLine = (int) \floor($coord / $mColumns); $mColumn = $coord % $mColumns; $select(); break; case "\033[B": if (-1 === $mColumn && -1 === $mLine) { $init(); break; } $unselect(); $coord = \min($count, $coord + $mColumns); $mLine = (int) \floor($coord / $mColumns); $mColumn = $coord % $mColumns; $select(); break; case "\t": case "\033[C": if (-1 === $mColumn && -1 === $mLine) { $init(); break; } $unselect(); $coord = \min($count, $coord + 1); $mLine = (int) \floor($coord / $mColumns); $mColumn = $coord % $mColumns; $select(); break; case "\033[D": if (-1 === $mColumn && -1 === $mLine) { $init(); break; } $unselect(); $coord = \max(0, $coord - 1); $mLine = (int) \floor($coord / $mColumns); $mColumn = $coord % $mColumns; $select(); break; case "\n": if (-1 !== $mColumn && -1 !== $mLine) { $tail = \mb_substr($line, $current); $current -= $length; $self->setLine( \mb_substr($line, 0, $current). $solution[$coord]. $tail ); $self->setLineCurrent( $current + \mb_strlen($solution[$coord]) ); ConsoleCursor::move('←', $length); $output->writeAll($solution[$coord]); ConsoleCursor::clear('→'); $output->writeAll($tail); ConsoleCursor::move('←', \mb_strlen($tail)); } // no break default: $mColumn = -1; $mLine = -1; $coord = -1; ConsoleCursor::save(); ConsoleCursor::move('↓ LEFT'); ConsoleCursor::clear('↓'); ConsoleCursor::restore(); if ("\033" !== $char && "\n" !== $char) { $self->setBuffer($char); return $self->_readLine($char); } break 2; } } return $state; } $tail = \mb_substr($line, $current); $current -= $length; $self->setLine( \mb_substr($line, 0, $current). $solution. $tail ); $self->setLineCurrent( $current + \mb_strlen($solution) ); ConsoleCursor::move('←', $length); $output->writeAll($solution); ConsoleCursor::clear('→'); $output->writeAll($tail); ConsoleCursor::move('←', \mb_strlen($tail)); return $state; } } /* * Advanced interaction. */ Console::advancedInteraction(); PK*Z%D"Readline/Hoa/ProtocolException.phpnuW+Aparse($terminfo); return; } /** * Parse. */ protected function parse(string $terminfo): array { if (!\file_exists($terminfo)) { throw new ConsoleException('Terminfo file %s does not exist.', 0, $terminfo); } $data = \file_get_contents($terminfo); $length = \strlen($data); $out = ['file' => $terminfo]; $headers = [ 'data_size' => $length, 'header_size' => 12, 'magic_number' => (\ord($data[1]) << 8) | \ord($data[0]), 'names_size' => (\ord($data[3]) << 8) | \ord($data[2]), 'bool_count' => (\ord($data[5]) << 8) | \ord($data[4]), 'number_count' => (\ord($data[7]) << 8) | \ord($data[6]), 'string_count' => (\ord($data[9]) << 8) | \ord($data[8]), 'string_table_size' => (\ord($data[11]) << 8) | \ord($data[10]), ]; $out['headers'] = $headers; // Names. $i = $headers['header_size']; $nameAndDescription = \explode('|', \substr($data, $i, $headers['names_size'] - 1)); $out['name'] = $nameAndDescription[0]; $out['description'] = $nameAndDescription[1]; // Booleans. $i += $headers['names_size']; $booleans = []; $booleanNames = &static::$_booleans; for ( $e = 0, $max = $i + $headers['bool_count']; $i < $max; ++$e, ++$i ) { $booleans[$booleanNames[$e]] = 1 === \ord($data[$i]); } $out['booleans'] = $booleans; // Numbers. if (1 === ($i % 2)) { ++$i; } $numbers = []; $numberNames = &static::$_numbers; for ( $e = 0, $max = $i + $headers['number_count'] * 2; $i < $max; ++$e, $i += 2 ) { $name = $numberNames[$e]; $data_i0 = \ord($data[$i]); $data_i1 = \ord($data[$i + 1]); if ($data_i1 === 255 && $data_i0 === 255) { $numbers[$name] = -1; } else { $numbers[$name] = ($data_i1 << 8) | $data_i0; } } $out['numbers'] = $numbers; // Strings. $strings = []; $stringNames = &static::$_strings; $ii = $i + $headers['string_count'] * 2; for ( $e = 0, $max = $ii; $i < $max; ++$e, $i += 2 ) { $name = $stringNames[$e]; $data_i0 = \ord($data[$i]); $data_i1 = \ord($data[$i + 1]); if ($data_i1 === 255 && $data_i0 === 255) { continue; } $a = ($data_i1 << 8) | $data_i0; $strings[$name] = $a; if (65534 === $a) { continue; } $b = $ii + $a; $c = $b; while ($c < $length && \ord($data[$c])) { $c++; } $value = \substr($data, $b, $c - $b); $strings[$name] = false !== $value ? $value : null; } $out['strings'] = $strings; return $this->_informations = $out; } /** * Get all informations. */ public function getInformations(): array { return $this->_informations; } /** * Get a boolean value. */ public function has(string $boolean): bool { if (!isset($this->_informations['booleans'][$boolean])) { return false; } return $this->_informations['booleans'][$boolean]; } /** * Get a number value. */ public function count(string $number): int { if (!isset($this->_informations['numbers'][$number])) { return 0; } return $this->_informations['numbers'][$number]; } /** * Get a string value. */ public function get(string $string) { if (!isset($this->_informations['strings'][$string])) { return null; } return $this->_informations['strings'][$string]; } /** * Get current term profile. */ public static function getTerm(): string { return isset($_SERVER['TERM']) && !empty($_SERVER['TERM']) ? $_SERVER['TERM'] : (\defined('PHP_WINDOWS_VERSION_PLATFORM') ? 'windows-ansi' : 'xterm'); } /** * Get pathname to the current terminfo. */ public static function getTerminfo($term = null): string { $paths = []; if (isset($_SERVER['TERMINFO'])) { $paths[] = $_SERVER['TERMINFO']; } if (isset($_SERVER['HOME'])) { $paths[] = $_SERVER['HOME'].\DIRECTORY_SEPARATOR.'.terminfo'; } if (isset($_SERVER['TERMINFO_DIRS'])) { foreach (\explode(':', $_SERVER['TERMINFO_DIRS']) as $path) { $paths[] = $path; } } $paths[] = '/usr/share/terminfo'; $paths[] = '/usr/share/lib/terminfo'; $paths[] = '/lib/terminfo'; $paths[] = '/usr/lib/terminfo'; $paths[] = '/usr/local/share/terminfo'; $paths[] = '/usr/local/share/lib/terminfo'; $paths[] = '/usr/local/lib/terminfo'; $paths[] = '/usr/local/ncurses/lib/terminfo'; $paths[] = 'hoa://Library/Terminfo'; $term = $term ?: static::getTerm(); $fileHexa = \dechex(\ord($term[0])).\DIRECTORY_SEPARATOR.$term; $fileAlpha = $term[0].\DIRECTORY_SEPARATOR.$term; $pathname = null; foreach ($paths as $path) { if (\file_exists($_ = $path.\DIRECTORY_SEPARATOR.$fileHexa) || \file_exists($_ = $path.\DIRECTORY_SEPARATOR.$fileAlpha)) { $pathname = $_; break; } } if (null === $pathname && 'xterm' !== $term) { return static::getTerminfo('xterm'); } return $pathname ?? ''; } /** * Check whether all required terminfo capabilities are defined. */ public static function isSupported(): bool { if (static::getTerminfo() === '') { return false; } $requiredVars = [ 'clear_screen', 'clr_bol', 'clr_eol', 'clr_eos', 'initialize_color', 'parm_down_cursor', 'parm_index', 'parm_left_cursor', 'parm_right_cursor', 'parm_rindex', 'parm_up_cursor', 'user6', 'user7', ]; $tput = new self(); foreach ($requiredVars as $var) { if ($tput->get($var) === null) { return false; } } return true; } } PK*ZU+Readline/Hoa/IteratorRecursiveDirectory.phpnuW+A_relativePath = $path; $this->setSplFileInfoClass($splFileInfoClass); return; } /** * Current. * Please, see \RecursiveDirectoryIterator::current() method. */ #[\ReturnTypeWillChange] public function current() { $out = parent::current(); if (null !== $this->_splFileInfoClass && $out instanceof \SplFileInfo) { $out->setInfoClass($this->_splFileInfoClass); $out = $out->getFileInfo(); if ($out instanceof IteratorSplFileInfo) { $out->setRelativePath($this->getRelativePath()); } } return $out; } /** * Get children. * Please, see \RecursiveDirectoryIterator::getChildren() method. */ #[\ReturnTypeWillChange] public function getChildren() { $out = parent::getChildren(); $out->_relativePath = $this->getRelativePath(); $out->setSplFileInfoClass($this->_splFileInfoClass); return $out; } /** * Set SplFileInfo classname. */ public function setSplFileInfoClass($splFileInfoClass) { $this->_splFileInfoClass = $splFileInfoClass; } /** * Get relative path (if given). */ public function getRelativePath(): string { return $this->_relativePath; } } PK*Z#"Readline/Hoa/AutocompleterPath.phpnuW+AsetRoot($root); } if (null !== $iteratorFactory) { $this->setIteratorFactory($iteratorFactory); } } /** * Complete a word. * Returns null for no word, a full-word or an array of full-words. */ public function complete(&$prefix) { $root = $this->getRoot(); if (static::PWD === $root) { $root = \getcwd(); } $path = $root.\DIRECTORY_SEPARATOR.$prefix; if (!\is_dir($path)) { $path = \dirname($path).\DIRECTORY_SEPARATOR; $prefix = \basename($prefix); } else { $prefix = null; } $iteratorFactory = $this->getIteratorFactory() ?: static::getDefaultIteratorFactory(); try { $iterator = $iteratorFactory($path); $out = []; $length = \mb_strlen($prefix); foreach ($iterator as $fileinfo) { $filename = $fileinfo->getFilename(); if (null === $prefix || (\mb_substr($filename, 0, $length) === $prefix)) { if ($fileinfo->isDir()) { $out[] = $filename.'/'; } else { $out[] = $filename; } } } } catch (\Exception $e) { return null; } $count = \count($out); if (1 === $count) { return $out[0]; } if (0 === $count) { return null; } return $out; } /** * Get definition of a word. */ public function getWordDefinition(): string { return '/?[\w\d\\_\-\.]+(/[\w\d\\_\-\.]*)*'; } /** * Set root. */ public function setRoot(string $root) { $old = $this->_root; $this->_root = $root; return $old; } /** * Get root. */ public function getRoot() { return $this->_root; } /** * Set iterator factory (a finder). */ public function setIteratorFactory(\Closure $iteratorFactory) { $old = $this->_iteratorFactory; $this->_iteratorFactory = $iteratorFactory; return $old; } /** * Get iterator factory. */ public function getIteratorFactory() { return $this->_iteratorFactory; } /** * Get default iterator factory (based on \DirectoryIterator). */ public static function getDefaultIteratorFactory() { return function ($path) { return new \DirectoryIterator($path); }; } } PK*ZL^9 9 Readline/Hoa/StreamIn.phpnuW+Aread(). */ public function readString(int $length); /** * Read a character. * It could be equivalent to $this->read(1). */ public function readCharacter(); /** * Read a boolean. */ public function readBoolean(); /** * Read an integer. */ public function readInteger(int $length = 1); /** * Read a float. */ public function readFloat(int $length = 1); /** * Read an array. * In most cases, it could be an alias to the $this->scanf() method. */ public function readArray(); /** * Read a line. */ public function readLine(); /** * Read all, i.e. read as much as possible. */ public function readAll(int $offset = 0); /** * Parse input from a stream according to a format. */ public function scanf(string $format): array; } PK*Z,EReadline/Hoa/ConsoleOutput.phpnuW+A_output = $output; return; } /** * Get the real output stream. */ public function getStream(): StreamOut { return $this->_output; } /** * Write n characters. */ public function write(string $string, int $length) { if (0 > $length) { throw new ConsoleException('Length must be greater than 0, given %d.', 0, $length); } $out = \substr($string, 0, $length); if (true === $this->isMultiplexerConsidered()) { if (true === Console::isTmuxRunning()) { $out = "\033Ptmux;". \str_replace("\033", "\033\033", $out). "\033\\"; } $length = \strlen($out); } if (null === $this->_output) { echo $out; } else { $this->_output->write($out, $length); } } /** * Write a string. */ public function writeString(string $string) { $string = (string) $string; return $this->write($string, \strlen($string)); } /** * Write a character. */ public function writeCharacter(string $character) { return $this->write((string) $character[0], 1); } /** * Write a boolean. */ public function writeBoolean(bool $boolean) { return $this->write(((bool) $boolean) ? '1' : '0', 1); } /** * Write an integer. */ public function writeInteger(int $integer) { $integer = (string) (int) $integer; return $this->write($integer, \strlen($integer)); } /** * Write a float. */ public function writeFloat(float $float) { $float = (string) (float) $float; return $this->write($float, \strlen($float)); } /** * Write an array. */ public function writeArray(array $array) { $array = \var_export($array, true); return $this->write($array, \strlen($array)); } /** * Write a line. */ public function writeLine(string $line) { if (false === $n = \strpos($line, "\n")) { return $this->write($line."\n", \strlen($line) + 1); } ++$n; return $this->write(\substr($line, 0, $n), $n); } /** * Write all, i.e. as much as possible. */ public function writeAll(string $string) { return $this->write($string ?? '', \strlen($string ?? '')); } /** * Truncate a stream to a given length. */ public function truncate(int $size): bool { return false; } /** * Consider the multiplexer (if running) while writing on the output. */ public function considerMultiplexer(bool $consider): bool { $old = $this->_considerMultiplexer; $this->_considerMultiplexer = $consider; return $old; } /** * Check whether the multiplexer must be considered or not. */ public function isMultiplexerConsidered(): bool { return $this->_considerMultiplexer; } } PK*ZXt $Readline/Hoa/ProtocolNodeLibrary.phpnuW+A_reach) as $part) { $out[] = "\r".$part.\strtolower($head).$queue; } $out[] = "\r".\dirname(__DIR__, 5).$queue; return \implode(';', $out); } $out = []; foreach (\explode(';', $this->_reach) as $part) { $pos = \strrpos(\rtrim($part, \DIRECTORY_SEPARATOR), \DIRECTORY_SEPARATOR) + 1; $head = \substr($part, 0, $pos); $tail = \substr($part, $pos); $out[] = $head.\strtolower($tail); } $this->_reach = \implode(';', $out); return parent::reach($queue); } } PK*Z&b b Readline/Hoa/StreamTouchable.phpnuW+AgetStreamName()); } /** * Get directory name component of path. */ public function getDirname(): string { return \dirname($this->getStreamName()); } /** * Get size. */ public function getSize(): int { if (false === $this->getStatistic()) { return false; } return \filesize($this->getStreamName()); } /** * Get informations about a file. */ public function getStatistic(): array { return \fstat($this->getStream()); } /** * Get last access time of file. */ public function getATime(): int { return \fileatime($this->getStreamName()); } /** * Get inode change time of file. */ public function getCTime(): int { return \filectime($this->getStreamName()); } /** * Get file modification time. */ public function getMTime(): int { return \filemtime($this->getStreamName()); } /** * Get file group. */ public function getGroup(): int { return \filegroup($this->getStreamName()); } /** * Get file owner. */ public function getOwner(): int { return \fileowner($this->getStreamName()); } /** * Get file permissions. */ public function getPermissions(): int { return \fileperms($this->getStreamName()); } /** * Get file permissions as a string. * Result sould be interpreted like this: * * s: socket; * * l: symbolic link; * * -: regular; * * b: block special; * * d: directory; * * c: character special; * * p: FIFO pipe; * * u: unknown. */ public function getReadablePermissions(): string { $p = $this->getPermissions(); if (($p & 0xC000) === 0xC000) { $out = 's'; } elseif (($p & 0xA000) === 0xA000) { $out = 'l'; } elseif (($p & 0x8000) === 0x8000) { $out = '-'; } elseif (($p & 0x6000) === 0x6000) { $out = 'b'; } elseif (($p & 0x4000) === 0x4000) { $out = 'd'; } elseif (($p & 0x2000) === 0x2000) { $out = 'c'; } elseif (($p & 0x1000) === 0x1000) { $out = 'p'; } else { $out = 'u'; } $out .= (($p & 0x0100) ? 'r' : '-'). (($p & 0x0080) ? 'w' : '-'). (($p & 0x0040) ? (($p & 0x0800) ? 's' : 'x') : (($p & 0x0800) ? 'S' : '-')). (($p & 0x0020) ? 'r' : '-'). (($p & 0x0010) ? 'w' : '-'). (($p & 0x0008) ? (($p & 0x0400) ? 's' : 'x') : (($p & 0x0400) ? 'S' : '-')). (($p & 0x0004) ? 'r' : '-'). (($p & 0x0002) ? 'w' : '-'). (($p & 0x0001) ? (($p & 0x0200) ? 't' : 'x') : (($p & 0x0200) ? 'T' : '-')); return $out; } /** * Check if the file is readable. */ public function isReadable(): bool { return \is_readable($this->getStreamName()); } /** * Check if the file is writable. */ public function isWritable(): bool { return \is_writable($this->getStreamName()); } /** * Check if the file is executable. */ public function isExecutable(): bool { return \is_executable($this->getStreamName()); } /** * Clear file status cache. */ public function clearStatisticCache() { \clearstatcache(true, $this->getStreamName()); } /** * Clear all files status cache. */ public static function clearAllStatisticCaches() { \clearstatcache(); } /** * Set access and modification time of file. */ public function touch(?int $time = null, ?int $atime = null): bool { if (null === $time) { $time = \time(); } if (null === $atime) { $atime = $time; } return \touch($this->getStreamName(), $time, $atime); } /** * Copy file. * Return the destination file path if succeed, false otherwise. */ public function copy(string $to, bool $force = StreamTouchable::DO_NOT_OVERWRITE): bool { $from = $this->getStreamName(); if ($force === StreamTouchable::DO_NOT_OVERWRITE && true === \file_exists($to)) { return true; } if (null === $this->getStreamContext()) { return @\copy($from, $to); } return @\copy($from, $to, $this->getStreamContext()->getContext()); } /** * Move a file. */ public function move( string $name, bool $force = StreamTouchable::DO_NOT_OVERWRITE, bool $mkdir = StreamTouchable::DO_NOT_MAKE_DIRECTORY ): bool { $from = $this->getStreamName(); if ($force === StreamTouchable::DO_NOT_OVERWRITE && true === \file_exists($name)) { return false; } if (StreamTouchable::MAKE_DIRECTORY === $mkdir) { FileDirectory::create( \dirname($name), FileDirectory::MODE_CREATE_RECURSIVE ); } if (null === $this->getStreamContext()) { return @\rename($from, $name); } return @\rename($from, $name, $this->getStreamContext()->getContext()); } /** * Delete a file. */ public function delete(): bool { if (null === $this->getStreamContext()) { return @\unlink($this->getStreamName()); } return @\unlink( $this->getStreamName(), $this->getStreamContext()->getContext() ); } /** * Change file group. */ public function changeGroup($group): bool { return \chgrp($this->getStreamName(), $group); } /** * Change file mode. */ public function changeMode(int $mode): bool { return \chmod($this->getStreamName(), $mode); } /** * Change file owner. */ public function changeOwner($user): bool { return \chown($this->getStreamName(), $user); } /** * Change the current umask. */ public static function umask(?int $umask = null): int { if (null === $umask) { return \umask(); } return \umask($umask); } /** * Check if it is a file. */ public function isFile(): bool { return \is_file($this->getStreamName()); } /** * Check if it is a link. */ public function isLink(): bool { return \is_link($this->getStreamName()); } /** * Check if it is a directory. */ public function isDirectory(): bool { return \is_dir($this->getStreamName()); } /** * Check if it is a socket. */ public function isSocket(): bool { return \filetype($this->getStreamName()) === 'socket'; } /** * Check if it is a FIFO pipe. */ public function isFIFOPipe(): bool { return \filetype($this->getStreamName()) === 'fifo'; } /** * Check if it is character special file. */ public function isCharacterSpecial(): bool { return \filetype($this->getStreamName()) === 'char'; } /** * Check if it is block special. */ public function isBlockSpecial(): bool { return \filetype($this->getStreamName()) === 'block'; } /** * Check if it is an unknown type. */ public function isUnknown(): bool { return \filetype($this->getStreamName()) === 'unknown'; } /** * Set the open mode. */ protected function setMode(string $mode) { $old = $this->_mode; $this->_mode = $mode; return $old; } /** * Get the open mode. */ public function getMode() { return $this->_mode; } /** * Get inode. */ public function getINode(): int { return \fileinode($this->getStreamName()); } /** * Check if the system is case sensitive or not. */ public static function isCaseSensitive(): bool { return !( \file_exists(\mb_strtolower(__FILE__)) && \file_exists(\mb_strtoupper(__FILE__)) ); } /** * Get a canonicalized absolute pathname. */ public function getRealPath(): string { if (false === $out = \realpath($this->getStreamName())) { return $this->getStreamName(); } return $out; } /** * Get file extension (if exists). */ public function getExtension(): string { return \pathinfo( $this->getStreamName(), \PATHINFO_EXTENSION ); } /** * Get filename without extension. */ public function getFilename(): string { $file = \basename($this->getStreamName()); if (\defined('PATHINFO_FILENAME')) { return \pathinfo($file, \PATHINFO_FILENAME); } if (\strstr($file, '.')) { return \substr($file, 0, \strrpos($file, '.')); } return $file; } } PK*Zq 'Readline/Hoa/Terminfo/78/xterm-256colornuW+A%&xterm-256color|xterm with 256 colorsP&*.9JLPWYfjnx| #'-39?EINRW\`gnrz"$'y|~ !(/7?GOW_gov}'.5<CKS[cks{ $c [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?12l[?25h[?12;25h(0[?1049h[%p1%dX(B(B[?1049l[?5h$<100/>[?5l[!p[?3;4l>[3~OBOP[21~OQOROS[15~[17~[18~[19~[20~OH[2~OD[6~[5~OCOA[?1l>[?1h=[?1034l[?1034h[%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dS[%p1%dL[%p1%dD[%p1%dC[%p1%dT[%p1%dAc[!p[?3;4l>8[%i%p1%dd7 M%?%p9%t(0%e(B%;[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;mH OE``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~[?7h[?7lOFOM[3;2~[2;2~[6;2~[5;2~[23~[24~[15;2~[17;2~[18;2~[19;2~[20;2~[21;2~[23;2~[24;2~[15;5~[17;5~[18;5~[19;5~[20;5~[21;5~[23;5~[24;5~[15;6~[17;6~[18;6~[19;6~[20;6~[21;6~[23;6~[24;6~[15;3~[17;3~[18;3~[19;3~[20;3~[21;3~[23;3~[24;3~[%i%d;%dR[?1;2c]4;%p1%d;rgb:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;mlm:v#*18?FMT[bipw~ &-4;BIPW^e  %).38=BHNTZ`flrx~ "',048[3;3~[3;4~[3;5~[3;6~[3;7~[2;3~[2;4~[2;5~[2;6~[2;7~[6;3~[6;4~[6;5~[6;6~[6;7~[5;3~[5;4~[5;5~[5;6~[5;7~AXG0E0S0kDC3kDC4kDC5kDC6kDC7kDNkDN3kDN4kDN5kDN6kDN7kEND3kEND4kEND5kEND6kEND7kHOM3kHOM4kHOM5kHOM6kHOM7kIC3kIC4kIC5kIC6kIC7kLFT3kLFT4kLFT5kLFT6kLFT7kNXT3kNXT4kNXT5kNXT6kNXT7kPRV3kPRV4kPRV5kPRV6kPRV7kRIT3kRIT4kRIT5kRIT6kRIT7kUPkUP3kUP4kUP5kUP6kUP7ka2kb1kb3kc2PK*Zw崺 Readline/Hoa/Terminfo/78/xtermnuW+A0&lxterm|xterm terminal emulator (X Window System)P@&*.9JLPWYfjnx| #'-39?EINRW\`gnrz"$'y|~ !(/7?GOW_gov}'.5<CKS[cks{NR\fi [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?12l[?25h[?12;25h(0[?1049h[%p1%dX(B(B[?1049l[?5h$<100/>[?5l[!p[?3;4l>[3~OBOP[21~OQOROS[15~[17~[18~[19~[20~OH[2~OD[6~[5~OCOA[?1l>[?1h=[?1034l[?1034h[%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dS[%p1%dL[%p1%dD[%p1%dC[%p1%dT[%p1%dAc[!p[?3;4l>8[%i%p1%dd7 M%?%p9%t(0%e(B%;[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;mH OE``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~[?7h[?7lOFOM[3;2~[2;2~[6;2~[5;2~[23~[24~[15;2~[17;2~[18;2~[19;2~[20;2~[21;2~[23;2~[24;2~[15;5~[17;5~[18;5~[19;5~[20;5~[21;5~[23;5~[24;5~[15;6~[17;6~[18;6~[19;6~[20;6~[21;6~[23;6~[24;6~[15;3~[17;3~[18;3~[19;3~[20;3~[21;3~[23;3~[24;3~[%i%d;%dR[?1;2c[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m[3%p1%dm[4%p1%dmlm9s#*18?FMT[bipw~ &-4;BIPW^e #(-27<BHNTZ`flrx}  !&*.2[3;3~[3;4~[3;5~[3;6~[3;7~[2;3~[2;4~[2;5~[2;6~[2;7~[6;3~[6;4~[6;5~[6;6~[6;7~[5;3~[5;4~[5;5~[5;6~[5;7~AXXMkDC3kDC4kDC5kDC6kDC7kDNkDN3kDN4kDN5kDN6kDN7kEND3kEND4kEND5kEND6kEND7kHOM3kHOM4kHOM5kHOM6kHOM7kIC3kIC4kIC5kIC6kIC7kLFT3kLFT4kLFT5kLFT6kLFT7kNXT3kNXT4kNXT5kNXT6kNXT7kPRV3kPRV4kPRV5kPRV6kPRV7kRIT3kRIT4kRIT5kRIT6kRIT7kUPkUP3kUP4kUP5kUP6kUP7ka2kb1kb3kc2PK*Z %Readline/Hoa/Terminfo/77/windows-ansinuW+A(&}Dansi|ansi/pc-term compatible with colorP@ '8<@DHLPTZ_dinsx 2=? (,048> [%i%p1%dG[%i%p1%d;%p2%dH[%p1%dX [%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dS[%p1%dL[%p1%dD[%p1%dC[%p1%dT[%p1%dA%p1%c[%p2%{1}%-%db[%i%p1%dd [0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;11%;mH+,-.0`a-hjklmno~pqrs_tuvwxyz{|}~[%i%d;%dR[?%[;0123456789]c[3%p1%dm[4%p1%dm(B)B*B+BAXPK*Z%Readline/Hoa/StreamPathable.phpnuW+A_flags = IteratorFileSystem::KEY_AS_PATHNAME | IteratorFileSystem::CURRENT_AS_FILEINFO | IteratorFileSystem::SKIP_DOTS; $this->_first = \RecursiveIteratorIterator::SELF_FIRST; return; } /** * Select a directory to scan. */ public function in($paths): self { if (!\is_array($paths)) { $paths = [$paths]; } foreach ($paths as $path) { if (1 === \preg_match('/[\*\?\[\]]/', $path)) { $iterator = new \CallbackFilterIterator( new \GlobIterator(\rtrim($path, \DIRECTORY_SEPARATOR)), function ($current) { return $current->isDir(); } ); foreach ($iterator as $fileInfo) { $this->_paths[] = $fileInfo->getPathname(); } } else { $this->_paths[] = $path; } } return $this; } /** * Set max depth for recursion. */ public function maxDepth(int $depth): self { $this->_maxDepth = $depth; return $this; } /** * Include files in the result. */ public function files(): self { $this->_types[] = 'file'; return $this; } /** * Include directories in the result. */ public function directories(): self { $this->_types[] = 'dir'; return $this; } /** * Include links in the result. */ public function links(): self { $this->_types[] = 'link'; return $this; } /** * Follow symbolink links. */ public function followSymlinks(bool $flag = true): self { if (true === $flag) { $this->_flags ^= IteratorFileSystem::FOLLOW_SYMLINKS; } else { $this->_flags |= IteratorFileSystem::FOLLOW_SYMLINKS; } return $this; } /** * Include files that match a regex. * Example: * $this->name('#\.php$#');. */ public function name(string $regex): self { $this->_filters[] = function (\SplFileInfo $current) use ($regex) { return 0 !== \preg_match($regex, $current->getBasename()); }; return $this; } /** * Exclude directories that match a regex. * Example: * $this->notIn('#^\.(git|hg)$#');. */ public function notIn(string $regex): self { $this->_filters[] = function (\SplFileInfo $current) use ($regex) { foreach (\explode(\DIRECTORY_SEPARATOR, $current->getPathname()) as $part) { if (0 !== \preg_match($regex, $part)) { return false; } } return true; }; return $this; } /** * Include files that respect a certain size. * The size is a string of the form: * operator number unit * where * • operator could be: <, <=, >, >= or =; * • number is a positive integer; * • unit could be: b (default), Kb, Mb, Gb, Tb, Pb, Eb, Zb, Yb. * Example: * $this->size('>= 12Kb');. */ public function size(string $size): self { if (0 === \preg_match('#^(<|<=|>|>=|=)\s*(\d+)\s*((?:[KMGTPEZY])b)?$#', $size, $matches)) { return $this; } $number = (float) ($matches[2]); $unit = $matches[3] ?? 'b'; $operator = $matches[1]; switch ($unit) { case 'b': break; // kilo case 'Kb': $number <<= 10; break; // mega. case 'Mb': $number <<= 20; break; // giga. case 'Gb': $number <<= 30; break; // tera. case 'Tb': $number *= 1099511627776; break; // peta. case 'Pb': $number *= 1024 ** 5; break; // exa. case 'Eb': $number *= 1024 ** 6; break; // zetta. case 'Zb': $number *= 1024 ** 7; break; // yota. case 'Yb': $number *= 1024 ** 8; break; } $filter = null; switch ($operator) { case '<': $filter = function (\SplFileInfo $current) use ($number) { return $current->getSize() < $number; }; break; case '<=': $filter = function (\SplFileInfo $current) use ($number) { return $current->getSize() <= $number; }; break; case '>': $filter = function (\SplFileInfo $current) use ($number) { return $current->getSize() > $number; }; break; case '>=': $filter = function (\SplFileInfo $current) use ($number) { return $current->getSize() >= $number; }; break; case '=': $filter = function (\SplFileInfo $current) use ($number) { return $current->getSize() === $number; }; break; } $this->_filters[] = $filter; return $this; } /** * Whether we should include dots or not (respectively . and ..). */ public function dots(bool $flag = true): self { if (true === $flag) { $this->_flags ^= IteratorFileSystem::SKIP_DOTS; } else { $this->_flags |= IteratorFileSystem::SKIP_DOTS; } return $this; } /** * Include files that are owned by a certain owner. */ public function owner(int $owner): self { $this->_filters[] = function (\SplFileInfo $current) use ($owner) { return $current->getOwner() === $owner; }; return $this; } /** * Format date. * Date can have the following syntax: * date * since date * until date * If the date does not have the “ago” keyword, it will be added. * Example: “42 hours” is equivalent to “since 42 hours” which is equivalent * to “since 42 hours ago”. */ protected function formatDate(string $date, &$operator): int { $operator = -1; if (0 === \preg_match('#\bago\b#', $date)) { $date .= ' ago'; } if (0 !== \preg_match('#^(since|until)\b(.+)$#', $date, $matches)) { $time = \strtotime($matches[2]); if ('until' === $matches[1]) { $operator = 1; } } else { $time = \strtotime($date); } return $time; } /** * Include files that have been changed from a certain date. * Example: * $this->changed('since 13 days');. */ public function changed(string $date): self { $time = $this->formatDate($date, $operator); if (-1 === $operator) { $this->_filters[] = function (\SplFileInfo $current) use ($time) { return $current->getCTime() >= $time; }; } else { $this->_filters[] = function (\SplFileInfo $current) use ($time) { return $current->getCTime() < $time; }; } return $this; } /** * Include files that have been modified from a certain date. * Example: * $this->modified('since 13 days');. */ public function modified(string $date): self { $time = $this->formatDate($date, $operator); if (-1 === $operator) { $this->_filters[] = function (\SplFileInfo $current) use ($time) { return $current->getMTime() >= $time; }; } else { $this->_filters[] = function (\SplFileInfo $current) use ($time) { return $current->getMTime() < $time; }; } return $this; } /** * Add your own filter. * The callback will receive 3 arguments: $current, $key and $iterator. It * must return a boolean: true to include the file, false to exclude it. * Example: * // Include files that are readable * $this->filter(function ($current) { * return $current->isReadable(); * });. */ public function filter($callback): self { $this->_filters[] = $callback; return $this; } /** * Sort result by name. * If \Collator exists (from ext/intl), the $locale argument will be used * for its constructor. Else, strcmp() will be used. * Example: * $this->sortByName('fr_FR');. */ public function sortByName(string $locale = 'root'): self { if (true === \class_exists('Collator', false)) { $collator = new \Collator($locale); $this->_sorts[] = function (\SplFileInfo $a, \SplFileInfo $b) use ($collator) { return $collator->compare($a->getPathname(), $b->getPathname()); }; } else { $this->_sorts[] = function (\SplFileInfo $a, \SplFileInfo $b) { return \strcmp($a->getPathname(), $b->getPathname()); }; } return $this; } /** * Sort result by size. * Example: * $this->sortBySize();. */ public function sortBySize(): self { $this->_sorts[] = function (\SplFileInfo $a, \SplFileInfo $b) { return $a->getSize() < $b->getSize(); }; return $this; } /** * Add your own sort. * The callback will receive 2 arguments: $a and $b. Please see the uasort() * function. * Example: * // Sort files by their modified time. * $this->sort(function ($a, $b) { * return $a->getMTime() < $b->getMTime(); * });. */ public function sort($callable): self { $this->_sorts[] = $callable; return $this; } /** * Child comes first when iterating. */ public function childFirst(): self { $this->_first = \RecursiveIteratorIterator::CHILD_FIRST; return $this; } /** * Get the iterator. */ public function getIterator() { $_iterator = new \AppendIterator(); $types = $this->getTypes(); if (!empty($types)) { $this->_filters[] = function (\SplFileInfo $current) use ($types) { return \in_array($current->getType(), $types); }; } $maxDepth = $this->getMaxDepth(); $splFileInfo = $this->getSplFileInfo(); foreach ($this->getPaths() as $path) { if (1 === $maxDepth) { $iterator = new \IteratorIterator( new IteratorRecursiveDirectory( $path, $this->getFlags(), $splFileInfo ), $this->getFirst() ); } else { $iterator = new \RecursiveIteratorIterator( new IteratorRecursiveDirectory( $path, $this->getFlags(), $splFileInfo ), $this->getFirst() ); if (1 < $maxDepth) { $iterator->setMaxDepth($maxDepth - 1); } } $_iterator->append($iterator); } foreach ($this->getFilters() as $filter) { $_iterator = new \CallbackFilterIterator( $_iterator, $filter ); } $sorts = $this->getSorts(); if (empty($sorts)) { return $_iterator; } $array = \iterator_to_array($_iterator); foreach ($sorts as $sort) { \uasort($array, $sort); } return new \ArrayIterator($array); } /** * Set SplFileInfo classname. */ public function setSplFileInfo(string $splFileInfo): string { $old = $this->_splFileInfo; $this->_splFileInfo = $splFileInfo; return $old; } /** * Get SplFileInfo classname. */ public function getSplFileInfo(): string { return $this->_splFileInfo; } /** * Get all paths. */ protected function getPaths(): array { return $this->_paths; } /** * Get max depth. */ public function getMaxDepth(): int { return $this->_maxDepth; } /** * Get types. */ public function getTypes(): array { return $this->_types; } /** * Get filters. */ protected function getFilters(): array { return $this->_filters; } /** * Get sorts. */ protected function getSorts(): array { return $this->_sorts; } /** * Get flags. */ public function getFlags(): int { return $this->_flags; } /** * Get first. */ public function getFirst(): int { return $this->_first; } } PK*Z= Readline/Hoa/EventException.phpnuW+AwriteAll("\033[8;".$y.';'.$x.'t'); return; } /** * Get current size (x and y) of the window. */ public static function getSize(): array { if (\defined('PHP_WINDOWS_VERSION_PLATFORM')) { $modecon = \explode("\n", \ltrim(ConsoleProcessus::execute('mode con'))); $_y = \trim($modecon[2]); \preg_match('#[^:]+:\s*([0-9]+)#', $_y, $matches); $y = (int) $matches[1]; $_x = \trim($modecon[3]); \preg_match('#[^:]+:\s*([0-9]+)#', $_x, $matches); $x = (int) $matches[1]; return [ 'x' => $x, 'y' => $y, ]; } $term = ''; if (isset($_SERVER['TERM'])) { $term = 'TERM="'.$_SERVER['TERM'].'" '; } $command = $term.'tput cols && '.$term.'tput lines'; $tput = ConsoleProcessus::execute($command, false); if (!empty($tput)) { list($x, $y) = \explode("\n", $tput); return [ 'x' => (int) $x, 'y' => (int) $y, ]; } // DECSLPP. Console::getOutput()->writeAll("\033[18t"); $input = Console::getInput(); // Read \033[8;y;xt. $input->read(4); // skip \033, [, 8 and ;. $x = null; $y = null; $handle = &$y; while (true) { $char = $input->readCharacter(); switch ($char) { case ';': $handle = &$x; break; case 't': break 2; default: if (false === \ctype_digit($char)) { break 2; } $handle .= $char; } } if (null === $x || null === $y) { return [ 'x' => 0, 'y' => 0, ]; } return [ 'x' => (int) $x, 'y' => (int) $y, ]; } /** * Move to X and Y (in pixels). */ public static function moveTo(int $x, int $y) { if (\defined('PHP_WINDOWS_VERSION_PLATFORM')) { return; } // DECSLPP. Console::getOutput()->writeAll("\033[3;".$x.';'.$y.'t'); return; } /** * Get current position (x and y) of the window (in pixels). */ public static function getPosition(): array { if (\defined('PHP_WINDOWS_VERSION_PLATFORM')) { return ['x' => 0, 'y' => 0]; } // DECSLPP. Console::getOutput()->writeAll("\033[13t"); $input = Console::getInput(); // Read \033[3;x;yt. $input->read(4); // skip \033, [, 3 and ;. $x = null; $y = null; $handle = &$x; while (true) { $char = $input->readCharacter(); switch ($char) { case ';': $handle = &$y; break; case 't': break 2; default: $handle .= $char; } } return [ 'x' => (int) $x, 'y' => (int) $y, ]; } /** * Scroll whole page. * Directions can be: * • u, up, ↑ : scroll whole page up; * • d, down, ↓ : scroll whole page down. * Directions can be concatenated by a single space. */ public static function scroll(string $directions, int $repeat = 1) { if (\defined('PHP_WINDOWS_VERSION_PLATFORM')) { return; } if (1 > $repeat) { return; } elseif (1 === $repeat) { $handle = \explode(' ', $directions); } else { $handle = \explode(' ', $directions, 1); } $tput = Console::getTput(); $count = ['up' => 0, 'down' => 0]; foreach ($handle as $direction) { switch ($direction) { case 'u': case 'up': case '↑': ++$count['up']; break; case 'd': case 'down': case '↓': ++$count['down']; break; } } $output = Console::getOutput(); if (0 < $count['up']) { $output->writeAll( \str_replace( '%p1%d', $count['up'] * $repeat, $tput->get('parm_index') ) ); } if (0 < $count['down']) { $output->writeAll( \str_replace( '%p1%d', $count['down'] * $repeat, $tput->get('parm_rindex') ) ); } return; } /** * Minimize the window. */ public static function minimize() { if (\defined('PHP_WINDOWS_VERSION_PLATFORM')) { return; } // DECSLPP. Console::getOutput()->writeAll("\033[2t"); return; } /** * Restore the window (de-minimize). */ public static function restore() { if (\defined('PHP_WINDOWS_VERSION_PLATFORM')) { return; } Console::getOutput()->writeAll("\033[1t"); return; } /** * Raise the window to the front of the stacking order. */ public static function raise() { if (\defined('PHP_WINDOWS_VERSION_PLATFORM')) { return; } Console::getOutput()->writeAll("\033[5t"); return; } /** * Lower the window to the bottom of the stacking order. */ public static function lower() { if (\defined('PHP_WINDOWS_VERSION_PLATFORM')) { return; } Console::getOutput()->writeAll("\033[6t"); return; } /** * Set title. */ public static function setTitle(string $title) { if (\defined('PHP_WINDOWS_VERSION_PLATFORM')) { return; } // DECSLPP. Console::getOutput()->writeAll("\033]0;".$title."\033\\"); return; } /** * Get title. */ public static function getTitle() { if (\defined('PHP_WINDOWS_VERSION_PLATFORM')) { return null; } // DECSLPP. Console::getOutput()->writeAll("\033[21t"); $input = Console::getInput(); $read = [$input->getStream()->getStream()]; $write = []; $except = []; $out = null; if (0 === \stream_select($read, $write, $except, 0, 50000)) { return $out; } // Read \033]l\033\ $input->read(3); // skip \033, ] and l. while (true) { $char = $input->readCharacter(); if ("\033" === $char) { $chaar = $input->readCharacter(); if ('\\' === $chaar) { break; } $char .= $chaar; } $out .= $char; } return $out; } /** * Get label. */ public static function getLabel() { if (\defined('PHP_WINDOWS_VERSION_PLATFORM')) { return null; } // DECSLPP. Console::getOutput()->writeAll("\033[20t"); $input = Console::getInput(); $read = [$input->getStream()->getStream()]; $write = []; $except = []; $out = null; if (0 === \stream_select($read, $write, $except, 0, 50000)) { return $out; } // Read \033]L<label>\033\ $input->read(3); // skip \033, ] and L. while (true) { $char = $input->readCharacter(); if ("\033" === $char) { $chaar = $input->readCharacter(); if ('\\' === $chaar) { break; } $char .= $chaar; } $out .= $char; } return $out; } /** * Refresh the window. */ public static function refresh() { if (\defined('PHP_WINDOWS_VERSION_PLATFORM')) { return; } // DECSLPP. Console::getOutput()->writeAll("\033[7t"); return; } /** * Set clipboard value. */ public static function copy(string $data) { if (\defined('PHP_WINDOWS_VERSION_PLATFORM')) { return; } $out = "\033]52;;".\base64_encode($data)."\033\\"; $output = Console::getOutput(); $considerMultiplexer = $output->considerMultiplexer(true); $output->writeAll($out); $output->considerMultiplexer($considerMultiplexer); return; } } /* * Advanced interaction. */ Console::advancedInteraction(); /* * Event. */ if (\function_exists('pcntl_signal')) { ConsoleWindow::getInstance(); \pcntl_signal( \SIGWINCH, function () { static $_window = null; if (null === $_window) { $_window = ConsoleWindow::getInstance(); } Event::notify( 'hoa://Event/Console/Window:resize', $_window, new EventBucket([ 'size' => ConsoleWindow::getSize(), ]) ); } ); } PK������*Z%������Readline/Hoa/File.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Class \Hoa\File. * * File handler. */ abstract class File extends FileGeneric implements StreamBufferable, StreamLockable, StreamPointable { /** * Open for reading only; place the file pointer at the beginning of the * file. */ const MODE_READ = 'rb'; /** * Open for reading and writing; place the file pointer at the beginning of * the file. */ const MODE_READ_WRITE = 'r+b'; /** * Open for writing only; place the file pointer at the beginning of the * file and truncate the file to zero length. If the file does not exist, * attempt to create it. */ const MODE_TRUNCATE_WRITE = 'wb'; /** * Open for reading and writing; place the file pointer at the beginning of * the file and truncate the file to zero length. If the file does not * exist, attempt to create it. */ const MODE_TRUNCATE_READ_WRITE = 'w+b'; /** * Open for writing only; place the file pointer at the end of the file. If * the file does not exist, attempt to create it. */ const MODE_APPEND_WRITE = 'ab'; /** * Open for reading and writing; place the file pointer at the end of the * file. If the file does not exist, attempt to create it. */ const MODE_APPEND_READ_WRITE = 'a+b'; /** * Create and open for writing only; place the file pointer at the beginning * of the file. If the file already exits, the fopen() call with fail by * returning false and generating an error of level E_WARNING. If the file * does not exist, attempt to create it. This is equivalent to specifying * O_EXCL | O_CREAT flags for the underlying open(2) system call. */ const MODE_CREATE_WRITE = 'xb'; /** * Create and open for reading and writing; place the file pointer at the * beginning of the file. If the file already exists, the fopen() call with * fail by returning false and generating an error of level E_WARNING. If * the file does not exist, attempt to create it. This is equivalent to * specifying O_EXCL | O_CREAT flags for the underlying open(2) system call. */ const MODE_CREATE_READ_WRITE = 'x+b'; /** * Open a file. */ public function __construct( string $streamName, string $mode, ?string $context = null, bool $wait = false ) { $this->setMode($mode); switch ($streamName) { case '0': $streamName = 'php://stdin'; break; case '1': $streamName = 'php://stdout'; break; case '2': $streamName = 'php://stderr'; break; default: if (true === \ctype_digit($streamName)) { $streamName = 'php://fd/'.$streamName; } } parent::__construct($streamName, $context, $wait); return; } /** * Open the stream and return the associated resource. */ protected function &_open(string $streamName, ?StreamContext $context = null) { if (\substr($streamName, 0, 4) === 'file' && false === \is_dir(\dirname($streamName))) { throw new FileException('Directory %s does not exist. Could not open file %s.', 1, [\dirname($streamName), \basename($streamName)]); } if (null === $context) { if (false === $out = @\fopen($streamName, $this->getMode(), true)) { throw new FileException('Failed to open stream %s.', 2, $streamName); } return $out; } $out = @\fopen( $streamName, $this->getMode(), true, $context->getContext() ); if (false === $out) { throw new FileException('Failed to open stream %s.', 3, $streamName); } return $out; } /** * Close the current stream. */ protected function _close(): bool { return @\fclose($this->getStream()); } /** * Start a new buffer. * The callable acts like a light filter. */ public function newBuffer($callable = null, ?int $size = null): int { $this->setStreamBuffer($size); // @todo manage $callable as a filter? return 1; } /** * Flush the output to a stream. */ public function flush(): bool { return \fflush($this->getStream()); } /** * Delete buffer. */ public function deleteBuffer(): bool { return $this->disableStreamBuffer(); } /** * Get bufffer level. */ public function getBufferLevel(): int { return 1; } /** * Get buffer size. */ public function getBufferSize(): int { return $this->getStreamBufferSize(); } /** * Portable advisory locking. */ public function lock(int $operation): bool { return \flock($this->getStream(), $operation); } /** * Rewind the position of a stream pointer. */ public function rewind(): bool { return \rewind($this->getStream()); } /** * Seek on a stream pointer. */ public function seek(int $offset, int $whence = StreamPointable::SEEK_SET): int { return \fseek($this->getStream(), $offset, $whence); } /** * Get the current position of the stream pointer. */ public function tell(): int { $stream = $this->getStream(); if (null === $stream) { return 0; } return \ftell($stream); } /** * Create a file. */ public static function create(string $name) { if (\file_exists($name)) { return true; } return \touch($name); } } PK������*Zi- �� ��!��Readline/Hoa/StreamBufferable.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Interface \Hoa\Stream\IStream\Bufferable. * * Interface for bufferable streams. It's complementary to native buffer support * of Hoa\Stream (please, see *StreamBuffer*() methods). Classes implementing * this interface are able to create nested buffers, flush them etc. */ interface StreamBufferable extends IStream { /** * Start a new buffer. * The callable acts like a light filter. */ public function newBuffer($callable = null, ?int $size = null): int; /** * Flush the buffer. */ public function flush(); /** * Delete buffer. */ public function deleteBuffer(): bool; /** * Get bufffer level. */ public function getBufferLevel(): int; /** * Get buffer size. */ public function getBufferSize(): int; } PK������*Zq������Readline/Hoa/EventSource.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Each object which is listenable must implement this interface. */ interface EventSource { } PK������*Zh& :�� :����Readline/Hoa/Stream.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Class \Hoa\Stream. * * Static register for all streams (files, sockets etc.). */ abstract class Stream implements IStream, EventListenable { use EventListens; /** * Name index in the stream bucket. */ const NAME = 0; /** * Handler index in the stream bucket. */ const HANDLER = 1; /** * Resource index in the stream bucket. */ const RESOURCE = 2; /** * Context index in the stream bucket. */ const CONTEXT = 3; /** * Default buffer size. */ const DEFAULT_BUFFER_SIZE = 8192; /** * Current stream bucket. */ protected $_bucket = []; /** * Static stream register. */ private static $_register = []; /** * Buffer size (default is 8Ko). */ protected $_bufferSize = self::DEFAULT_BUFFER_SIZE; /** * Original stream name, given to the stream constructor. */ protected $_streamName = null; /** * Context name. */ protected $_context = null; /** * Whether the opening has been deferred. */ protected $_hasBeenDeferred = false; /** * Whether this stream is already opened by another handler. */ protected $_borrowing = false; /** * Set the current stream. * If not exists in the register, try to call the * `$this->_open()` method. Please, see the `self::_getStream()` method. */ public function __construct(string $streamName, ?string $context = null, bool $wait = false) { $this->_streamName = $streamName; $this->_context = $context; $this->_hasBeenDeferred = $wait; $this->setListener( new EventListener( $this, [ 'authrequire', 'authresult', 'complete', 'connect', 'failure', 'mimetype', 'progress', 'redirect', 'resolve', 'size', ] ) ); if (true === $wait) { return; } $this->open(); return; } /** * Get a stream in the register. * If the stream does not exist, try to open it by calling the * $handler->_open() method. */ private static function &_getStream( string $streamName, self $handler, ?string $context = null ): array { $name = \md5($streamName); if (null !== $context) { if (false === StreamContext::contextExists($context)) { throw new StreamException('Context %s was not previously declared, cannot retrieve '.'this context.', 0, $context); } $context = StreamContext::getInstance($context); } if (!isset(self::$_register[$name])) { self::$_register[$name] = [ self::NAME => $streamName, self::HANDLER => $handler, self::RESOURCE => $handler->_open($streamName, $context), self::CONTEXT => $context, ]; Event::register( 'hoa://Event/Stream/'.$streamName, $handler ); // Add :open-ready? Event::register( 'hoa://Event/Stream/'.$streamName.':close-before', $handler ); } else { $handler->_borrowing = true; } if (null === self::$_register[$name][self::RESOURCE]) { self::$_register[$name][self::RESOURCE] = $handler->_open($streamName, $context); } return self::$_register[$name]; } /** * Open the stream and return the associated resource. * Note: This method is protected, but do not forget that it could be * overloaded into a public context. */ abstract protected function &_open(string $streamName, ?StreamContext $context = null); /** * Close the current stream. * Note: this method is protected, but do not forget that it could be * overloaded into a public context. */ abstract protected function _close(): bool; /** * Open the stream. */ final public function open(): self { $context = $this->_context; if (true === $this->hasBeenDeferred()) { if (null === $context) { $handle = StreamContext::getInstance(\uniqid()); $handle->setParameters([ 'notification' => [$this, '_notify'], ]); $context = $handle->getId(); } elseif (true === StreamContext::contextExists($context)) { $handle = StreamContext::getInstance($context); $parameters = $handle->getParameters(); if (!isset($parameters['notification'])) { $handle->setParameters([ 'notification' => [$this, '_notify'], ]); } } } $this->_bufferSize = self::DEFAULT_BUFFER_SIZE; $this->_bucket = self::_getStream( $this->_streamName, $this, $context ); return $this; } /** * Close the current stream. */ final public function close() { $streamName = $this->getStreamName(); if (null === $streamName) { return; } $name = \md5($streamName); if (!isset(self::$_register[$name])) { return; } Event::notify( 'hoa://Event/Stream/'.$streamName.':close-before', $this, new EventBucket() ); if (false === $this->_close()) { return; } unset(self::$_register[$name]); $this->_bucket[self::HANDLER] = null; Event::unregister( 'hoa://Event/Stream/'.$streamName ); Event::unregister( 'hoa://Event/Stream/'.$streamName.':close-before' ); return; } /** * Get the current stream name. */ public function getStreamName() { if (empty($this->_bucket)) { return null; } return $this->_bucket[self::NAME]; } /** * Get the current stream. */ public function getStream() { if (empty($this->_bucket)) { return null; } return $this->_bucket[self::RESOURCE]; } /** * Get the current stream context. */ public function getStreamContext() { if (empty($this->_bucket)) { return null; } return $this->_bucket[self::CONTEXT]; } /** * Get stream handler according to its name. */ public static function getStreamHandler(string $streamName) { $name = \md5($streamName); if (!isset(self::$_register[$name])) { return null; } return self::$_register[$name][self::HANDLER]; } /** * Set the current stream. Useful to manage a stack of streams (e.g. socket * and select). Notice that it could be unsafe to use this method without * taking time to think about it two minutes. Resource of type “Unknown” is * considered as valid. */ public function _setStream($stream) { if (false === \is_resource($stream) && ('resource' !== \gettype($stream) || 'Unknown' !== \get_resource_type($stream))) { throw new StreamException('Try to change the stream resource with an invalid one; '.'given %s.', 1, \gettype($stream)); } $old = $this->_bucket[self::RESOURCE]; $this->_bucket[self::RESOURCE] = $stream; return $old; } /** * Check if the stream is opened. */ public function isOpened(): bool { return \is_resource($this->getStream()); } /** * Set the timeout period. */ public function setStreamTimeout(int $seconds, int $microseconds = 0): bool { return \stream_set_timeout($this->getStream(), $seconds, $microseconds); } /** * Whether the opening of the stream has been deferred. */ protected function hasBeenDeferred() { return $this->_hasBeenDeferred; } /** * Check whether the connection has timed out or not. * This is basically a shortcut of `getStreamMetaData` + the `timed_out` * index, but the resulting code is more readable. */ public function hasTimedOut(): bool { $metaData = $this->getStreamMetaData(); return true === $metaData['timed_out']; } /** * Set blocking/non-blocking mode. */ public function setStreamBlocking(bool $mode): bool { return \stream_set_blocking($this->getStream(), $mode); } /** * Set stream buffer. * Output using fwrite() (or similar function) is normally buffered at 8 Ko. * This means that if there are two processes wanting to write to the same * output stream, each is paused after 8 Ko of data to allow the other to * write. */ public function setStreamBuffer(int $buffer): bool { // Zero means success. $out = 0 === \stream_set_write_buffer($this->getStream(), $buffer); if (true === $out) { $this->_bufferSize = $buffer; } return $out; } /** * Disable stream buffering. * Alias of $this->setBuffer(0). */ public function disableStreamBuffer(): bool { return $this->setStreamBuffer(0); } /** * Get stream buffer size. */ public function getStreamBufferSize(): int { return $this->_bufferSize; } /** * Get stream wrapper name. */ public function getStreamWrapperName(): string { if (false === $pos = \strpos($this->getStreamName(), '://')) { return 'file'; } return \substr($this->getStreamName(), 0, $pos); } /** * Get stream meta data. */ public function getStreamMetaData(): array { return \stream_get_meta_data($this->getStream()); } /** * Whether this stream is already opened by another handler. */ public function isBorrowing(): bool { return $this->_borrowing; } /** * Notification callback. */ public function _notify( int $ncode, int $severity, $message, $code, $transferred, $max ) { static $_map = [ \STREAM_NOTIFY_AUTH_REQUIRED => 'authrequire', \STREAM_NOTIFY_AUTH_RESULT => 'authresult', \STREAM_NOTIFY_COMPLETED => 'complete', \STREAM_NOTIFY_CONNECT => 'connect', \STREAM_NOTIFY_FAILURE => 'failure', \STREAM_NOTIFY_MIME_TYPE_IS => 'mimetype', \STREAM_NOTIFY_PROGRESS => 'progress', \STREAM_NOTIFY_REDIRECTED => 'redirect', \STREAM_NOTIFY_RESOLVE => 'resolve', \STREAM_NOTIFY_FILE_SIZE_IS => 'size', ]; $this->getListener()->fire($_map[$ncode], new EventBucket([ 'code' => $code, 'severity' => $severity, 'message' => $message, 'transferred' => $transferred, 'max' => $max, ])); } /** * Call the $handler->close() method on each stream in the static stream * register. * This method does not check the return value of $handler->close(). Thus, * if a stream is persistent, the $handler->close() should do anything. It * is a very generic method. */ final public static function _Hoa_Stream() { foreach (self::$_register as $entry) { $entry[self::HANDLER]->close(); } return; } /** * Transform object to string. */ public function __toString(): string { return $this->getStreamName(); } /** * Close the stream when destructing. */ public function __destruct() { if (false === $this->isOpened()) { return; } $this->close(); return; } } /** * Class \Hoa\Stream\_Protocol. * * The `hoa://Library/Stream` node. * * @license New BSD License */ class _Protocol extends ProtocolNode { /** * Component's name. * * @var string */ protected $_name = 'Stream'; /** * ID of the component. * * @param string $id ID of the component * * @return mixed */ public function reachId(string $id) { return Stream::getStreamHandler($id); } } /* * Shutdown method. */ \register_shutdown_function([Stream::class, '_Hoa_Stream']); /** * Add the `hoa://Library/Stream` node. Should be use to reach/get an entry * in the stream register. */ $protocol = Protocol::getInstance(); $protocol['Library'][] = new _Protocol(); PK������*ZB{������Readline/Hoa/Protocol.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Root of the `hoa://` protocol. */ class Protocol extends ProtocolNode { /** * No resolution value. * * @const string */ const NO_RESOLUTION = '/hoa/flatland'; /** * Singleton. */ private static $_instance = null; /** * Cache of resolver. */ private static $_cache = []; /** * Initialize the protocol. */ public function __construct() { $this->initialize(); return; } /** * Singleton. * To use the `hoa://` protocol shared by everyone. */ public static function getInstance(): self { if (null === static::$_instance) { static::$_instance = new self(); } return static::$_instance; } /** * Initialize the protocol. */ protected function initialize() { $root = \dirname(__DIR__, 3); $argv0 = isset($_SERVER['argv'][0]) ? \realpath($_SERVER['argv'][0]) : false; $cwd = 'cli' === \PHP_SAPI ? false !== $argv0 ? \dirname($argv0) : '' : \getcwd(); $this[] = new ProtocolNode( 'Application', $cwd.\DIRECTORY_SEPARATOR, [ new ProtocolNode('Public', 'Public'.\DIRECTORY_SEPARATOR), ] ); $this[] = new ProtocolNode( 'Data', \dirname($cwd).\DIRECTORY_SEPARATOR, [ new ProtocolNode( 'Etc', 'Etc'.\DIRECTORY_SEPARATOR, [ new ProtocolNode('Configuration', 'Configuration'.\DIRECTORY_SEPARATOR), new ProtocolNode('Locale', 'Locale'.\DIRECTORY_SEPARATOR), ] ), new ProtocolNode('Lost+found', 'Lost+found'.\DIRECTORY_SEPARATOR), new ProtocolNode('Temporary', 'Temporary'.\DIRECTORY_SEPARATOR), new ProtocolNode( 'Variable', 'Variable'.\DIRECTORY_SEPARATOR, [ new ProtocolNode('Cache', 'Cache'.\DIRECTORY_SEPARATOR), new ProtocolNode('Database', 'Database'.\DIRECTORY_SEPARATOR), new ProtocolNode('Log', 'Log'.\DIRECTORY_SEPARATOR), new ProtocolNode('Private', 'Private'.\DIRECTORY_SEPARATOR), new ProtocolNode('Run', 'Run'.\DIRECTORY_SEPARATOR), new ProtocolNode('Test', 'Test'.\DIRECTORY_SEPARATOR), ] ), ] ); $this[] = new ProtocolNodeLibrary( 'Library', $root.\DIRECTORY_SEPARATOR.'Hoathis'.\DIRECTORY_SEPARATOR.';'. $root.\DIRECTORY_SEPARATOR.'Hoa'.\DIRECTORY_SEPARATOR ); } /** * Resolve (unfold) an `hoa://` path to its real resource. * * If `$exists` is set to `true`, try to find the first that exists, * otherwise returns the first solution. If `$unfold` is set to `true`, * it returns all the paths. */ public function resolve(string $path, bool $exists = true, bool $unfold = false) { if (\substr($path, 0, 6) !== 'hoa://') { if (true === \is_dir($path)) { $path = \rtrim($path, '/\\'); if ('' === $path) { $path = '/'; } } return $path; } if (isset(self::$_cache[$path])) { $handle = self::$_cache[$path]; } else { $out = $this->_resolve($path, $handle); // Not a path but a resource. if (!\is_array($handle)) { return $out; } $handle = \array_values(\array_unique($handle, \SORT_REGULAR)); foreach ($handle as &$entry) { if (true === \is_dir($entry)) { $entry = \rtrim($entry, '/\\'); if ('' === $entry) { $entry = '/'; } } } self::$_cache[$path] = $handle; } if (true === $unfold) { if (true !== $exists) { return $handle; } $out = []; foreach ($handle as $solution) { if (\file_exists($solution)) { $out[] = $solution; } } return $out; } if (true !== $exists) { return $handle[0]; } foreach ($handle as $solution) { if (\file_exists($solution)) { return $solution; } } return static::NO_RESOLUTION; } /** * Clear the cache. */ public static function clearCache() { self::$_cache = []; } } PK������*Z} �� ����Readline/Hoa/Ustring.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * This class represents a UTF-8 string. * Please, see: * * http://www.ietf.org/rfc/rfc3454.txt, * * http://unicode.org/reports/tr9/, * * http://www.unicode.org/Public/6.0.0/ucd/UnicodeData.txt. */ class Ustring { /** * Check if ext/mbstring is available. */ public static function checkMbString(): bool { return \function_exists('mb_substr'); } /** * Get the number of column positions of a wide-character. * * This is a PHP implementation of wcwidth() and wcswidth() (defined in IEEE * Std 1002.1-2001) for Unicode, by Markus Kuhn. Please, see * http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c. * * The wcwidth(wc) function shall either return 0 (if wc is a null * wide-character code), or return the number of column positions to be * occupied by the wide-character code wc, or return -1 (if wc does not * correspond to a printable wide-character code). */ public static function getCharWidth(string $char): int { $char = (string) $char; $c = static::toCode($char); // Test for 8-bit control characters. if (0x0 === $c) { return 0; } if (0x20 > $c || (0x7F <= $c && $c < 0xA0)) { return -1; } // Non-spacing characters. if (0xAD !== $c && 0 !== \preg_match('#^[\p{Mn}\p{Me}\p{Cf}\x{1160}-\x{11ff}\x{200b}]#u', $char)) { return 0; } // If we arrive here, $c is not a combining C0/C1 control character. return 1 + (0x1100 <= $c && (0x115F >= $c || // Hangul Jamo init. consonants 0x2329 === $c || 0x232A === $c || (0x2E80 <= $c && 0xA4CF >= $c && 0x303F !== $c) || // CJK…Yi (0xAC00 <= $c && 0xD7A3 >= $c) || // Hangul Syllables (0xF900 <= $c && 0xFAFF >= $c) || // CJK Compatibility Ideographs (0xFE10 <= $c && 0xFE19 >= $c) || // Vertical forms (0xFE30 <= $c && 0xFE6F >= $c) || // CJK Compatibility Forms (0xFF00 <= $c && 0xFF60 >= $c) || // Fullwidth Forms (0xFFE0 <= $c && 0xFFE6 >= $c) || (0x20000 <= $c && 0x2FFFD >= $c) || (0x30000 <= $c && 0x3FFFD >= $c))); } /** * Check whether the character is printable or not. */ public static function isCharPrintable(string $char): bool { return 1 <= static::getCharWidth($char); } /** * Get a decimal code representation of a specific character. */ public static function toCode(string $char): int { $char = (string) $char; $code = \ord($char[0]); $bytes = 1; if (!($code & 0x80)) { // 0xxxxxxx return $code; } if (($code & 0xE0) === 0xC0) { // 110xxxxx $bytes = 2; $code = $code & ~0xC0; } elseif (($code & 0xF0) === 0xE0) { // 1110xxxx $bytes = 3; $code = $code & ~0xE0; } elseif (($code & 0xF8) === 0xF0) { // 11110xxx $bytes = 4; $code = $code & ~0xF0; } for ($i = 2; $i <= $bytes; $i++) { // 10xxxxxx $code = ($code << 6) + (\ord($char[$i - 1]) & ~0x80); } return $code; } } PK������*ZDQ��Q����Readline/Hoa/FileRead.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Class \Hoa\File\Read. * * File handler. */ class FileRead extends File implements StreamIn { /** * Open a file. */ public function __construct( string $streamName, string $mode = parent::MODE_READ, ?string $context = null, bool $wait = false ) { parent::__construct($streamName, $mode, $context, $wait); return; } /** * Open the stream and return the associated resource. */ protected function &_open(string $streamName, ?StreamContext $context = null) { static $createModes = [ parent::MODE_READ, ]; if (!\in_array($this->getMode(), $createModes)) { throw new FileException('Open mode are not supported; given %d. Only %s are supported.', 0, [$this->getMode(), \implode(', ', $createModes)]); } \preg_match('#^(\w+)://#', $streamName, $match); if (((isset($match[1]) && $match[1] === 'file') || !isset($match[1])) && !\file_exists($streamName)) { throw new FileDoesNotExistException('File %s does not exist.', 1, $streamName); } $out = parent::_open($streamName, $context); return $out; } /** * Test for end-of-file. */ public function eof(): bool { return \feof($this->getStream()); } /** * Read n characters. */ public function read(int $length) { if (0 > $length) { throw new FileException('Length must be greater than 0, given %d.', 2, $length); } return \fread($this->getStream(), $length); } /** * Alias of $this->read(). */ public function readString(int $length) { return $this->read($length); } /** * Read a character. */ public function readCharacter() { return \fgetc($this->getStream()); } /** * Read a boolean. */ public function readBoolean() { return (bool) $this->read(1); } /** * Read an integer. */ public function readInteger(int $length = 1) { return (int) $this->read($length); } /** * Read a float. */ public function readFloat(int $length = 1) { return (float) $this->read($length); } /** * Read an array. * Alias of the $this->scanf() method. */ public function readArray(?string $format = null) { return $this->scanf($format); } /** * Read a line. */ public function readLine() { return \fgets($this->getStream()); } /** * Read all, i.e. read as much as possible. */ public function readAll(int $offset = 0) { return \stream_get_contents($this->getStream(), -1, $offset); } /** * Parse input from a stream according to a format. */ public function scanf(string $format): array { return \fscanf($this->getStream(), $format); } } PK������*Z.0 ��0 ����Readline/Hoa/StreamLockable.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Interface \Hoa\Stream\IStream\Lockable. * * Interface for lockable input/output. * * @license New BSD License */ interface StreamLockable extends IStream { /** * Acquire a shared lock (reader). * * @const int */ const LOCK_SHARED = \LOCK_SH; /** * Acquire an exclusive lock (writer). * * @const int */ const LOCK_EXCLUSIVE = \LOCK_EX; /** * Release a lock (shared or exclusive). * * @const int */ const LOCK_RELEASE = \LOCK_UN; /** * If we do not want $this->lock() to block while locking. * * @const int */ const LOCK_NO_BLOCK = \LOCK_NB; /** * Portable advisory locking. * Should take a look at stream_supports_lock(). * * @param int $operation operation, use the self::LOCK_* constants * * @return bool */ public function lock(int $operation): bool; } PK������*Z �� ��#��Readline/Hoa/IteratorFileSystem.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Class \Hoa\Iterator\FileSystem. * * Extending the SPL FileSystemIterator class. */ class IteratorFileSystem extends \FilesystemIterator { /** * SplFileInfo classname. */ protected $_splFileInfoClass = null; /** * Constructor. * Please, see \FileSystemIterator::__construct() method. * We add the $splFileInfoClass parameter. */ public function __construct(string $path, ?int $flags = null, ?string $splFileInfoClass = null) { $this->_splFileInfoClass = $splFileInfoClass; if (null === $flags) { parent::__construct($path); } else { parent::__construct($path, $flags); } return; } /** * Current. * Please, see \FileSystemIterator::current() method. */ #[\ReturnTypeWillChange] public function current() { $out = parent::current(); if (null !== $this->_splFileInfoClass && $out instanceof \SplFileInfo) { $out->setInfoClass($this->_splFileInfoClass); $out = $out->getFileInfo(); } return $out; } } PK������*Zi}�G��G����Readline/Hoa/IStream.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Interface \Hoa\Stream\IStream\Stream. * * Interface for all streams. */ interface IStream { /** * Get the current stream. */ public function getStream(); } PK������*Z+������Readline/Hoa/ProtocolNode.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Abstract class for all `hoa://`'s nodes. */ class ProtocolNode implements \ArrayAccess, \IteratorAggregate { /** * Node's name. */ protected $_name = null; /** * Path for the `reach` method. */ protected $_reach = null; /** * Children of the node. */ private $_children = []; /** * Construct a protocol's node. * If it is not a data object (i.e. if it does not extend this class to * overload the `$_name` attribute), we can set the `$_name` attribute * dynamically. This is useful to create a node on-the-fly. */ public function __construct(?string $name = null, ?string $reach = null, array $children = []) { if (null !== $name) { $this->_name = $name; } if (null !== $reach) { $this->_reach = $reach; } foreach ($children as $child) { $this[] = $child; } return; } /** * Add a node. */ #[\ReturnTypeWillChange] public function offsetSet($name, $node) { if (!($node instanceof self)) { throw new ProtocolException('Protocol node must extend %s.', 0, __CLASS__); } if (empty($name)) { $name = $node->getName(); } if (empty($name)) { throw new ProtocolException('Cannot add a node to the `hoa://` protocol without a name.', 1); } $this->_children[$name] = $node; } /** * Get a specific node. */ public function offsetGet($name): self { if (!isset($this[$name])) { throw new ProtocolException('Node %s does not exist.', 2, $name); } return $this->_children[$name]; } /** * Check if a node exists. */ public function offsetExists($name): bool { return true === \array_key_exists($name, $this->_children); } /** * Remove a node. */ #[\ReturnTypeWillChange] public function offsetUnset($name) { unset($this->_children[$name]); } /** * Resolve a path, i.e. iterate the nodes tree and reach the queue of * the path. */ protected function _resolve(string $path, &$accumulator, ?string $id = null) { if (\substr($path, 0, 6) === 'hoa://') { $path = \substr($path, 6); } if (empty($path)) { return null; } if (null === $accumulator) { $accumulator = []; $posId = \strpos($path, '#'); if (false !== $posId) { $id = \substr($path, $posId + 1); $path = \substr($path, 0, $posId); } else { $id = null; } } $path = \trim($path, '/'); $pos = \strpos($path, '/'); if (false !== $pos) { $next = \substr($path, 0, $pos); } else { $next = $path; } if (isset($this[$next])) { if (false === $pos) { if (null === $id) { $this->_resolveChoice($this[$next]->reach(), $accumulator); return true; } $accumulator = null; return $this[$next]->reachId($id); } $tnext = $this[$next]; $this->_resolveChoice($tnext->reach(), $accumulator); return $tnext->_resolve(\substr($path, $pos + 1), $accumulator, $id); } $this->_resolveChoice($this->reach($path), $accumulator); return true; } /** * Resolve choices, i.e. a reach value has a “;”. */ protected function _resolveChoice($reach, &$accumulator) { if (null === $reach) { $reach = ''; } if (empty($accumulator)) { $accumulator = \explode(';', $reach); return; } if (false === \strpos($reach, ';')) { if (false !== $pos = \strrpos($reach, "\r")) { $reach = \substr($reach, $pos + 1); foreach ($accumulator as &$entry) { $entry = null; } } foreach ($accumulator as &$entry) { $entry .= $reach; } return; } $choices = \explode(';', $reach); $ref = $accumulator; $accumulator = []; foreach ($choices as $choice) { if (false !== $pos = \strrpos($choice, "\r")) { $choice = \substr($choice, $pos + 1); foreach ($ref as $entry) { $accumulator[] = $choice; } } else { foreach ($ref as $entry) { $accumulator[] = $entry.$choice; } } } unset($ref); return; } /** * Queue of the node. * Generic one. Must be overrided in children classes. */ public function reach(?string $queue = null) { return empty($queue) ? $this->_reach : $queue; } /** * ID of the component. * Generic one. Should be overrided in children classes. */ public function reachId(string $id) { throw new ProtocolException('The node %s has no ID support (tried to reach #%s).', 4, [$this->getName(), $id]); } /** * Set a new reach value. */ public function setReach(string $reach) { $old = $this->_reach; $this->_reach = $reach; return $old; } /** * Get node's name. */ public function getName() { return $this->_name; } /** * Get reach's root. */ protected function getReach() { return $this->_reach; } /** * Get an iterator. */ public function getIterator(): \ArrayIterator { return new \ArrayIterator($this->_children); } /** * Get root the protocol. */ public static function getRoot(): Protocol { return Protocol::getInstance(); } /** * Print a tree of component. */ public function __toString(): string { static $i = 0; $out = \str_repeat(' ', $i).$this->getName()."\n"; foreach ($this as $node) { ++$i; $out .= $node; --$i; } return $out; } } PK������*ZuA��A��"��Readline/Hoa/FileLinkReadWrite.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Class \Hoa\File\Link\ReadWrite. * * File handler. */ class FileLinkReadWrite extends FileLink implements StreamIn, StreamOut { /** * Open a file. */ public function __construct( string $streamName, string $mode = parent::MODE_APPEND_READ_WRITE, ?string $context = null, bool $wait = false ) { parent::__construct($streamName, $mode, $context, $wait); return; } /** * Open the stream and return the associated resource. */ protected function &_open(string $streamName, ?StreamContext $context = null) { static $createModes = [ parent::MODE_READ_WRITE, parent::MODE_TRUNCATE_READ_WRITE, parent::MODE_APPEND_READ_WRITE, parent::MODE_CREATE_READ_WRITE, ]; if (!\in_array($this->getMode(), $createModes)) { throw new FileException('Open mode are not supported; given %d. Only %s are supported.', 0, [$this->getMode(), \implode(', ', $createModes)]); } \preg_match('#^(\w+)://#', $streamName, $match); if (((isset($match[1]) && $match[1] === 'file') || !isset($match[1])) && !\file_exists($streamName) && parent::MODE_READ_WRITE === $this->getMode()) { throw new FileDoesNotExistException('File %s does not exist.', 1, $streamName); } $out = parent::_open($streamName, $context); return $out; } /** * Test for end-of-file. */ public function eof(): bool { return \feof($this->getStream()); } /** * Read n characters. */ public function read(int $length) { if (0 > $length) { throw new FileException('Length must be greater than 0, given %d.', 2, $length); } return \fread($this->getStream(), $length); } /** * Alias of $this->read(). */ public function readString(int $length) { return $this->read($length); } /** * Read a character. */ public function readCharacter() { return \fgetc($this->getStream()); } /** * Read a boolean. */ public function readBoolean() { return (bool) $this->read(1); } /** * Read an integer. */ public function readInteger(int $length = 1) { return (int) $this->read($length); } /** * Read a float. */ public function readFloat(int $length = 1) { return (float) $this->read($length); } /** * Read an array. * Alias of the $this->scanf() method. */ public function readArray(?string $format = null) { return $this->scanf($format); } /** * Read a line. */ public function readLine() { return \fgets($this->getStream()); } /** * Read all, i.e. read as much as possible. */ public function readAll(int $offset = 0) { return \stream_get_contents($this->getStream(), -1, $offset); } /** * Parse input from a stream according to a format. */ public function scanf(string $format): array { return \fscanf($this->getStream(), $format); } /** * Write n characters. */ public function write(string $string, int $length) { if (0 > $length) { throw new FileException('Length must be greater than 0, given %d.', 3, $length); } return \fwrite($this->getStream(), $string, $length); } /** * Write a string. */ public function writeString(string $string) { $string = (string) $string; return $this->write($string, \strlen($string)); } /** * Write a character. */ public function writeCharacter(string $char) { return $this->write((string) $char[0], 1); } /** * Write a boolean. */ public function writeBoolean(bool $boolean) { return $this->write((string) (bool) $boolean, 1); } /** * Write an integer. */ public function writeInteger(int $integer) { $integer = (string) (int) $integer; return $this->write($integer, \strlen($integer)); } /** * Write a float. */ public function writeFloat(float $float) { $float = (string) (float) $float; return $this->write($float, \strlen($float)); } /** * Write an array. */ public function writeArray(array $array) { $array = \var_export($array, true); return $this->write($array, \strlen($array)); } /** * Write a line. */ public function writeLine(string $line) { if (false === $n = \strpos($line, "\n")) { return $this->write($line."\n", \strlen($line) + 1); } ++$n; return $this->write(\substr($line, 0, $n), $n); } /** * Write all, i.e. as much as possible. */ public function writeAll(string $string) { return $this->write($string, \strlen($string)); } /** * Truncate a file to a given length. */ public function truncate(int $size): bool { return \ftruncate($this->getStream(), $size); } } PK������*Z2Q��Q��*��Readline/Hoa/FileDoesNotExistException.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Class \Hoa\File\Exception\FileDoesNotExist. * * Extending the \Hoa\File\Exception class. * * @license New BSD License */ class FileDoesNotExistException extends FileException { } PK������*Z,QX ��X ����Readline/Hoa/EventListens.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Implementation of a listener. */ trait EventListens { /** * Listener instance of type `Hoa\Event\Listener`. */ protected $_listener = null; /** * Attaches a callable to a listenable component. */ public function on(string $listenerId, $callable): EventListenable { $listener = $this->getListener(); if (null === $listener) { throw new EventException('Cannot attach a callable to the listener %s because '.'it has not been initialized yet.', 0, static::class); } $listener->attach($listenerId, $callable); return $this; } /** * Sets a new listener. */ protected function setListener(EventListener $listener) { $old = $this->_listener; $this->_listener = $listener; return $old; } /** * Returns the listener. */ protected function getListener() { return $this->_listener; } } PK������*Z-Y` �� ��'��Readline/Hoa/AutocompleterAggregate.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Class \Hoa\Console\Readline\Autocompleter\Aggregate. * * Aggregate several autocompleters. */ class AutocompleterAggregate implements Autocompleter { /** * List of autocompleters. */ protected $_autocompleters = null; /** * Constructor. */ public function __construct(array $autocompleters) { $this->setAutocompleters($autocompleters); return; } /** * Complete a word. * Returns null for no word, a full-word or an array of full-words. */ public function complete(&$prefix) { foreach ($this->getAutocompleters() as $autocompleter) { $preg = \preg_match( '#('.$autocompleter->getWordDefinition().')$#u', $prefix, $match ); if (0 === $preg) { continue; } $_prefix = $match[0]; if (null === $out = $autocompleter->complete($_prefix)) { continue; } $prefix = $_prefix; return $out; } return null; } /** * Set/initialize list of autocompleters. */ protected function setAutocompleters(array $autocompleters) { $old = $this->_autocompleters; $this->_autocompleters = new \ArrayObject($autocompleters); return $old; } /** * Get list of autocompleters. */ public function getAutocompleters() { return $this->_autocompleters; } /** * Get definition of a word. */ public function getWordDefinition(): string { return '.*'; } } PK������*ZGʰQ������Readline/Hoa/FileLink.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Class \Hoa\File\Link. * * Link handler. */ class FileLink extends File { /** * Open a link. */ public function __construct( string $streamName, string $mode, ?string $context = null, bool $wait = false ) { if (!\is_link($streamName)) { throw new FileException('File %s is not a link.', 0, $streamName); } parent::__construct($streamName, $mode, $context, $wait); return; } /** * Get informations about a link. */ public function getStatistic(): array { return \lstat($this->getStreamName()); } /** * Change file group. */ public function changeGroup($group): bool { return \lchgrp($this->getStreamName(), $group); } /** * Change file owner. */ public function changeOwner($user): bool { return \lchown($this->getStreamName(), $user); } /** * Get file permissions. */ public function getPermissions(): int { return 41453; // i.e. lrwxr-xr-x } /** * Get the target of a symbolic link. */ public function getTarget(): FileGeneric { $target = \dirname($this->getStreamName()).\DIRECTORY_SEPARATOR. $this->getTargetName(); $context = null !== $this->getStreamContext() ? $this->getStreamContext()->getCurrentId() : null; if (true === \is_link($target)) { return new FileLinkReadWrite( $target, File::MODE_APPEND_READ_WRITE, $context ); } elseif (true === \is_file($target)) { return new FileReadWrite( $target, File::MODE_APPEND_READ_WRITE, $context ); } elseif (true === \is_dir($target)) { return new FileDirectory( $target, File::MODE_READ, $context ); } throw new FileException('Cannot find an appropriated object that matches with '.'path %s when defining it.', 1, $target); } /** * Get the target name of a symbolic link. */ public function getTargetName(): string { return \readlink($this->getStreamName()); } /** * Create a link. */ public static function create(string $name, string $target): bool { if (false !== \linkinfo($name)) { return true; } return \symlink($target, $name); } } PK������*ZzX��X����Readline/Hoa/FileDirectory.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Class \Hoa\File\Directory. * * Directory handler. */ class FileDirectory extends FileGeneric { /** * Open for reading. */ const MODE_READ = 'rb'; /** * Open for reading and writing. If the directory does not exist, attempt to * create it. */ const MODE_CREATE = 'xb'; /** * Open for reading and writing. If the directory does not exist, attempt to * create it recursively. */ const MODE_CREATE_RECURSIVE = 'xrb'; /** * Open a directory. */ public function __construct( string $streamName, string $mode = self::MODE_READ, ?string $context = null, bool $wait = false ) { $this->setMode($mode); parent::__construct($streamName, $context, $wait); return; } /** * Open the stream and return the associated resource. */ protected function &_open(string $streamName, ?StreamContext $context = null) { if (false === \is_dir($streamName)) { if ($this->getMode() === self::MODE_READ) { throw new FileDoesNotExistException('Directory %s does not exist.', 0, $streamName); } else { self::create( $streamName, $this->getMode(), null !== $context ? $context->getContext() : null ); } } $out = null; return $out; } /** * Close the current stream. */ protected function _close(): bool { return true; } /** * Recursive copy of a directory. */ public function copy(string $to, bool $force = StreamTouchable::DO_NOT_OVERWRITE): bool { if (empty($to)) { throw new FileException('The destination path (to copy) is empty.', 1); } $from = $this->getStreamName(); $fromLength = \strlen($from) + 1; $finder = new FileFinder(); $finder->in($from); self::create($to, self::MODE_CREATE_RECURSIVE); foreach ($finder as $file) { $relative = \substr($file->getPathname(), $fromLength); $_to = $to.\DIRECTORY_SEPARATOR.$relative; if (true === $file->isDir()) { self::create($_to, self::MODE_CREATE); continue; } // This is not possible to do `$file->open()->copy(); // $file->close();` because the file will be opened in read and // write mode. In a PHAR for instance, this operation is // forbidden. So a special care must be taken to open file in read // only mode. $handle = null; if (true === $file->isFile()) { $handle = new FileRead($file->getPathname()); } elseif (true === $file->isDir()) { $handle = new self($file->getPathName()); } elseif (true === $file->isLink()) { $handle = new FileLinkRead($file->getPathName()); } if (null !== $handle) { $handle->copy($_to, $force); $handle->close(); } } return true; } /** * Delete a directory. */ public function delete(): bool { $from = $this->getStreamName(); $finder = new FileFinder(); $finder->in($from) ->childFirst(); foreach ($finder as $file) { $file->open()->delete(); $file->close(); } if (null === $this->getStreamContext()) { return @\rmdir($from); } return @\rmdir($from, $this->getStreamContext()->getContext()); } /** * Create a directory. */ public static function create( string $name, string $mode = self::MODE_CREATE_RECURSIVE, ?string $context = null ): bool { if (true === \is_dir($name)) { return true; } if (empty($name)) { return false; } if (null !== $context) { if (false === StreamContext::contextExists($context)) { throw new FileException('Context %s was not previously declared, cannot retrieve '.'this context.', 2, $context); } else { $context = StreamContext::getInstance($context); } } if (null === $context) { return @\mkdir( $name, 0755, self::MODE_CREATE_RECURSIVE === $mode ); } return @\mkdir( $name, 0755, self::MODE_CREATE_RECURSIVE === $mode, $context->getContext() ); } } PK������*Z3R:5��5�� ��Readline/Hoa/ProtocolWrapper.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Stream wrapper for the `hoa://` protocol. */ class ProtocolWrapper { /** * Opened stream as a resource. */ private $_stream = null; /** * Stream name (filename). */ private $_streamName = null; /** * Stream context (given by the streamWrapper class) as a resource. */ public $context = null; /** * Get the real path of the given URL. * Could return false if the path cannot be reached. */ public static function realPath(string $path, bool $exists = true) { return ProtocolNode::getRoot()->resolve($path, $exists); } /** * Retrieve the underlying resource. * * `$castAs` can be `STREAM_CAST_FOR_SELECT` when `stream_select` is * calling `stream_cast` or `STREAM_CAST_AS_STREAM` when `stream_cast` is * called for other uses. */ public function stream_cast(int $castAs) { return null; } /** * Closes a resource. * This method is called in response to `fclose`. * All resources that were locked, or allocated, by the wrapper should be * released. */ public function stream_close() { if (true === @\fclose($this->getStream())) { $this->_stream = null; $this->_streamName = null; } } /** * Tests for end-of-file on a file pointer. * This method is called in response to feof(). */ public function stream_eof(): bool { return \feof($this->getStream()); } /** * Flush the output. * This method is called in respond to fflush(). * If we have cached data in our stream but not yet stored it into the * underlying storage, we should do so now. */ public function stream_flush(): bool { return \fflush($this->getStream()); } /** * Advisory file locking. * This method is called in response to flock(), when file_put_contents() * (when flags contains LOCK_EX), stream_set_blocking() and when closing the * stream (LOCK_UN). * * Operation is one the following: * * LOCK_SH to acquire a shared lock (reader) ; * * LOCK_EX to acquire an exclusive lock (writer) ; * * LOCK_UN to release a lock (shared or exclusive) ; * * LOCK_NB if we don't want flock() to * block while locking (not supported on * Windows). */ public function stream_lock(int $operation): bool { return \flock($this->getStream(), $operation); } /** * Change stream options. * This method is called to set metadata on the stream. It is called when * one of the following functions is called on a stream URL: touch, chmod, * chown or chgrp. * * Option must be one of the following constant: * * STREAM_META_TOUCH, * * STREAM_META_OWNER_NAME, * * STREAM_META_OWNER, * * STREAM_META_GROUP_NAME, * * STREAM_META_GROUP, * * STREAM_META_ACCESS. * * Values are arguments of `touch`, `chmod`, `chown`, and `chgrp`. */ public function stream_metadata(string $path, int $option, $values): bool { $path = static::realPath($path, false); switch ($option) { case \STREAM_META_TOUCH: $arity = \count($values); if (0 === $arity) { $out = \touch($path); } elseif (1 === $arity) { $out = \touch($path, $values[0]); } else { $out = \touch($path, $values[0], $values[1]); } break; case \STREAM_META_OWNER_NAME: case \STREAM_META_OWNER: $out = \chown($path, $values); break; case \STREAM_META_GROUP_NAME: case \STREAM_META_GROUP: $out = \chgrp($path, $values); break; case \STREAM_META_ACCESS: $out = \chmod($path, $values); break; default: $out = false; } return $out; } /** * Open file or URL. * This method is called immediately after the wrapper is initialized (f.e. * by fopen() and file_get_contents()). */ public function stream_open(string $path, string $mode, int $options, &$openedPath): bool { $path = static::realPath($path, 'r' === $mode[0]); if (Protocol::NO_RESOLUTION === $path) { return false; } if (null === $this->context) { $openedPath = \fopen($path, $mode, $options & \STREAM_USE_PATH); } else { $openedPath = \fopen( $path, $mode, (bool) ($options & \STREAM_USE_PATH), $this->context ); } if (false === \is_resource($openedPath)) { return false; } $this->_stream = $openedPath; $this->_streamName = $path; return true; } /** * Read from stream. * This method is called in response to fread() and fgets(). */ public function stream_read(int $size): string { return \fread($this->getStream(), $size); } /** * Seek to specific location in a stream. * This method is called in response to fseek(). * The read/write position of the stream should be updated according to the * $offset and $whence. * * The possible values for `$whence` are: * * SEEK_SET to set position equal to $offset bytes, * * SEEK_CUR to set position to current location plus `$offset`, * * SEEK_END to set position to end-of-file plus `$offset`. */ public function stream_seek(int $offset, int $whence = \SEEK_SET): bool { return 0 === \fseek($this->getStream(), $offset, $whence); } /** * Retrieve information about a file resource. * This method is called in response to fstat(). */ public function stream_stat(): array { return \fstat($this->getStream()); } /** * Retrieve the current position of a stream. * This method is called in response to ftell(). */ public function stream_tell(): int { return \ftell($this->getStream()); } /** * Truncate a stream to a given length. */ public function stream_truncate(int $size): bool { return \ftruncate($this->getStream(), $size); } /** * Write to stream. * This method is called in response to fwrite(). */ public function stream_write(string $data): int { return \fwrite($this->getStream(), $data); } /** * Close directory handle. * This method is called in to closedir(). * Any resources which were locked, or allocated, during opening and use of * the directory stream should be released. */ public function dir_closedir() { \closedir($this->getStream()); $this->_stream = null; $this->_streamName = null; } /** * Open directory handle. * This method is called in response to opendir(). * * The `$options` input represents whether or not to enforce safe_mode * (0x04). It is not used here. */ public function dir_opendir(string $path, int $options): bool { $path = static::realPath($path); $handle = null; if (null === $this->context) { $handle = @\opendir($path); } else { $handle = @\opendir($path, $this->context); } if (false === $handle) { return false; } $this->_stream = $handle; $this->_streamName = $path; return true; } /** * Read entry from directory handle. * This method is called in response to readdir(). * * @return mixed */ public function dir_readdir() { return \readdir($this->getStream()); } /** * Rewind directory handle. * This method is called in response to rewinddir(). * Should reset the output generated by self::dir_readdir, i.e. the next * call to self::dir_readdir should return the first entry in the location * returned by self::dir_opendir. */ public function dir_rewinddir() { \rewinddir($this->getStream()); } /** * Create a directory. * This method is called in response to mkdir(). */ public function mkdir(string $path, int $mode, int $options): bool { if (null === $this->context) { return \mkdir( static::realPath($path, false), $mode, $options | \STREAM_MKDIR_RECURSIVE ); } return \mkdir( static::realPath($path, false), $mode, (bool) ($options | \STREAM_MKDIR_RECURSIVE), $this->context ); } /** * Rename a file or directory. * This method is called in response to rename(). * Should attempt to rename $from to $to. */ public function rename(string $from, string $to): bool { if (null === $this->context) { return \rename(static::realPath($from), static::realPath($to, false)); } return \rename( static::realPath($from), static::realPath($to, false), $this->context ); } /** * Remove a directory. * This method is called in response to rmdir(). * The `$options` input is a bitwise mask of values. It is not used here. */ public function rmdir(string $path, int $options): bool { if (null === $this->context) { return \rmdir(static::realPath($path)); } return \rmdir(static::realPath($path), $this->context); } /** * Delete a file. * This method is called in response to unlink(). */ public function unlink(string $path): bool { if (null === $this->context) { return \unlink(static::realPath($path)); } return \unlink(static::realPath($path), $this->context); } /** * Retrieve information about a file. * This method is called in response to all stat() related functions. * The `$flags` input holds additional flags set by the streams API. It * can hold one or more of the following values OR'd together. * STREAM_URL_STAT_LINK: for resource with the ability to link to other * resource (such as an HTTP location: forward, or a filesystem * symlink). This flag specified that only information about the link * itself should be returned, not the resource pointed to by the * link. This flag is set in response to calls to lstat(), is_link(), or * filetype(). STREAM_URL_STAT_QUIET: if this flag is set, our wrapper * should not raise any errors. If this flag is not set, we are * responsible for reporting errors using the trigger_error() function * during stating of the path. */ public function url_stat(string $path, int $flags) { $path = static::realPath($path); if (Protocol::NO_RESOLUTION === $path) { if ($flags & \STREAM_URL_STAT_QUIET) { return 0; } else { return \trigger_error( 'Path '.$path.' cannot be resolved.', \E_WARNING ); } } if ($flags & \STREAM_URL_STAT_LINK) { return @\lstat($path); } return @\stat($path); } /** * Get stream resource. */ public function getStream() { return $this->_stream; } /** * Get stream name. */ public function getStreamName() { return $this->_streamName; } } /* * Register the `hoa://` protocol. */ \stream_wrapper_register('hoa', ProtocolWrapper::class); PK������*Z>Wd �� ����Readline/Hoa/EventBucket.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * This class is the object which is transmit through event channels. */ class EventBucket { /** * The source object (must be of kind `Hoa\Event\Source`). */ protected $_source = null; /** * Data attached to the bucket. */ protected $_data = null; /** * Allocates a new bucket with various data attached to it. */ public function __construct($data = null) { $this->setData($data); return; } /** * Sends this object on the event channel. */ public function send(string $eventId, EventSource $source) { return Event::notify($eventId, $source, $this); } /** * Sets a new source. */ public function setSource(EventSource $source) { $old = $this->_source; $this->_source = $source; return $old; } /** * Returns the source. */ public function getSource() { return $this->_source; } /** * Sets new data. */ public function setData($data) { $old = $this->_data; $this->_data = $data; return $old; } /** * Returns the data. */ public function getData() { return $this->_data; } } PK������*Zk}T��T����Readline/Hoa/Autocompleter.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Interface \Hoa\Console\Readline\Autocompleter. * * Interface for all auto-completers. */ interface Autocompleter { /** * Complete a word. * Returns null for no word, a full-word or an array of full-words. */ public function complete(&$prefix); /** * Get definition of a word. * Example: \b\w+\b. PCRE delimiters and options must not be provided. */ public function getWordDefinition(): string; } PK������*Z������Readline/Hoa/Xcallable.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Build a callable object, i.e. `function`, `class::method`, `object->method` or * closure. They all have the same behaviour. This callable is an extension of * native PHP callable (aka callback) to integrate Hoa's structures. */ class Xcallable { /** * Callback with the PHP format. */ protected $_callback = null; /** * Callable hash. */ protected $_hash = null; /** * Allocates a xcallable based on a callback. * * Accepted forms: * * `'function'`, * * `'class::method'`, * * `'class', 'method'`, * * `$object, 'method'`, * * `$object, ''`, * * `function (…) { … }`, * * `['class', 'method']`, * * `[$object, 'method']`. * * # Examples * * ```php * $toUpper = new Hoa\Consistency\Xcallable('strtoupper'); * assert('FOO' === $toUpper('foo')); * ``` * * # Exceptions * * A `Hoa\Consistency\Exception` exception is thrown if the callback form * is invalid. * * ```php,must_throw(Hoa\Consistency\Exception) * new Hoa\Consistency\Xcallable('Foo:'); * ``` */ public function __construct($call, $able = '') { if ($call instanceof \Closure) { $this->_callback = $call; return; } if (!\is_string($able)) { throw new Exception('Bad callback form; the able part must be a string.', 0); } if ('' === $able) { if (\is_string($call)) { if (false === \strpos($call, '::')) { if (!\function_exists($call)) { throw new Exception('Bad callback form; function %s does not exist.', 1, $call); } $this->_callback = $call; return; } list($call, $able) = \explode('::', $call); } elseif (\is_object($call)) { if ($call instanceof StreamOut) { $able = null; } elseif (\method_exists($call, '__invoke')) { $able = '__invoke'; } else { throw new Exception('Bad callback form; an object but without a known '.'method.', 2); } } elseif (\is_array($call) && isset($call[0])) { if (!isset($call[1])) { $this->__construct($call[0]); return; } $this->__construct($call[0], $call[1]); return; } else { throw new Exception('Bad callback form.', 3); } } $this->_callback = [$call, $able]; return; } /** * Calls the callable. */ public function __invoke(...$arguments) { $callback = $this->getValidCallback($arguments); return $callback(...$arguments); } /** * Returns a valid PHP callback. */ public function getValidCallback(array &$arguments = []) { $callback = $this->_callback; $head = null; if (isset($arguments[0])) { $head = &$arguments[0]; } // If method is undetermined, we find it (we understand event bucket and // stream). if (null !== $head && \is_array($callback) && null === $callback[1]) { if ($head instanceof EventBucket) { $head = $head->getData(); } switch ($type = \gettype($head)) { case 'string': if (1 === \strlen($head)) { $method = 'writeCharacter'; } else { $method = 'writeString'; } break; case 'boolean': case 'integer': case 'array': $method = 'write'.\ucfirst($type); break; case 'double': $method = 'writeFloat'; break; default: $method = 'writeAll'; $head = $head."\n"; } $callback[1] = $method; } return $callback; } /** * Computes the hash of this callable. * * Will produce: * * `function#…`, * * `class#…::…`, * * `object(…)#…::…`, * * `closure(…)`. */ public function getHash(): string { if (null !== $this->_hash) { return $this->_hash; } $_ = &$this->_callback; if (\is_string($_)) { return $this->_hash = 'function#'.$_; } if (\is_array($_)) { return $this->_hash = (\is_object($_[0]) ? 'object('.\spl_object_hash($_[0]).')'. '#'.\get_class($_[0]) : 'class#'.$_[0]). '::'. (null !== $_[1] ? $_[1] : '???'); } return $this->_hash = 'closure('.\spl_object_hash($_).')'; } /** * The string representation of a callable is its hash. */ public function __toString(): string { return $this->getHash(); } /** * Hoa's xcallable() helper. */ public static function from($call, $able = '') { if ($call instanceof self) { return $call; } return new self($call, $able); } } PK������*ZQd���� ��Readline/Hoa/StreamException.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Class \Hoa\Stream\Exception. * * Extending the \Hoa\Exception\Exception class. */ class StreamException extends Exception { } PK������*Z 4��4����Readline/Hoa/FileReadWrite.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Class \Hoa\File\ReadWrite. * * File handler. */ class FileReadWrite extends File implements StreamIn, StreamOut { /** * Open a file. */ public function __construct( string $streamName, string $mode = parent::MODE_APPEND_READ_WRITE, ?string $context = null, bool $wait = false ) { parent::__construct($streamName, $mode, $context, $wait); return; } /** * Open the stream and return the associated resource. */ protected function &_open(string $streamName, ?StreamContext $context = null) { static $createModes = [ parent::MODE_READ_WRITE, parent::MODE_TRUNCATE_READ_WRITE, parent::MODE_APPEND_READ_WRITE, parent::MODE_CREATE_READ_WRITE, ]; if (!\in_array($this->getMode(), $createModes)) { throw new FileException('Open mode are not supported; given %d. Only %s are supported.', 0, [$this->getMode(), \implode(', ', $createModes)]); } \preg_match('#^(\w+)://#', $streamName, $match); if (((isset($match[1]) && $match[1] === 'file') || !isset($match[1])) && !\file_exists($streamName) && parent::MODE_READ_WRITE === $this->getMode()) { throw new FileDoesNotExistException('File %s does not exist.', 1, $streamName); } $out = parent::_open($streamName, $context); return $out; } /** * Test for end-of-file. */ public function eof(): bool { return \feof($this->getStream()); } /** * Read n characters. */ public function read(int $length) { if (0 > $length) { throw new FileException('Length must be greater than 0, given %d.', 2, $length); } return \fread($this->getStream(), $length); } /** * Alias of $this->read(). */ public function readString(int $length) { return $this->read($length); } /** * Read a character. */ public function readCharacter() { return \fgetc($this->getStream()); } /** * Read a boolean. */ public function readBoolean() { return (bool) $this->read(1); } /** * Read an integer. */ public function readInteger(int $length = 1) { return (int) $this->read($length); } /** * Read a float. */ public function readFloat(int $length = 1) { return (float) $this->read($length); } /** * Read an array. * Alias of the $this->scanf() method. */ public function readArray(?string $format = null) { return $this->scanf($format); } /** * Read a line. */ public function readLine() { return \fgets($this->getStream()); } /** * Read all, i.e. read as much as possible. */ public function readAll(int $offset = 0) { return \stream_get_contents($this->getStream(), -1, $offset); } /** * Parse input from a stream according to a format. */ public function scanf(string $format): array { return \fscanf($this->getStream(), $format); } /** * Write n characters. */ public function write(string $string, int $length) { if (0 > $length) { throw new FileException('Length must be greater than 0, given %d.', 3, $length); } return \fwrite($this->getStream(), $string, $length); } /** * Write a string. */ public function writeString(string $string) { $string = (string) $string; return $this->write($string, \strlen($string)); } /** * Write a character. */ public function writeCharacter(string $char) { return $this->write((string) $char[0], 1); } /** * Write a boolean. */ public function writeBoolean(bool $boolean) { return $this->write((string) (bool) $boolean, 1); } /** * Write an integer. */ public function writeInteger(int $integer) { $integer = (string) (int) $integer; return $this->write($integer, \strlen($integer)); } /** * Write a float. */ public function writeFloat(float $float) { $float = (string) (float) $float; return $this->write($float, \strlen($float)); } /** * Write an array. */ public function writeArray(array $array) { $array = \var_export($array, true); return $this->write($array, \strlen($array)); } /** * Write a line. */ public function writeLine(string $line) { if (false === $n = \strpos($line, "\n")) { return $this->write($line."\n", \strlen($line) + 1); } ++$n; return $this->write(\substr($line, 0, $n), $n); } /** * Write all, i.e. as much as possible. */ public function writeAll(string $string) { return $this->write($string, \strlen($string)); } /** * Truncate a file to a given length. */ public function truncate(int $size): bool { return \ftruncate($this->getStream(), $size); } } PK������*Z-=d��d����Readline/Hoa/FileLinkRead.phpnu�W+A��������<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Class \Hoa\File\Link\Read. * * File handler. * * @license New BSD License */ class FileLinkRead extends FileLink implements StreamIn { /** * Open a file. * * @param string $streamName stream name * @param string $mode open mode, see the parent::MODE_* constants * @param string $context context ID (please, see the * \Hoa\Stream\Context class) * @param bool $wait differ opening or not */ public function __construct( string $streamName, string $mode = parent::MODE_READ, ?string $context = null, bool $wait = false ) { parent::__construct($streamName, $mode, $context, $wait); return; } /** * Open the stream and return the associated resource. * * @param string $streamName Stream name (e.g. path or URL). * @param \Hoa\Stream\Context $context context * * @return resource * * @throws \Hoa\File\Exception\FileDoesNotExist * @throws \Hoa\File\Exception */ protected function &_open(string $streamName, ?StreamContext $context = null) { static $createModes = [ parent::MODE_READ, ]; if (!\in_array($this->getMode(), $createModes)) { throw new FileException('Open mode are not supported; given %d. Only %s are supported.', 0, [$this->getMode(), \implode(', ', $createModes)]); } \preg_match('#^(\w+)://#', $streamName, $match); if (((isset($match[1]) && $match[1] === 'file') || !isset($match[1])) && !\file_exists($streamName)) { throw new FileDoesNotExistException('File %s does not exist.', 1, $streamName); } $out = parent::_open($streamName, $context); return $out; } /** * Test for end-of-file. * * @return bool */ public function eof(): bool { return \feof($this->getStream()); } /** * Read n characters. * * @param int $length length * * @return string * * @throws \Hoa\File\Exception */ public function read(int $length) { if (0 > $length) { throw new FileException('Length must be greater than 0, given %d.', 2, $length); } return \fread($this->getStream(), $length); } /** * Alias of $this->read(). * * @param int $length length * * @return string */ public function readString(int $length) { return $this->read($length); } /** * Read a character. * * @return string */ public function readCharacter() { return \fgetc($this->getStream()); } /** * Read a boolean. * * @return bool */ public function readBoolean() { return (bool) $this->read(1); } /** * Read an integer. * * @param int $length length * * @return int */ public function readInteger(int $length = 1) { return (int) $this->read($length); } /** * Read a float. * * @param int $length length * * @return float */ public function readFloat(int $length = 1) { return (float) $this->read($length); } /** * Read an array. * Alias of the $this->scanf() method. * * @param string $format format (see printf's formats) * * @return array */ public function readArray(?string $format = null) { return $this->scanf($format); } /** * Read a line. * * @return string */ public function readLine() { return \fgets($this->getStream()); } /** * Read all, i.e. read as much as possible. * * @param int $offset offset * * @return string */ public function readAll(int $offset = 0) { return \stream_get_contents($this->getStream(), -1, $offset); } /** * Parse input from a stream according to a format. * * @param string $format format (see printf's formats) * * @return array */ public function scanf(string $format): array { return \fscanf($this->getStream(), $format); } } PK������*Z^hm������Readline/Userland.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Readline; use Psy\Exception\BreakException; use Psy\Readline\Hoa\Console as HoaConsole; use Psy\Readline\Hoa\ConsoleCursor as HoaConsoleCursor; use Psy\Readline\Hoa\ConsoleInput as HoaConsoleInput; use Psy\Readline\Hoa\ConsoleOutput as HoaConsoleOutput; use Psy\Readline\Hoa\ConsoleTput as HoaConsoleTput; use Psy\Readline\Hoa\Readline as HoaReadline; use Psy\Readline\Hoa\Ustring as HoaUstring; /** * Userland Readline implementation. */ class Userland implements Readline { private HoaReadline $hoaReadline; private ?string $lastPrompt = null; private HoaConsoleTput $tput; private HoaConsoleInput $input; private HoaConsoleOutput $output; public static function isSupported(): bool { static::bootstrapHoa(); return HoaUstring::checkMbString() && HoaConsoleTput::isSupported(); } /** * {@inheritdoc} */ public static function supportsBracketedPaste(): bool { return false; } /** * Doesn't (currently) support history file, size or erase dupes configs. */ public function __construct($historyFile = null, $historySize = 0, $eraseDups = false) { static::bootstrapHoa(true); $this->hoaReadline = new HoaReadline(); $this->hoaReadline->addMapping('\C-l', function () { $this->redisplay(); return HoaReadline::STATE_NO_ECHO; }); $this->tput = new HoaConsoleTput(); HoaConsole::setTput($this->tput); $this->input = new HoaConsoleInput(); HoaConsole::setInput($this->input); $this->output = new HoaConsoleOutput(); HoaConsole::setOutput($this->output); } /** * Bootstrap some things that Hoa used to do itself. */ public static function bootstrapHoa(bool $withTerminalResize = false) { // A side effect registers hoa:// stream wrapper \class_exists('Psy\Readline\Hoa\ProtocolWrapper'); // A side effect registers hoa://Library/Stream \class_exists('Psy\Readline\Hoa\Stream'); // A side effect binds terminal resize $withTerminalResize && \class_exists('Psy\Readline\Hoa\ConsoleWindow'); } /** * {@inheritdoc} */ public function addHistory(string $line): bool { $this->hoaReadline->addHistory($line); return true; } /** * {@inheritdoc} */ public function clearHistory(): bool { $this->hoaReadline->clearHistory(); return true; } /** * {@inheritdoc} */ public function listHistory(): array { $i = 0; $list = []; while (($item = $this->hoaReadline->getHistory($i++)) !== null) { $list[] = $item; } return $list; } /** * {@inheritdoc} */ public function readHistory(): bool { return true; } /** * {@inheritdoc} * * @throws BreakException if user hits Ctrl+D * * @return string */ public function readline(?string $prompt = null) { $this->lastPrompt = $prompt; return $this->hoaReadline->readLine($prompt); } /** * {@inheritdoc} */ public function redisplay() { $currentLine = $this->hoaReadline->getLine(); HoaConsoleCursor::clear('all'); echo $this->lastPrompt, $currentLine; } /** * {@inheritdoc} */ public function writeHistory(): bool { return true; } } PK������*Zm&fN �� ����Readline/Transient.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Readline; use Psy\Exception\BreakException; /** * An array-based Readline emulation implementation. */ class Transient implements Readline { private array $history; private int $historySize; private bool $eraseDups; /** @var resource */ private $stdin; /** * Transient Readline is always supported. * * {@inheritdoc} */ public static function isSupported(): bool { return true; } /** * {@inheritdoc} */ public static function supportsBracketedPaste(): bool { return false; } /** * Transient Readline constructor. */ public function __construct($historyFile = null, $historySize = 0, $eraseDups = false) { // don't do anything with the history file... $this->history = []; $this->historySize = $historySize; $this->eraseDups = $eraseDups ?? false; } /** * {@inheritdoc} */ public function addHistory(string $line): bool { if ($this->eraseDups) { if (($key = \array_search($line, $this->history)) !== false) { unset($this->history[$key]); } } $this->history[] = $line; if ($this->historySize > 0) { $histsize = \count($this->history); if ($histsize > $this->historySize) { $this->history = \array_slice($this->history, $histsize - $this->historySize); } } $this->history = \array_values($this->history); return true; } /** * {@inheritdoc} */ public function clearHistory(): bool { $this->history = []; return true; } /** * {@inheritdoc} */ public function listHistory(): array { return $this->history; } /** * {@inheritdoc} */ public function readHistory(): bool { return true; } /** * {@inheritdoc} * * @throws BreakException if user hits Ctrl+D * * @return false|string */ public function readline(?string $prompt = null) { echo $prompt; return \rtrim(\fgets($this->getStdin()), "\n\r"); } /** * {@inheritdoc} */ public function redisplay() { // noop } /** * {@inheritdoc} */ public function writeHistory(): bool { return true; } /** * Get a STDIN file handle. * * @throws BreakException if user hits Ctrl+D * * @return resource */ private function getStdin() { if (!isset($this->stdin)) { $this->stdin = \fopen('php://stdin', 'r'); } if (\feof($this->stdin)) { throw new BreakException('Ctrl+D'); } return $this->stdin; } } PK������*Z+0# �� ����ExecutionLoopClosure.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy; use Psy\Exception\BreakException; use Psy\Exception\ThrowUpException; /** * The Psy Shell's execution loop scope. * * @todo Switch ExecutionClosure to a generator and get rid of the duplicate closure implementations? */ class ExecutionLoopClosure extends ExecutionClosure { /** * @param Shell $__psysh__ */ public function __construct(Shell $__psysh__) { $this->setClosure($__psysh__, function () use ($__psysh__) { // Restore execution scope variables \extract($__psysh__->getScopeVariables(false)); while (true) { $__psysh__->beforeLoop(); try { $__psysh__->getInput(); try { // Pull in any new execution scope variables if ($__psysh__->getLastExecSuccess()) { \extract($__psysh__->getScopeVariablesDiff(\get_defined_vars())); } // Buffer stdout; we'll need it later \ob_start([$__psysh__, 'writeStdout'], 1); // Convert all errors to exceptions \set_error_handler([$__psysh__, 'handleError']); // Evaluate the current code buffer $_ = eval($__psysh__->onExecute($__psysh__->flushCode() ?: ExecutionClosure::NOOP_INPUT)); } catch (\Throwable $_e) { // Clean up on our way out. if (\ob_get_level() > 0) { \ob_end_clean(); } throw $_e; } finally { // Won't be needing this anymore \restore_error_handler(); } // Flush stdout (write to shell output, plus save to magic variable) \ob_end_flush(); // Save execution scope variables for next time $__psysh__->setScopeVariables(\get_defined_vars()); $__psysh__->writeReturnValue($_); } catch (BreakException $_e) { $__psysh__->writeException($_e); return; } catch (ThrowUpException $_e) { $__psysh__->writeException($_e); throw $_e; } catch (\Throwable $_e) { $__psysh__->writeException($_e); } $__psysh__->afterLoop(); } }); } } PK������*Z������Sudo/SudoVisitor.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Sudo; use PhpParser\Node; use PhpParser\Node\Arg; use PhpParser\Node\Expr\Assign; use PhpParser\Node\Expr\ClassConstFetch; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\New_; use PhpParser\Node\Expr\PropertyFetch; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Expr\StaticPropertyFetch; use PhpParser\Node\Identifier; use PhpParser\Node\Name; use PhpParser\Node\Name\FullyQualified as FullyQualifiedName; use PhpParser\Node\Scalar\String_; use PhpParser\NodeVisitorAbstract; use Psy\Sudo; /** * A PHP Parser node visitor which rewrites property and method access to use * the Psy\Sudo visibility bypass methods. * * @todo handle assigning by reference */ class SudoVisitor extends NodeVisitorAbstract { const PROPERTY_FETCH = 'fetchProperty'; const PROPERTY_ASSIGN = 'assignProperty'; const METHOD_CALL = 'callMethod'; const STATIC_PROPERTY_FETCH = 'fetchStaticProperty'; const STATIC_PROPERTY_ASSIGN = 'assignStaticProperty'; const STATIC_CALL = 'callStatic'; const CLASS_CONST_FETCH = 'fetchClassConst'; const NEW_INSTANCE = 'newInstance'; /** * {@inheritdoc} * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { if ($node instanceof PropertyFetch) { $name = $node->name instanceof Identifier ? $node->name->toString() : $node->name; $args = [ $node->var, \is_string($name) ? new String_($name) : $name, ]; return $this->prepareCall(self::PROPERTY_FETCH, $args); } elseif ($node instanceof Assign && $node->var instanceof PropertyFetch) { $target = $node->var; $name = $target->name instanceof Identifier ? $target->name->toString() : $target->name; $args = [ $target->var, \is_string($name) ? new String_($name) : $name, $node->expr, ]; return $this->prepareCall(self::PROPERTY_ASSIGN, $args); } elseif ($node instanceof MethodCall) { $name = $node->name instanceof Identifier ? $node->name->toString() : $node->name; $args = $node->args; \array_unshift($args, new Arg(\is_string($name) ? new String_($name) : $name)); \array_unshift($args, new Arg($node->var)); // not using prepareCall because the $node->args we started with are already Arg instances return new StaticCall(new FullyQualifiedName(Sudo::class), self::METHOD_CALL, $args); } elseif ($node instanceof StaticPropertyFetch) { $class = $node->class instanceof Name ? $node->class->toString() : $node->class; $name = $node->name instanceof Identifier ? $node->name->toString() : $node->name; $args = [ \is_string($class) ? new String_($class) : $class, \is_string($name) ? new String_($name) : $name, ]; return $this->prepareCall(self::STATIC_PROPERTY_FETCH, $args); } elseif ($node instanceof Assign && $node->var instanceof StaticPropertyFetch) { $target = $node->var; $class = $target->class instanceof Name ? $target->class->toString() : $target->class; $name = $target->name instanceof Identifier ? $target->name->toString() : $target->name; $args = [ \is_string($class) ? new String_($class) : $class, \is_string($name) ? new String_($name) : $name, $node->expr, ]; return $this->prepareCall(self::STATIC_PROPERTY_ASSIGN, $args); } elseif ($node instanceof StaticCall) { $args = $node->args; $class = $node->class instanceof Name ? $node->class->toString() : $node->class; $name = $node->name instanceof Identifier ? $node->name->toString() : $node->name; \array_unshift($args, new Arg(\is_string($name) ? new String_($name) : $name)); \array_unshift($args, new Arg(\is_string($class) ? new String_($class) : $class)); // not using prepareCall because the $node->args we started with are already Arg instances return new StaticCall(new FullyQualifiedName(Sudo::class), self::STATIC_CALL, $args); } elseif ($node instanceof ClassConstFetch) { $class = $node->class instanceof Name ? $node->class->toString() : $node->class; $name = $node->name instanceof Identifier ? $node->name->toString() : $node->name; $args = [ \is_string($class) ? new String_($class) : $class, \is_string($name) ? new String_($name) : $name, ]; return $this->prepareCall(self::CLASS_CONST_FETCH, $args); } elseif ($node instanceof New_) { $args = $node->args; $class = $node->class instanceof Name ? $node->class->toString() : $node->class; \array_unshift($args, new Arg(\is_string($class) ? new String_($class) : $class)); // not using prepareCall because the $node->args we started with are already Arg instances return new StaticCall(new FullyQualifiedName(Sudo::class), self::NEW_INSTANCE, $args); } } private function prepareCall(string $method, array $args): StaticCall { return new StaticCall(new FullyQualifiedName(Sudo::class), $method, \array_map(function ($arg) { return new Arg($arg); }, $args)); } } PK������*Z�C'���� ��SystemEnv.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy; /** * Environment variables implementation via getenv(). */ class SystemEnv implements EnvInterface { /** * Get an environment variable by name. * * @return string|null */ public function get(string $key) { if (isset($_SERVER[$key]) && $_SERVER[$key]) { return $_SERVER[$key]; } $result = \getenv($key); return $result === false ? null : $result; } } PK������*Z:��:��5��TabCompletion/Matcher/AbstractContextAwareMatcher.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\TabCompletion\Matcher; use Psy\Context; use Psy\ContextAware; /** * An abstract tab completion Matcher which implements ContextAware. * * The AutoCompleter service will inject a Context instance into all * ContextAware Matchers. * * @author Marc Garcia <markcial@gmail.com> */ abstract class AbstractContextAwareMatcher extends AbstractMatcher implements ContextAware { /** * Context instance (for ContextAware interface). * * @var Context */ protected $context; /** * ContextAware interface. * * @param Context $context */ public function setContext(Context $context) { $this->context = $context; } /** * Get a Context variable by name. * * @param string $var Variable name * * @return mixed */ protected function getVariable(string $var) { return $this->context->get($var); } /** * Get all variables in the current Context. * * @return array */ protected function getVariables(): array { return $this->context->getAll(); } } PK������*Z����,��TabCompletion/Matcher/MongoClientMatcher.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\TabCompletion\Matcher; /** * A MongoDB Client tab completion Matcher. * * This matcher provides completion for MongoClient database names. * * @author Marc Garcia <markcial@gmail.com> */ class MongoClientMatcher extends AbstractContextAwareMatcher { /** * {@inheritdoc} */ public function getMatches(array $tokens, array $info = []): array { $input = $this->getInput($tokens); $firstToken = \array_pop($tokens); if (self::tokenIs($firstToken, self::T_STRING)) { // second token is the object operator \array_pop($tokens); } $objectToken = \array_pop($tokens); $objectName = \str_replace('$', '', $objectToken[1]); $object = $this->getVariable($objectName); if (!$object instanceof \MongoClient) { return []; } $list = $object->listDBs(); return \array_filter( \array_map(function ($info) { return $info['name']; }, $list['databases']), function ($var) use ($input) { return AbstractMatcher::startsWith($input, $var); } ); } /** * {@inheritdoc} */ public function hasMatched(array $tokens): bool { $token = \array_pop($tokens); $prevToken = \array_pop($tokens); switch (true) { case self::tokenIs($token, self::T_OBJECT_OPERATOR): case self::tokenIs($prevToken, self::T_OBJECT_OPERATOR): return true; } return false; } } PK������*Z옵 �� ��.��TabCompletion/Matcher/ObjectMethodsMatcher.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\TabCompletion\Matcher; use InvalidArgumentException; /** * An object method tab completion Matcher. * * This matcher provides completion for methods of objects in the current * Context. * * @author Marc Garcia <markcial@gmail.com> */ class ObjectMethodsMatcher extends AbstractContextAwareMatcher { /** * {@inheritdoc} */ public function getMatches(array $tokens, array $info = []): array { $input = $this->getInput($tokens); $firstToken = \array_pop($tokens); if (self::tokenIs($firstToken, self::T_STRING)) { // second token is the object operator \array_pop($tokens); } $objectToken = \array_pop($tokens); if (!\is_array($objectToken)) { return []; } $objectName = \str_replace('$', '', $objectToken[1]); try { $object = $this->getVariable($objectName); } catch (InvalidArgumentException $e) { return []; } if (!\is_object($object)) { return []; } return \array_filter( \get_class_methods($object), function ($var) use ($input) { return AbstractMatcher::startsWith($input, $var) && // also check that we do not suggest invoking a super method(__construct, __wakeup, …) !AbstractMatcher::startsWith('__', $var); } ); } /** * {@inheritdoc} */ public function hasMatched(array $tokens): bool { $token = \array_pop($tokens); $prevToken = \array_pop($tokens); switch (true) { case self::tokenIs($token, self::T_OBJECT_OPERATOR): case self::tokenIs($prevToken, self::T_OBJECT_OPERATOR): return true; } return false; } } PK������*Z�9����*��TabCompletion/Matcher/VariablesMatcher.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\TabCompletion\Matcher; /** * A variable name tab completion Matcher. * * This matcher provides completion for variable names in the current Context. * * @author Marc Garcia <markcial@gmail.com> */ class VariablesMatcher extends AbstractContextAwareMatcher { /** * {@inheritdoc} */ public function getMatches(array $tokens, array $info = []): array { $var = \str_replace('$', '', $this->getInput($tokens)); return \array_filter(\array_keys($this->getVariables()), function ($variable) use ($var) { return AbstractMatcher::startsWith($var, $variable); }); } /** * {@inheritdoc} */ public function hasMatched(array $tokens): bool { $token = \array_pop($tokens); switch (true) { case self::hasToken([self::T_OPEN_TAG, self::T_VARIABLE], $token): case \is_string($token) && $token === '$': case self::isOperator($token): return true; } return false; } } PK������*Z)0����1��TabCompletion/Matcher/ObjectAttributesMatcher.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\TabCompletion\Matcher; use InvalidArgumentException; /** * An object attribute tab completion Matcher. * * This matcher provides completion for properties of objects in the current * Context. * * @author Marc Garcia <markcial@gmail.com> */ class ObjectAttributesMatcher extends AbstractContextAwareMatcher { /** * {@inheritdoc} */ public function getMatches(array $tokens, array $info = []): array { $input = $this->getInput($tokens); $firstToken = \array_pop($tokens); if (self::tokenIs($firstToken, self::T_STRING)) { // second token is the object operator \array_pop($tokens); } $objectToken = \array_pop($tokens); if (!\is_array($objectToken)) { return []; } $objectName = \str_replace('$', '', $objectToken[1]); try { $object = $this->getVariable($objectName); } catch (InvalidArgumentException $e) { return []; } if (!\is_object($object)) { return []; } return \array_filter( \array_keys(\get_class_vars(\get_class($object))), function ($var) use ($input) { return AbstractMatcher::startsWith($input, $var); } ); } /** * {@inheritdoc} */ public function hasMatched(array $tokens): bool { $token = \array_pop($tokens); $prevToken = \array_pop($tokens); switch (true) { case self::tokenIs($token, self::T_OBJECT_OPERATOR): case self::tokenIs($prevToken, self::T_OBJECT_OPERATOR): return true; } return false; } } PK������*Z(%����:��TabCompletion/Matcher/FunctionDefaultParametersMatcher.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\TabCompletion\Matcher; class FunctionDefaultParametersMatcher extends AbstractDefaultParametersMatcher { public function getMatches(array $tokens, array $info = []): array { \array_pop($tokens); // open bracket $functionName = \array_pop($tokens); try { $reflection = new \ReflectionFunction($functionName[1]); } catch (\ReflectionException $e) { return []; } $parameters = $reflection->getParameters(); return $this->getDefaultParameterCompletion($parameters); } public function hasMatched(array $tokens): bool { $openBracket = \array_pop($tokens); if ($openBracket !== '(') { return false; } $functionName = \array_pop($tokens); if (!self::tokenIs($functionName, self::T_STRING)) { return false; } if (!\function_exists($functionName[1])) { return false; } return true; } } PK������*Z>2����-��TabCompletion/Matcher/ClassMethodsMatcher.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\TabCompletion\Matcher; /** * A class method tab completion Matcher. * * Given a namespace and class, this matcher provides completion for static * methods. * * @author Marc Garcia <markcial@gmail.com> */ class ClassMethodsMatcher extends AbstractMatcher { /** * {@inheritdoc} */ public function getMatches(array $tokens, array $info = []): array { $input = $this->getInput($tokens); $firstToken = \array_pop($tokens); if (self::tokenIs($firstToken, self::T_STRING)) { // second token is the nekudotayim operator \array_pop($tokens); } $class = $this->getNamespaceAndClass($tokens); try { $reflection = new \ReflectionClass($class); } catch (\ReflectionException $re) { return []; } if (self::needCompleteClass($tokens[1])) { $methods = $reflection->getMethods(); } else { $methods = $reflection->getMethods(\ReflectionMethod::IS_STATIC); } $methods = \array_map(function (\ReflectionMethod $method) { return $method->getName(); }, $methods); return \array_map( function ($name) use ($class) { $chunks = \explode('\\', $class); $className = \array_pop($chunks); return $className.'::'.$name; }, \array_filter($methods, function ($method) use ($input) { return AbstractMatcher::startsWith($input, $method); }) ); } /** * {@inheritdoc} */ public function hasMatched(array $tokens): bool { $token = \array_pop($tokens); $prevToken = \array_pop($tokens); switch (true) { case self::tokenIs($prevToken, self::T_DOUBLE_COLON) && self::tokenIs($token, self::T_STRING): case self::tokenIs($token, self::T_DOUBLE_COLON): return true; } return false; } } PK������*Z.����:��TabCompletion/Matcher/AbstractDefaultParametersMatcher.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\TabCompletion\Matcher; abstract class AbstractDefaultParametersMatcher extends AbstractContextAwareMatcher { /** * @param \ReflectionParameter[] $reflectionParameters * * @return array */ public function getDefaultParameterCompletion(array $reflectionParameters): array { $parametersProcessed = []; foreach ($reflectionParameters as $parameter) { if (!$parameter->isDefaultValueAvailable()) { return []; } $defaultValue = $this->valueToShortString($parameter->getDefaultValue()); $parametersProcessed[] = \sprintf('$%s = %s', $parameter->getName(), $defaultValue); } if (empty($parametersProcessed)) { return []; } return [\implode(', ', $parametersProcessed).')']; } /** * Takes in the default value of a parameter and turns it into a * string representation that fits inline. * This is not 100% true to the original (newlines are inlined, for example). * * @param mixed $value */ private function valueToShortString($value): string { if (!\is_array($value)) { return \json_encode($value); } $chunks = []; $chunksSequential = []; $allSequential = true; foreach ($value as $key => $item) { $allSequential = $allSequential && \is_numeric($key) && $key === \count($chunksSequential); $keyString = $this->valueToShortString($key); $itemString = $this->valueToShortString($item); $chunks[] = "{$keyString} => {$itemString}"; $chunksSequential[] = $itemString; } $chunksToImplode = $allSequential ? $chunksSequential : $chunks; return '['.\implode(', ', $chunksToImplode).']'; } } PK������*Z9"k����*��TabCompletion/Matcher/FunctionsMatcher.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\TabCompletion\Matcher; /** * A function name tab completion Matcher. * * This matcher provides completion for all internal and user-defined functions. * * @author Marc Garcia <markcial@gmail.com> */ class FunctionsMatcher extends AbstractMatcher { /** * {@inheritdoc} */ public function getMatches(array $tokens, array $info = []): array { $func = $this->getInput($tokens); $functions = \get_defined_functions(); $allFunctions = \array_merge($functions['user'], $functions['internal']); return \array_filter($allFunctions, function ($function) use ($func) { return AbstractMatcher::startsWith($func, $function); }); } /** * {@inheritdoc} */ public function hasMatched(array $tokens): bool { $token = \array_pop($tokens); $prevToken = \array_pop($tokens); switch (true) { case self::tokenIs($prevToken, self::T_NEW): return false; case self::hasToken([self::T_OPEN_TAG, self::T_STRING], $token): case self::isOperator($token): return true; } return false; } } PK������*Z[,��,��)��TabCompletion/Matcher/KeywordsMatcher.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\TabCompletion\Matcher; /** * A PHP keyword tab completion Matcher. * * This matcher provides completion for all function-like PHP keywords. * * @author Marc Garcia <markcial@gmail.com> */ class KeywordsMatcher extends AbstractMatcher { protected $keywords = [ 'array', 'clone', 'declare', 'die', 'echo', 'empty', 'eval', 'exit', 'include', 'include_once', 'isset', 'list', 'print', 'require', 'require_once', 'unset', ]; protected $mandatoryStartKeywords = [ 'die', 'echo', 'print', 'unset', ]; /** * Get all (completable) PHP keywords. * * @return string[] */ public function getKeywords(): array { return $this->keywords; } /** * Check whether $keyword is a (completable) PHP keyword. * * @param string $keyword */ public function isKeyword(string $keyword): bool { return \in_array($keyword, $this->keywords); } /** * {@inheritdoc} */ public function getMatches(array $tokens, array $info = []): array { $input = $this->getInput($tokens); return \array_filter($this->keywords, function ($keyword) use ($input) { return AbstractMatcher::startsWith($input, $keyword); }); } /** * {@inheritdoc} */ public function hasMatched(array $tokens): bool { $token = \array_pop($tokens); $prevToken = \array_pop($tokens); switch (true) { case self::hasToken([self::T_OPEN_TAG, self::T_VARIABLE], $token): // case is_string($token) && $token === '$': case self::hasToken([self::T_OPEN_TAG, self::T_VARIABLE], $prevToken) && self::tokenIs($token, self::T_STRING): case self::isOperator($token): return true; } return false; } } PK������*Z\* �� ��+��TabCompletion/Matcher/ClassNamesMatcher.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\TabCompletion\Matcher; /** * A class name tab completion Matcher. * * This matcher provides completion for all declared classes. * * @author Marc Garcia <markcial@gmail.com> */ class ClassNamesMatcher extends AbstractMatcher { /** * {@inheritdoc} */ public function getMatches(array $tokens, array $info = []): array { $class = $this->getNamespaceAndClass($tokens); if ($class !== '' && $class[0] === '\\') { $class = \substr($class, 1, \strlen($class)); } $quotedClass = \preg_quote($class); return \array_map( function ($className) use ($class) { // get the number of namespace separators $nsPos = \substr_count($class, '\\'); $pieces = \explode('\\', $className); // $methods = Mirror::get($class); return \implode('\\', \array_slice($pieces, $nsPos, \count($pieces))); }, \array_filter( \array_merge(\get_declared_classes(), \get_declared_interfaces()), function ($className) use ($quotedClass) { return AbstractMatcher::startsWith($quotedClass, $className); } ) ); } /** * {@inheritdoc} */ public function hasMatched(array $tokens): bool { $token = \array_pop($tokens); $prevToken = \array_pop($tokens); $ignoredTokens = [ self::T_INCLUDE, self::T_INCLUDE_ONCE, self::T_REQUIRE, self::T_REQUIRE_ONCE, ]; switch (true) { case self::hasToken([$ignoredTokens], $token): case self::hasToken([$ignoredTokens], $prevToken): case \is_string($token) && $token === '$': return false; case self::hasToken([self::T_NEW, self::T_OPEN_TAG, self::T_NS_SEPARATOR, self::T_STRING], $prevToken): case self::hasToken([self::T_NEW, self::T_OPEN_TAG, self::T_NS_SEPARATOR], $token): case self::hasToken([self::T_OPEN_TAG, self::T_VARIABLE], $token): case self::isOperator($token): return true; } return false; } } PK������*ZR����>��TabCompletion/Matcher/ObjectMethodDefaultParametersMatcher.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\TabCompletion\Matcher; class ObjectMethodDefaultParametersMatcher extends AbstractDefaultParametersMatcher { public function getMatches(array $tokens, array $info = []): array { $openBracket = \array_pop($tokens); $functionName = \array_pop($tokens); $methodOperator = \array_pop($tokens); $objectToken = \array_pop($tokens); if (!\is_array($objectToken)) { return []; } $objectName = \str_replace('$', '', $objectToken[1]); try { $object = $this->getVariable($objectName); $reflection = new \ReflectionObject($object); } catch (\InvalidArgumentException $e) { return []; } catch (\ReflectionException $e) { return []; } $methods = $reflection->getMethods(); foreach ($methods as $method) { if ($method->getName() === $functionName[1]) { return $this->getDefaultParameterCompletion($method->getParameters()); } } return []; } public function hasMatched(array $tokens): bool { $openBracket = \array_pop($tokens); if ($openBracket !== '(') { return false; } $functionName = \array_pop($tokens); if (!self::tokenIs($functionName, self::T_STRING)) { return false; } $operator = \array_pop($tokens); if (!self::tokenIs($operator, self::T_OBJECT_OPERATOR)) { return false; } return true; } } PK������*Z٭F����0��TabCompletion/Matcher/ClassAttributesMatcher.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\TabCompletion\Matcher; /** * A class attribute tab completion Matcher. * * Given a namespace and class, this matcher provides completion for constants * and static properties. * * @author Marc Garcia <markcial@gmail.com> */ class ClassAttributesMatcher extends AbstractMatcher { /** * {@inheritdoc} */ public function getMatches(array $tokens, array $info = []): array { $input = $this->getInput($tokens); $firstToken = \array_pop($tokens); if (self::tokenIs($firstToken, self::T_STRING)) { // second token is the nekudotayim operator \array_pop($tokens); } $class = $this->getNamespaceAndClass($tokens); try { $reflection = new \ReflectionClass($class); } catch (\ReflectionException $re) { return []; } $vars = \array_merge( \array_map( function ($var) { return '$'.$var; }, \array_keys($reflection->getStaticProperties()) ), \array_keys($reflection->getConstants()) ); return \array_map( function ($name) use ($class) { $chunks = \explode('\\', $class); $className = \array_pop($chunks); return $className.'::'.$name; }, \array_filter( $vars, function ($var) use ($input) { return AbstractMatcher::startsWith($input, $var); } ) ); } /** * {@inheritdoc} */ public function hasMatched(array $tokens): bool { $token = \array_pop($tokens); $prevToken = \array_pop($tokens); switch (true) { case self::tokenIs($prevToken, self::T_DOUBLE_COLON) && self::tokenIs($token, self::T_STRING): case self::tokenIs($token, self::T_DOUBLE_COLON): return true; } return false; } } PK������*ZI �� ��)��TabCompletion/Matcher/CommandsMatcher.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\TabCompletion\Matcher; use Psy\Command\Command; /** * A Psy Command tab completion Matcher. * * This matcher provides completion for all registered Psy Command names and * aliases. * * @author Marc Garcia <markcial@gmail.com> */ class CommandsMatcher extends AbstractMatcher { /** @var string[] */ protected $commands = []; /** * CommandsMatcher constructor. * * @param Command[] $commands */ public function __construct(array $commands) { $this->setCommands($commands); } /** * Set Commands for completion. * * @param Command[] $commands */ public function setCommands(array $commands) { $names = []; foreach ($commands as $command) { $names = \array_merge([$command->getName()], $names); $names = \array_merge($command->getAliases(), $names); } $this->commands = $names; } /** * Check whether a command $name is defined. * * @param string $name */ protected function isCommand(string $name): bool { return \in_array($name, $this->commands); } /** * Check whether input matches a defined command. * * @param string $name */ protected function matchCommand(string $name): bool { foreach ($this->commands as $cmd) { if ($this->startsWith($name, $cmd)) { return true; } } return false; } /** * {@inheritdoc} */ public function getMatches(array $tokens, array $info = []): array { $input = $this->getInput($tokens); return \array_filter($this->commands, function ($command) use ($input) { return AbstractMatcher::startsWith($input, $command); }); } /** * {@inheritdoc} */ public function hasMatched(array $tokens): bool { /* $openTag */ \array_shift($tokens); $command = \array_shift($tokens); switch (true) { case self::tokenIs($command, self::T_STRING) && !$this->isCommand($command[1]) && $this->matchCommand($command[1]) && empty($tokens): return true; } return false; } } PK������*ZTٔ����.��TabCompletion/Matcher/MongoDatabaseMatcher.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\TabCompletion\Matcher; /** * A MongoDB tab completion Matcher. * * This matcher provides completion for Mongo collection names. * * @author Marc Garcia <markcial@gmail.com> */ class MongoDatabaseMatcher extends AbstractContextAwareMatcher { /** * {@inheritdoc} */ public function getMatches(array $tokens, array $info = []): array { $input = $this->getInput($tokens); $firstToken = \array_pop($tokens); if (self::tokenIs($firstToken, self::T_STRING)) { // second token is the object operator \array_pop($tokens); } $objectToken = \array_pop($tokens); $objectName = \str_replace('$', '', $objectToken[1]); $object = $this->getVariable($objectName); if (!$object instanceof \MongoDB) { return []; } return \array_filter( $object->getCollectionNames(), function ($var) use ($input) { return AbstractMatcher::startsWith($input, $var); } ); } /** * {@inheritdoc} */ public function hasMatched(array $tokens): bool { $token = \array_pop($tokens); $prevToken = \array_pop($tokens); switch (true) { case self::tokenIs($token, self::T_OBJECT_OPERATOR): case self::tokenIs($prevToken, self::T_OBJECT_OPERATOR): return true; } return false; } } PK������*Z(}5F��F��)��TabCompletion/Matcher/AbstractMatcher.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\TabCompletion\Matcher; /** * Abstract tab completion Matcher. * * @author Marc Garcia <markcial@gmail.com> */ abstract class AbstractMatcher { /** Syntax types */ const CONSTANT_SYNTAX = '^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$'; const VAR_SYNTAX = '^\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$'; const MISC_OPERATORS = '+-*/^|&'; /** Token values */ const T_OPEN_TAG = 'T_OPEN_TAG'; const T_VARIABLE = 'T_VARIABLE'; const T_OBJECT_OPERATOR = 'T_OBJECT_OPERATOR'; const T_DOUBLE_COLON = 'T_DOUBLE_COLON'; const T_NEW = 'T_NEW'; const T_CLONE = 'T_CLONE'; const T_NS_SEPARATOR = 'T_NS_SEPARATOR'; const T_STRING = 'T_STRING'; const T_NAME_QUALIFIED = 'T_NAME_QUALIFIED'; const T_WHITESPACE = 'T_WHITESPACE'; const T_AND_EQUAL = 'T_AND_EQUAL'; const T_BOOLEAN_AND = 'T_BOOLEAN_AND'; const T_BOOLEAN_OR = 'T_BOOLEAN_OR'; const T_ENCAPSED_AND_WHITESPACE = 'T_ENCAPSED_AND_WHITESPACE'; const T_REQUIRE = 'T_REQUIRE'; const T_REQUIRE_ONCE = 'T_REQUIRE_ONCE'; const T_INCLUDE = 'T_INCLUDE'; const T_INCLUDE_ONCE = 'T_INCLUDE_ONCE'; /** * Check whether this matcher can provide completions for $tokens. * * @param array $tokens Tokenized readline input * * @return false */ public function hasMatched(array $tokens): bool { return false; } /** * Get current readline input word. * * @param array $tokens Tokenized readline input (see token_get_all) */ protected function getInput(array $tokens): string { $var = ''; $firstToken = \array_pop($tokens); if (self::tokenIs($firstToken, self::T_STRING)) { $var = $firstToken[1]; } return $var; } /** * Get current namespace and class (if any) from readline input. * * @param array $tokens Tokenized readline input (see token_get_all) */ protected function getNamespaceAndClass(array $tokens): string { $class = ''; while (self::hasToken( [self::T_NS_SEPARATOR, self::T_STRING, self::T_NAME_QUALIFIED], $token = \array_pop($tokens) )) { if (self::needCompleteClass($token)) { continue; } $class = $token[1].$class; } return $class; } /** * Provide tab completion matches for readline input. * * @param array $tokens information substracted with get_token_all * @param array $info readline_info object * * @return array The matches resulting from the query */ abstract public function getMatches(array $tokens, array $info = []): array; /** * Check whether $word starts with $prefix. * * @param string $prefix * @param string $word */ public static function startsWith(string $prefix, string $word): bool { return \preg_match(\sprintf('#^%s#', $prefix), $word); } /** * Check whether $token matches a given syntax pattern. * * @param mixed $token A PHP token (see token_get_all) * @param string $syntax A syntax pattern (default: variable pattern) */ public static function hasSyntax($token, string $syntax = self::VAR_SYNTAX): bool { if (!\is_array($token)) { return false; } $regexp = \sprintf('#%s#', $syntax); return (bool) \preg_match($regexp, $token[1]); } /** * Check whether $token type is $which. * * @param mixed $token A PHP token (see token_get_all) * @param string $which A PHP token type */ public static function tokenIs($token, string $which): bool { if (!\is_array($token)) { return false; } return \token_name($token[0]) === $which; } /** * Check whether $token is an operator. * * @param mixed $token A PHP token (see token_get_all) */ public static function isOperator($token): bool { if (!\is_string($token)) { return false; } return \strpos(self::MISC_OPERATORS, $token) !== false; } public static function needCompleteClass($token): bool { return \in_array($token[1], ['doc', 'ls', 'show']); } /** * Check whether $token type is present in $coll. * * @param array $coll A list of token types * @param mixed $token A PHP token (see token_get_all) */ public static function hasToken(array $coll, $token): bool { if (!\is_array($token)) { return false; } return \in_array(\token_name($token[0]), $coll); } } PK������*Zkp~m��m��=��TabCompletion/Matcher/ClassMethodDefaultParametersMatcher.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\TabCompletion\Matcher; class ClassMethodDefaultParametersMatcher extends AbstractDefaultParametersMatcher { public function getMatches(array $tokens, array $info = []): array { $openBracket = \array_pop($tokens); $functionName = \array_pop($tokens); $methodOperator = \array_pop($tokens); $class = $this->getNamespaceAndClass($tokens); try { $reflection = new \ReflectionClass($class); } catch (\ReflectionException $e) { // In this case the class apparently does not exist, so we can do nothing return []; } $methods = $reflection->getMethods(\ReflectionMethod::IS_STATIC); foreach ($methods as $method) { if ($method->getName() === $functionName[1]) { return $this->getDefaultParameterCompletion($method->getParameters()); } } return []; } public function hasMatched(array $tokens): bool { $openBracket = \array_pop($tokens); if ($openBracket !== '(') { return false; } $functionName = \array_pop($tokens); if (!self::tokenIs($functionName, self::T_STRING)) { return false; } $operator = \array_pop($tokens); if (!self::tokenIs($operator, self::T_DOUBLE_COLON)) { return false; } return true; } } PK������*ZR=M��M��*��TabCompletion/Matcher/ConstantsMatcher.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\TabCompletion\Matcher; /** * A constant name tab completion Matcher. * * This matcher provides completion for all defined constants. * * @author Marc Garcia <markcial@gmail.com> */ class ConstantsMatcher extends AbstractMatcher { /** * {@inheritdoc} */ public function getMatches(array $tokens, array $info = []): array { $const = $this->getInput($tokens); return \array_filter(\array_keys(\get_defined_constants()), function ($constant) use ($const) { return AbstractMatcher::startsWith($const, $constant); }); } /** * {@inheritdoc} */ public function hasMatched(array $tokens): bool { $token = \array_pop($tokens); $prevToken = \array_pop($tokens); switch (true) { case self::tokenIs($prevToken, self::T_NEW): case self::tokenIs($prevToken, self::T_NS_SEPARATOR): return false; case self::hasToken([self::T_OPEN_TAG, self::T_STRING], $token): case self::isOperator($token): return true; } return false; } } PK������*Z١5] ��] ����TabCompletion/AutoCompleter.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\TabCompletion; use Psy\TabCompletion\Matcher\AbstractMatcher; /** * A readline tab completion service. * * @author Marc Garcia <markcial@gmail.com> */ class AutoCompleter { /** @var Matcher\AbstractMatcher[] */ protected $matchers; /** * Register a tab completion Matcher. * * @param AbstractMatcher $matcher */ public function addMatcher(AbstractMatcher $matcher) { $this->matchers[] = $matcher; } /** * Activate readline tab completion. */ public function activate() { \readline_completion_function([&$this, 'callback']); } /** * Handle readline completion. * * @param string $input Readline current word * @param int $index Current word index * @param array $info readline_info() data * * @return array */ public function processCallback(string $input, int $index, array $info = []): array { // Some (Windows?) systems provide incomplete `readline_info`, so let's // try to work around it. $line = $info['line_buffer']; if (isset($info['end'])) { $line = \substr($line, 0, $info['end']); } if ($line === '' && $input !== '') { $line = $input; } $tokens = \token_get_all('<?php '.$line); // remove whitespaces $tokens = \array_filter($tokens, function ($token) { return !AbstractMatcher::tokenIs($token, AbstractMatcher::T_WHITESPACE); }); // reset index from 0 to remove missing index number $tokens = \array_values($tokens); $matches = []; foreach ($this->matchers as $matcher) { if ($matcher->hasMatched($tokens)) { $matches = \array_merge($matcher->getMatches($tokens, $info), $matches); } } $matches = \array_unique($matches); return !empty($matches) ? $matches : ['']; } /** * The readline_completion_function callback handler. * * @see processCallback * * @param string $input * @param int $index * * @return array */ public function callback(string $input, int $index): array { return $this->processCallback($input, $index, \readline_info()); } /** * Remove readline callback handler on destruct. */ public function __destruct() { // PHP didn't implement the whole readline API when they first switched // to libedit. And they still haven't. if (\function_exists('readline_callback_handler_remove')) { \readline_callback_handler_remove(); } } } PK������*ZAa��a��"��Reflection/ReflectionNamespace.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Reflection; /** * A fake Reflector for namespaces. */ class ReflectionNamespace implements \Reflector { private string $name; /** * Construct a ReflectionNamespace object. * * @param string $name */ public function __construct(string $name) { $this->name = $name; } /** * Gets the constant name. * * @return string */ public function getName(): string { return $this->name; } /** * This can't (and shouldn't) do anything :). * * @throws \RuntimeException */ public static function export($name) { throw new \RuntimeException('Not yet implemented because it\'s unclear what I should do here :)'); } /** * To string. * * @return string */ public function __toString(): string { return $this->getName(); } } PK������*Z!y �� ��!��Reflection/ReflectionConstant.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Reflection; /** * Somehow the standard reflection library doesn't include constants. * * ReflectionConstant corrects that omission. */ class ReflectionConstant implements \Reflector { public $name; /** @var mixed */ private $value; private const MAGIC_CONSTANTS = [ '__LINE__', '__FILE__', '__DIR__', '__FUNCTION__', '__CLASS__', '__TRAIT__', '__METHOD__', '__NAMESPACE__', '__COMPILER_HALT_OFFSET__', ]; /** * Construct a ReflectionConstant object. * * @param string $name */ public function __construct(string $name) { $this->name = $name; if (!\defined($name) && !self::isMagicConstant($name)) { throw new \InvalidArgumentException('Unknown constant: '.$name); } if (!self::isMagicConstant($name)) { $this->value = @\constant($name); } } /** * Exports a reflection. * * @param string $name * @param bool $return pass true to return the export, as opposed to emitting it * * @return string|null */ public static function export(string $name, bool $return = false) { $refl = new self($name); $value = $refl->getValue(); $str = \sprintf('Constant [ %s %s ] { %s }', \gettype($value), $refl->getName(), $value); if ($return) { return $str; } echo $str."\n"; } public static function isMagicConstant($name) { return \in_array($name, self::MAGIC_CONSTANTS); } /** * Get the constant's docblock. * * @return false */ public function getDocComment(): bool { return false; } /** * Gets the constant name. */ public function getName(): string { return $this->name; } /** * Gets the namespace name. * * Returns '' when the constant is not namespaced. */ public function getNamespaceName(): string { if (!$this->inNamespace()) { return ''; } return \preg_replace('/\\\\[^\\\\]+$/', '', $this->name); } /** * Gets the value of the constant. * * @return mixed */ public function getValue() { return $this->value; } /** * Checks if this constant is defined in a namespace. */ public function inNamespace(): bool { return \strpos($this->name, '\\') !== false; } /** * To string. */ public function __toString(): string { return $this->getName(); } /** * Gets the constant's file name. * * Currently returns null, because if it returns a file name the signature * formatter will barf. */ public function getFileName() { return; // return $this->class->getFileName(); } /** * Get the code start line. * * @throws \RuntimeException */ public function getStartLine() { throw new \RuntimeException('Not yet implemented because it\'s unclear what I should do here :)'); } /** * Get the code end line. * * @throws \RuntimeException */ public function getEndLine() { return $this->getStartLine(); } } PK������*Z.' ��' ��3��Reflection/ReflectionLanguageConstructParameter.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Reflection; /** * A fake ReflectionParameter but for language construct parameters. * * It stubs out all the important bits and returns whatever was passed in $opts. */ class ReflectionLanguageConstructParameter extends \ReflectionParameter { /** @var string|array|object */ private $function; /** @var int|string */ private $parameter; private array $opts; /** * @param string|array|object $function * @param int|string $parameter * @param array $opts */ public function __construct($function, $parameter, array $opts) { $this->function = $function; $this->parameter = $parameter; $this->opts = $opts; } /** * No class here. */ public function getClass(): ?\ReflectionClass { return null; } /** * Is the param an array? * * @return bool */ public function isArray(): bool { return \array_key_exists('isArray', $this->opts) && $this->opts['isArray']; } /** * Get param default value. * * @todo remove \ReturnTypeWillChange attribute after dropping support for PHP 7.x (when we can use mixed type) * * @return mixed */ #[\ReturnTypeWillChange] public function getDefaultValue() { if ($this->isDefaultValueAvailable()) { return $this->opts['defaultValue']; } return null; } /** * Get param name. * * @return string */ public function getName(): string { return $this->parameter; } /** * Is the param optional? * * @return bool */ public function isOptional(): bool { return \array_key_exists('isOptional', $this->opts) && $this->opts['isOptional']; } /** * Does the param have a default value? * * @return bool */ public function isDefaultValueAvailable(): bool { return \array_key_exists('defaultValue', $this->opts); } /** * Is the param passed by reference? * * (I don't think this is true for anything we need to fake a param for) * * @return bool */ public function isPassedByReference(): bool { return \array_key_exists('isPassedByReference', $this->opts) && $this->opts['isPassedByReference']; } } PK������*Z9 �� ��*��Reflection/ReflectionLanguageConstruct.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Reflection; /** * A fake ReflectionFunction but for language constructs. */ class ReflectionLanguageConstruct extends \ReflectionFunctionAbstract { public $keyword; /** * Language construct parameter definitions. */ private const LANGUAGE_CONSTRUCTS = [ 'isset' => [ 'var' => [], '...' => [ 'isOptional' => true, 'defaultValue' => null, ], ], 'unset' => [ 'var' => [], '...' => [ 'isOptional' => true, 'defaultValue' => null, ], ], 'empty' => [ 'var' => [], ], 'echo' => [ 'arg1' => [], '...' => [ 'isOptional' => true, 'defaultValue' => null, ], ], 'print' => [ 'arg' => [], ], 'die' => [ 'status' => [ 'isOptional' => true, 'defaultValue' => 0, ], ], 'exit' => [ 'status' => [ 'isOptional' => true, 'defaultValue' => 0, ], ], ]; /** * Construct a ReflectionLanguageConstruct object. * * @param string $keyword */ public function __construct(string $keyword) { if (!self::isLanguageConstruct($keyword)) { throw new \InvalidArgumentException('Unknown language construct: '.$keyword); } $this->keyword = $keyword; } /** * This can't (and shouldn't) do anything :). * * @throws \RuntimeException */ public static function export($name) { throw new \RuntimeException('Not yet implemented because it\'s unclear what I should do here :)'); } /** * Get language construct name. */ public function getName(): string { return $this->keyword; } /** * None of these return references. */ public function returnsReference(): bool { return false; } /** * Get language construct params. * * @return array */ public function getParameters(): array { $params = []; foreach (self::LANGUAGE_CONSTRUCTS[$this->keyword] as $parameter => $opts) { $params[] = new ReflectionLanguageConstructParameter($this->keyword, $parameter, $opts); } return $params; } /** * Gets the file name from a language construct. * * (Hint: it always returns false) * * @todo remove \ReturnTypeWillChange attribute after dropping support for PHP 7.x (when we can use union types) * * @return string|false (false) */ #[\ReturnTypeWillChange] public function getFileName() { return false; } /** * To string. */ public function __toString(): string { return $this->getName(); } /** * Check whether keyword is a (known) language construct. * * @param string $keyword */ public static function isLanguageConstruct(string $keyword): bool { return \array_key_exists($keyword, self::LANGUAGE_CONSTRUCTS); } } PK������*Z-wH��H����Output/ShellOutput.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Output; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Formatter\OutputFormatterInterface; use Symfony\Component\Console\Output\ConsoleOutput; /** * A ConsoleOutput subclass specifically for Psy Shell output. */ class ShellOutput extends ConsoleOutput { const NUMBER_LINES = 128; private int $paging = 0; private OutputPager $pager; private Theme $theme; /** * Construct a ShellOutput instance. * * @param mixed $verbosity (default: self::VERBOSITY_NORMAL) * @param bool|null $decorated (default: null) * @param OutputFormatterInterface|null $formatter (default: null) * @param string|OutputPager|null $pager (default: null) */ public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, ?OutputFormatterInterface $formatter = null, $pager = null, $theme = null) { parent::__construct($verbosity, $decorated, $formatter); $this->theme = $theme ?? new Theme('modern'); $this->initFormatters(); if ($pager === null) { $this->pager = new PassthruPager($this); } elseif (\is_string($pager)) { $this->pager = new ProcOutputPager($this, $pager); } elseif ($pager instanceof OutputPager) { $this->pager = $pager; } else { throw new \InvalidArgumentException('Unexpected pager parameter: '.$pager); } } /** * Page multiple lines of output. * * The output pager is started * * If $messages is callable, it will be called, passing this output instance * for rendering. Otherwise, all passed $messages are paged to output. * * Upon completion, the output pager is flushed. * * @param string|array|\Closure $messages A string, array of strings or a callback * @param int $type (default: 0) */ public function page($messages, int $type = 0) { if (\is_string($messages)) { $messages = (array) $messages; } if (!\is_array($messages) && !\is_callable($messages)) { throw new \InvalidArgumentException('Paged output requires a string, array or callback'); } $this->startPaging(); if (\is_callable($messages)) { $messages($this); } else { $this->write($messages, true, $type); } $this->stopPaging(); } /** * Start sending output to the output pager. */ public function startPaging() { $this->paging++; } /** * Stop paging output and flush the output pager. */ public function stopPaging() { $this->paging--; $this->closePager(); } /** * Writes a message to the output. * * Optionally, pass `$type | self::NUMBER_LINES` as the $type parameter to * number the lines of output. * * @throws \InvalidArgumentException When unknown output type is given * * @param string|array $messages The message as an array of lines or a single string * @param bool $newline Whether to add a newline or not * @param int $type The type of output */ public function write($messages, $newline = false, $type = 0): void { if ($this->getVerbosity() === self::VERBOSITY_QUIET) { return; } $messages = (array) $messages; if ($type & self::NUMBER_LINES) { $pad = \strlen((string) \count($messages)); $template = $this->isDecorated() ? "<aside>%{$pad}s</aside>: %s" : "%{$pad}s: %s"; if ($type & self::OUTPUT_RAW) { $messages = \array_map([OutputFormatter::class, 'escape'], $messages); } foreach ($messages as $i => $line) { $messages[$i] = \sprintf($template, $i, $line); } // clean this up for super. $type = $type & ~self::NUMBER_LINES & ~self::OUTPUT_RAW; } parent::write($messages, $newline, $type); } /** * Writes a message to the output. * * Handles paged output, or writes directly to the output stream. * * @param string $message A message to write to the output * @param bool $newline Whether to add a newline or not */ public function doWrite($message, $newline): void { // @todo Update OutputPager interface to require doWrite if ($this->paging > 0 && $this->pager instanceof ProcOutputPager) { $this->pager->doWrite($message, $newline); } else { parent::doWrite($message, $newline); } } /** * Set the output Theme. */ public function setTheme(Theme $theme) { $this->theme = $theme; $this->initFormatters(); } /** * Flush and close the output pager. */ private function closePager() { if ($this->paging <= 0) { $this->pager->close(); } } /** * Initialize output formatter styles. */ private function initFormatters() { $useGrayFallback = !$this->grayExists(); $this->theme->applyStyles($this->getFormatter(), $useGrayFallback); $this->theme->applyErrorStyles($this->getErrorOutput()->getFormatter(), $useGrayFallback); } /** * Checks if the "gray" color exists on the output. */ private function grayExists(): bool { try { $this->write('<fg=gray></>'); } catch (\InvalidArgumentException $e) { return false; } return true; } } PK������*Z.q7)��)����Output/PassthruPager.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Output; use Symfony\Component\Console\Output\StreamOutput; /** * A passthrough pager is a no-op. It simply wraps a StreamOutput's stream and * does nothing when the pager is closed. */ class PassthruPager extends StreamOutput implements OutputPager { /** * Constructor. * * @param StreamOutput $output */ public function __construct(StreamOutput $output) { parent::__construct($output->getStream()); } /** * Close the current pager process. */ public function close() { // nothing to do here } } PK������*Z㭐6��6����Output/OutputPager.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Output; use Symfony\Component\Console\Output\OutputInterface; /** * An output pager is much the same as a regular OutputInterface, but allows * the stream to be flushed to a pager periodically. */ interface OutputPager extends OutputInterface { /** * Close the current pager process. */ public function close(); } PK������*ZGA �� ����Output/ProcOutputPager.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Output; use Symfony\Component\Console\Output\StreamOutput; /** * ProcOutputPager class. * * A ProcOutputPager instance wraps a regular StreamOutput's stream. Rather * than writing directly to the stream, it shells out to a pager process and * gives that process the stream as stdout. This means regular *nix commands * like `less` and `more` can be used to page large amounts of output. */ class ProcOutputPager extends StreamOutput implements OutputPager { /** @var ?resource */ private $proc = null; /** @var ?resource */ private $pipe = null; /** @var resource */ private $stream; private string $cmd; /** * Constructor. * * @param StreamOutput $output * @param string $cmd Pager process command (default: 'less -R -F -X') */ public function __construct(StreamOutput $output, string $cmd = 'less -R -F -X') { $this->stream = $output->getStream(); $this->cmd = $cmd; } /** * Writes a message to the output. * * @param string $message A message to write to the output * @param bool $newline Whether to add a newline or not * * @throws \RuntimeException When unable to write output (should never happen) */ public function doWrite($message, $newline): void { $pipe = $this->getPipe(); if (false === @\fwrite($pipe, $message.($newline ? \PHP_EOL : ''))) { // @codeCoverageIgnoreStart // should never happen $this->close(); throw new \RuntimeException('Unable to write output'); // @codeCoverageIgnoreEnd } \fflush($pipe); } /** * Close the current pager process. */ public function close() { if (isset($this->pipe)) { \fclose($this->pipe); } if (isset($this->proc)) { $exit = \proc_close($this->proc); if ($exit !== 0) { throw new \RuntimeException('Error closing output stream'); } } $this->pipe = null; $this->proc = null; } /** * Get a pipe for paging output. * * If no active pager process exists, fork one and return its input pipe. */ private function getPipe() { if (!isset($this->pipe) || !isset($this->proc)) { $desc = [['pipe', 'r'], $this->stream, \fopen('php://stderr', 'w')]; $this->proc = \proc_open($this->cmd, $desc, $pipes); if (!\is_resource($this->proc)) { throw new \RuntimeException('Error opening output stream'); } $this->pipe = $pipes[0]; } return $this->pipe; } } PK������*Z.������Output/Theme.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Output; use Symfony\Component\Console\Formatter\OutputFormatterInterface; use Symfony\Component\Console\Formatter\OutputFormatterStyle; /** * An output Theme, which controls prompt strings, formatter styles, and compact output. */ class Theme { const MODERN_THEME = []; // Defaults :) const COMPACT_THEME = [ 'compact' => true, ]; const CLASSIC_THEME = [ 'compact' => true, 'prompt' => '>>> ', 'bufferPrompt' => '... ', 'replayPrompt' => '--> ', 'returnValue' => '=> ', ]; const DEFAULT_STYLES = [ 'info' => ['white', 'blue', ['bold']], 'warning' => ['black', 'yellow'], 'error' => ['white', 'red', ['bold']], 'whisper' => ['gray'], 'aside' => ['blue'], 'strong' => [null, null, ['bold']], 'return' => ['cyan'], 'urgent' => ['red'], 'hidden' => ['black'], // Visibility 'public' => [null, null, ['bold']], 'protected' => ['yellow'], 'private' => ['red'], 'global' => ['cyan', null, ['bold']], 'const' => ['cyan'], 'class' => ['blue', null, ['underscore']], 'function' => [null], 'default' => [null], // Types 'number' => ['magenta'], 'integer' => ['magenta'], 'float' => ['yellow'], 'string' => ['green'], 'bool' => ['cyan'], 'keyword' => ['yellow'], 'comment' => ['blue'], 'code_comment' => ['gray'], 'object' => ['blue'], 'resource' => ['yellow'], // Code-specific formatting 'inline_html' => ['cyan'], ]; const ERROR_STYLES = ['info', 'warning', 'error', 'whisper', 'class']; private bool $compact = false; private string $prompt = '> '; private string $bufferPrompt = '. '; private string $replayPrompt = '- '; private string $returnValue = '= '; private string $grayFallback = 'blue'; private array $styles = []; /** * @param string|array $config theme name or config options */ public function __construct($config = 'modern') { if (\is_string($config)) { switch ($config) { case 'modern': $config = static::MODERN_THEME; break; case 'compact': $config = static::COMPACT_THEME; break; case 'classic': $config = static::CLASSIC_THEME; break; default: \trigger_error(\sprintf('Unknown theme: %s', $config), \E_USER_NOTICE); $config = static::MODERN_THEME; break; } } if (!\is_array($config)) { throw new \InvalidArgumentException('Invalid theme config'); } foreach ($config as $name => $value) { switch ($name) { case 'compact': $this->setCompact($value); break; case 'prompt': $this->setPrompt($value); break; case 'bufferPrompt': $this->setBufferPrompt($value); break; case 'replayPrompt': $this->setReplayPrompt($value); break; case 'returnValue': $this->setReturnValue($value); break; case 'grayFallback': $this->setGrayFallback($value); break; } } $this->setStyles($config['styles'] ?? []); } /** * Enable or disable compact output. */ public function setCompact(bool $compact) { $this->compact = $compact; } /** * Get whether to use compact output. */ public function compact(): bool { return $this->compact; } /** * Set the prompt string. */ public function setPrompt(string $prompt) { $this->prompt = $prompt; } /** * Get the prompt string. */ public function prompt(): string { return $this->prompt; } /** * Set the buffer prompt string (used for multi-line input continuation). */ public function setBufferPrompt(string $bufferPrompt) { $this->bufferPrompt = $bufferPrompt; } /** * Get the buffer prompt string (used for multi-line input continuation). */ public function bufferPrompt(): string { return $this->bufferPrompt; } /** * Set the prompt string used when replaying history. */ public function setReplayPrompt(string $replayPrompt) { $this->replayPrompt = $replayPrompt; } /** * Get the prompt string used when replaying history. */ public function replayPrompt(): string { return $this->replayPrompt; } /** * Set the return value marker. */ public function setReturnValue(string $returnValue) { $this->returnValue = $returnValue; } /** * Get the return value marker. */ public function returnValue(): string { return $this->returnValue; } /** * Set the fallback color when "gray" is unavailable. */ public function setGrayFallback(string $grayFallback) { $this->grayFallback = $grayFallback; } /** * Set the shell output formatter styles. * * Accepts a map from style name to [fg, bg, options], for example: * * [ * 'error' => ['white', 'red', ['bold']], * 'warning' => ['black', 'yellow'], * ] * * Foreground, background or options can be null, or even omitted entirely. */ public function setStyles(array $styles) { foreach (\array_keys(static::DEFAULT_STYLES) as $name) { $this->styles[$name] = $styles[$name] ?? static::DEFAULT_STYLES[$name]; } } /** * Apply the current output formatter styles. */ public function applyStyles(OutputFormatterInterface $formatter, bool $useGrayFallback) { foreach (\array_keys(static::DEFAULT_STYLES) as $name) { $formatter->setStyle($name, new OutputFormatterStyle(...$this->getStyle($name, $useGrayFallback))); } } /** * Apply the current output formatter error styles. */ public function applyErrorStyles(OutputFormatterInterface $errorFormatter, bool $useGrayFallback) { foreach (static::ERROR_STYLES as $name) { $errorFormatter->setStyle($name, new OutputFormatterStyle(...$this->getStyle($name, $useGrayFallback))); } } private function getStyle(string $name, bool $useGrayFallback): array { return \array_map(function ($style) use ($useGrayFallback) { return ($useGrayFallback && $style === 'gray') ? $this->grayFallback : $style; }, $this->styles[$name]); } } PK������*Z~7��7����ContextAware.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy; /** * ContextAware interface. * * This interface is used to pass the Shell's context into commands and such * which require access to the current scope variables. */ interface ContextAware { /** * Set the Context reference. * * @param Context $context */ public function setContext(Context $context); } PK������*ZUv��v�� ��Context.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/recursion-context. * * (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\RecursionContext; use const PHP_INT_MAX; use const PHP_INT_MIN; use function array_key_exists; use function array_pop; use function array_slice; use function count; use function is_array; use function is_object; use function random_int; use function spl_object_hash; use SplObjectStorage; /** * A context containing previously processed arrays and objects * when recursively processing a value. */ final class Context { /** * @var array[] */ private $arrays; /** * @var SplObjectStorage */ private $objects; /** * Initialises the context. */ public function __construct() { $this->arrays = []; $this->objects = new SplObjectStorage; } /** * @codeCoverageIgnore */ public function __destruct() { foreach ($this->arrays as &$array) { if (is_array($array)) { array_pop($array); array_pop($array); } } } /** * Adds a value to the context. * * @param array|object $value the value to add * * @throws InvalidArgumentException Thrown if $value is not an array or object * * @return bool|int|string the ID of the stored value, either as a string or integer * * @psalm-template T * @psalm-param T $value * @param-out T $value */ public function add(&$value) { if (is_array($value)) { return $this->addArray($value); } if (is_object($value)) { return $this->addObject($value); } throw new InvalidArgumentException( 'Only arrays and objects are supported' ); } /** * Checks if the given value exists within the context. * * @param array|object $value the value to check * * @throws InvalidArgumentException Thrown if $value is not an array or object * * @return false|int|string the string or integer ID of the stored value if it has already been seen, or false if the value is not stored * * @psalm-template T * @psalm-param T $value * @param-out T $value */ public function contains(&$value) { if (is_array($value)) { return $this->containsArray($value); } if (is_object($value)) { return $this->containsObject($value); } throw new InvalidArgumentException( 'Only arrays and objects are supported' ); } /** * @return bool|int */ private function addArray(array &$array) { $key = $this->containsArray($array); if ($key !== false) { return $key; } $key = count($this->arrays); $this->arrays[] = &$array; if (!array_key_exists(PHP_INT_MAX, $array) && !array_key_exists(PHP_INT_MAX - 1, $array)) { $array[] = $key; $array[] = $this->objects; } else { /* cover the improbable case too */ /* Note that array_slice (used in containsArray) will return the * last two values added *not necessarily* the highest integer * keys in the array, so the order of these writes to $array * is important, but the actual keys used is not. */ do { $key = random_int(PHP_INT_MIN, PHP_INT_MAX); } while (array_key_exists($key, $array)); $array[$key] = $key; do { $key = random_int(PHP_INT_MIN, PHP_INT_MAX); } while (array_key_exists($key, $array)); $array[$key] = $this->objects; } return $key; } /** * @param object $object */ private function addObject($object): string { if (!$this->objects->contains($object)) { $this->objects->attach($object); } return spl_object_hash($object); } /** * @return false|int */ private function containsArray(array &$array) { $end = array_slice($array, -2); return isset($end[1]) && $end[1] === $this->objects ? $end[0] : false; } /** * @param object $value * * @return false|string */ private function containsObject($value) { if ($this->objects->contains($value)) { return spl_object_hash($value); } return false; } } PK������*Z.8��8�� ��functions.phpnu�W+A��������<?php namespace GuzzleHttp; /** * Debug function used to describe the provided value type and class. * * @param mixed $input Any type of variable to describe the type of. This * parameter misses a typehint because of that. * * @return string Returns a string containing the type of the variable and * if a class is provided, the class name. * * @deprecated describe_type will be removed in guzzlehttp/guzzle:8.0. Use Utils::describeType instead. */ function describe_type($input): string { return Utils::describeType($input); } /** * Parses an array of header lines into an associative array of headers. * * @param iterable $lines Header lines array of strings in the following * format: "Name: Value" * * @deprecated headers_from_lines will be removed in guzzlehttp/guzzle:8.0. Use Utils::headersFromLines instead. */ function headers_from_lines(iterable $lines): array { return Utils::headersFromLines($lines); } /** * Returns a debug stream based on the provided variable. * * @param mixed $value Optional value * * @return resource * * @deprecated debug_resource will be removed in guzzlehttp/guzzle:8.0. Use Utils::debugResource instead. */ function debug_resource($value = null) { return Utils::debugResource($value); } /** * Chooses and creates a default handler to use based on the environment. * * The returned handler is not wrapped by any default middlewares. * * @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the best handler for the given system. * * @throws \RuntimeException if no viable Handler is available. * * @deprecated choose_handler will be removed in guzzlehttp/guzzle:8.0. Use Utils::chooseHandler instead. */ function choose_handler(): callable { return Utils::chooseHandler(); } /** * Get the default User-Agent string to use with Guzzle. * * @deprecated default_user_agent will be removed in guzzlehttp/guzzle:8.0. Use Utils::defaultUserAgent instead. */ function default_user_agent(): string { return Utils::defaultUserAgent(); } /** * Returns the default cacert bundle for the current system. * * First, the openssl.cafile and curl.cainfo php.ini settings are checked. * If those settings are not configured, then the common locations for * bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X * and Windows are checked. If any of these file locations are found on * disk, they will be utilized. * * Note: the result of this function is cached for subsequent calls. * * @throws \RuntimeException if no bundle can be found. * * @deprecated default_ca_bundle will be removed in guzzlehttp/guzzle:8.0. This function is not needed in PHP 5.6+. */ function default_ca_bundle(): string { return Utils::defaultCaBundle(); } /** * Creates an associative array of lowercase header names to the actual * header casing. * * @deprecated normalize_header_keys will be removed in guzzlehttp/guzzle:8.0. Use Utils::normalizeHeaderKeys instead. */ function normalize_header_keys(array $headers): array { return Utils::normalizeHeaderKeys($headers); } /** * Returns true if the provided host matches any of the no proxy areas. * * This method will strip a port from the host if it is present. Each pattern * can be matched with an exact match (e.g., "foo.com" == "foo.com") or a * partial match: (e.g., "foo.com" == "baz.foo.com" and ".foo.com" == * "baz.foo.com", but ".foo.com" != "foo.com"). * * Areas are matched in the following cases: * 1. "*" (without quotes) always matches any hosts. * 2. An exact match. * 3. The area starts with "." and the area is the last part of the host. e.g. * '.mit.edu' will match any host that ends with '.mit.edu'. * * @param string $host Host to check against the patterns. * @param string[] $noProxyArray An array of host patterns. * * @throws Exception\InvalidArgumentException * * @deprecated is_host_in_noproxy will be removed in guzzlehttp/guzzle:8.0. Use Utils::isHostInNoProxy instead. */ function is_host_in_noproxy(string $host, array $noProxyArray): bool { return Utils::isHostInNoProxy($host, $noProxyArray); } /** * Wrapper for json_decode that throws when an error occurs. * * @param string $json JSON data to parse * @param bool $assoc When true, returned objects will be converted * into associative arrays. * @param int $depth User specified recursion depth. * @param int $options Bitmask of JSON decode options. * * @return object|array|string|int|float|bool|null * * @throws Exception\InvalidArgumentException if the JSON cannot be decoded. * * @see https://www.php.net/manual/en/function.json-decode.php * @deprecated json_decode will be removed in guzzlehttp/guzzle:8.0. Use Utils::jsonDecode instead. */ function json_decode(string $json, bool $assoc = false, int $depth = 512, int $options = 0) { return Utils::jsonDecode($json, $assoc, $depth, $options); } /** * Wrapper for JSON encoding that throws when an error occurs. * * @param mixed $value The value being encoded * @param int $options JSON encode option bitmask * @param int $depth Set the maximum depth. Must be greater than zero. * * @throws Exception\InvalidArgumentException if the JSON cannot be encoded. * * @see https://www.php.net/manual/en/function.json-encode.php * @deprecated json_encode will be removed in guzzlehttp/guzzle:8.0. Use Utils::jsonEncode instead. */ function json_encode($value, int $options = 0, int $depth = 512): string { return Utils::jsonEncode($value, $options, $depth); } PK������*Z������VarDumper/Cloner.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\VarDumper; use Symfony\Component\VarDumper\Caster\Caster; use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Cloner\Stub; use Symfony\Component\VarDumper\Cloner\VarCloner; /** * A PsySH-specialized VarCloner. */ class Cloner extends VarCloner { private int $filter = 0; /** * {@inheritdoc} */ public function cloneVar($var, $filter = 0): Data { $this->filter = $filter; return parent::cloneVar($var, $filter); } /** * {@inheritdoc} */ protected function castResource(Stub $stub, $isNested): array { return Caster::EXCLUDE_VERBOSE & $this->filter ? [] : parent::castResource($stub, $isNested); } } PK������*Z~v �� ����VarDumper/Dumper.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\VarDumper; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\VarDumper\Cloner\Cursor; use Symfony\Component\VarDumper\Dumper\CliDumper; /** * A PsySH-specialized CliDumper. */ class Dumper extends CliDumper { private OutputFormatter $formatter; private bool $forceArrayIndexes; private const ONLY_CONTROL_CHARS = '/^[\x00-\x1F\x7F]+$/'; private const CONTROL_CHARS = '/([\x00-\x1F\x7F]+)/'; private const CONTROL_CHARS_MAP = [ "\0" => '\0', "\t" => '\t', "\n" => '\n', "\v" => '\v', "\f" => '\f', "\r" => '\r', "\033" => '\e', ]; public function __construct(OutputFormatter $formatter, $forceArrayIndexes = false) { $this->formatter = $formatter; $this->forceArrayIndexes = $forceArrayIndexes; parent::__construct(); $this->setColors(false); } /** * {@inheritdoc} */ public function enterHash(Cursor $cursor, $type, $class, $hasChild): void { if (Cursor::HASH_INDEXED === $type || Cursor::HASH_ASSOC === $type) { $class = 0; } parent::enterHash($cursor, $type, $class, $hasChild); } /** * {@inheritdoc} */ protected function dumpKey(Cursor $cursor): void { if ($this->forceArrayIndexes || Cursor::HASH_INDEXED !== $cursor->hashType) { parent::dumpKey($cursor); } } protected function style($style, $value, $attr = []): string { if ('ref' === $style) { $value = \strtr($value, '@', '#'); } $styled = ''; $cchr = $this->styles['cchr']; $chunks = \preg_split(self::CONTROL_CHARS, $value, -1, \PREG_SPLIT_NO_EMPTY | \PREG_SPLIT_DELIM_CAPTURE); foreach ($chunks as $chunk) { if (\preg_match(self::ONLY_CONTROL_CHARS, $chunk)) { $chars = ''; $i = 0; do { $chars .= isset(self::CONTROL_CHARS_MAP[$chunk[$i]]) ? self::CONTROL_CHARS_MAP[$chunk[$i]] : \sprintf('\x%02X', \ord($chunk[$i])); } while (isset($chunk[++$i])); $chars = $this->formatter->escape($chars); $styled .= "<{$cchr}>{$chars}</{$cchr}>"; } else { $styled .= $this->formatter->escape($chunk); } } $style = $this->styles[$style]; return "<{$style}>{$styled}</{$style}>"; } /** * {@inheritdoc} */ protected function dumpLine($depth, $endOfValue = false): void { if ($endOfValue && 0 < $depth) { $this->line .= ','; } $this->line = $this->formatter->format($this->line); parent::dumpLine($depth, $endOfValue); } } PK������*Z#}U&��&����VarDumper/Presenter.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\VarDumper; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\VarDumper\Caster\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * A Presenter service. */ class Presenter { const VERBOSE = 1; private Cloner $cloner; private Dumper $dumper; private const IMPORTANT_EXCEPTIONS = [ "\0*\0message", "\0*\0code", "\0*\0file", "\0*\0line", "\0Exception\0previous", ]; private const STYLES = [ 'num' => 'number', 'integer' => 'integer', 'float' => 'float', 'const' => 'const', 'str' => 'string', 'cchr' => 'default', 'note' => 'class', 'ref' => 'default', 'public' => 'public', 'protected' => 'protected', 'private' => 'private', 'meta' => 'comment', 'key' => 'comment', 'index' => 'number', ]; public function __construct(OutputFormatter $formatter, $forceArrayIndexes = false) { // Work around https://github.com/symfony/symfony/issues/23572 $oldLocale = \setlocale(\LC_NUMERIC, 0); \setlocale(\LC_NUMERIC, 'C'); $this->dumper = new Dumper($formatter, $forceArrayIndexes); $this->dumper->setStyles(self::STYLES); // Now put the locale back \setlocale(\LC_NUMERIC, $oldLocale); $this->cloner = new Cloner(); $this->cloner->addCasters(['*' => function ($obj, array $a, Stub $stub, $isNested, $filter = 0) { if ($filter || $isNested) { if ($obj instanceof \Throwable) { $a = Caster::filter($a, Caster::EXCLUDE_NOT_IMPORTANT | Caster::EXCLUDE_EMPTY, self::IMPORTANT_EXCEPTIONS); } else { $a = Caster::filter($a, Caster::EXCLUDE_PROTECTED | Caster::EXCLUDE_PRIVATE); } } return $a; }]); } /** * Register casters. * * @see http://symfony.com/doc/current/components/var_dumper/advanced.html#casters * * @param callable[] $casters A map of casters */ public function addCasters(array $casters) { $this->cloner->addCasters($casters); } /** * Present a reference to the value. * * @param mixed $value */ public function presentRef($value): string { return $this->present($value, 0); } /** * Present a full representation of the value. * * If $depth is 0, the value will be presented as a ref instead. * * @param mixed $value * @param int $depth (default: null) * @param int $options One of Presenter constants */ public function present($value, ?int $depth = null, int $options = 0): string { $data = $this->cloner->cloneVar($value, !($options & self::VERBOSE) ? Caster::EXCLUDE_VERBOSE : 0); if (null !== $depth) { $data = $data->withMaxDepth($depth); } // Work around https://github.com/symfony/symfony/issues/23572 $oldLocale = \setlocale(\LC_NUMERIC, 0); \setlocale(\LC_NUMERIC, 'C'); $output = ''; $this->dumper->dump($data, function ($line, $depth) use (&$output) { if ($depth >= 0) { if ('' !== $output) { $output .= \PHP_EOL; } $output .= \str_repeat(' ', $depth).$line; } }); // Now put the locale back \setlocale(\LC_NUMERIC, $oldLocale); return OutputFormatter::escape($output); } } PK������*Z $������VarDumper/PresenterAware.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\VarDumper; /** * Presenter injects itself as a dependency to all objects which * implement PresenterAware. */ interface PresenterAware { /** * Set a reference to the Presenter. * * @param Presenter $presenter */ public function setPresenter(Presenter $presenter); } PK������*ZտQ,��Q,����CodeCleaner.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy; use PhpParser\NodeTraverser; use PhpParser\Parser; use PhpParser\PrettyPrinter\Standard as Printer; use Psy\CodeCleaner\AbstractClassPass; use Psy\CodeCleaner\AssignThisVariablePass; use Psy\CodeCleaner\CalledClassPass; use Psy\CodeCleaner\CallTimePassByReferencePass; use Psy\CodeCleaner\CodeCleanerPass; use Psy\CodeCleaner\EmptyArrayDimFetchPass; use Psy\CodeCleaner\ExitPass; use Psy\CodeCleaner\FinalClassPass; use Psy\CodeCleaner\FunctionContextPass; use Psy\CodeCleaner\FunctionReturnInWriteContextPass; use Psy\CodeCleaner\ImplicitReturnPass; use Psy\CodeCleaner\IssetPass; use Psy\CodeCleaner\LabelContextPass; use Psy\CodeCleaner\LeavePsyshAlonePass; use Psy\CodeCleaner\ListPass; use Psy\CodeCleaner\LoopContextPass; use Psy\CodeCleaner\MagicConstantsPass; use Psy\CodeCleaner\NamespacePass; use Psy\CodeCleaner\PassableByReferencePass; use Psy\CodeCleaner\RequirePass; use Psy\CodeCleaner\ReturnTypePass; use Psy\CodeCleaner\StrictTypesPass; use Psy\CodeCleaner\UseStatementPass; use Psy\CodeCleaner\ValidClassNamePass; use Psy\CodeCleaner\ValidConstructorPass; use Psy\CodeCleaner\ValidFunctionNamePass; use Psy\Exception\ParseErrorException; /** * A service to clean up user input, detect parse errors before they happen, * and generally work around issues with the PHP code evaluation experience. */ class CodeCleaner { private bool $yolo = false; private bool $strictTypes = false; private Parser $parser; private Printer $printer; private NodeTraverser $traverser; private ?array $namespace = null; /** * CodeCleaner constructor. * * @param Parser|null $parser A PhpParser Parser instance. One will be created if not explicitly supplied * @param Printer|null $printer A PhpParser Printer instance. One will be created if not explicitly supplied * @param NodeTraverser|null $traverser A PhpParser NodeTraverser instance. One will be created if not explicitly supplied * @param bool $yolo run without input validation * @param bool $strictTypes enforce strict types by default */ public function __construct(?Parser $parser = null, ?Printer $printer = null, ?NodeTraverser $traverser = null, bool $yolo = false, bool $strictTypes = false) { $this->yolo = $yolo; $this->strictTypes = $strictTypes; $this->parser = $parser ?? (new ParserFactory())->createParser(); $this->printer = $printer ?: new Printer(); $this->traverser = $traverser ?: new NodeTraverser(); foreach ($this->getDefaultPasses() as $pass) { $this->traverser->addVisitor($pass); } } /** * Check whether this CodeCleaner is in YOLO mode. */ public function yolo(): bool { return $this->yolo; } /** * Get default CodeCleaner passes. * * @return CodeCleanerPass[] */ private function getDefaultPasses(): array { $useStatementPass = new UseStatementPass(); $namespacePass = new NamespacePass($this); // Try to add implicit `use` statements and an implicit namespace, // based on the file in which the `debug` call was made. $this->addImplicitDebugContext([$useStatementPass, $namespacePass]); // A set of code cleaner passes that don't try to do any validation, and // only do minimal rewriting to make things work inside the REPL. // // When in --yolo mode, these are the only code cleaner passes used. $rewritePasses = [ new LeavePsyshAlonePass(), $useStatementPass, // must run before the namespace pass new ExitPass(), new ImplicitReturnPass(), new MagicConstantsPass(), $namespacePass, // must run after the implicit return pass new RequirePass(), new StrictTypesPass($this->strictTypes), ]; if ($this->yolo) { return $rewritePasses; } return [ // Validation passes new AbstractClassPass(), new AssignThisVariablePass(), new CalledClassPass(), new CallTimePassByReferencePass(), new FinalClassPass(), new FunctionContextPass(), new FunctionReturnInWriteContextPass(), new IssetPass(), new LabelContextPass(), new ListPass(), new LoopContextPass(), new PassableByReferencePass(), new ReturnTypePass(), new EmptyArrayDimFetchPass(), new ValidConstructorPass(), // Rewriting shenanigans ...$rewritePasses, // Namespace-aware validation (which depends on aforementioned shenanigans) new ValidClassNamePass(), new ValidFunctionNamePass(), ]; } /** * "Warm up" code cleaner passes when we're coming from a debug call. * * This is useful, for example, for `UseStatementPass` and `NamespacePass` * which keep track of state between calls, to maintain the current * namespace and a map of use statements. * * @param array $passes */ private function addImplicitDebugContext(array $passes) { $file = $this->getDebugFile(); if ($file === null) { return; } try { $code = @\file_get_contents($file); if (!$code) { return; } $stmts = $this->parse($code, true); if ($stmts === false) { return; } // Set up a clean traverser for just these code cleaner passes // @todo Pass visitors directly to once we drop support for PHP-Parser 4.x $traverser = new NodeTraverser(); foreach ($passes as $pass) { $traverser->addVisitor($pass); } $traverser->traverse($stmts); } catch (\Throwable $e) { // Don't care. } } /** * Search the stack trace for a file in which the user called Psy\debug. * * @return string|null */ private static function getDebugFile() { $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS); foreach (\array_reverse($trace) as $stackFrame) { if (!self::isDebugCall($stackFrame)) { continue; } if (\preg_match('/eval\(/', $stackFrame['file'])) { \preg_match_all('/([^\(]+)\((\d+)/', $stackFrame['file'], $matches); return $matches[1][0]; } return $stackFrame['file']; } } /** * Check whether a given backtrace frame is a call to Psy\debug. * * @param array $stackFrame */ private static function isDebugCall(array $stackFrame): bool { $class = isset($stackFrame['class']) ? $stackFrame['class'] : null; $function = isset($stackFrame['function']) ? $stackFrame['function'] : null; return ($class === null && $function === 'Psy\\debug') || ($class === Shell::class && $function === 'debug'); } /** * Clean the given array of code. * * @throws ParseErrorException if the code is invalid PHP, and cannot be coerced into valid PHP * * @param array $codeLines * @param bool $requireSemicolons * * @return string|false Cleaned PHP code, False if the input is incomplete */ public function clean(array $codeLines, bool $requireSemicolons = false) { $stmts = $this->parse('<?php '.\implode(\PHP_EOL, $codeLines).\PHP_EOL, $requireSemicolons); if ($stmts === false) { return false; } // Catch fatal errors before they happen $stmts = $this->traverser->traverse($stmts); // Work around https://github.com/nikic/PHP-Parser/issues/399 $oldLocale = \setlocale(\LC_NUMERIC, 0); \setlocale(\LC_NUMERIC, 'C'); $code = $this->printer->prettyPrint($stmts); // Now put the locale back \setlocale(\LC_NUMERIC, $oldLocale); return $code; } /** * Set the current local namespace. */ public function setNamespace(?array $namespace = null) { $this->namespace = $namespace; } /** * Get the current local namespace. * * @return array|null */ public function getNamespace() { return $this->namespace; } /** * Lex and parse a block of code. * * @see Parser::parse * * @throws ParseErrorException for parse errors that can't be resolved by * waiting a line to see what comes next * * @return array|false A set of statements, or false if incomplete */ protected function parse(string $code, bool $requireSemicolons = false) { try { return $this->parser->parse($code); } catch (\PhpParser\Error $e) { if ($this->parseErrorIsUnclosedString($e, $code)) { return false; } if ($this->parseErrorIsUnterminatedComment($e, $code)) { return false; } if ($this->parseErrorIsTrailingComma($e, $code)) { return false; } if (!$this->parseErrorIsEOF($e)) { throw ParseErrorException::fromParseError($e); } if ($requireSemicolons) { return false; } try { // Unexpected EOF, try again with an implicit semicolon return $this->parser->parse($code.';'); } catch (\PhpParser\Error $e) { return false; } } } private function parseErrorIsEOF(\PhpParser\Error $e): bool { $msg = $e->getRawMessage(); return ($msg === 'Unexpected token EOF') || (\strpos($msg, 'Syntax error, unexpected EOF') !== false); } /** * A special test for unclosed single-quoted strings. * * Unlike (all?) other unclosed statements, single quoted strings have * their own special beautiful snowflake syntax error just for * themselves. */ private function parseErrorIsUnclosedString(\PhpParser\Error $e, string $code): bool { if ($e->getRawMessage() !== 'Syntax error, unexpected T_ENCAPSED_AND_WHITESPACE') { return false; } try { $this->parser->parse($code."';"); } catch (\Throwable $e) { return false; } return true; } private function parseErrorIsUnterminatedComment(\PhpParser\Error $e, string $code): bool { return $e->getRawMessage() === 'Unterminated comment'; } private function parseErrorIsTrailingComma(\PhpParser\Error $e, string $code): bool { return ($e->getRawMessage() === 'A trailing comma is not allowed here') && (\substr(\rtrim($code), -1) === ','); } } PK������*Z<Ǫ0~��~����Input/SilentInput.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Input; /** * A simple class used internally by PsySH to represent silent input. * * Silent input is generally used for non-user-generated code, such as the * rewritten user code run by sudo command. Silent input isn't echoed before * evaluating, and it's not added to the readline history. */ class SilentInput { private string $inputString; /** * Constructor. * * @param string $inputString */ public function __construct(string $inputString) { $this->inputString = $inputString; } /** * To. String. */ public function __toString(): string { return $this->inputString; } } PK������*Zu8C��C����Input/FilterOptions.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Input; use Psy\Exception\ErrorException; use Psy\Exception\RuntimeException; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; /** * Parse, validate and match --grep, --insensitive and --invert command options. */ class FilterOptions { private bool $filter = false; private ?string $pattern = null; private bool $insensitive = false; private bool $invert = false; /** * Get input option definitions for filtering. * * @return InputOption[] */ public static function getOptions(): array { return [ new InputOption('grep', 'G', InputOption::VALUE_REQUIRED, 'Limit to items matching the given pattern (string or regex).'), new InputOption('insensitive', 'i', InputOption::VALUE_NONE, 'Case-insensitive search (requires --grep).'), new InputOption('invert', 'v', InputOption::VALUE_NONE, 'Inverted search (requires --grep).'), ]; } /** * Bind input and prepare filter. * * @param InputInterface $input */ public function bind(InputInterface $input) { $this->validateInput($input); if (!$pattern = $input->getOption('grep')) { $this->filter = false; return; } if (!$this->stringIsRegex($pattern)) { $pattern = '/'.\preg_quote($pattern, '/').'/'; } if ($insensitive = $input->getOption('insensitive')) { $pattern .= 'i'; } $this->validateRegex($pattern); $this->filter = true; $this->pattern = $pattern; $this->insensitive = $insensitive; $this->invert = $input->getOption('invert'); } /** * Check whether the bound input has filter options. */ public function hasFilter(): bool { return $this->filter; } /** * Check whether a string matches the current filter options. * * @param string $string * @param array $matches */ public function match(string $string, ?array &$matches = null): bool { return $this->filter === false || (\preg_match($this->pattern, $string, $matches) xor $this->invert); } /** * Validate that grep, invert and insensitive input options are consistent. * * @throws RuntimeException if input is invalid * * @param InputInterface $input */ private function validateInput(InputInterface $input) { if (!$input->getOption('grep')) { foreach (['invert', 'insensitive'] as $option) { if ($input->getOption($option)) { throw new RuntimeException('--'.$option.' does not make sense without --grep'); } } } } /** * Check whether a string appears to be a regular expression. * * @param string $string */ private function stringIsRegex(string $string): bool { return \substr($string, 0, 1) === '/' && \substr($string, -1) === '/' && \strlen($string) >= 3; } /** * Validate that $pattern is a valid regular expression. * * @throws RuntimeException if pattern is invalid * * @param string $pattern */ private function validateRegex(string $pattern) { \set_error_handler([ErrorException::class, 'throwException']); try { \preg_match($pattern, ''); } catch (ErrorException $e) { throw new RuntimeException(\str_replace('preg_match(): ', 'Invalid regular expression: ', $e->getRawMessage())); } finally { \restore_error_handler(); } } } PK������*Z+��+����Input/ShellInput.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Input; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\StringInput; /** * A StringInput subclass specialized for code arguments. */ class ShellInput extends StringInput { public const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)'; private bool $hasCodeArgument = false; /** * Unlike the parent implementation's tokens, this contains an array of * token/rest pairs, so that code arguments can be handled while parsing. */ private array $tokenPairs; private array $parsed = []; /** * Constructor. * * @param string $input An array of parameters from the CLI (in the argv format) */ public function __construct(string $input) { parent::__construct($input); $this->tokenPairs = $this->tokenize($input); } /** * {@inheritdoc} * * @throws \InvalidArgumentException if $definition has CodeArgument before the final argument position */ public function bind(InputDefinition $definition): void { $hasCodeArgument = false; if ($definition->getArgumentCount() > 0) { $args = $definition->getArguments(); $lastArg = \array_pop($args); foreach ($args as $arg) { if ($arg instanceof CodeArgument) { $msg = \sprintf('Unexpected CodeArgument before the final position: %s', $arg->getName()); throw new \InvalidArgumentException($msg); } } if ($lastArg instanceof CodeArgument) { $hasCodeArgument = true; } } $this->hasCodeArgument = $hasCodeArgument; parent::bind($definition); } /** * Tokenizes a string. * * The version of this on StringInput is good, but doesn't handle code * arguments if they're at all complicated. This does :) * * @param string $input The input to tokenize * * @return array An array of token/rest pairs * * @throws \InvalidArgumentException When unable to parse input (should never happen) */ private function tokenize(string $input): array { $tokens = []; $length = \strlen($input); $cursor = 0; while ($cursor < $length) { if (\preg_match('/\s+/A', $input, $match, 0, $cursor)) { } elseif (\preg_match('/([^="\'\s]+?)(=?)('.StringInput::REGEX_QUOTED_STRING.'+)/A', $input, $match, 0, $cursor)) { $tokens[] = [ $match[1].$match[2].\stripcslashes(\str_replace(['"\'', '\'"', '\'\'', '""'], '', \substr($match[3], 1, \strlen($match[3]) - 2))), \stripcslashes(\substr($input, $cursor)), ]; } elseif (\preg_match('/'.StringInput::REGEX_QUOTED_STRING.'/A', $input, $match, 0, $cursor)) { $tokens[] = [ \stripcslashes(\substr($match[0], 1, \strlen($match[0]) - 2)), \stripcslashes(\substr($input, $cursor)), ]; } elseif (\preg_match('/'.self::REGEX_STRING.'/A', $input, $match, 0, $cursor)) { $tokens[] = [ \stripcslashes($match[1]), \stripcslashes(\substr($input, $cursor)), ]; } else { // should never happen // @codeCoverageIgnoreStart throw new \InvalidArgumentException(\sprintf('Unable to parse input near "... %s ..."', \substr($input, $cursor, 10))); // @codeCoverageIgnoreEnd } $cursor += \strlen($match[0]); } return $tokens; } /** * Same as parent, but with some bonus handling for code arguments. */ protected function parse(): void { $parseOptions = true; $this->parsed = $this->tokenPairs; while (null !== $tokenPair = \array_shift($this->parsed)) { // token is what you'd expect. rest is the remainder of the input // string, including token, and will be used if this is a code arg. list($token, $rest) = $tokenPair; if ($parseOptions && '' === $token) { $this->parseShellArgument($token, $rest); } elseif ($parseOptions && '--' === $token) { $parseOptions = false; } elseif ($parseOptions && 0 === \strpos($token, '--')) { $this->parseLongOption($token); } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) { $this->parseShortOption($token); } else { $this->parseShellArgument($token, $rest); } } } /** * Parses an argument, with bonus handling for code arguments. * * @param string $token The current token * @param string $rest The remaining unparsed input, including the current token * * @throws \RuntimeException When too many arguments are given */ private function parseShellArgument(string $token, string $rest) { $c = \count($this->arguments); // if input is expecting another argument, add it if ($this->definition->hasArgument($c)) { $arg = $this->definition->getArgument($c); if ($arg instanceof CodeArgument) { // When we find a code argument, we're done parsing. Add the // remaining input to the current argument and call it a day. $this->parsed = []; $this->arguments[$arg->getName()] = $rest; } else { $this->arguments[$arg->getName()] = $arg->isArray() ? [$token] : $token; } return; } // (copypasta) // // @codeCoverageIgnoreStart // if last argument isArray(), append token to last argument if ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) { $arg = $this->definition->getArgument($c - 1); $this->arguments[$arg->getName()][] = $token; return; } // unexpected argument $all = $this->definition->getArguments(); if (\count($all)) { throw new \RuntimeException(\sprintf('Too many arguments, expected arguments "%s".', \implode('" "', \array_keys($all)))); } throw new \RuntimeException(\sprintf('No arguments expected, got "%s".', $token)); // @codeCoverageIgnoreEnd } // Everything below this is copypasta from ArgvInput private methods // @codeCoverageIgnoreStart /** * Parses a short option. * * @param string $token The current token */ private function parseShortOption(string $token) { $name = \substr($token, 1); if (\strlen($name) > 1) { if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) { // an option with a value (with no space) $this->addShortOption($name[0], \substr($name, 1)); } else { $this->parseShortOptionSet($name); } } else { $this->addShortOption($name, null); } } /** * Parses a short option set. * * @param string $name The current token * * @throws \RuntimeException When option given doesn't exist */ private function parseShortOptionSet(string $name) { $len = \strlen($name); for ($i = 0; $i < $len; $i++) { if (!$this->definition->hasShortcut($name[$i])) { throw new \RuntimeException(\sprintf('The "-%s" option does not exist.', $name[$i])); } $option = $this->definition->getOptionForShortcut($name[$i]); if ($option->acceptValue()) { $this->addLongOption($option->getName(), $i === $len - 1 ? null : \substr($name, $i + 1)); break; } else { $this->addLongOption($option->getName(), null); } } } /** * Parses a long option. * * @param string $token The current token */ private function parseLongOption(string $token) { $name = \substr($token, 2); if (false !== $pos = \strpos($name, '=')) { if (($value = \substr($name, $pos + 1)) === '') { \array_unshift($this->parsed, [$value, null]); } $this->addLongOption(\substr($name, 0, $pos), $value); } else { $this->addLongOption($name, null); } } /** * Adds a short option value. * * @param string $shortcut The short option key * @param mixed $value The value for the option * * @throws \RuntimeException When option given doesn't exist */ private function addShortOption(string $shortcut, $value) { if (!$this->definition->hasShortcut($shortcut)) { throw new \RuntimeException(\sprintf('The "-%s" option does not exist.', $shortcut)); } $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); } /** * Adds a long option value. * * @param string $name The long option key * @param mixed $value The value for the option * * @throws \RuntimeException When option given doesn't exist */ private function addLongOption(string $name, $value) { if (!$this->definition->hasOption($name)) { throw new \RuntimeException(\sprintf('The "--%s" option does not exist.', $name)); } $option = $this->definition->getOption($name); if (null !== $value && !$option->acceptValue()) { throw new \RuntimeException(\sprintf('The "--%s" option does not accept a value.', $name)); } if (\in_array($value, ['', null], true) && $option->acceptValue() && \count($this->parsed)) { // if option accepts an optional or mandatory argument // let's see if there is one provided $next = \array_shift($this->parsed); $nextToken = $next[0]; if ((isset($nextToken[0]) && '-' !== $nextToken[0]) || \in_array($nextToken, ['', null], true)) { $value = $nextToken; } else { \array_unshift($this->parsed, $next); } } if ($value === null) { if ($option->isValueRequired()) { throw new \RuntimeException(\sprintf('The "--%s" option requires a value.', $name)); } if (!$option->isArray() && !$option->isValueOptional()) { $value = true; } } if ($option->isArray()) { $this->options[$name][] = $value; } else { $this->options[$name] = $value; } } // @codeCoverageIgnoreEnd } PK������*ZŠ|H �� ����Input/CodeArgument.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Input; use Symfony\Component\Console\Input\InputArgument; /** * An input argument for code. * * A CodeArgument must be the final argument of the command. Once all options * and other arguments are used, any remaining input until the end of the string * is considered part of a single CodeArgument, regardless of spaces, quoting, * escaping, etc. * * This means commands can support crazy input like * * parse function() { return "wheee\n"; } * * ... without having to put the code in a quoted string and escape everything. */ class CodeArgument extends InputArgument { /** * Constructor. * * @param string $name The argument name * @param int $mode The argument mode: self::REQUIRED or self::OPTIONAL * @param string $description A description text * @param mixed $default The default value (for self::OPTIONAL mode only) * * @throws \InvalidArgumentException When argument mode is not valid */ public function __construct(string $name, ?int $mode = null, string $description = '', $default = null) { if ($mode & InputArgument::IS_ARRAY) { throw new \InvalidArgumentException('Argument mode IS_ARRAY is not valid'); } parent::__construct($name, $mode, $description, $default); } } PK������*Z5 2��2����Command/HistoryCommand.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use Psy\Input\FilterOptions; use Psy\Output\ShellOutput; use Psy\Readline\Readline; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * Psy Shell history command. * * Shows, searches and replays readline history. Not too shabby. */ class HistoryCommand extends Command { private FilterOptions $filter; private Readline $readline; /** * {@inheritdoc} */ public function __construct($name = null) { $this->filter = new FilterOptions(); parent::__construct($name); } /** * Set the Shell's Readline service. * * @param Readline $readline */ public function setReadline(Readline $readline) { $this->readline = $readline; } /** * {@inheritdoc} */ protected function configure() { list($grep, $insensitive, $invert) = FilterOptions::getOptions(); $this ->setName('history') ->setAliases(['hist']) ->setDefinition([ new InputOption('show', 's', InputOption::VALUE_REQUIRED, 'Show the given range of lines.'), new InputOption('head', 'H', InputOption::VALUE_REQUIRED, 'Display the first N items.'), new InputOption('tail', 'T', InputOption::VALUE_REQUIRED, 'Display the last N items.'), $grep, $insensitive, $invert, new InputOption('no-numbers', 'N', InputOption::VALUE_NONE, 'Omit line numbers.'), new InputOption('save', '', InputOption::VALUE_REQUIRED, 'Save history to a file.'), new InputOption('replay', '', InputOption::VALUE_NONE, 'Replay.'), new InputOption('clear', '', InputOption::VALUE_NONE, 'Clear the history.'), ]) ->setDescription('Show the Psy Shell history.') ->setHelp( <<<'HELP' Show, search, save or replay the Psy Shell history. e.g. <return>>>> history --grep /[bB]acon/</return> <return>>>> history --show 0..10 --replay</return> <return>>>> history --clear</return> <return>>>> history --tail 1000 --save somefile.txt</return> HELP ); } /** * {@inheritdoc} * * @return int 0 if everything went fine, or an exit code */ protected function execute(InputInterface $input, OutputInterface $output): int { $this->validateOnlyOne($input, ['show', 'head', 'tail']); $this->validateOnlyOne($input, ['save', 'replay', 'clear']); $history = $this->getHistorySlice( $input->getOption('show'), $input->getOption('head'), $input->getOption('tail') ); $highlighted = false; $this->filter->bind($input); if ($this->filter->hasFilter()) { $matches = []; $highlighted = []; foreach ($history as $i => $line) { if ($this->filter->match($line, $matches)) { if (isset($matches[0])) { $chunks = \explode($matches[0], $history[$i]); $chunks = \array_map([__CLASS__, 'escape'], $chunks); $glue = \sprintf('<urgent>%s</urgent>', self::escape($matches[0])); $highlighted[$i] = \implode($glue, $chunks); } } else { unset($history[$i]); } } } if ($save = $input->getOption('save')) { $output->writeln(\sprintf('Saving history in %s...', $save)); \file_put_contents($save, \implode(\PHP_EOL, $history).\PHP_EOL); $output->writeln('<info>History saved.</info>'); } elseif ($input->getOption('replay')) { if (!($input->getOption('show') || $input->getOption('head') || $input->getOption('tail'))) { throw new \InvalidArgumentException('You must limit history via --head, --tail or --show before replaying'); } $count = \count($history); $output->writeln(\sprintf('Replaying %d line%s of history', $count, ($count !== 1) ? 's' : '')); $this->getShell()->addInput($history); } elseif ($input->getOption('clear')) { $this->clearHistory(); $output->writeln('<info>History cleared.</info>'); } else { $type = $input->getOption('no-numbers') ? 0 : ShellOutput::NUMBER_LINES; if (!$highlighted) { $type = $type | OutputInterface::OUTPUT_RAW; } $output->page($highlighted ?: $history, $type); } return 0; } /** * Extract a range from a string. * * @param string $range * * @return int[] [ start, end ] */ private function extractRange(string $range): array { if (\preg_match('/^\d+$/', $range)) { return [(int) $range, (int) $range + 1]; } $matches = []; if ($range !== '..' && \preg_match('/^(\d*)\.\.(\d*)$/', $range, $matches)) { $start = $matches[1] ? (int) $matches[1] : 0; $end = $matches[2] ? (int) $matches[2] + 1 : \PHP_INT_MAX; return [$start, $end]; } throw new \InvalidArgumentException('Unexpected range: '.$range); } /** * Retrieve a slice of the readline history. * * @param string|null $show * @param string|null $head * @param string|null $tail * * @return array A slice of history */ private function getHistorySlice($show, $head, $tail): array { $history = $this->readline->listHistory(); // don't show the current `history` invocation \array_pop($history); if ($show) { list($start, $end) = $this->extractRange($show); $length = $end - $start; } elseif ($head) { if (!\preg_match('/^\d+$/', $head)) { throw new \InvalidArgumentException('Please specify an integer argument for --head'); } $start = 0; $length = (int) $head; } elseif ($tail) { if (!\preg_match('/^\d+$/', $tail)) { throw new \InvalidArgumentException('Please specify an integer argument for --tail'); } $start = \count($history) - (int) $tail; $length = (int) $tail + 1; } else { return $history; } return \array_slice($history, $start, $length, true); } /** * Validate that only one of the given $options is set. * * @param InputInterface $input * @param array $options */ private function validateOnlyOne(InputInterface $input, array $options) { $count = 0; foreach ($options as $opt) { if ($input->getOption($opt)) { $count++; } } if ($count > 1) { throw new \InvalidArgumentException('Please specify only one of --'.\implode(', --', $options)); } } /** * Clear the readline history. */ private function clearHistory() { $this->readline->clearHistory(); } public static function escape(string $string): string { return OutputFormatter::escape($string); } } PK������*Zm��m����Command/ClearCommand.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * Clear the Psy Shell. * * Just what it says on the tin. */ class ClearCommand extends Command { /** * {@inheritdoc} */ protected function configure() { $this ->setName('clear') ->setDefinition([]) ->setDescription('Clear the Psy Shell screen.') ->setHelp( <<<'HELP' Clear the Psy Shell screen. Pro Tip: If your PHP has readline support, you should be able to use ctrl+l too! HELP ); } /** * {@inheritdoc} * * @return int 0 if everything went fine, or an exit code */ protected function execute(InputInterface $input, OutputInterface $output): int { $output->write(\sprintf('%c[2J%c[0;0f', 27, 27)); return 0; } } PK������*Z �� ����Command/DumpCommand.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use Psy\Exception\RuntimeException; use Psy\Input\CodeArgument; use Psy\Output\ShellOutput; use Psy\VarDumper\Presenter; use Psy\VarDumper\PresenterAware; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * Dump an object or primitive. * * This is like var_dump but *way* awesomer. */ class DumpCommand extends ReflectingCommand implements PresenterAware { private Presenter $presenter; /** * PresenterAware interface. * * @param Presenter $presenter */ public function setPresenter(Presenter $presenter) { $this->presenter = $presenter; } /** * {@inheritdoc} */ protected function configure() { $this ->setName('dump') ->setDefinition([ new CodeArgument('target', CodeArgument::REQUIRED, 'A target object or primitive to dump.'), new InputOption('depth', '', InputOption::VALUE_REQUIRED, 'Depth to parse.', 10), new InputOption('all', 'a', InputOption::VALUE_NONE, 'Include private and protected methods and properties.'), ]) ->setDescription('Dump an object or primitive.') ->setHelp( <<<'HELP' Dump an object or primitive. This is like var_dump but <strong>way</strong> awesomer. e.g. <return>>>> dump $_</return> <return>>>> dump $someVar</return> <return>>>> dump $stuff->getAll()</return> HELP ); } /** * {@inheritdoc} * * @return int 0 if everything went fine, or an exit code */ protected function execute(InputInterface $input, OutputInterface $output): int { if (!$output instanceof ShellOutput) { throw new RuntimeException('DumpCommand requires a ShellOutput'); } $depth = $input->getOption('depth'); $target = $this->resolveCode($input->getArgument('target')); $output->page($this->presenter->present($target, $depth, $input->getOption('all') ? Presenter::VERBOSE : 0)); if (\is_object($target)) { $this->setCommandScopeVariables(new \ReflectionObject($target)); } return 0; } } PK������*ZѠ&��&����Command/ListCommand.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use Psy\Command\ListCommand\ClassConstantEnumerator; use Psy\Command\ListCommand\ClassEnumerator; use Psy\Command\ListCommand\ConstantEnumerator; use Psy\Command\ListCommand\FunctionEnumerator; use Psy\Command\ListCommand\GlobalVariableEnumerator; use Psy\Command\ListCommand\MethodEnumerator; use Psy\Command\ListCommand\PropertyEnumerator; use Psy\Command\ListCommand\VariableEnumerator; use Psy\Exception\RuntimeException; use Psy\Input\CodeArgument; use Psy\Input\FilterOptions; use Psy\Output\ShellOutput; use Psy\VarDumper\Presenter; use Psy\VarDumper\PresenterAware; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * List available local variables, object properties, etc. */ class ListCommand extends ReflectingCommand implements PresenterAware { protected Presenter $presenter; protected array $enumerators; /** * PresenterAware interface. * * @param Presenter $presenter */ public function setPresenter(Presenter $presenter) { $this->presenter = $presenter; } /** * {@inheritdoc} */ protected function configure() { list($grep, $insensitive, $invert) = FilterOptions::getOptions(); $this ->setName('ls') ->setAliases(['dir']) ->setDefinition([ new CodeArgument('target', CodeArgument::OPTIONAL, 'A target class or object to list.'), new InputOption('vars', '', InputOption::VALUE_NONE, 'Display variables.'), new InputOption('constants', 'c', InputOption::VALUE_NONE, 'Display defined constants.'), new InputOption('functions', 'f', InputOption::VALUE_NONE, 'Display defined functions.'), new InputOption('classes', 'k', InputOption::VALUE_NONE, 'Display declared classes.'), new InputOption('interfaces', 'I', InputOption::VALUE_NONE, 'Display declared interfaces.'), new InputOption('traits', 't', InputOption::VALUE_NONE, 'Display declared traits.'), new InputOption('no-inherit', '', InputOption::VALUE_NONE, 'Exclude inherited methods, properties and constants.'), new InputOption('properties', 'p', InputOption::VALUE_NONE, 'Display class or object properties (public properties by default).'), new InputOption('methods', 'm', InputOption::VALUE_NONE, 'Display class or object methods (public methods by default).'), $grep, $insensitive, $invert, new InputOption('globals', 'g', InputOption::VALUE_NONE, 'Include global variables.'), new InputOption('internal', 'n', InputOption::VALUE_NONE, 'Limit to internal functions and classes.'), new InputOption('user', 'u', InputOption::VALUE_NONE, 'Limit to user-defined constants, functions and classes.'), new InputOption('category', 'C', InputOption::VALUE_REQUIRED, 'Limit to constants in a specific category (e.g. "date").'), new InputOption('all', 'a', InputOption::VALUE_NONE, 'Include private and protected methods and properties.'), new InputOption('long', 'l', InputOption::VALUE_NONE, 'List in long format: includes class names and method signatures.'), ]) ->setDescription('List local, instance or class variables, methods and constants.') ->setHelp( <<<'HELP' List variables, constants, classes, interfaces, traits, functions, methods, and properties. Called without options, this will return a list of variables currently in scope. If a target object is provided, list properties, constants and methods of that target. If a class, interface or trait name is passed instead, list constants and methods on that class. e.g. <return>>>> ls</return> <return>>>> ls $foo</return> <return>>>> ls -k --grep mongo -i</return> <return>>>> ls -al ReflectionClass</return> <return>>>> ls --constants --category date</return> <return>>>> ls -l --functions --grep /^array_.*/</return> <return>>>> ls -l --properties new DateTime()</return> HELP ); } /** * {@inheritdoc} * * @return int 0 if everything went fine, or an exit code */ protected function execute(InputInterface $input, OutputInterface $output): int { $this->validateInput($input); $this->initEnumerators(); $method = $input->getOption('long') ? 'writeLong' : 'write'; if ($target = $input->getArgument('target')) { list($target, $reflector) = $this->getTargetAndReflector($target); } else { $reflector = null; } // @todo something cleaner than this :-/ if ($output instanceof ShellOutput && $input->getOption('long')) { $output->startPaging(); } foreach ($this->enumerators as $enumerator) { $this->$method($output, $enumerator->enumerate($input, $reflector, $target)); } if ($output instanceof ShellOutput && $input->getOption('long')) { $output->stopPaging(); } // Set some magic local variables if ($reflector !== null) { $this->setCommandScopeVariables($reflector); } return 0; } /** * Initialize Enumerators. */ protected function initEnumerators() { if (!isset($this->enumerators)) { $mgr = $this->presenter; $this->enumerators = [ new ClassConstantEnumerator($mgr), new ClassEnumerator($mgr), new ConstantEnumerator($mgr), new FunctionEnumerator($mgr), new GlobalVariableEnumerator($mgr), new PropertyEnumerator($mgr), new MethodEnumerator($mgr), new VariableEnumerator($mgr, $this->context), ]; } } /** * Write the list items to $output. * * @param OutputInterface $output * @param array $result List of enumerated items */ protected function write(OutputInterface $output, array $result) { if (\count($result) === 0) { return; } foreach ($result as $label => $items) { $names = \array_map([$this, 'formatItemName'], $items); $output->writeln(\sprintf('<strong>%s</strong>: %s', $label, \implode(', ', $names))); } } /** * Write the list items to $output. * * Items are listed one per line, and include the item signature. * * @param OutputInterface $output * @param array $result List of enumerated items */ protected function writeLong(OutputInterface $output, array $result) { if (\count($result) === 0) { return; } $table = $this->getTable($output); foreach ($result as $label => $items) { $output->writeln(''); $output->writeln(\sprintf('<strong>%s:</strong>', $label)); $table->setRows([]); foreach ($items as $item) { $table->addRow([$this->formatItemName($item), $item['value']]); } $table->render(); } } /** * Format an item name given its visibility. * * @param array $item */ private function formatItemName(array $item): string { return \sprintf('<%s>%s</%s>', $item['style'], OutputFormatter::escape($item['name']), $item['style']); } /** * Validate that input options make sense, provide defaults when called without options. * * @throws RuntimeException if options are inconsistent * * @param InputInterface $input */ private function validateInput(InputInterface $input) { if (!$input->getArgument('target')) { // if no target is passed, there can be no properties or methods foreach (['properties', 'methods', 'no-inherit'] as $option) { if ($input->getOption($option)) { throw new RuntimeException('--'.$option.' does not make sense without a specified target'); } } foreach (['globals', 'vars', 'constants', 'functions', 'classes', 'interfaces', 'traits'] as $option) { if ($input->getOption($option)) { return; } } // default to --vars if no other options are passed $input->setOption('vars', true); } else { // if a target is passed, classes, functions, etc don't make sense foreach (['vars', 'globals'] as $option) { if ($input->getOption($option)) { throw new RuntimeException('--'.$option.' does not make sense with a specified target'); } } // @todo ensure that 'functions', 'classes', 'interfaces', 'traits' only accept namespace target? foreach (['constants', 'properties', 'methods', 'functions', 'classes', 'interfaces', 'traits'] as $option) { if ($input->getOption($option)) { return; } } // default to --constants --properties --methods if no other options are passed $input->setOption('constants', true); $input->setOption('properties', true); $input->setOption('methods', true); } } } PK������*ZT@/ ��/ ����Command/HelpCommand.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use Psy\Output\ShellOutput; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * Help command. * * Lists available commands, and gives command-specific help when asked nicely. */ class HelpCommand extends Command { private ?Command $command = null; /** * {@inheritdoc} */ protected function configure() { $this ->setName('help') ->setAliases(['?']) ->setDefinition([ new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name.', null), ]) ->setDescription('Show a list of commands. Type `help [foo]` for information about [foo].') ->setHelp('My. How meta.'); } /** * Helper for setting a subcommand to retrieve help for. * * @param Command $command */ public function setCommand(Command $command) { $this->command = $command; } /** * {@inheritdoc} * * @return int 0 if everything went fine, or an exit code */ protected function execute(InputInterface $input, OutputInterface $output): int { if ($this->command !== null) { // help for an individual command $output->page($this->command->asText()); $this->command = null; } elseif ($name = $input->getArgument('command_name')) { // help for an individual command $output->page($this->getApplication()->get($name)->asText()); } else { // list available commands $commands = $this->getApplication()->all(); $table = $this->getTable($output); foreach ($commands as $name => $command) { if ($name !== $command->getName()) { continue; } if ($command->getAliases()) { $aliases = \sprintf('<comment>Aliases:</comment> %s', \implode(', ', $command->getAliases())); } else { $aliases = ''; } $table->addRow([ \sprintf('<info>%s</info>', $name), $command->getDescription(), $aliases, ]); } if ($output instanceof ShellOutput) { $output->startPaging(); } $table->render(); if ($output instanceof ShellOutput) { $output->stopPaging(); } } return 0; } } PK������*ZĿhh ��h ����Command/ParseCommand.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use PhpParser\Node; use PhpParser\Parser; use Psy\Context; use Psy\ContextAware; use Psy\Input\CodeArgument; use Psy\ParserFactory; use Psy\VarDumper\Presenter; use Psy\VarDumper\PresenterAware; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\VarDumper\Caster\Caster; /** * Parse PHP code and show the abstract syntax tree. */ class ParseCommand extends Command implements ContextAware, PresenterAware { protected Context $context; private Presenter $presenter; private Parser $parser; /** * {@inheritdoc} */ public function __construct($name = null) { $this->parser = (new ParserFactory())->createParser(); parent::__construct($name); } /** * ContextAware interface. * * @param Context $context */ public function setContext(Context $context) { $this->context = $context; } /** * PresenterAware interface. * * @param Presenter $presenter */ public function setPresenter(Presenter $presenter) { $this->presenter = clone $presenter; $this->presenter->addCasters([ Node::class => function (Node $node, array $a) { $a = [ Caster::PREFIX_VIRTUAL.'type' => $node->getType(), Caster::PREFIX_VIRTUAL.'attributes' => $node->getAttributes(), ]; foreach ($node->getSubNodeNames() as $name) { $a[Caster::PREFIX_VIRTUAL.$name] = $node->$name; } return $a; }, ]); } /** * {@inheritdoc} */ protected function configure() { $this ->setName('parse') ->setDefinition([ new CodeArgument('code', CodeArgument::REQUIRED, 'PHP code to parse.'), new InputOption('depth', '', InputOption::VALUE_REQUIRED, 'Depth to parse.', 10), ]) ->setDescription('Parse PHP code and show the abstract syntax tree.') ->setHelp( <<<'HELP' Parse PHP code and show the abstract syntax tree. This command is used in the development of PsySH. Given a string of PHP code, it pretty-prints the PHP Parser parse tree. See https://github.com/nikic/PHP-Parser It prolly won't be super useful for most of you, but it's here if you want to play. HELP ); } /** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output): int { $code = $input->getArgument('code'); $depth = $input->getOption('depth'); $nodes = $this->parser->parse($code); $output->page($this->presenter->present($nodes, $depth)); $this->context->setReturnValue($nodes); return 0; } } PK������*ZYO&��&����Command/ShowCommand.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use Psy\Exception\RuntimeException; use Psy\Exception\UnexpectedTargetException; use Psy\Formatter\CodeFormatter; use Psy\Formatter\SignatureFormatter; use Psy\Input\CodeArgument; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * Show the code for an object, class, constant, method or property. */ class ShowCommand extends ReflectingCommand { private ?\Throwable $lastException = null; private ?int $lastExceptionIndex = null; /** * {@inheritdoc} */ protected function configure() { $this ->setName('show') ->setDefinition([ new CodeArgument('target', CodeArgument::OPTIONAL, 'Function, class, instance, constant, method or property to show.'), new InputOption('ex', null, InputOption::VALUE_OPTIONAL, 'Show last exception context. Optionally specify a stack index.', 1), ]) ->setDescription('Show the code for an object, class, constant, method or property.') ->setHelp( <<<HELP Show the code for an object, class, constant, method or property, or the context of the last exception. <return>show --ex</return> defaults to showing the lines surrounding the location of the last exception. Invoking it more than once travels up the exception's stack trace, and providing a number shows the context of the given index of the trace. e.g. <return>>>> show \$myObject</return> <return>>>> show Psy\Shell::debug</return> <return>>>> show --ex</return> <return>>>> show --ex 3</return> HELP ); } /** * {@inheritdoc} * * @return int 0 if everything went fine, or an exit code */ protected function execute(InputInterface $input, OutputInterface $output): int { // n.b. As far as I can tell, InputInterface doesn't want to tell me // whether an option with an optional value was actually passed. If you // call `$input->getOption('ex')`, it will return the default, both when // `--ex` is specified with no value, and when `--ex` isn't specified at // all. // // So we're doing something sneaky here. If we call `getOptions`, it'll // return the default value when `--ex` is not present, and `null` if // `--ex` is passed with no value. /shrug $opts = $input->getOptions(); // Strict comparison to `1` (the default value) here, because `--ex 1` // will come in as `"1"`. Now we can tell the difference between // "no --ex present", because it's the integer 1, "--ex with no value", // because it's `null`, and "--ex 1", because it's the string "1". if ($opts['ex'] !== 1) { if ($input->getArgument('target')) { throw new \InvalidArgumentException('Too many arguments (supply either "target" or "--ex")'); } $this->writeExceptionContext($input, $output); return 0; } if ($input->getArgument('target')) { $this->writeCodeContext($input, $output); return 0; } throw new RuntimeException('Not enough arguments (missing: "target")'); } private function writeCodeContext(InputInterface $input, OutputInterface $output) { try { list($target, $reflector) = $this->getTargetAndReflector($input->getArgument('target')); } catch (UnexpectedTargetException $e) { // If we didn't get a target and Reflector, maybe we got a filename? $target = $e->getTarget(); if (\is_string($target) && \is_file($target) && $code = @\file_get_contents($target)) { $file = \realpath($target); if ($file !== $this->context->get('__file')) { $this->context->setCommandScopeVariables([ '__file' => $file, '__dir' => \dirname($file), ]); } $output->page(CodeFormatter::formatCode($code)); return; } else { throw $e; } } // Set some magic local variables $this->setCommandScopeVariables($reflector); try { $output->page(CodeFormatter::format($reflector)); } catch (RuntimeException $e) { $output->writeln(SignatureFormatter::format($reflector)); throw $e; } } private function writeExceptionContext(InputInterface $input, OutputInterface $output) { $exception = $this->context->getLastException(); if ($exception !== $this->lastException) { $this->lastException = null; $this->lastExceptionIndex = null; } $opts = $input->getOptions(); if ($opts['ex'] === null) { if ($this->lastException && $this->lastExceptionIndex !== null) { $index = $this->lastExceptionIndex + 1; } else { $index = 0; } } else { $index = \max(0, (int) $input->getOption('ex') - 1); } $trace = $exception->getTrace(); \array_unshift($trace, [ 'file' => $exception->getFile(), 'line' => $exception->getLine(), ]); if ($index >= \count($trace)) { $index = 0; } $this->lastException = $exception; $this->lastExceptionIndex = $index; $output->writeln($this->getShell()->formatException($exception)); $output->writeln('--'); $this->writeTraceLine($output, $trace, $index); $this->writeTraceCodeSnippet($output, $trace, $index); $this->setCommandScopeVariablesFromContext($trace[$index]); } private function writeTraceLine(OutputInterface $output, array $trace, $index) { $file = isset($trace[$index]['file']) ? $this->replaceCwd($trace[$index]['file']) : 'n/a'; $line = isset($trace[$index]['line']) ? $trace[$index]['line'] : 'n/a'; $output->writeln(\sprintf( 'From <info>%s:%d</info> at <strong>level %d</strong> of backtrace (of %d):', OutputFormatter::escape($file), OutputFormatter::escape($line), $index + 1, \count($trace) )); } private function replaceCwd(string $file): string { if ($cwd = \getcwd()) { $cwd = \rtrim($cwd, \DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR; } if ($cwd === false) { return $file; } else { return \preg_replace('/^'.\preg_quote($cwd, '/').'/', '', $file); } } private function writeTraceCodeSnippet(OutputInterface $output, array $trace, $index) { if (!isset($trace[$index]['file'])) { return; } $file = $trace[$index]['file']; if ($fileAndLine = $this->extractEvalFileAndLine($file)) { list($file, $line) = $fileAndLine; } else { if (!isset($trace[$index]['line'])) { return; } $line = $trace[$index]['line']; } if (\is_file($file)) { $code = @\file_get_contents($file); } if (empty($code)) { return; } $startLine = \max($line - 5, 0); $endLine = $line + 5; $output->write(CodeFormatter::formatCode($code, $startLine, $endLine, $line), false); } private function setCommandScopeVariablesFromContext(array $context) { $vars = []; if (isset($context['class'])) { $vars['__class'] = $context['class']; if (isset($context['function'])) { $vars['__method'] = $context['function']; } try { $refl = new \ReflectionClass($context['class']); if ($namespace = $refl->getNamespaceName()) { $vars['__namespace'] = $namespace; } } catch (\Throwable $e) { // oh well } } elseif (isset($context['function'])) { $vars['__function'] = $context['function']; try { $refl = new \ReflectionFunction($context['function']); if ($namespace = $refl->getNamespaceName()) { $vars['__namespace'] = $namespace; } } catch (\Throwable $e) { // oh well } } if (isset($context['file'])) { $file = $context['file']; if ($fileAndLine = $this->extractEvalFileAndLine($file)) { list($file, $line) = $fileAndLine; } elseif (isset($context['line'])) { $line = $context['line']; } if (\is_file($file)) { $vars['__file'] = $file; if (isset($line)) { $vars['__line'] = $line; } $vars['__dir'] = \dirname($file); } } $this->context->setCommandScopeVariables($vars); } private function extractEvalFileAndLine(string $file) { if (\preg_match('/(.*)\\((\\d+)\\) : eval\\(\\)\'d code$/', $file, $matches)) { return [$matches[1], $matches[2]]; } } } PK������*Z������Command/EditCommand.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use Psy\ConfigPaths; use Psy\Context; use Psy\ContextAware; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; class EditCommand extends Command implements ContextAware { private string $runtimeDir = ''; private Context $context; /** * Constructor. * * @param string $runtimeDir The directory to use for temporary files * @param string|null $name The name of the command; passing null means it must be set in configure() * * @throws \Symfony\Component\Console\Exception\LogicException When the command name is empty */ public function __construct($runtimeDir, $name = null) { parent::__construct($name); $this->runtimeDir = $runtimeDir; } protected function configure() { $this ->setName('edit') ->setDefinition([ new InputArgument('file', InputArgument::OPTIONAL, 'The file to open for editing. If this is not given, edits a temporary file.', null), new InputOption( 'exec', 'e', InputOption::VALUE_NONE, 'Execute the file content after editing. This is the default when a file name argument is not given.', null ), new InputOption( 'no-exec', 'E', InputOption::VALUE_NONE, 'Do not execute the file content after editing. This is the default when a file name argument is given.', null ), ]) ->setDescription('Open an external editor. Afterwards, get produced code in input buffer.') ->setHelp('Set the EDITOR environment variable to something you\'d like to use.'); } /** * @param InputInterface $input * @param OutputInterface $output * * @return int 0 if everything went fine, or an exit code * * @throws \InvalidArgumentException when both exec and no-exec flags are given or if a given variable is not found in the current context * @throws \UnexpectedValueException if file_get_contents on the edited file returns false instead of a string */ protected function execute(InputInterface $input, OutputInterface $output): int { if ($input->getOption('exec') && $input->getOption('no-exec')) { throw new \InvalidArgumentException('The --exec and --no-exec flags are mutually exclusive'); } $filePath = $this->extractFilePath($input->getArgument('file')); $execute = $this->shouldExecuteFile( $input->getOption('exec'), $input->getOption('no-exec'), $filePath ); $shouldRemoveFile = false; if ($filePath === null) { ConfigPaths::ensureDir($this->runtimeDir); $filePath = \tempnam($this->runtimeDir, 'psysh-edit-command'); $shouldRemoveFile = true; } $editedContent = $this->editFile($filePath, $shouldRemoveFile); if ($execute) { $this->getShell()->addInput($editedContent); } return 0; } /** * @param bool $execOption * @param bool $noExecOption * @param string|null $filePath */ private function shouldExecuteFile(bool $execOption, bool $noExecOption, ?string $filePath = null): bool { if ($execOption) { return true; } if ($noExecOption) { return false; } // By default, code that is edited is executed if there was no given input file path return $filePath === null; } /** * @param string|null $fileArgument * * @return string|null The file path to edit, null if the input was null, or the value of the referenced variable * * @throws \InvalidArgumentException If the variable is not found in the current context */ private function extractFilePath(?string $fileArgument = null) { // If the file argument was a variable, get it from the context if ($fileArgument !== null && $fileArgument !== '' && $fileArgument[0] === '$') { $fileArgument = $this->context->get(\preg_replace('/^\$/', '', $fileArgument)); } return $fileArgument; } /** * @param string $filePath * @param bool $shouldRemoveFile * * @throws \UnexpectedValueException if file_get_contents on $filePath returns false instead of a string */ private function editFile(string $filePath, bool $shouldRemoveFile): string { $escapedFilePath = \escapeshellarg($filePath); $editor = (isset($_SERVER['EDITOR']) && $_SERVER['EDITOR']) ? $_SERVER['EDITOR'] : 'nano'; $pipes = []; $proc = \proc_open("{$editor} {$escapedFilePath}", [\STDIN, \STDOUT, \STDERR], $pipes); \proc_close($proc); $editedContent = @\file_get_contents($filePath); if ($shouldRemoveFile) { @\unlink($filePath); } if ($editedContent === false) { throw new \UnexpectedValueException("Reading {$filePath} returned false"); } return $editedContent; } /** * Set the Context reference. * * @param Context $context */ public function setContext(Context $context) { $this->context = $context; } } PK������*ZK|��|��'��Command/TimeitCommand/TimeitVisitor.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command\TimeitCommand; use PhpParser\Node; use PhpParser\Node\Arg; use PhpParser\Node\Expr; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\FunctionLike; use PhpParser\Node\Name\FullyQualified as FullyQualifiedName; use PhpParser\Node\Stmt\Expression; use PhpParser\Node\Stmt\Return_; use PhpParser\NodeVisitorAbstract; use Psy\CodeCleaner\NoReturnValue; use Psy\Command\TimeitCommand; /** * A node visitor for instrumenting code to be executed by the `timeit` command. * * Injects `TimeitCommand::markStart()` at the start of code to be executed, and * `TimeitCommand::markEnd()` at the end, and on top-level return statements. */ class TimeitVisitor extends NodeVisitorAbstract { private int $functionDepth = 0; /** * {@inheritdoc} * * @return Node[]|null Array of nodes */ public function beforeTraverse(array $nodes) { $this->functionDepth = 0; } /** * {@inheritdoc} * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { // keep track of nested function-like nodes, because they can have // returns statements... and we don't want to call markEnd for those. if ($node instanceof FunctionLike) { $this->functionDepth++; return; } // replace any top-level `return` statements with a `markEnd` call if ($this->functionDepth === 0 && $node instanceof Return_) { return new Return_($this->getEndCall($node->expr), $node->getAttributes()); } } /** * {@inheritdoc} * * @return int|Node|Node[]|null Replacement node (or special return value) */ public function leaveNode(Node $node) { if ($node instanceof FunctionLike) { $this->functionDepth--; } } /** * {@inheritdoc} * * @return Node[]|null Array of nodes */ public function afterTraverse(array $nodes) { // prepend a `markStart` call \array_unshift($nodes, new Expression($this->getStartCall(), [])); // append a `markEnd` call (wrapping the final node, if it's an expression) $last = $nodes[\count($nodes) - 1]; if ($last instanceof Expr) { \array_pop($nodes); $nodes[] = $this->getEndCall($last); } elseif ($last instanceof Expression) { \array_pop($nodes); $nodes[] = new Expression($this->getEndCall($last->expr), $last->getAttributes()); } elseif ($last instanceof Return_) { // nothing to do here, we're already ending with a return call } else { $nodes[] = new Expression($this->getEndCall(), []); } return $nodes; } /** * Get PhpParser AST nodes for a `markStart` call. * * @return \PhpParser\Node\Expr\StaticCall */ private function getStartCall(): StaticCall { return new StaticCall(new FullyQualifiedName(TimeitCommand::class), 'markStart'); } /** * Get PhpParser AST nodes for a `markEnd` call. * * Optionally pass in a return value. * * @param Expr|null $arg */ private function getEndCall(?Expr $arg = null): StaticCall { if ($arg === null) { $arg = NoReturnValue::create(); } return new StaticCall(new FullyQualifiedName(TimeitCommand::class), 'markEnd', [new Arg($arg)]); } } PK������*Z]k: �� ����Command/BufferCommand.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use Psy\Output\ShellOutput; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * Interact with the current code buffer. * * Shows and clears the buffer for the current multi-line expression. */ class BufferCommand extends Command { /** * {@inheritdoc} */ protected function configure() { $this ->setName('buffer') ->setAliases(['buf']) ->setDefinition([ new InputOption('clear', '', InputOption::VALUE_NONE, 'Clear the current buffer.'), ]) ->setDescription('Show (or clear) the contents of the code input buffer.') ->setHelp( <<<'HELP' Show the contents of the code buffer for the current multi-line expression. Optionally, clear the buffer by passing the <info>--clear</info> option. HELP ); } /** * {@inheritdoc} * * @return int 0 if everything went fine, or an exit code */ protected function execute(InputInterface $input, OutputInterface $output): int { $shell = $this->getShell(); $buf = $shell->getCodeBuffer(); if ($input->getOption('clear')) { $shell->resetCodeBuffer(); $output->writeln($this->formatLines($buf, 'urgent'), ShellOutput::NUMBER_LINES); } else { $output->writeln($this->formatLines($buf), ShellOutput::NUMBER_LINES); } return 0; } /** * A helper method for wrapping buffer lines in `<urgent>` and `<return>` formatter strings. * * @param array $lines * @param string $type (default: 'return') * * @return array Formatted strings */ protected function formatLines(array $lines, string $type = 'return'): array { $template = \sprintf('<%s>%%s</%s>', $type, $type); return \array_map(function ($line) use ($template) { return \sprintf($template, $line); }, $lines); } } PK������*Z6fD��D����Command/TimeitCommand.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use PhpParser\NodeTraverser; use PhpParser\PrettyPrinter\Standard as Printer; use Psy\Command\TimeitCommand\TimeitVisitor; use Psy\Input\CodeArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * Class TimeitCommand. */ class TimeitCommand extends Command { const RESULT_MSG = '<info>Command took %.6f seconds to complete.</info>'; const AVG_RESULT_MSG = '<info>Command took %.6f seconds on average (%.6f median; %.6f total) to complete.</info>'; // All times stored as nanoseconds! private static ?int $start = null; private static array $times = []; private CodeArgumentParser $parser; private NodeTraverser $traverser; private Printer $printer; /** * {@inheritdoc} */ public function __construct($name = null) { $this->parser = new CodeArgumentParser(); // @todo Pass visitor directly to once we drop support for PHP-Parser 4.x $this->traverser = new NodeTraverser(); $this->traverser->addVisitor(new TimeitVisitor()); $this->printer = new Printer(); parent::__construct($name); } /** * {@inheritdoc} */ protected function configure() { $this ->setName('timeit') ->setDefinition([ new InputOption('num', 'n', InputOption::VALUE_REQUIRED, 'Number of iterations.'), new CodeArgument('code', CodeArgument::REQUIRED, 'Code to execute.'), ]) ->setDescription('Profiles with a timer.') ->setHelp( <<<'HELP' Time profiling for functions and commands. e.g. <return>>>> timeit sleep(1)</return> <return>>>> timeit -n1000 $closure()</return> HELP ); } /** * {@inheritdoc} * * @return int 0 if everything went fine, or an exit code */ protected function execute(InputInterface $input, OutputInterface $output): int { $code = $input->getArgument('code'); $num = (int) ($input->getOption('num') ?: 1); $shell = $this->getShell(); $instrumentedCode = $this->instrumentCode($code); self::$times = []; do { $_ = $shell->execute($instrumentedCode); $this->ensureEndMarked(); } while (\count(self::$times) < $num); $shell->writeReturnValue($_); $times = self::$times; self::$times = []; if ($num === 1) { $output->writeln(\sprintf(self::RESULT_MSG, $times[0] / 1e+9)); } else { $total = \array_sum($times); \rsort($times); $median = $times[\round($num / 2)]; $output->writeln(\sprintf(self::AVG_RESULT_MSG, ($total / $num) / 1e+9, $median / 1e+9, $total / 1e+9)); } return 0; } /** * Internal method for marking the start of timeit execution. * * A static call to this method will be injected at the start of the timeit * input code to instrument the call. We will use the saved start time to * more accurately calculate time elapsed during execution. */ public static function markStart() { self::$start = \hrtime(true); } /** * Internal method for marking the end of timeit execution. * * A static call to this method is injected by TimeitVisitor at the end * of the timeit input code to instrument the call. * * Note that this accepts an optional $ret parameter, which is used to pass * the return value of the last statement back out of timeit. This saves us * a bunch of code rewriting shenanigans. * * @param mixed $ret * * @return mixed it just passes $ret right back */ public static function markEnd($ret = null) { self::$times[] = \hrtime(true) - self::$start; self::$start = null; return $ret; } /** * Ensure that the end of code execution was marked. * * The end *should* be marked in the instrumented code, but just in case * we'll add a fallback here. */ private function ensureEndMarked() { if (self::$start !== null) { self::markEnd(); } } /** * Instrument code for timeit execution. * * This inserts `markStart` and `markEnd` calls to ensure that (reasonably) * accurate times are recorded for just the code being executed. */ private function instrumentCode(string $code): string { return $this->printer->prettyPrint($this->traverser->traverse($this->parser->parse($code))); } } PK������*Z9E������Command/PsyVersionCommand.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * A dumb little command for printing out the current Psy Shell version. */ class PsyVersionCommand extends Command { /** * {@inheritdoc} */ protected function configure() { $this ->setName('version') ->setDefinition([]) ->setDescription('Show Psy Shell version.') ->setHelp('Show Psy Shell version.'); } /** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output): int { $output->writeln($this->getApplication()->getVersion()); return 0; } } PK������*ZrT �� ����Command/SudoCommand.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use PhpParser\NodeTraverser; use PhpParser\PrettyPrinter\Standard as Printer; use Psy\Input\CodeArgument; use Psy\Readline\Readline; use Psy\Sudo\SudoVisitor; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * Evaluate PHP code, bypassing visibility restrictions. */ class SudoCommand extends Command { private Readline $readline; private CodeArgumentParser $parser; private NodeTraverser $traverser; private Printer $printer; /** * {@inheritdoc} */ public function __construct($name = null) { $this->parser = new CodeArgumentParser(); // @todo Pass visitor directly to once we drop support for PHP-Parser 4.x $this->traverser = new NodeTraverser(); $this->traverser->addVisitor(new SudoVisitor()); $this->printer = new Printer(); parent::__construct($name); } /** * Set the Shell's Readline service. * * @param Readline $readline */ public function setReadline(Readline $readline) { $this->readline = $readline; } /** * {@inheritdoc} */ protected function configure() { $this ->setName('sudo') ->setDefinition([ new CodeArgument('code', CodeArgument::REQUIRED, 'Code to execute.'), ]) ->setDescription('Evaluate PHP code, bypassing visibility restrictions.') ->setHelp( <<<'HELP' Evaluate PHP code, bypassing visibility restrictions. e.g. <return>>>> $sekret->whisper("hi")</return> <return>PHP error: Call to private method Sekret::whisper() from context '' on line 1</return> <return>>>> sudo $sekret->whisper("hi")</return> <return>=> "hi"</return> <return>>>> $sekret->word</return> <return>PHP error: Cannot access private property Sekret::$word on line 1</return> <return>>>> sudo $sekret->word</return> <return>=> "hi"</return> <return>>>> $sekret->word = "please"</return> <return>PHP error: Cannot access private property Sekret::$word on line 1</return> <return>>>> sudo $sekret->word = "please"</return> <return>=> "please"</return> HELP ); } /** * {@inheritdoc} * * @return int 0 if everything went fine, or an exit code */ protected function execute(InputInterface $input, OutputInterface $output): int { $code = $input->getArgument('code'); // special case for !! if ($code === '!!') { $history = $this->readline->listHistory(); if (\count($history) < 2) { throw new \InvalidArgumentException('No previous command to replay'); } $code = $history[\count($history) - 2]; } $nodes = $this->traverser->traverse($this->parser->parse($code)); $sudoCode = $this->printer->prettyPrint($nodes); $shell = $this->getShell(); $shell->addCode($sudoCode, !$shell->hasCode()); return 0; } } PK������*Z Q������Command/WtfCommand.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use Psy\Context; use Psy\ContextAware; use Psy\Input\FilterOptions; use Psy\Output\ShellOutput; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * Show the last uncaught exception. */ class WtfCommand extends TraceCommand implements ContextAware { protected Context $context; /** * ContextAware interface. * * @param Context $context */ public function setContext(Context $context) { $this->context = $context; } /** * {@inheritdoc} */ protected function configure() { list($grep, $insensitive, $invert) = FilterOptions::getOptions(); $this ->setName('wtf') ->setAliases(['last-exception', 'wtf?']) ->setDefinition([ new InputArgument('incredulity', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'Number of lines to show.'), new InputOption('all', 'a', InputOption::VALUE_NONE, 'Show entire backtrace.'), $grep, $insensitive, $invert, ]) ->setDescription('Show the backtrace of the most recent exception.') ->setHelp( <<<'HELP' Shows a few lines of the backtrace of the most recent exception. If you want to see more lines, add more question marks or exclamation marks: e.g. <return>>>> wtf ?</return> <return>>>> wtf ?!???!?!?</return> To see the entire backtrace, pass the -a/--all flag: e.g. <return>>>> wtf -a</return> HELP ); } /** * {@inheritdoc} * * @return int 0 if everything went fine, or an exit code */ protected function execute(InputInterface $input, OutputInterface $output): int { $this->filter->bind($input); $incredulity = \implode('', $input->getArgument('incredulity')); if (\strlen(\preg_replace('/[\\?!]/', '', $incredulity))) { throw new \InvalidArgumentException('Incredulity must include only "?" and "!"'); } $exception = $this->context->getLastException(); $count = $input->getOption('all') ? \PHP_INT_MAX : \max(3, \pow(2, \strlen($incredulity) + 1)); if ($output instanceof ShellOutput) { $output->startPaging(); } do { $traceCount = \count($exception->getTrace()); $showLines = $count; // Show the whole trace if we'd only be hiding a few lines if ($traceCount < \max($count * 1.2, $count + 2)) { $showLines = \PHP_INT_MAX; } $trace = $this->getBacktrace($exception, $showLines); $moreLines = $traceCount - \count($trace); $output->writeln($this->getShell()->formatException($exception)); $output->writeln('--'); $output->write($trace, true, ShellOutput::NUMBER_LINES); $output->writeln(''); if ($moreLines > 0) { $output->writeln(\sprintf( '<aside>Use <return>wtf -a</return> to see %d more lines</aside>', $moreLines )); $output->writeln(''); } } while ($exception = $exception->getPrevious()); if ($output instanceof ShellOutput) { $output->stopPaging(); } return 0; } } PK������*ZSrP �� ����Command/ThrowUpCommand.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use PhpParser\Node\Arg; use PhpParser\Node\Expr\New_; use PhpParser\Node\Expr\Throw_; use PhpParser\Node\Expr\Variable; use PhpParser\Node\Name\FullyQualified as FullyQualifiedName; use PhpParser\Node\Scalar\String_; use PhpParser\Node\Stmt\Expression; use PhpParser\PrettyPrinter\Standard as Printer; use Psy\Exception\ThrowUpException; use Psy\Input\CodeArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * Throw an exception or error out of the Psy Shell. */ class ThrowUpCommand extends Command { private CodeArgumentParser $parser; private Printer $printer; /** * {@inheritdoc} */ public function __construct($name = null) { $this->parser = new CodeArgumentParser(); $this->printer = new Printer(); parent::__construct($name); } /** * {@inheritdoc} */ protected function configure() { $this ->setName('throw-up') ->setDefinition([ new CodeArgument('exception', CodeArgument::OPTIONAL, 'Exception or Error to throw.'), ]) ->setDescription('Throw an exception or error out of the Psy Shell.') ->setHelp( <<<'HELP' Throws an exception or error out of the current the Psy Shell instance. By default it throws the most recent exception. e.g. <return>>>> throw-up</return> <return>>>> throw-up $e</return> <return>>>> throw-up new Exception('WHEEEEEE!')</return> <return>>>> throw-up "bye!"</return> HELP ); } /** * {@inheritdoc} * * @return int 0 if everything went fine, or an exit code * * @throws \InvalidArgumentException if there is no exception to throw */ protected function execute(InputInterface $input, OutputInterface $output): int { $args = $this->prepareArgs($input->getArgument('exception')); $throwStmt = new Expression(new Throw_(new New_(new FullyQualifiedName(ThrowUpException::class), $args))); $throwCode = $this->printer->prettyPrint([$throwStmt]); $shell = $this->getShell(); $shell->addCode($throwCode, !$shell->hasCode()); return 0; } /** * Parse the supplied command argument. * * If no argument was given, this falls back to `$_e` * * @throws \InvalidArgumentException if there is no exception to throw * * @param string $code * * @return Arg[] */ private function prepareArgs(?string $code = null): array { if (!$code) { // Default to last exception if nothing else was supplied return [new Arg(new Variable('_e'))]; } $nodes = $this->parser->parse($code); if (\count($nodes) !== 1) { throw new \InvalidArgumentException('No idea how to throw this'); } $node = $nodes[0]; $expr = $node->expr; $args = [new Arg($expr, false, false, $node->getAttributes())]; // Allow throwing via a string, e.g. `throw-up "SUP"` if ($expr instanceof String_) { return [new New_(new FullyQualifiedName(\Exception::class), $args)]; } return $args; } } PK������*Zuj.*��.*����Command/ReflectingCommand.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use PhpParser\NodeTraverser; use PhpParser\PrettyPrinter\Standard as Printer; use Psy\CodeCleaner\NoReturnValue; use Psy\Context; use Psy\ContextAware; use Psy\Exception\ErrorException; use Psy\Exception\RuntimeException; use Psy\Exception\UnexpectedTargetException; use Psy\Reflection\ReflectionConstant; use Psy\Sudo\SudoVisitor; use Psy\Util\Mirror; /** * An abstract command with helpers for inspecting the current context. */ abstract class ReflectingCommand extends Command implements ContextAware { const CLASS_OR_FUNC = '/^[\\\\\w]+$/'; const CLASS_MEMBER = '/^([\\\\\w]+)::(\w+)$/'; const CLASS_STATIC = '/^([\\\\\w]+)::\$(\w+)$/'; const INSTANCE_MEMBER = '/^(\$\w+)(::|->)(\w+)$/'; protected Context $context; private CodeArgumentParser $parser; private NodeTraverser $traverser; private Printer $printer; /** * {@inheritdoc} */ public function __construct($name = null) { $this->parser = new CodeArgumentParser(); // @todo Pass visitor directly to once we drop support for PHP-Parser 4.x $this->traverser = new NodeTraverser(); $this->traverser->addVisitor(new SudoVisitor()); $this->printer = new Printer(); parent::__construct($name); } /** * ContextAware interface. * * @param Context $context */ public function setContext(Context $context) { $this->context = $context; } /** * Get the target for a value. * * @throws \InvalidArgumentException when the value specified can't be resolved * * @param string $valueName Function, class, variable, constant, method or property name * * @return array (class or instance name, member name, kind) */ protected function getTarget(string $valueName): array { $valueName = \trim($valueName); $matches = []; switch (true) { case \preg_match(self::CLASS_OR_FUNC, $valueName, $matches): return [$this->resolveName($matches[0], true), null, 0]; case \preg_match(self::CLASS_MEMBER, $valueName, $matches): return [$this->resolveName($matches[1]), $matches[2], Mirror::CONSTANT | Mirror::METHOD]; case \preg_match(self::CLASS_STATIC, $valueName, $matches): return [$this->resolveName($matches[1]), $matches[2], Mirror::STATIC_PROPERTY | Mirror::PROPERTY]; case \preg_match(self::INSTANCE_MEMBER, $valueName, $matches): if ($matches[2] === '->') { $kind = Mirror::METHOD | Mirror::PROPERTY; } else { $kind = Mirror::CONSTANT | Mirror::METHOD; } return [$this->resolveObject($matches[1]), $matches[3], $kind]; default: return [$this->resolveObject($valueName), null, 0]; } } /** * Resolve a class or function name (with the current shell namespace). * * @throws ErrorException when `self` or `static` is used in a non-class scope * * @param string $name * @param bool $includeFunctions (default: false) */ protected function resolveName(string $name, bool $includeFunctions = false): string { $shell = $this->getShell(); // While not *technically* 100% accurate, let's treat `self` and `static` as equivalent. if (\in_array(\strtolower($name), ['self', 'static'])) { if ($boundClass = $shell->getBoundClass()) { return $boundClass; } if ($boundObject = $shell->getBoundObject()) { return \get_class($boundObject); } $msg = \sprintf('Cannot use "%s" when no class scope is active', \strtolower($name)); throw new ErrorException($msg, 0, \E_USER_ERROR, "eval()'d code", 1); } if (\substr($name, 0, 1) === '\\') { return $name; } // Check $name against the current namespace and use statements. if (self::couldBeClassName($name)) { try { $name = $this->resolveCode($name.'::class'); } catch (RuntimeException $e) { // /shrug } } if ($namespace = $shell->getNamespace()) { $fullName = $namespace.'\\'.$name; if (\class_exists($fullName) || \interface_exists($fullName) || ($includeFunctions && \function_exists($fullName))) { return $fullName; } } return $name; } /** * Check whether a given name could be a class name. */ protected function couldBeClassName(string $name): bool { // Regex based on https://www.php.net/manual/en/language.oop5.basic.php#language.oop5.basic.class return \preg_match('/^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*(\\\\[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)*$/', $name) === 1; } /** * Get a Reflector and documentation for a function, class or instance, constant, method or property. * * @param string $valueName Function, class, variable, constant, method or property name * * @return array (value, Reflector) */ protected function getTargetAndReflector(string $valueName): array { list($value, $member, $kind) = $this->getTarget($valueName); return [$value, Mirror::get($value, $member, $kind)]; } /** * Resolve code to a value in the current scope. * * @throws RuntimeException when the code does not return a value in the current scope * * @param string $code * * @return mixed Variable value */ protected function resolveCode(string $code) { try { // Add an implicit `sudo` to target resolution. $nodes = $this->traverser->traverse($this->parser->parse($code)); $sudoCode = $this->printer->prettyPrint($nodes); $value = $this->getShell()->execute($sudoCode, true); } catch (\Throwable $e) { // Swallow all exceptions? } if (!isset($value) || $value instanceof NoReturnValue) { throw new RuntimeException('Unknown target: '.$code); } return $value; } /** * Resolve code to an object in the current scope. * * @throws UnexpectedTargetException when the code resolves to a non-object value * * @param string $code * * @return object Variable instance */ private function resolveObject(string $code) { $value = $this->resolveCode($code); if (!\is_object($value)) { throw new UnexpectedTargetException($value, 'Unable to inspect a non-object'); } return $value; } /** * Get a variable from the current shell scope. * * @param string $name * * @return mixed */ protected function getScopeVariable(string $name) { return $this->context->get($name); } /** * Get all scope variables from the current shell scope. * * @return array */ protected function getScopeVariables(): array { return $this->context->getAll(); } /** * Given a Reflector instance, set command-scope variables in the shell * execution context. This is used to inject magic $__class, $__method and * $__file variables (as well as a handful of others). * * @param \Reflector $reflector */ protected function setCommandScopeVariables(\Reflector $reflector) { $vars = []; switch (\get_class($reflector)) { case \ReflectionClass::class: case \ReflectionObject::class: $vars['__class'] = $reflector->name; if ($reflector->inNamespace()) { $vars['__namespace'] = $reflector->getNamespaceName(); } break; case \ReflectionMethod::class: $vars['__method'] = \sprintf('%s::%s', $reflector->class, $reflector->name); $vars['__class'] = $reflector->class; $classReflector = $reflector->getDeclaringClass(); if ($classReflector->inNamespace()) { $vars['__namespace'] = $classReflector->getNamespaceName(); } break; case \ReflectionFunction::class: $vars['__function'] = $reflector->name; if ($reflector->inNamespace()) { $vars['__namespace'] = $reflector->getNamespaceName(); } break; case \ReflectionGenerator::class: $funcReflector = $reflector->getFunction(); $vars['__function'] = $funcReflector->name; if ($funcReflector->inNamespace()) { $vars['__namespace'] = $funcReflector->getNamespaceName(); } if ($fileName = $reflector->getExecutingFile()) { $vars['__file'] = $fileName; $vars['__line'] = $reflector->getExecutingLine(); $vars['__dir'] = \dirname($fileName); } break; case \ReflectionProperty::class: case \ReflectionClassConstant::class: $classReflector = $reflector->getDeclaringClass(); $vars['__class'] = $classReflector->name; if ($classReflector->inNamespace()) { $vars['__namespace'] = $classReflector->getNamespaceName(); } // no line for these, but this'll do if ($fileName = $reflector->getDeclaringClass()->getFileName()) { $vars['__file'] = $fileName; $vars['__dir'] = \dirname($fileName); } break; case ReflectionConstant::class: if ($reflector->inNamespace()) { $vars['__namespace'] = $reflector->getNamespaceName(); } break; } if ($reflector instanceof \ReflectionClass || $reflector instanceof \ReflectionFunctionAbstract) { if ($fileName = $reflector->getFileName()) { $vars['__file'] = $fileName; $vars['__line'] = $reflector->getStartLine(); $vars['__dir'] = \dirname($fileName); } } $this->context->setCommandScopeVariables($vars); } } PK������*Z� �� ��"��Command/ListCommand/Enumerator.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command\ListCommand; use Psy\Formatter\SignatureFormatter; use Psy\Input\FilterOptions; use Psy\Util\Mirror; use Psy\VarDumper\Presenter; use Symfony\Component\Console\Input\InputInterface; /** * Abstract Enumerator class. */ abstract class Enumerator { // Output styles const IS_PUBLIC = 'public'; const IS_PROTECTED = 'protected'; const IS_PRIVATE = 'private'; const IS_GLOBAL = 'global'; const IS_CONSTANT = 'const'; const IS_CLASS = 'class'; const IS_FUNCTION = 'function'; private FilterOptions $filter; private Presenter $presenter; /** * Enumerator constructor. * * @param Presenter $presenter */ public function __construct(Presenter $presenter) { $this->filter = new FilterOptions(); $this->presenter = $presenter; } /** * Return a list of categorized things with the given input options and target. * * @param InputInterface $input * @param \Reflector|null $reflector * @param mixed $target * * @return array */ public function enumerate(InputInterface $input, ?\Reflector $reflector = null, $target = null): array { $this->filter->bind($input); return $this->listItems($input, $reflector, $target); } /** * Enumerate specific items with the given input options and target. * * Implementing classes should return an array of arrays: * * [ * 'Constants' => [ * 'FOO' => [ * 'name' => 'FOO', * 'style' => 'public', * 'value' => '123', * ], * ], * ] * * @param InputInterface $input * @param \Reflector|null $reflector * @param mixed $target * * @return array */ abstract protected function listItems(InputInterface $input, ?\Reflector $reflector = null, $target = null): array; protected function showItem($name) { return $this->filter->match($name); } protected function presentRef($value) { return $this->presenter->presentRef($value); } protected function presentSignature($target) { // This might get weird if the signature is actually for a reflector. Hrm. if (!$target instanceof \Reflector) { $target = Mirror::get($target); } return SignatureFormatter::format($target); } } PK������*Z-8 �� ��*��Command/ListCommand/VariableEnumerator.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command\ListCommand; use Psy\Context; use Psy\VarDumper\Presenter; use Symfony\Component\Console\Input\InputInterface; /** * Variable Enumerator class. */ class VariableEnumerator extends Enumerator { // n.b. this array is the order in which special variables will be listed private const SPECIAL_NAMES = [ '_', '_e', '__out', '__function', '__method', '__class', '__namespace', '__file', '__line', '__dir', ]; private $context; /** * Variable Enumerator constructor. * * Unlike most other enumerators, the Variable Enumerator needs access to * the current scope variables, so we need to pass it a Context instance. * * @param Presenter $presenter * @param Context $context */ public function __construct(Presenter $presenter, Context $context) { $this->context = $context; parent::__construct($presenter); } /** * {@inheritdoc} */ protected function listItems(InputInterface $input, ?\Reflector $reflector = null, $target = null): array { // only list variables when no Reflector is present. if ($reflector !== null || $target !== null) { return []; } // only list variables if we are specifically asked if (!$input->getOption('vars')) { return []; } $showAll = $input->getOption('all'); $variables = $this->prepareVariables($this->getVariables($showAll)); if (empty($variables)) { return []; } return [ 'Variables' => $variables, ]; } /** * Get scope variables. * * @param bool $showAll Include special variables (e.g. $_) * * @return array */ protected function getVariables(bool $showAll): array { $scopeVars = $this->context->getAll(); \uksort($scopeVars, function ($a, $b) { $aIndex = \array_search($a, self::SPECIAL_NAMES); $bIndex = \array_search($b, self::SPECIAL_NAMES); if ($aIndex !== false) { if ($bIndex !== false) { return $aIndex - $bIndex; } return 1; } if ($bIndex !== false) { return -1; } return \strnatcasecmp($a, $b); }); $ret = []; foreach ($scopeVars as $name => $val) { if (!$showAll && \in_array($name, self::SPECIAL_NAMES)) { continue; } $ret[$name] = $val; } return $ret; } /** * Prepare formatted variable array. * * @param array $variables * * @return array */ protected function prepareVariables(array $variables): array { // My kingdom for a generator. $ret = []; foreach ($variables as $name => $val) { if ($this->showItem($name)) { $fname = '$'.$name; $ret[$fname] = [ 'name' => $fname, 'style' => \in_array($name, self::SPECIAL_NAMES) ? self::IS_PRIVATE : self::IS_PUBLIC, 'value' => $this->presentRef($val), ]; } } return $ret; } } PK������*ZcR_��_��*��Command/ListCommand/PropertyEnumerator.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command\ListCommand; use Symfony\Component\Console\Input\InputInterface; /** * Property Enumerator class. */ class PropertyEnumerator extends Enumerator { /** * {@inheritdoc} */ protected function listItems(InputInterface $input, ?\Reflector $reflector = null, $target = null): array { // only list properties when a Reflector is present. if ($reflector === null) { return []; } // We can only list properties on actual class (or object) reflectors. if (!$reflector instanceof \ReflectionClass) { return []; } // only list properties if we are specifically asked if (!$input->getOption('properties')) { return []; } $showAll = $input->getOption('all'); $noInherit = $input->getOption('no-inherit'); $properties = $this->prepareProperties($this->getProperties($showAll, $reflector, $noInherit), $target); if (empty($properties)) { return []; } $ret = []; $ret[$this->getKindLabel($reflector)] = $properties; return $ret; } /** * Get defined properties for the given class or object Reflector. * * @param bool $showAll Include private and protected properties * @param \ReflectionClass $reflector * @param bool $noInherit Exclude inherited properties * * @return array */ protected function getProperties(bool $showAll, \ReflectionClass $reflector, bool $noInherit = false): array { $className = $reflector->getName(); $properties = []; foreach ($reflector->getProperties() as $property) { if ($noInherit && $property->getDeclaringClass()->getName() !== $className) { continue; } if ($showAll || $property->isPublic()) { $properties[$property->getName()] = $property; } } \ksort($properties, \SORT_NATURAL | \SORT_FLAG_CASE); return $properties; } /** * Prepare formatted property array. * * @param array $properties * * @return array */ protected function prepareProperties(array $properties, $target = null): array { // My kingdom for a generator. $ret = []; foreach ($properties as $name => $property) { if ($this->showItem($name)) { $fname = '$'.$name; $ret[$fname] = [ 'name' => $fname, 'style' => $this->getVisibilityStyle($property), 'value' => $this->presentValue($property, $target), ]; } } return $ret; } /** * Get a label for the particular kind of "class" represented. * * @param \ReflectionClass $reflector */ protected function getKindLabel(\ReflectionClass $reflector): string { if (\method_exists($reflector, 'isTrait') && $reflector->isTrait()) { return 'Trait Properties'; } else { return 'Class Properties'; } } /** * Get output style for the given property's visibility. * * @param \ReflectionProperty $property */ private function getVisibilityStyle(\ReflectionProperty $property): string { if ($property->isPublic()) { return self::IS_PUBLIC; } elseif ($property->isProtected()) { return self::IS_PROTECTED; } else { return self::IS_PRIVATE; } } /** * Present the $target's current value for a reflection property. * * @param \ReflectionProperty $property * @param mixed $target */ protected function presentValue(\ReflectionProperty $property, $target): string { if (!$target) { return ''; } // If $target is a class or trait (try to) get the default // value for the property. if (!\is_object($target)) { try { $refl = new \ReflectionClass($target); $props = $refl->getDefaultProperties(); if (\array_key_exists($property->name, $props)) { $suffix = $property->isStatic() ? '' : ' <aside>(default)</aside>'; return $this->presentRef($props[$property->name]).$suffix; } } catch (\Throwable $e) { // Well, we gave it a shot. } return ''; } $property->setAccessible(true); $value = $property->getValue($target); return $this->presentRef($value); } } PK������*ZƗgR �� ��*��Command/ListCommand/FunctionEnumerator.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command\ListCommand; use Psy\Reflection\ReflectionNamespace; use Symfony\Component\Console\Input\InputInterface; /** * Function Enumerator class. */ class FunctionEnumerator extends Enumerator { /** * {@inheritdoc} */ protected function listItems(InputInterface $input, ?\Reflector $reflector = null, $target = null): array { // if we have a reflector, ensure that it's a namespace reflector if (($target !== null || $reflector !== null) && !$reflector instanceof ReflectionNamespace) { return []; } // only list functions if we are specifically asked if (!$input->getOption('functions')) { return []; } if ($input->getOption('user')) { $label = 'User Functions'; $functions = $this->getFunctions('user'); } elseif ($input->getOption('internal')) { $label = 'Internal Functions'; $functions = $this->getFunctions('internal'); } else { $label = 'Functions'; $functions = $this->getFunctions(); } $prefix = $reflector === null ? null : \strtolower($reflector->getName()).'\\'; $functions = $this->prepareFunctions($functions, $prefix); if (empty($functions)) { return []; } $ret = []; $ret[$label] = $functions; return $ret; } /** * Get defined functions. * * Optionally limit functions to "user" or "internal" functions. * * @param string|null $type "user" or "internal" (default: both) * * @return array */ protected function getFunctions(?string $type = null): array { $funcs = \get_defined_functions(); if ($type) { return $funcs[$type]; } else { return \array_merge($funcs['internal'], $funcs['user']); } } /** * Prepare formatted function array. * * @param array $functions * @param string $prefix * * @return array */ protected function prepareFunctions(array $functions, ?string $prefix = null): array { \natcasesort($functions); // My kingdom for a generator. $ret = []; foreach ($functions as $name) { if ($prefix !== null && \strpos(\strtolower($name), $prefix) !== 0) { continue; } if ($this->showItem($name)) { try { $ret[$name] = [ 'name' => $name, 'style' => self::IS_FUNCTION, 'value' => $this->presentSignature($name), ]; } catch (\Throwable $e) { // Ignore failures. } } } return $ret; } } PK������*Z-����*��Command/ListCommand/ConstantEnumerator.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command\ListCommand; use Psy\Reflection\ReflectionNamespace; use Symfony\Component\Console\Input\InputInterface; /** * Constant Enumerator class. */ class ConstantEnumerator extends Enumerator { // Because `Json` is ugly. private const CATEGORY_LABELS = [ 'libxml' => 'libxml', 'openssl' => 'OpenSSL', 'pcre' => 'PCRE', 'sqlite3' => 'SQLite3', 'curl' => 'cURL', 'dom' => 'DOM', 'ftp' => 'FTP', 'gd' => 'GD', 'gmp' => 'GMP', 'iconv' => 'iconv', 'json' => 'JSON', 'ldap' => 'LDAP', 'mbstring' => 'mbstring', 'odbc' => 'ODBC', 'pcntl' => 'PCNTL', 'pgsql' => 'pgsql', 'posix' => 'POSIX', 'mysqli' => 'mysqli', 'soap' => 'SOAP', 'exif' => 'EXIF', 'sysvmsg' => 'sysvmsg', 'xml' => 'XML', 'xsl' => 'XSL', ]; /** * {@inheritdoc} */ protected function listItems(InputInterface $input, ?\Reflector $reflector = null, $target = null): array { // if we have a reflector, ensure that it's a namespace reflector if (($target !== null || $reflector !== null) && !$reflector instanceof ReflectionNamespace) { return []; } // only list constants if we are specifically asked if (!$input->getOption('constants')) { return []; } $user = $input->getOption('user'); $internal = $input->getOption('internal'); $category = $input->getOption('category'); if ($category) { $category = \strtolower($category); if ($category === 'internal') { $internal = true; $category = null; } elseif ($category === 'user') { $user = true; $category = null; } } $ret = []; if ($user) { $ret['User Constants'] = $this->getConstants('user'); } if ($internal) { $ret['Internal Constants'] = $this->getConstants('internal'); } if ($category) { $caseCategory = \array_key_exists($category, self::CATEGORY_LABELS) ? self::CATEGORY_LABELS[$category] : \ucfirst($category); $label = $caseCategory.' Constants'; $ret[$label] = $this->getConstants($category); } if (!$user && !$internal && !$category) { $ret['Constants'] = $this->getConstants(); } if ($reflector !== null) { $prefix = \strtolower($reflector->getName()).'\\'; foreach ($ret as $key => $names) { foreach (\array_keys($names) as $name) { if (\strpos(\strtolower($name), $prefix) !== 0) { unset($ret[$key][$name]); } } } } return \array_map([$this, 'prepareConstants'], \array_filter($ret)); } /** * Get defined constants. * * Optionally restrict constants to a given category, e.g. "date". If the * category is "internal", include all non-user-defined constants. * * @param string $category * * @return array */ protected function getConstants(?string $category = null): array { if (!$category) { return \get_defined_constants(); } $consts = \get_defined_constants(true); if ($category === 'internal') { unset($consts['user']); return \array_merge(...\array_values($consts)); } foreach ($consts as $key => $value) { if (\strtolower($key) === $category) { return $value; } } return []; } /** * Prepare formatted constant array. * * @param array $constants * * @return array */ protected function prepareConstants(array $constants): array { // My kingdom for a generator. $ret = []; $names = \array_keys($constants); \natcasesort($names); foreach ($names as $name) { if ($this->showItem($name)) { $ret[$name] = [ 'name' => $name, 'style' => self::IS_CONSTANT, 'value' => $this->presentRef($constants[$name]), ]; } } return $ret; } } PK������*Zy4����0��Command/ListCommand/GlobalVariableEnumerator.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command\ListCommand; use Symfony\Component\Console\Input\InputInterface; /** * Global Variable Enumerator class. */ class GlobalVariableEnumerator extends Enumerator { /** * {@inheritdoc} */ protected function listItems(InputInterface $input, ?\Reflector $reflector = null, $target = null): array { // only list globals when no Reflector is present. if ($reflector !== null || $target !== null) { return []; } // only list globals if we are specifically asked if (!$input->getOption('globals')) { return []; } $globals = $this->prepareGlobals($this->getGlobals()); if (empty($globals)) { return []; } return [ 'Global Variables' => $globals, ]; } /** * Get defined global variables. * * @return array */ protected function getGlobals(): array { global $GLOBALS; $names = \array_keys($GLOBALS); \natcasesort($names); $ret = []; foreach ($names as $name) { $ret[$name] = $GLOBALS[$name]; } return $ret; } /** * Prepare formatted global variable array. * * @param array $globals * * @return array */ protected function prepareGlobals(array $globals): array { // My kingdom for a generator. $ret = []; foreach ($globals as $name => $value) { if ($this->showItem($name)) { $fname = '$'.$name; $ret[$fname] = [ 'name' => $fname, 'style' => self::IS_GLOBAL, 'value' => $this->presentRef($value), ]; } } return $ret; } } PK������*Z@w �� ��/��Command/ListCommand/ClassConstantEnumerator.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command\ListCommand; use Symfony\Component\Console\Input\InputInterface; /** * Class Constant Enumerator class. */ class ClassConstantEnumerator extends Enumerator { /** * {@inheritdoc} */ protected function listItems(InputInterface $input, ?\Reflector $reflector = null, $target = null): array { // only list constants when a Reflector is present. if ($reflector === null) { return []; } // We can only list constants on actual class (or object) reflectors. if (!$reflector instanceof \ReflectionClass) { // @todo handle ReflectionExtension as well return []; } // only list constants if we are specifically asked if (!$input->getOption('constants')) { return []; } $noInherit = $input->getOption('no-inherit'); $constants = $this->prepareConstants($this->getConstants($reflector, $noInherit)); if (empty($constants)) { return []; } $ret = []; $ret[$this->getKindLabel($reflector)] = $constants; return $ret; } /** * Get defined constants for the given class or object Reflector. * * @param \ReflectionClass $reflector * @param bool $noInherit Exclude inherited constants * * @return array */ protected function getConstants(\ReflectionClass $reflector, bool $noInherit = false): array { $className = $reflector->getName(); $constants = []; foreach ($reflector->getConstants() as $name => $constant) { $constReflector = new \ReflectionClassConstant($reflector->name, $name); if ($noInherit && $constReflector->getDeclaringClass()->getName() !== $className) { continue; } $constants[$name] = $constReflector; } \ksort($constants, \SORT_NATURAL | \SORT_FLAG_CASE); return $constants; } /** * Prepare formatted constant array. * * @param array $constants * * @return array */ protected function prepareConstants(array $constants): array { // My kingdom for a generator. $ret = []; foreach ($constants as $name => $constant) { if ($this->showItem($name)) { $ret[$name] = [ 'name' => $name, 'style' => self::IS_CONSTANT, 'value' => $this->presentRef($constant->getValue()), ]; } } return $ret; } /** * Get a label for the particular kind of "class" represented. * * @param \ReflectionClass $reflector */ protected function getKindLabel(\ReflectionClass $reflector): string { if ($reflector->isInterface()) { return 'Interface Constants'; } else { return 'Class Constants'; } } } PK������*Zߊ-����'��Command/ListCommand/ClassEnumerator.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command\ListCommand; use Psy\Reflection\ReflectionNamespace; use Symfony\Component\Console\Input\InputInterface; /** * Class Enumerator class. */ class ClassEnumerator extends Enumerator { /** * {@inheritdoc} */ protected function listItems(InputInterface $input, ?\Reflector $reflector = null, $target = null): array { // if we have a reflector, ensure that it's a namespace reflector if (($target !== null || $reflector !== null) && !$reflector instanceof ReflectionNamespace) { return []; } $internal = $input->getOption('internal'); $user = $input->getOption('user'); $prefix = $reflector === null ? null : \strtolower($reflector->getName()).'\\'; $ret = []; // only list classes, interfaces and traits if we are specifically asked if ($input->getOption('classes')) { $ret = \array_merge($ret, $this->filterClasses('Classes', \get_declared_classes(), $internal, $user, $prefix)); } if ($input->getOption('interfaces')) { $ret = \array_merge($ret, $this->filterClasses('Interfaces', \get_declared_interfaces(), $internal, $user, $prefix)); } if ($input->getOption('traits')) { $ret = \array_merge($ret, $this->filterClasses('Traits', \get_declared_traits(), $internal, $user, $prefix)); } return \array_map([$this, 'prepareClasses'], \array_filter($ret)); } /** * Filter a list of classes, interfaces or traits. * * If $internal or $user is defined, results will be limited to internal or * user-defined classes as appropriate. * * @param string $key * @param array $classes * @param bool $internal * @param bool $user * @param string $prefix * * @return array */ protected function filterClasses(string $key, array $classes, bool $internal, bool $user, ?string $prefix = null): array { $ret = []; if ($internal) { $ret['Internal '.$key] = \array_filter($classes, function ($class) use ($prefix) { if ($prefix !== null && \strpos(\strtolower($class), $prefix) !== 0) { return false; } $refl = new \ReflectionClass($class); return $refl->isInternal(); }); } if ($user) { $ret['User '.$key] = \array_filter($classes, function ($class) use ($prefix) { if ($prefix !== null && \strpos(\strtolower($class), $prefix) !== 0) { return false; } $refl = new \ReflectionClass($class); return !$refl->isInternal(); }); } if (!$user && !$internal) { $ret[$key] = \array_filter($classes, function ($class) use ($prefix) { return $prefix === null || \strpos(\strtolower($class), $prefix) === 0; }); } return $ret; } /** * Prepare formatted class array. * * @param array $classes * * @return array */ protected function prepareClasses(array $classes): array { \natcasesort($classes); // My kingdom for a generator. $ret = []; foreach ($classes as $name) { if ($this->showItem($name)) { $ret[$name] = [ 'name' => $name, 'style' => self::IS_CLASS, 'value' => $this->presentSignature($name), ]; } } return $ret; } } PK������*Zv6����(��Command/ListCommand/MethodEnumerator.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command\ListCommand; use Symfony\Component\Console\Input\InputInterface; /** * Method Enumerator class. */ class MethodEnumerator extends Enumerator { /** * {@inheritdoc} */ protected function listItems(InputInterface $input, ?\Reflector $reflector = null, $target = null): array { // only list methods when a Reflector is present. if ($reflector === null) { return []; } // We can only list methods on actual class (or object) reflectors. if (!$reflector instanceof \ReflectionClass) { return []; } // only list methods if we are specifically asked if (!$input->getOption('methods')) { return []; } $showAll = $input->getOption('all'); $noInherit = $input->getOption('no-inherit'); $methods = $this->prepareMethods($this->getMethods($showAll, $reflector, $noInherit)); if (empty($methods)) { return []; } $ret = []; $ret[$this->getKindLabel($reflector)] = $methods; return $ret; } /** * Get defined methods for the given class or object Reflector. * * @param bool $showAll Include private and protected methods * @param \ReflectionClass $reflector * @param bool $noInherit Exclude inherited methods * * @return array */ protected function getMethods(bool $showAll, \ReflectionClass $reflector, bool $noInherit = false): array { $className = $reflector->getName(); $methods = []; foreach ($reflector->getMethods() as $name => $method) { // For some reason PHP reflection shows private methods from the parent class, even // though they're effectively worthless. Let's suppress them here, like --no-inherit if (($noInherit || $method->isPrivate()) && $method->getDeclaringClass()->getName() !== $className) { continue; } if ($showAll || $method->isPublic()) { $methods[$method->getName()] = $method; } } \ksort($methods, \SORT_NATURAL | \SORT_FLAG_CASE); return $methods; } /** * Prepare formatted method array. * * @param array $methods * * @return array */ protected function prepareMethods(array $methods): array { // My kingdom for a generator. $ret = []; foreach ($methods as $name => $method) { if ($this->showItem($name)) { $ret[$name] = [ 'name' => $name, 'style' => $this->getVisibilityStyle($method), 'value' => $this->presentSignature($method), ]; } } return $ret; } /** * Get a label for the particular kind of "class" represented. * * @param \ReflectionClass $reflector */ protected function getKindLabel(\ReflectionClass $reflector): string { if ($reflector->isInterface()) { return 'Interface Methods'; } elseif (\method_exists($reflector, 'isTrait') && $reflector->isTrait()) { return 'Trait Methods'; } else { return 'Class Methods'; } } /** * Get output style for the given method's visibility. * * @param \ReflectionMethod $method */ private function getVisibilityStyle(\ReflectionMethod $method): string { if ($method->isPublic()) { return self::IS_PUBLIC; } elseif ($method->isProtected()) { return self::IS_PROTECTED; } else { return self::IS_PRIVATE; } } } PK������*Z$��$����Command/Command.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use Psy\Shell; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command as BaseCommand; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Helper\TableStyle; use Symfony\Component\Console\Output\OutputInterface; /** * The Psy Shell base command. */ abstract class Command extends BaseCommand { /** * Sets the application instance for this command. * * @param Application|null $application An Application instance * * @api */ public function setApplication(?Application $application = null): void { if ($application !== null && !$application instanceof Shell) { throw new \InvalidArgumentException('PsySH Commands require an instance of Psy\Shell'); } parent::setApplication($application); } /** * getApplication, but is guaranteed to return a Shell instance. */ protected function getShell(): Shell { $shell = $this->getApplication(); if (!$shell instanceof Shell) { throw new \RuntimeException('PsySH Commands require an instance of Psy\Shell'); } return $shell; } /** * {@inheritdoc} */ public function asText(): string { $messages = [ '<comment>Usage:</comment>', ' '.$this->getSynopsis(), '', ]; if ($this->getAliases()) { $messages[] = $this->aliasesAsText(); } if ($this->getArguments()) { $messages[] = $this->argumentsAsText(); } if ($this->getOptions()) { $messages[] = $this->optionsAsText(); } if ($help = $this->getProcessedHelp()) { $messages[] = '<comment>Help:</comment>'; $messages[] = ' '.\str_replace("\n", "\n ", $help)."\n"; } return \implode("\n", $messages); } /** * {@inheritdoc} */ private function getArguments(): array { $hidden = $this->getHiddenArguments(); return \array_filter($this->getNativeDefinition()->getArguments(), function ($argument) use ($hidden) { return !\in_array($argument->getName(), $hidden); }); } /** * These arguments will be excluded from help output. * * @return string[] */ protected function getHiddenArguments(): array { return ['command']; } /** * {@inheritdoc} */ private function getOptions(): array { $hidden = $this->getHiddenOptions(); return \array_filter($this->getNativeDefinition()->getOptions(), function ($option) use ($hidden) { return !\in_array($option->getName(), $hidden); }); } /** * These options will be excluded from help output. * * @return string[] */ protected function getHiddenOptions(): array { return ['verbose']; } /** * Format command aliases as text.. */ private function aliasesAsText(): string { return '<comment>Aliases:</comment> <info>'.\implode(', ', $this->getAliases()).'</info>'.\PHP_EOL; } /** * Format command arguments as text. */ private function argumentsAsText(): string { $max = $this->getMaxWidth(); $messages = []; $arguments = $this->getArguments(); if (!empty($arguments)) { $messages[] = '<comment>Arguments:</comment>'; foreach ($arguments as $argument) { if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) { $default = \sprintf('<comment> (default: %s)</comment>', $this->formatDefaultValue($argument->getDefault())); } else { $default = ''; } $name = $argument->getName(); $pad = \str_pad('', $max - \strlen($name)); $description = \str_replace("\n", "\n".\str_pad('', $max + 2, ' '), $argument->getDescription()); $messages[] = \sprintf(' <info>%s</info>%s %s%s', $name, $pad, $description, $default); } $messages[] = ''; } return \implode(\PHP_EOL, $messages); } /** * Format options as text. */ private function optionsAsText(): string { $max = $this->getMaxWidth(); $messages = []; $options = $this->getOptions(); if ($options) { $messages[] = '<comment>Options:</comment>'; foreach ($options as $option) { if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) { $default = \sprintf('<comment> (default: %s)</comment>', $this->formatDefaultValue($option->getDefault())); } else { $default = ''; } $multiple = $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''; $description = \str_replace("\n", "\n".\str_pad('', $max + 2, ' '), $option->getDescription()); $optionMax = $max - \strlen($option->getName()) - 2; $messages[] = \sprintf( " <info>%s</info> %-{$optionMax}s%s%s%s", '--'.$option->getName(), $option->getShortcut() ? \sprintf('(-%s) ', $option->getShortcut()) : '', $description, $default, $multiple ); } $messages[] = ''; } return \implode(\PHP_EOL, $messages); } /** * Calculate the maximum padding width for a set of lines. */ private function getMaxWidth(): int { $max = 0; foreach ($this->getOptions() as $option) { $nameLength = \strlen($option->getName()) + 2; if ($option->getShortcut()) { $nameLength += \strlen($option->getShortcut()) + 3; } $max = \max($max, $nameLength); } foreach ($this->getArguments() as $argument) { $max = \max($max, \strlen($argument->getName())); } return ++$max; } /** * Format an option default as text. * * @param mixed $default */ private function formatDefaultValue($default): string { if (\is_array($default) && $default === \array_values($default)) { return \sprintf("['%s']", \implode("', '", $default)); } return \str_replace("\n", '', \var_export($default, true)); } /** * Get a Table instance. * * @return Table */ protected function getTable(OutputInterface $output) { $style = new TableStyle(); // Symfony 4.1 deprecated single-argument style setters. if (\method_exists($style, 'setVerticalBorderChars')) { $style->setVerticalBorderChars(' '); $style->setHorizontalBorderChars(''); $style->setCrossingChars('', '', '', '', '', '', '', '', ''); } else { $style->setVerticalBorderChar(' '); $style->setHorizontalBorderChar(''); $style->setCrossingChar(''); } $table = new Table($output); return $table ->setRows([]) ->setStyle($style); } } PK������*Zll)������Command/WhereamiCommand.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use Psy\Formatter\CodeFormatter; use Psy\Output\ShellOutput; use Psy\Shell; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * Show the context of where you opened the debugger. */ class WhereamiCommand extends Command { private array $backtrace; public function __construct() { $this->backtrace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS); parent::__construct(); } /** * {@inheritdoc} */ protected function configure() { $this ->setName('whereami') ->setDefinition([ new InputOption('num', 'n', InputOption::VALUE_OPTIONAL, 'Number of lines before and after.', '5'), new InputOption('file', 'f|a', InputOption::VALUE_NONE, 'Show the full source for the current file.'), ]) ->setDescription('Show where you are in the code.') ->setHelp( <<<'HELP' Show where you are in the code. Optionally, include the number of lines before and after you want to display, or --file for the whole file. e.g. <return>> whereami </return> <return>> whereami -n10</return> <return>> whereami --file</return> HELP ); } /** * Obtains the correct stack frame in the full backtrace. * * @return array */ protected function trace(): array { foreach (\array_reverse($this->backtrace) as $stackFrame) { if ($this->isDebugCall($stackFrame)) { return $stackFrame; } } return \end($this->backtrace); } private static function isDebugCall(array $stackFrame): bool { $class = isset($stackFrame['class']) ? $stackFrame['class'] : null; $function = isset($stackFrame['function']) ? $stackFrame['function'] : null; return ($class === null && $function === 'Psy\\debug') || ($class === Shell::class && \in_array($function, ['__construct', 'debug'])); } /** * Determine the file and line based on the specific backtrace. * * @return array */ protected function fileInfo(): array { $stackFrame = $this->trace(); if (\preg_match('/eval\(/', $stackFrame['file'])) { \preg_match_all('/([^\(]+)\((\d+)/', $stackFrame['file'], $matches); $file = $matches[1][0]; $line = (int) $matches[2][0]; } else { $file = $stackFrame['file']; $line = $stackFrame['line']; } return \compact('file', 'line'); } /** * {@inheritdoc} * * @return int 0 if everything went fine, or an exit code */ protected function execute(InputInterface $input, OutputInterface $output): int { $info = $this->fileInfo(); $num = $input->getOption('num'); $lineNum = $info['line']; $startLine = \max($lineNum - $num, 1); $endLine = $lineNum + $num; $code = \file_get_contents($info['file']); if ($input->getOption('file')) { $startLine = 1; $endLine = null; } if ($output instanceof ShellOutput) { $output->startPaging(); } $output->writeln(\sprintf('From <info>%s:%s</info>:', $this->replaceCwd($info['file']), $lineNum)); $output->write(CodeFormatter::formatCode($code, $startLine, $endLine, $lineNum), false); if ($output instanceof ShellOutput) { $output->stopPaging(); } return 0; } /** * Replace the given directory from the start of a filepath. * * @param string $file */ private function replaceCwd(string $file): string { $cwd = \getcwd(); if ($cwd === false) { return $file; } $cwd = \rtrim($cwd, \DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR; return \preg_replace('/^'.\preg_quote($cwd, '/').'/', '', $file); } } PK������*Ze=#��#����Command/DocCommand.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use Psy\Formatter\DocblockFormatter; use Psy\Formatter\SignatureFormatter; use Psy\Input\CodeArgument; use Psy\Output\ShellOutput; use Psy\Reflection\ReflectionConstant; use Psy\Reflection\ReflectionLanguageConstruct; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * Read the documentation for an object, class, constant, method or property. */ class DocCommand extends ReflectingCommand { const INHERIT_DOC_TAG = '{@inheritdoc}'; /** * {@inheritdoc} */ protected function configure() { $this ->setName('doc') ->setAliases(['rtfm', 'man']) ->setDefinition([ new InputOption('all', 'a', InputOption::VALUE_NONE, 'Show documentation for superclasses as well as the current class.'), new CodeArgument('target', CodeArgument::REQUIRED, 'Function, class, instance, constant, method or property to document.'), ]) ->setDescription('Read the documentation for an object, class, constant, method or property.') ->setHelp( <<<HELP Read the documentation for an object, class, constant, method or property. It's awesome for well-documented code, not quite as awesome for poorly documented code. e.g. <return>>>> doc preg_replace</return> <return>>>> doc Psy\Shell</return> <return>>>> doc Psy\Shell::debug</return> <return>>>> \$s = new Psy\Shell</return> <return>>>> doc \$s->run</return> HELP ); } /** * {@inheritdoc} * * @return int 0 if everything went fine, or an exit code */ protected function execute(InputInterface $input, OutputInterface $output): int { $value = $input->getArgument('target'); if (ReflectionLanguageConstruct::isLanguageConstruct($value)) { $reflector = new ReflectionLanguageConstruct($value); $doc = $this->getManualDocById($value); } else { list($target, $reflector) = $this->getTargetAndReflector($value); $doc = $this->getManualDoc($reflector) ?: DocblockFormatter::format($reflector); } $db = $this->getShell()->getManualDb(); if ($output instanceof ShellOutput) { $output->startPaging(); } // Maybe include the declaring class if ($reflector instanceof \ReflectionMethod || $reflector instanceof \ReflectionProperty) { $output->writeln(SignatureFormatter::format($reflector->getDeclaringClass())); } $output->writeln(SignatureFormatter::format($reflector)); $output->writeln(''); if (empty($doc) && !$db) { $output->writeln('<warning>PHP manual not found</warning>'); $output->writeln(' To document core PHP functionality, download the PHP reference manual:'); $output->writeln(' https://github.com/bobthecow/psysh/wiki/PHP-manual'); } else { $output->writeln($doc); } // Implicit --all if the original docblock has an {@inheritdoc} tag. if ($input->getOption('all') || \stripos($doc, self::INHERIT_DOC_TAG) !== false) { $parent = $reflector; foreach ($this->getParentReflectors($reflector) as $parent) { $output->writeln(''); $output->writeln('---'); $output->writeln(''); // Maybe include the declaring class if ($parent instanceof \ReflectionMethod || $parent instanceof \ReflectionProperty) { $output->writeln(SignatureFormatter::format($parent->getDeclaringClass())); } $output->writeln(SignatureFormatter::format($parent)); $output->writeln(''); if ($doc = $this->getManualDoc($parent) ?: DocblockFormatter::format($parent)) { $output->writeln($doc); } } } if ($output instanceof ShellOutput) { $output->stopPaging(); } // Set some magic local variables $this->setCommandScopeVariables($reflector); return 0; } private function getManualDoc($reflector) { switch (\get_class($reflector)) { case \ReflectionClass::class: case \ReflectionObject::class: case \ReflectionFunction::class: $id = $reflector->name; break; case \ReflectionMethod::class: $id = $reflector->class.'::'.$reflector->name; break; case \ReflectionProperty::class: $id = $reflector->class.'::$'.$reflector->name; break; case \ReflectionClassConstant::class: // @todo this is going to collide with ReflectionMethod ids // someday... start running the query by id + type if the DB // supports it. $id = $reflector->class.'::'.$reflector->name; break; case ReflectionConstant::class: $id = $reflector->name; break; default: return false; } return $this->getManualDocById($id); } /** * Get all all parent Reflectors for a given Reflector. * * For example, passing a Class, Object or TraitReflector will yield all * traits and parent classes. Passing a Method or PropertyReflector will * yield Reflectors for the same-named method or property on all traits and * parent classes. * * @return \Generator a whole bunch of \Reflector instances */ private function getParentReflectors($reflector): \Generator { $seenClasses = []; switch (\get_class($reflector)) { case \ReflectionClass::class: case \ReflectionObject::class: foreach ($reflector->getTraits() as $trait) { if (!\in_array($trait->getName(), $seenClasses)) { $seenClasses[] = $trait->getName(); yield $trait; } } foreach ($reflector->getInterfaces() as $interface) { if (!\in_array($interface->getName(), $seenClasses)) { $seenClasses[] = $interface->getName(); yield $interface; } } while ($reflector = $reflector->getParentClass()) { yield $reflector; foreach ($reflector->getTraits() as $trait) { if (!\in_array($trait->getName(), $seenClasses)) { $seenClasses[] = $trait->getName(); yield $trait; } } foreach ($reflector->getInterfaces() as $interface) { if (!\in_array($interface->getName(), $seenClasses)) { $seenClasses[] = $interface->getName(); yield $interface; } } } return; case \ReflectionMethod::class: foreach ($this->getParentReflectors($reflector->getDeclaringClass()) as $parent) { if ($parent->hasMethod($reflector->getName())) { $parentMethod = $parent->getMethod($reflector->getName()); if (!\in_array($parentMethod->getDeclaringClass()->getName(), $seenClasses)) { $seenClasses[] = $parentMethod->getDeclaringClass()->getName(); yield $parentMethod; } } } return; case \ReflectionProperty::class: foreach ($this->getParentReflectors($reflector->getDeclaringClass()) as $parent) { if ($parent->hasProperty($reflector->getName())) { $parentProperty = $parent->getProperty($reflector->getName()); if (!\in_array($parentProperty->getDeclaringClass()->getName(), $seenClasses)) { $seenClasses[] = $parentProperty->getDeclaringClass()->getName(); yield $parentProperty; } } } break; } } private function getManualDocById($id) { if ($db = $this->getShell()->getManualDb()) { $result = $db->query(\sprintf('SELECT doc FROM php_manual WHERE id = %s', $db->quote($id))); if ($result !== false) { return $result->fetchColumn(0); } } } } PK������*Z+ �� ����Command/TraceCommand.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use Psy\Formatter\TraceFormatter; use Psy\Input\FilterOptions; use Psy\Output\ShellOutput; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * Show the current stack trace. */ class TraceCommand extends Command { protected $filter; /** * {@inheritdoc} */ public function __construct($name = null) { $this->filter = new FilterOptions(); parent::__construct($name); } /** * {@inheritdoc} */ protected function configure() { list($grep, $insensitive, $invert) = FilterOptions::getOptions(); $this ->setName('trace') ->setDefinition([ new InputOption('include-psy', 'p', InputOption::VALUE_NONE, 'Include Psy in the call stack.'), new InputOption('num', 'n', InputOption::VALUE_REQUIRED, 'Only include NUM lines.'), $grep, $insensitive, $invert, ]) ->setDescription('Show the current call stack.') ->setHelp( <<<'HELP' Show the current call stack. Optionally, include PsySH in the call stack by passing the <info>--include-psy</info> option. e.g. <return>> trace -n10</return> <return>> trace --include-psy</return> HELP ); } /** * {@inheritdoc} * * @return int 0 if everything went fine, or an exit code */ protected function execute(InputInterface $input, OutputInterface $output): int { $this->filter->bind($input); $trace = $this->getBacktrace(new \Exception(), $input->getOption('num'), $input->getOption('include-psy')); $output->page($trace, ShellOutput::NUMBER_LINES); return 0; } /** * Get a backtrace for an exception or error. * * Optionally limit the number of rows to include with $count, and exclude * Psy from the trace. * * @param \Throwable $e The exception or error with a backtrace * @param int $count (default: PHP_INT_MAX) * @param bool $includePsy (default: true) * * @return array Formatted stacktrace lines */ protected function getBacktrace(\Throwable $e, ?int $count = null, bool $includePsy = true): array { return TraceFormatter::formatTrace($e, $this->filter, $count, $includePsy); } } PK������*Zil������Command/ExitCommand.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use Psy\Exception\BreakException; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * Exit the Psy Shell. * * Just what it says on the tin. */ class ExitCommand extends Command { /** * {@inheritdoc} */ protected function configure() { $this ->setName('exit') ->setAliases(['quit', 'q']) ->setDefinition([]) ->setDescription('End the current session and return to caller.') ->setHelp( <<<'HELP' End the current session and return to caller. e.g. <return>>>> exit</return> HELP ); } /** * {@inheritdoc} * * @return int 0 if everything went fine, or an exit code */ protected function execute(InputInterface $input, OutputInterface $output): int { throw new BreakException('Goodbye'); } } PK������*Zr������Command/CodeArgumentParser.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Command; use PhpParser\Parser; use Psy\Exception\ParseErrorException; use Psy\ParserFactory; /** * Class CodeArgumentParser. */ class CodeArgumentParser { private Parser $parser; public function __construct(?Parser $parser = null) { $this->parser = $parser ?? (new ParserFactory())->createParser(); } /** * Lex and parse a string of code into statements. * * This is intended for code arguments, so the code string *should not* start with <?php * * @throws ParseErrorException * * @return array Statements */ public function parse(string $code): array { $code = '<?php '.$code; try { return $this->parser->parse($code); } catch (\PhpParser\Error $e) { if (\strpos($e->getMessage(), 'unexpected EOF') === false) { throw ParseErrorException::fromParseError($e); } // If we got an unexpected EOF, let's try it again with a semicolon. try { return $this->parser->parse($code.';'); } catch (\PhpParser\Error $_e) { // Throw the original error, not the semicolon one. throw ParseErrorException::fromParseError($e); } } } } PK������*ZJ������ParserFactory.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy; use PhpParser\Parser; use PhpParser\ParserFactory as OriginalParserFactory; /** * Parser factory to abstract over PHP Parser library versions. */ class ParserFactory { /** * New parser instance. */ public function createParser(): Parser { $factory = new OriginalParserFactory(); if (!\method_exists($factory, 'createForHostVersion')) { return $factory->create(OriginalParserFactory::PREFER_PHP7); } return $factory->createForHostVersion(); } } PK������*Z[$$��$��"��CodeCleaner/ValidClassNamePass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Expr; use PhpParser\Node\Expr\Ternary; use PhpParser\Node\Stmt; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\Do_; use PhpParser\Node\Stmt\If_; use PhpParser\Node\Stmt\Interface_; use PhpParser\Node\Stmt\Switch_; use PhpParser\Node\Stmt\Trait_; use PhpParser\Node\Stmt\While_; use Psy\Exception\FatalErrorException; /** * Validate that classes exist. * * This pass throws a FatalErrorException rather than letting PHP run * headfirst into a real fatal error and die. */ class ValidClassNamePass extends NamespaceAwarePass { const CLASS_TYPE = 'class'; const INTERFACE_TYPE = 'interface'; const TRAIT_TYPE = 'trait'; private int $conditionalScopes = 0; /** * Validate class, interface and trait definitions. * * Validate them upon entering the node, so that we know about their * presence and can validate constant fetches and static calls in class or * trait methods. * * @param Node $node * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { parent::enterNode($node); if (self::isConditional($node)) { $this->conditionalScopes++; return; } if ($this->conditionalScopes === 0) { if ($node instanceof Class_) { $this->validateClassStatement($node); } elseif ($node instanceof Interface_) { $this->validateInterfaceStatement($node); } elseif ($node instanceof Trait_) { $this->validateTraitStatement($node); } } } /** * @param Node $node * * @return int|Node|Node[]|null Replacement node (or special return value) */ public function leaveNode(Node $node) { if (self::isConditional($node)) { $this->conditionalScopes--; } } private static function isConditional(Node $node): bool { return $node instanceof If_ || $node instanceof While_ || $node instanceof Do_ || $node instanceof Switch_ || $node instanceof Ternary; } /** * Validate a class definition statement. * * @param Class_ $stmt */ protected function validateClassStatement(Class_ $stmt) { $this->ensureCanDefine($stmt, self::CLASS_TYPE); if (isset($stmt->extends)) { $this->ensureClassExists($this->getFullyQualifiedName($stmt->extends), $stmt); } $this->ensureInterfacesExist($stmt->implements, $stmt); } /** * Validate an interface definition statement. * * @param Interface_ $stmt */ protected function validateInterfaceStatement(Interface_ $stmt) { $this->ensureCanDefine($stmt, self::INTERFACE_TYPE); $this->ensureInterfacesExist($stmt->extends, $stmt); } /** * Validate a trait definition statement. * * @param Trait_ $stmt */ protected function validateTraitStatement(Trait_ $stmt) { $this->ensureCanDefine($stmt, self::TRAIT_TYPE); } /** * Ensure that no class, interface or trait name collides with a new definition. * * @throws FatalErrorException * * @param Stmt $stmt * @param string $scopeType */ protected function ensureCanDefine(Stmt $stmt, string $scopeType = self::CLASS_TYPE) { // Anonymous classes don't have a name, and uniqueness shouldn't be enforced. if ($stmt->name === null) { return; } $name = $this->getFullyQualifiedName($stmt->name); // check for name collisions $errorType = null; if ($this->classExists($name)) { $errorType = self::CLASS_TYPE; } elseif ($this->interfaceExists($name)) { $errorType = self::INTERFACE_TYPE; } elseif ($this->traitExists($name)) { $errorType = self::TRAIT_TYPE; } if ($errorType !== null) { throw $this->createError(\sprintf('%s named %s already exists', \ucfirst($errorType), $name), $stmt); } // Store creation for the rest of this code snippet so we can find local // issue too $this->currentScope[\strtolower($name)] = $scopeType; } /** * Ensure that a referenced class exists. * * @throws FatalErrorException * * @param string $name * @param Stmt $stmt */ protected function ensureClassExists(string $name, Stmt $stmt) { if (!$this->classExists($name)) { throw $this->createError(\sprintf('Class \'%s\' not found', $name), $stmt); } } /** * Ensure that a referenced class _or interface_ exists. * * @throws FatalErrorException * * @param string $name * @param Stmt $stmt */ protected function ensureClassOrInterfaceExists(string $name, Stmt $stmt) { if (!$this->classExists($name) && !$this->interfaceExists($name)) { throw $this->createError(\sprintf('Class \'%s\' not found', $name), $stmt); } } /** * Ensure that a referenced class _or trait_ exists. * * @throws FatalErrorException * * @param string $name * @param Stmt $stmt */ protected function ensureClassOrTraitExists(string $name, Stmt $stmt) { if (!$this->classExists($name) && !$this->traitExists($name)) { throw $this->createError(\sprintf('Class \'%s\' not found', $name), $stmt); } } /** * Ensure that a statically called method exists. * * @throws FatalErrorException * * @param string $class * @param string $name * @param Stmt $stmt */ protected function ensureMethodExists(string $class, string $name, Stmt $stmt) { $this->ensureClassOrTraitExists($class, $stmt); // let's pretend all calls to self, parent and static are valid if (\in_array(\strtolower($class), ['self', 'parent', 'static'])) { return; } // ... and all calls to classes defined right now if ($this->findInScope($class) === self::CLASS_TYPE) { return; } // if method name is an expression, give it a pass for now if ($name instanceof Expr) { return; } if (!\method_exists($class, $name) && !\method_exists($class, '__callStatic')) { throw $this->createError(\sprintf('Call to undefined method %s::%s()', $class, $name), $stmt); } } /** * Ensure that a referenced interface exists. * * @throws FatalErrorException * * @param Interface_[] $interfaces * @param Stmt $stmt */ protected function ensureInterfacesExist(array $interfaces, Stmt $stmt) { foreach ($interfaces as $interface) { /** @var string $name */ $name = $this->getFullyQualifiedName($interface); if (!$this->interfaceExists($name)) { throw $this->createError(\sprintf('Interface \'%s\' not found', $name), $stmt); } } } /** * Check whether a class exists, or has been defined in the current code snippet. * * Gives `self`, `static` and `parent` a free pass. * * @param string $name */ protected function classExists(string $name): bool { // Give `self`, `static` and `parent` a pass. This will actually let // some errors through, since we're not checking whether the keyword is // being used in a class scope. if (\in_array(\strtolower($name), ['self', 'static', 'parent'])) { return true; } return \class_exists($name) || $this->findInScope($name) === self::CLASS_TYPE; } /** * Check whether an interface exists, or has been defined in the current code snippet. * * @param string $name */ protected function interfaceExists(string $name): bool { return \interface_exists($name) || $this->findInScope($name) === self::INTERFACE_TYPE; } /** * Check whether a trait exists, or has been defined in the current code snippet. * * @param string $name */ protected function traitExists(string $name): bool { return \trait_exists($name) || $this->findInScope($name) === self::TRAIT_TYPE; } /** * Find a symbol in the current code snippet scope. * * @param string $name * * @return string|null */ protected function findInScope(string $name) { $name = \strtolower($name); if (isset($this->currentScope[$name])) { return $this->currentScope[$name]; } } /** * Error creation factory. * * @param string $msg * @param Stmt $stmt */ protected function createError(string $msg, Stmt $stmt): FatalErrorException { return new FatalErrorException($msg, 0, \E_ERROR, null, $stmt->getStartLine()); } } PK������*Z'D$ ��$ ��"��CodeCleaner/NamespaceAwarePass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Name; use PhpParser\Node\Name\FullyQualified as FullyQualifiedName; use PhpParser\Node\Stmt\Namespace_; /** * Abstract namespace-aware code cleaner pass. */ abstract class NamespaceAwarePass extends CodeCleanerPass { protected array $namespace = []; protected array $currentScope = []; /** * @todo should this be final? Extending classes should be sure to either * use afterTraverse or call parent::beforeTraverse() when overloading. * * Reset the namespace and the current scope before beginning analysis * * @return Node[]|null Array of nodes */ public function beforeTraverse(array $nodes) { $this->namespace = []; $this->currentScope = []; } /** * @todo should this be final? Extending classes should be sure to either use * leaveNode or call parent::enterNode() when overloading * * @param Node $node * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { if ($node instanceof Namespace_) { $this->namespace = isset($node->name) ? $this->getParts($node->name) : []; } } /** * Get a fully-qualified name (class, function, interface, etc). * * @param mixed $name */ protected function getFullyQualifiedName($name): string { if ($name instanceof FullyQualifiedName) { return \implode('\\', $this->getParts($name)); } if ($name instanceof Name) { $name = $this->getParts($name); } elseif (!\is_array($name)) { $name = [$name]; } return \implode('\\', \array_merge($this->namespace, $name)); } /** * Backwards compatibility shim for PHP-Parser 4.x. * * At some point we might want to make $namespace a plain string, to match how Name works? */ protected function getParts(Name $name): array { return \method_exists($name, 'getParts') ? $name->getParts() : $name->parts; } } PK������*Z<5 ��5 �� ��CodeCleaner/LabelContextPass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\FunctionLike; use PhpParser\Node\Stmt\Goto_; use PhpParser\Node\Stmt\Label; use Psy\Exception\FatalErrorException; /** * CodeCleanerPass for label context. * * This class partially emulates the PHP label specification. * PsySH can not declare labels by sequentially executing lines with eval, * but since it is not a syntax error, no error is raised. * This class warns before invalid goto causes a fatal error. * Since this is a simple checker, it does not block real fatal error * with complex syntax. (ex. it does not parse inside function.) * * @see http://php.net/goto */ class LabelContextPass extends CodeCleanerPass { private int $functionDepth = 0; private array $labelDeclarations = []; private array $labelGotos = []; /** * @param array $nodes * * @return Node[]|null Array of nodes */ public function beforeTraverse(array $nodes) { $this->functionDepth = 0; $this->labelDeclarations = []; $this->labelGotos = []; } /** * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { if ($node instanceof FunctionLike) { $this->functionDepth++; return; } // node is inside function context if ($this->functionDepth !== 0) { return; } if ($node instanceof Goto_) { $this->labelGotos[\strtolower($node->name)] = $node->getStartLine(); } elseif ($node instanceof Label) { $this->labelDeclarations[\strtolower($node->name)] = $node->getStartLine(); } } /** * @param \PhpParser\Node $node * * @return int|Node|Node[]|null Replacement node (or special return value) */ public function leaveNode(Node $node) { if ($node instanceof FunctionLike) { $this->functionDepth--; } } /** * @return Node[]|null Array of nodes */ public function afterTraverse(array $nodes) { foreach ($this->labelGotos as $name => $line) { if (!isset($this->labelDeclarations[$name])) { $msg = "'goto' to undefined label '{$name}'"; throw new FatalErrorException($msg, 0, \E_ERROR, null, $line); } } } } PK������*ZwWiT �� ����CodeCleaner/NamespacePass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Name; use PhpParser\Node\Stmt\Namespace_; use Psy\CodeCleaner; /** * Provide implicit namespaces for subsequent execution. * * The namespace pass remembers the last standalone namespace line encountered: * * namespace Foo\Bar; * * ... which it then applies implicitly to all future evaluated code, until the * namespace is replaced by another namespace. To reset to the top level * namespace, enter `namespace {}`. This is a bit ugly, but it does the trick :) */ class NamespacePass extends CodeCleanerPass { private ?Name $namespace = null; private CodeCleaner $cleaner; /** * @param CodeCleaner $cleaner */ public function __construct(CodeCleaner $cleaner) { $this->cleaner = $cleaner; } /** * If this is a standalone namespace line, remember it for later. * * Otherwise, apply remembered namespaces to the code until a new namespace * is encountered. * * @param array $nodes * * @return Node[]|null Array of nodes */ public function beforeTraverse(array $nodes) { if (empty($nodes)) { return $nodes; } $last = \end($nodes); if ($last instanceof Namespace_) { $kind = $last->getAttribute('kind'); // Treat all namespace statements pre-PHP-Parser v3.1.2 as "open", // even though we really have no way of knowing. if ($kind === null || $kind === Namespace_::KIND_SEMICOLON) { // Save the current namespace for open namespaces $this->setNamespace($last->name); } else { // Clear the current namespace after a braced namespace $this->setNamespace(null); } return $nodes; } return $this->namespace ? [new Namespace_($this->namespace, $nodes)] : $nodes; } /** * Remember the namespace and (re)set the namespace on the CodeCleaner as * well. * * @param Name|null $namespace */ private function setNamespace(?Name $namespace) { $this->namespace = $namespace; $this->cleaner->setNamespace($namespace === null ? null : $this->getParts($namespace)); } /** * Backwards compatibility shim for PHP-Parser 4.x. * * At some point we might want to make the namespace a plain string, to match how Name works? */ protected function getParts(Name $name): array { return \method_exists($name, 'getParts') ? $name->getParts() : $name->parts; } } PK������*Zހ����#��CodeCleaner/LeavePsyshAlonePass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Expr\Variable; use Psy\Exception\RuntimeException; /** * Validate that the user input does not reference the `$__psysh__` variable. */ class LeavePsyshAlonePass extends CodeCleanerPass { /** * Validate that the user input does not reference the `$__psysh__` variable. * * @throws RuntimeException if the user is messing with $__psysh__ * * @param Node $node * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { if ($node instanceof Variable && $node->name === '__psysh__') { throw new RuntimeException('Don\'t mess with $__psysh__; bad things will happen'); } } } PK������*Z~>������CodeCleaner/LoopContextPass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Scalar\DNumber; use PhpParser\Node\Scalar\Float_; use PhpParser\Node\Scalar\Int_; use PhpParser\Node\Scalar\LNumber; use PhpParser\Node\Stmt\Break_; use PhpParser\Node\Stmt\Continue_; use PhpParser\Node\Stmt\Do_; use PhpParser\Node\Stmt\For_; use PhpParser\Node\Stmt\Foreach_; use PhpParser\Node\Stmt\Switch_; use PhpParser\Node\Stmt\While_; use Psy\Exception\FatalErrorException; /** * The loop context pass handles invalid `break` and `continue` statements. */ class LoopContextPass extends CodeCleanerPass { private int $loopDepth = 0; /** * {@inheritdoc} * * @return Node[]|null Array of nodes */ public function beforeTraverse(array $nodes) { $this->loopDepth = 0; } /** * @throws FatalErrorException if the node is a break or continue in a non-loop or switch context * @throws FatalErrorException if the node is trying to break out of more nested structures than exist * @throws FatalErrorException if the node is a break or continue and has a non-numeric argument * @throws FatalErrorException if the node is a break or continue and has an argument less than 1 * * @param Node $node * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { switch (true) { case $node instanceof Do_: case $node instanceof For_: case $node instanceof Foreach_: case $node instanceof Switch_: case $node instanceof While_: $this->loopDepth++; break; case $node instanceof Break_: case $node instanceof Continue_: $operator = $node instanceof Break_ ? 'break' : 'continue'; if ($this->loopDepth === 0) { $msg = \sprintf("'%s' not in the 'loop' or 'switch' context", $operator); throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine()); } // @todo Remove LNumber and DNumber once we drop support for PHP-Parser 4.x if ( $node->num instanceof LNumber || $node->num instanceof DNumber || $node->num instanceof Int_ || $node->num instanceof Float_ ) { $num = $node->num->value; if ($node->num instanceof DNumber || $num < 1) { $msg = \sprintf("'%s' operator accepts only positive numbers", $operator); throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine()); } if ($num > $this->loopDepth) { $msg = \sprintf("Cannot '%s' %d levels", $operator, $num); throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine()); } } elseif ($node->num) { $msg = \sprintf("'%s' operator with non-constant operand is no longer supported", $operator); throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine()); } break; } } /** * @param Node $node * * @return int|Node|Node[]|null Replacement node (or special return value) */ public function leaveNode(Node $node) { switch (true) { case $node instanceof Do_: case $node instanceof For_: case $node instanceof Foreach_: case $node instanceof Switch_: case $node instanceof While_: $this->loopDepth--; break; } } } PK������*Z0_��_��&��CodeCleaner/AssignThisVariablePass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Expr\Assign; use PhpParser\Node\Expr\Variable; use Psy\Exception\FatalErrorException; /** * Validate that the user input does not assign the `$this` variable. * * @author Martin Hasoň <martin.hason@gmail.com> */ class AssignThisVariablePass extends CodeCleanerPass { /** * Validate that the user input does not assign the `$this` variable. * * @throws FatalErrorException if the user assign the `$this` variable * * @param Node $node * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { if ($node instanceof Assign && $node->var instanceof Variable && $node->var->name === 'this') { throw new FatalErrorException('Cannot re-assign $this', 0, \E_ERROR, null, $node->getStartLine()); } } } PK������*Z20e����#��CodeCleaner/FunctionContextPass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Expr\Yield_; use PhpParser\Node\FunctionLike; use Psy\Exception\FatalErrorException; class FunctionContextPass extends CodeCleanerPass { private int $functionDepth = 0; /** * @param array $nodes * * @return Node[]|null Array of nodes */ public function beforeTraverse(array $nodes) { $this->functionDepth = 0; } /** * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { if ($node instanceof FunctionLike) { $this->functionDepth++; return; } // node is inside function context if ($this->functionDepth !== 0) { return; } // It causes fatal error. if ($node instanceof Yield_) { $msg = 'The "yield" expression can only be used inside a function'; throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine()); } } /** * @param \PhpParser\Node $node * * @return int|Node|Node[]|null Replacement node (or special return value) */ public function leaveNode(Node $node) { if ($node instanceof FunctionLike) { $this->functionDepth--; } } } PK������*Z������CodeCleaner/CodeCleanerPass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\NodeVisitorAbstract; /** * A CodeCleaner pass is a PhpParser Node Visitor. */ abstract class CodeCleanerPass extends NodeVisitorAbstract { // Wheee! } PK������*ZqƂ������CodeCleaner/ReturnTypePass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Expr\Closure; use PhpParser\Node\Expr\ConstFetch; use PhpParser\Node\Identifier; use PhpParser\Node\IntersectionType; use PhpParser\Node\Name; use PhpParser\Node\NullableType; use PhpParser\Node\Stmt\Function_; use PhpParser\Node\Stmt\Return_; use PhpParser\Node\UnionType; use Psy\Exception\FatalErrorException; /** * Add runtime validation for return types. */ class ReturnTypePass extends CodeCleanerPass { const MESSAGE = 'A function with return type must return a value'; const NULLABLE_MESSAGE = 'A function with return type must return a value (did you mean "return null;" instead of "return;"?)'; const VOID_MESSAGE = 'A void function must not return a value'; const VOID_NULL_MESSAGE = 'A void function must not return a value (did you mean "return;" instead of "return null;"?)'; const NULLABLE_VOID_MESSAGE = 'Void type cannot be nullable'; private array $returnTypeStack = []; /** * {@inheritdoc} * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { if ($this->isFunctionNode($node)) { $this->returnTypeStack[] = $node->returnType; return; } if (!empty($this->returnTypeStack) && $node instanceof Return_) { $expectedType = \end($this->returnTypeStack); if ($expectedType === null) { return; } $msg = null; if ($this->typeName($expectedType) === 'void') { // Void functions if ($expectedType instanceof NullableType) { $msg = self::NULLABLE_VOID_MESSAGE; } elseif ($node->expr instanceof ConstFetch && \strtolower($node->expr->name) === 'null') { $msg = self::VOID_NULL_MESSAGE; } elseif ($node->expr !== null) { $msg = self::VOID_MESSAGE; } } else { // Everything else if ($node->expr === null) { $msg = $expectedType instanceof NullableType ? self::NULLABLE_MESSAGE : self::MESSAGE; } } if ($msg !== null) { throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine()); } } } /** * {@inheritdoc} * * @return int|Node|Node[]|null Replacement node (or special return value) */ public function leaveNode(Node $node) { if (!empty($this->returnTypeStack) && $this->isFunctionNode($node)) { \array_pop($this->returnTypeStack); } } private function isFunctionNode(Node $node): bool { return $node instanceof Function_ || $node instanceof Closure; } private function typeName(Node $node): string { if ($node instanceof UnionType) { return \implode('|', \array_map([$this, 'typeName'], $node->types)); } if ($node instanceof IntersectionType) { return \implode('&', \array_map([$this, 'typeName'], $node->types)); } if ($node instanceof NullableType) { return $this->typeName($node->type); } if ($node instanceof Identifier || $node instanceof Name) { return $node->toLowerString(); } throw new \InvalidArgumentException('Unable to find type name'); } } PK������*Zo#V~��~����CodeCleaner/IssetPass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Expr\ArrayDimFetch; use PhpParser\Node\Expr\Isset_; use PhpParser\Node\Expr\NullsafePropertyFetch; use PhpParser\Node\Expr\PropertyFetch; use PhpParser\Node\Expr\Variable; use Psy\Exception\FatalErrorException; /** * Code cleaner pass to ensure we only allow variables, array fetch and property * fetch expressions in isset() calls. */ class IssetPass extends CodeCleanerPass { const EXCEPTION_MSG = 'Cannot use isset() on the result of an expression (you can use "null !== expression" instead)'; /** * @throws FatalErrorException * * @param Node $node * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { if (!$node instanceof Isset_) { return; } foreach ($node->vars as $var) { if (!$var instanceof Variable && !$var instanceof ArrayDimFetch && !$var instanceof PropertyFetch && !$var instanceof NullsafePropertyFetch) { throw new FatalErrorException(self::EXCEPTION_MSG, 0, \E_ERROR, null, $node->getStartLine()); } } } } PK������*Z@',��,��"��CodeCleaner/MagicConstantsPass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Name; use PhpParser\Node\Scalar\MagicConst\Dir; use PhpParser\Node\Scalar\MagicConst\File; use PhpParser\Node\Scalar\String_; /** * Swap out __DIR__ and __FILE__ magic constants with our best guess? */ class MagicConstantsPass extends CodeCleanerPass { /** * Swap out __DIR__ and __FILE__ constants, because the default ones when * calling eval() don't make sense. * * @param Node $node * * @return FuncCall|String_|null */ public function enterNode(Node $node) { if ($node instanceof Dir) { return new FuncCall(new Name('getcwd'), [], $node->getAttributes()); } elseif ($node instanceof File) { return new String_('', $node->getAttributes()); } } } PK������*ZlnV ��V ��!��CodeCleaner/AbstractClassPass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; use Psy\Exception\FatalErrorException; /** * The abstract class pass handles abstract classes and methods, complaining if there are too few or too many of either. */ class AbstractClassPass extends CodeCleanerPass { private Class_ $class; private array $abstractMethods; /** * @throws FatalErrorException if the node is an abstract function with a body * * @param Node $node * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { if ($node instanceof Class_) { $this->class = $node; $this->abstractMethods = []; } elseif ($node instanceof ClassMethod) { if ($node->isAbstract()) { $name = \sprintf('%s::%s', $this->class->name, $node->name); $this->abstractMethods[] = $name; if ($node->stmts !== null) { $msg = \sprintf('Abstract function %s cannot contain body', $name); throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine()); } } } } /** * @throws FatalErrorException if the node is a non-abstract class with abstract methods * * @param Node $node * * @return int|Node|Node[]|null Replacement node (or special return value) */ public function leaveNode(Node $node) { if ($node instanceof Class_) { $count = \count($this->abstractMethods); if ($count > 0 && !$node->isAbstract()) { $msg = \sprintf( 'Class %s contains %d abstract method%s must therefore be declared abstract or implement the remaining methods (%s)', $node->name, $count, ($count === 1) ? '' : 's', \implode(', ', $this->abstractMethods) ); throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine()); } } } } PK������*ZZJ. �� ��$��CodeCleaner/ValidConstructorPass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Name; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Namespace_; use Psy\Exception\FatalErrorException; /** * Validate that the constructor method is not static, and does not have a * return type. * * Checks both explicit __construct methods as well as old-style constructor * methods with the same name as the class (for non-namespaced classes). * * As of PHP 5.3.3, methods with the same name as the last element of a * namespaced class name will no longer be treated as constructor. This change * doesn't affect non-namespaced classes. * * @author Martin Hasoň <martin.hason@gmail.com> */ class ValidConstructorPass extends CodeCleanerPass { private array $namespace = []; /** * @return Node[]|null Array of nodes */ public function beforeTraverse(array $nodes) { $this->namespace = []; } /** * Validate that the constructor is not static and does not have a return type. * * @throws FatalErrorException the constructor function is static * @throws FatalErrorException the constructor function has a return type * * @param Node $node * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { if ($node instanceof Namespace_) { $this->namespace = isset($node->name) ? $this->getParts($node->name) : []; } elseif ($node instanceof Class_) { $constructor = null; foreach ($node->stmts as $stmt) { if ($stmt instanceof ClassMethod) { // If we find a new-style constructor, no need to look for the old-style if ('__construct' === \strtolower($stmt->name)) { $this->validateConstructor($stmt, $node); return; } // We found a possible old-style constructor (unless there is also a __construct method) if (empty($this->namespace) && \strtolower($node->name) === \strtolower($stmt->name)) { $constructor = $stmt; } } } if ($constructor) { $this->validateConstructor($constructor, $node); } } } /** * @throws FatalErrorException the constructor function is static * @throws FatalErrorException the constructor function has a return type * * @param Node $constructor * @param Node $classNode */ private function validateConstructor(Node $constructor, Node $classNode) { if ($constructor->isStatic()) { $msg = \sprintf( 'Constructor %s::%s() cannot be static', \implode('\\', \array_merge($this->namespace, (array) $classNode->name->toString())), $constructor->name ); throw new FatalErrorException($msg, 0, \E_ERROR, null, $classNode->getStartLine()); } if (\method_exists($constructor, 'getReturnType') && $constructor->getReturnType()) { $msg = \sprintf( 'Constructor %s::%s() cannot declare a return type', \implode('\\', \array_merge($this->namespace, (array) $classNode->name->toString())), $constructor->name ); throw new FatalErrorException($msg, 0, \E_ERROR, null, $classNode->getStartLine()); } } /** * Backwards compatibility shim for PHP-Parser 4.x. * * At some point we might want to make $namespace a plain string, to match how Name works? */ protected function getParts(Name $name): array { return \method_exists($name, 'getParts') ? $name->getParts() : $name->parts; } } PK������*Zmb[��[����CodeCleaner/ExitPass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Expr\Exit_; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Name\FullyQualified as FullyQualifiedName; use Psy\Exception\BreakException; class ExitPass extends CodeCleanerPass { /** * Converts exit calls to BreakExceptions. * * @param \PhpParser\Node $node * * @return int|Node|Node[]|null Replacement node (or special return value) */ public function leaveNode(Node $node) { if ($node instanceof Exit_) { return new StaticCall(new FullyQualifiedName(BreakException::class), 'exitShell'); } } } PK������*Z͠����&��CodeCleaner/EmptyArrayDimFetchPass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Expr\ArrayDimFetch; use PhpParser\Node\Expr\Assign; use PhpParser\Node\Expr\AssignRef; use PhpParser\Node\Stmt\Foreach_; use Psy\Exception\FatalErrorException; /** * Validate empty brackets are only used for assignment. */ class EmptyArrayDimFetchPass extends CodeCleanerPass { const EXCEPTION_MESSAGE = 'Cannot use [] for reading'; private array $theseOnesAreFine = []; /** * @return Node[]|null Array of nodes */ public function beforeTraverse(array $nodes) { $this->theseOnesAreFine = []; } /** * @throws FatalErrorException if the user used empty array dim fetch outside of assignment * * @param Node $node * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { if ($node instanceof Assign && $node->var instanceof ArrayDimFetch) { $this->theseOnesAreFine[] = $node->var; } elseif ($node instanceof AssignRef && $node->expr instanceof ArrayDimFetch) { $this->theseOnesAreFine[] = $node->expr; } elseif ($node instanceof Foreach_ && $node->valueVar instanceof ArrayDimFetch) { $this->theseOnesAreFine[] = $node->valueVar; } elseif ($node instanceof ArrayDimFetch && $node->var instanceof ArrayDimFetch) { // $a[]['b'] = 'c' if (\in_array($node, $this->theseOnesAreFine)) { $this->theseOnesAreFine[] = $node->var; } } if ($node instanceof ArrayDimFetch && $node->dim === null) { if (!\in_array($node, $this->theseOnesAreFine)) { throw new FatalErrorException(self::EXCEPTION_MESSAGE, $node->getStartLine()); } } } } PK������*ZEyq ��q ����CodeCleaner/StrictTypesPass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\DeclareItem; use PhpParser\Node\Scalar\Int_; use PhpParser\Node\Scalar\LNumber; use PhpParser\Node\Stmt\Declare_; use PhpParser\Node\Stmt\DeclareDeclare; use Psy\Exception\FatalErrorException; /** * Provide implicit strict types declarations for for subsequent execution. * * The strict types pass remembers the last strict types declaration: * * declare(strict_types=1); * * ... which it then applies implicitly to all future evaluated code, until it * is replaced by a new declaration. */ class StrictTypesPass extends CodeCleanerPass { const EXCEPTION_MESSAGE = 'strict_types declaration must have 0 or 1 as its value'; private bool $strictTypes; /** * @param bool $strictTypes enforce strict types by default */ public function __construct(bool $strictTypes = false) { $this->strictTypes = $strictTypes; } /** * If this is a standalone strict types declaration, remember it for later. * * Otherwise, apply remembered strict types declaration to to the code until * a new declaration is encountered. * * @throws FatalErrorException if an invalid `strict_types` declaration is found * * @param array $nodes * * @return Node[]|null Array of nodes */ public function beforeTraverse(array $nodes) { $prependStrictTypes = $this->strictTypes; foreach ($nodes as $node) { if ($node instanceof Declare_) { foreach ($node->declares as $declare) { if ($declare->key->toString() === 'strict_types') { $value = $declare->value; // @todo Remove LNumber once we drop support for PHP-Parser 4.x if ((!$value instanceof LNumber && !$value instanceof Int_) || ($value->value !== 0 && $value->value !== 1)) { throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getStartLine()); } $this->strictTypes = $value->value === 1; } } } } if ($prependStrictTypes) { $first = \reset($nodes); if (!$first instanceof Declare_) { // @todo Switch to PhpParser\Node\DeclareItem once we drop support for PHP-Parser 4.x // @todo Remove LNumber once we drop support for PHP-Parser 4.x $arg = \class_exists('PhpParser\Node\Scalar\Int_') ? new Int_(1) : new LNumber(1); $declareItem = \class_exists('PhpParser\Node\DeclareItem') ? new DeclareItem('strict_types', $arg) : new DeclareDeclare('strict_types', $arg); $declare = new Declare_([$declareItem]); \array_unshift($nodes, $declare); } } return $nodes; } } PK������*Z �� ��0��CodeCleaner/FunctionReturnInWriteContextPass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Expr\Array_; use PhpParser\Node\Expr\Assign; use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Expr\Isset_; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Stmt\Unset_; use PhpParser\Node\VariadicPlaceholder; use Psy\Exception\FatalErrorException; /** * Validate that the functions are used correctly. * * @author Martin Hasoň <martin.hason@gmail.com> */ class FunctionReturnInWriteContextPass extends CodeCleanerPass { const ISSET_MESSAGE = 'Cannot use isset() on the result of an expression (you can use "null !== expression" instead)'; const EXCEPTION_MESSAGE = "Can't use function return value in write context"; /** * Validate that the functions are used correctly. * * @throws FatalErrorException if a function is passed as an argument reference * @throws FatalErrorException if a function is used as an argument in the isset * @throws FatalErrorException if a value is assigned to a function * * @param Node $node * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { if ($node instanceof Array_ || $this->isCallNode($node)) { $items = $node instanceof Array_ ? $node->items : $node->args; foreach ($items as $item) { if ($item instanceof VariadicPlaceholder) { continue; } if ($item && $item->byRef && $this->isCallNode($item->value)) { throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getStartLine()); } } } elseif ($node instanceof Isset_ || $node instanceof Unset_) { foreach ($node->vars as $var) { if (!$this->isCallNode($var)) { continue; } $msg = $node instanceof Isset_ ? self::ISSET_MESSAGE : self::EXCEPTION_MESSAGE; throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine()); } } elseif ($node instanceof Assign && $this->isCallNode($node->var)) { throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getStartLine()); } } private function isCallNode(Node $node): bool { return $node instanceof FuncCall || $node instanceof MethodCall || $node instanceof StaticCall; } } PK������*Z%A ��A ����CodeCleaner/ListPass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\ArrayItem; use PhpParser\Node\Expr\Array_; use PhpParser\Node\Expr\ArrayDimFetch; // @todo Drop PhpParser\Node\Expr\ArrayItem once we drop support for PHP-Parser 4.x use PhpParser\Node\Expr\ArrayItem as LegacyArrayItem; use PhpParser\Node\Expr\Assign; use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Expr\List_; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\PropertyFetch; use PhpParser\Node\Expr\Variable; use Psy\Exception\ParseErrorException; /** * Validate that the list assignment. */ class ListPass extends CodeCleanerPass { /** * Validate use of list assignment. * * @throws ParseErrorException if the user used empty with anything but a variable * * @param Node $node * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { if (!$node instanceof Assign) { return; } if (!$node->var instanceof Array_ && !$node->var instanceof List_) { return; } // Polyfill for PHP-Parser 2.x $items = isset($node->var->items) ? $node->var->items : $node->var->vars; if ($items === [] || $items === [null]) { throw new ParseErrorException('Cannot use empty list', ['startLine' => $node->var->getStartLine(), 'endLine' => $node->var->getEndLine()]); } $itemFound = false; foreach ($items as $item) { if ($item === null) { continue; } $itemFound = true; if (!self::isValidArrayItem($item)) { $msg = 'Assignments can only happen to writable values'; throw new ParseErrorException($msg, ['startLine' => $item->getStartLine(), 'endLine' => $item->getEndLine()]); } } if (!$itemFound) { throw new ParseErrorException('Cannot use empty list'); } } /** * Validate whether a given item in an array is valid for short assignment. * * @param Node $item */ private static function isValidArrayItem(Node $item): bool { $value = ($item instanceof ArrayItem || $item instanceof LegacyArrayItem) ? $item->value : $item; while ($value instanceof ArrayDimFetch || $value instanceof PropertyFetch) { $value = $value->var; } // We just kind of give up if it's a method call. We can't tell if it's // valid via static analysis. return $value instanceof Variable || $value instanceof MethodCall || $value instanceof FuncCall; } } PK������*Zz~EL��L��+��CodeCleaner/CallTimePassByReferencePass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\VariadicPlaceholder; use Psy\Exception\FatalErrorException; /** * Validate that the user did not use the call-time pass-by-reference that causes a fatal error. * * As of PHP 5.4.0, call-time pass-by-reference was removed, so using it will raise a fatal error. * * @author Martin Hasoň <martin.hason@gmail.com> */ class CallTimePassByReferencePass extends CodeCleanerPass { const EXCEPTION_MESSAGE = 'Call-time pass-by-reference has been removed'; /** * Validate of use call-time pass-by-reference. * * @throws FatalErrorException if the user used call-time pass-by-reference * * @param Node $node * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { if (!$node instanceof FuncCall && !$node instanceof MethodCall && !$node instanceof StaticCall) { return; } foreach ($node->args as $arg) { if ($arg instanceof VariadicPlaceholder) { continue; } if ($arg->byRef) { throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getStartLine()); } } } } PK������*Z,{���� ��CodeCleaner/UseStatementPass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Name; use PhpParser\Node\Name\FullyQualified as FullyQualifiedName; use PhpParser\Node\Stmt\GroupUse; use PhpParser\Node\Stmt\Namespace_; use PhpParser\Node\Stmt\Use_; use PhpParser\Node\Stmt\UseItem; use PhpParser\Node\Stmt\UseUse; use PhpParser\NodeTraverser; /** * Provide implicit use statements for subsequent execution. * * The use statement pass remembers the last use statement line encountered: * * use Foo\Bar as Baz; * * ... which it then applies implicitly to all future evaluated code, until the * current namespace is replaced by another namespace. */ class UseStatementPass extends CodeCleanerPass { private array $aliases = []; private array $lastAliases = []; private ?Name $lastNamespace = null; /** * Re-load the last set of use statements on re-entering a namespace. * * This isn't how namespaces normally work, but because PsySH has to spin * up a new namespace for every line of code, we do this to make things * work like you'd expect. * * @param Node $node * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { if ($node instanceof Namespace_) { // If this is the same namespace as last namespace, let's do ourselves // a favor and reload all the aliases... if (\strtolower($node->name ?: '') === \strtolower($this->lastNamespace ?: '')) { $this->aliases = $this->lastAliases; } } } /** * If this statement is a namespace, forget all the aliases we had. * * If it's a use statement, remember the alias for later. Otherwise, apply * remembered aliases to the code. * * @param Node $node * * @return int|Node|Node[]|null Replacement node (or special return value) */ public function leaveNode(Node $node) { // Store a reference to every "use" statement, because we'll need them in a bit. if ($node instanceof Use_) { foreach ($node->uses as $useItem) { $this->aliases[\strtolower($useItem->getAlias())] = $useItem->name; } // @todo Rename to Node_Visitor::REMOVE_NODE once we drop support for PHP-Parser 4.x return NodeTraverser::REMOVE_NODE; } // Expand every "use" statement in the group into a full, standalone "use" and store 'em with the others. if ($node instanceof GroupUse) { foreach ($node->uses as $useItem) { $this->aliases[\strtolower($useItem->getAlias())] = Name::concat($node->prefix, $useItem->name, [ 'startLine' => $node->prefix->getAttribute('startLine'), 'endLine' => $useItem->name->getAttribute('endLine'), ]); } // @todo Rename to Node_Visitor::REMOVE_NODE once we drop support for PHP-Parser 4.x return NodeTraverser::REMOVE_NODE; } // Start fresh, since we're done with this namespace. if ($node instanceof Namespace_) { $this->lastNamespace = $node->name; $this->lastAliases = $this->aliases; $this->aliases = []; return; } // Do nothing with UseItem; this an entry in the list of uses in the use statement. // @todo Remove UseUse once we drop support for PHP-Parser 4.x if ($node instanceof UseUse || $node instanceof UseItem) { return; } // For everything else, we'll implicitly thunk all aliases into fully-qualified names. foreach ($node as $name => $subNode) { if ($subNode instanceof Name) { if ($replacement = $this->findAlias($subNode)) { $node->$name = $replacement; } } } return $node; } /** * Find class/namespace aliases. * * @param Name $name * * @return FullyQualifiedName|null */ private function findAlias(Name $name) { $that = \strtolower($name); foreach ($this->aliases as $alias => $prefix) { if ($that === $alias) { return new FullyQualifiedName($prefix->toString()); } elseif (\substr($that, 0, \strlen($alias) + 1) === $alias.'\\') { return new FullyQualifiedName($prefix->toString().\substr($name, \strlen($alias))); } } } } PK������*Z0⟉����'��CodeCleaner/PassableByReferencePass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Expr; use PhpParser\Node\Expr\Array_; use PhpParser\Node\Expr\ArrayDimFetch; use PhpParser\Node\Expr\ClassConstFetch; use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\PropertyFetch; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Expr\Variable; use PhpParser\Node\VariadicPlaceholder; use Psy\Exception\FatalErrorException; /** * Validate that only variables (and variable-like things) are passed by reference. */ class PassableByReferencePass extends CodeCleanerPass { const EXCEPTION_MESSAGE = 'Only variables can be passed by reference'; /** * @throws FatalErrorException if non-variables are passed by reference * * @param Node $node * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { // @todo support MethodCall and StaticCall as well. if ($node instanceof FuncCall) { // if function name is an expression or a variable, give it a pass for now. if ($node->name instanceof Expr || $node->name instanceof Variable) { return; } $name = (string) $node->name; if ($name === 'array_multisort') { return $this->validateArrayMultisort($node); } try { $refl = new \ReflectionFunction($name); } catch (\ReflectionException $e) { // Well, we gave it a shot! return; } $args = []; foreach ($node->args as $position => $arg) { if ($arg instanceof VariadicPlaceholder) { continue; } $args[$arg->name !== null ? $arg->name->name : $position] = $arg; } foreach ($refl->getParameters() as $key => $param) { if (\array_key_exists($key, $args) || \array_key_exists($param->name, $args)) { $arg = $args[$param->name] ?? $args[$key]; if ($param->isPassedByReference() && !$this->isPassableByReference($arg)) { throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getStartLine()); } } } } } private function isPassableByReference(Node $arg): bool { // Unpacked arrays can be passed by reference if ($arg->value instanceof Array_) { return $arg->unpack; } // FuncCall, MethodCall and StaticCall are all PHP _warnings_ not fatal errors, so we'll let // PHP handle those ones :) return $arg->value instanceof ClassConstFetch || $arg->value instanceof PropertyFetch || $arg->value instanceof Variable || $arg->value instanceof FuncCall || $arg->value instanceof MethodCall || $arg->value instanceof StaticCall || $arg->value instanceof ArrayDimFetch; } /** * Because array_multisort has a problematic signature... * * The argument order is all sorts of wonky, and whether something is passed * by reference or not depends on the values of the two arguments before it. * We'll do a good faith attempt at validating this, but err on the side of * permissive. * * This is why you don't design languages where core code and extensions can * implement APIs that wouldn't be possible in userland code. * * @throws FatalErrorException for clearly invalid arguments * * @param Node $node */ private function validateArrayMultisort(Node $node) { $nonPassable = 2; // start with 2 because the first one has to be passable by reference foreach ($node->args as $arg) { if ($this->isPassableByReference($arg)) { $nonPassable = 0; } elseif (++$nonPassable > 2) { // There can be *at most* two non-passable-by-reference args in a row. This is about // as close as we can get to validating the arguments for this function :-/ throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getStartLine()); } } } } PK������*ZIAW �� ����CodeCleaner/CalledClassPass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Expr\ConstFetch; use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Name; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\Trait_; use PhpParser\Node\VariadicPlaceholder; use Psy\Exception\ErrorException; /** * The called class pass throws warnings for get_class() and get_called_class() * outside a class context. */ class CalledClassPass extends CodeCleanerPass { private bool $inClass = false; /** * @param array $nodes * * @return Node[]|null Array of nodes */ public function beforeTraverse(array $nodes) { $this->inClass = false; } /** * @throws ErrorException if get_class or get_called_class is called without an object from outside a class * * @param Node $node * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { if ($node instanceof Class_ || $node instanceof Trait_) { $this->inClass = true; } elseif ($node instanceof FuncCall && !$this->inClass) { // We'll give any args at all (besides null) a pass. // Technically we should be checking whether the args are objects, but this will do for now. // // @todo switch this to actually validate args when we get context-aware code cleaner passes. if (!empty($node->args) && !$this->isNull($node->args[0])) { return; } // We'll ignore name expressions as well (things like `$foo()`) if (!($node->name instanceof Name)) { return; } $name = \strtolower($node->name); if (\in_array($name, ['get_class', 'get_called_class'])) { $msg = \sprintf('%s() called without object from outside a class', $name); throw new ErrorException($msg, 0, \E_USER_WARNING, null, $node->getStartLine()); } } } /** * @param Node $node * * @return int|Node|Node[]|null Replacement node (or special return value) */ public function leaveNode(Node $node) { if ($node instanceof Class_) { $this->inClass = false; } } private function isNull(Node $node): bool { if ($node instanceof VariadicPlaceholder) { return false; } return $node->value instanceof ConstFetch && \strtolower($node->value->name) === 'null'; } } PK������*ZT :������CodeCleaner/FinalClassPass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Stmt\Class_; use Psy\Exception\FatalErrorException; /** * The final class pass handles final classes. */ class FinalClassPass extends CodeCleanerPass { private array $finalClasses = []; /** * @param array $nodes * * @return Node[]|null Array of nodes */ public function beforeTraverse(array $nodes) { $this->finalClasses = []; } /** * @throws FatalErrorException if the node is a class that extends a final class * * @param Node $node * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { if ($node instanceof Class_) { if ($node->extends) { $extends = (string) $node->extends; if ($this->isFinalClass($extends)) { $msg = \sprintf('Class %s may not inherit from final class (%s)', $node->name, $extends); throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine()); } } if ($node->isFinal()) { $this->finalClasses[\strtolower($node->name)] = true; } } } /** * @param string $name Class name */ private function isFinalClass(string $name): bool { if (!\class_exists($name)) { return isset($this->finalClasses[\strtolower($name)]); } $refl = new \ReflectionClass($name); return $refl->isFinal(); } } PK������*Zj5<��<����CodeCleaner/NoReturnValue.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node\Expr\New_; use PhpParser\Node\Name\FullyQualified as FullyQualifiedName; /** * A class used internally by CodeCleaner to represent input, such as * non-expression statements, with no return value. * * Note that user code returning an instance of this class will act like it * has no return value, so you prolly shouldn't do that. */ class NoReturnValue { /** * Get PhpParser AST expression for creating a new NoReturnValue. */ public static function create(): New_ { return new New_(new FullyQualifiedName(self::class)); } } PK������*Z| ��| ��%��CodeCleaner/ValidFunctionNamePass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Stmt\Do_; use PhpParser\Node\Stmt\Function_; use PhpParser\Node\Stmt\If_; use PhpParser\Node\Stmt\Switch_; use PhpParser\Node\Stmt\While_; use Psy\Exception\FatalErrorException; /** * Validate that function calls will succeed. * * This pass throws a FatalErrorException rather than letting PHP run * headfirst into a real fatal error and die. */ class ValidFunctionNamePass extends NamespaceAwarePass { private int $conditionalScopes = 0; /** * Store newly defined function names on the way in, to allow recursion. * * @throws FatalErrorException if a function is redefined in a non-conditional scope * * @param Node $node * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $node) { parent::enterNode($node); if (self::isConditional($node)) { $this->conditionalScopes++; } elseif ($node instanceof Function_) { $name = $this->getFullyQualifiedName($node->name); // @todo add an "else" here which adds a runtime check for instances where we can't tell // whether a function is being redefined by static analysis alone. if ($this->conditionalScopes === 0) { if (\function_exists($name) || isset($this->currentScope[\strtolower($name)])) { $msg = \sprintf('Cannot redeclare %s()', $name); throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine()); } } $this->currentScope[\strtolower($name)] = true; } } /** * @param Node $node * * @return int|Node|Node[]|null Replacement node (or special return value) */ public function leaveNode(Node $node) { if (self::isConditional($node)) { $this->conditionalScopes--; } } private static function isConditional(Node $node) { return $node instanceof If_ || $node instanceof While_ || $node instanceof Do_ || $node instanceof Switch_; } } PK������*Z@Kw��w��"��CodeCleaner/ImplicitReturnPass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Expr; use PhpParser\Node\Expr\Exit_; use PhpParser\Node\Stmt; use PhpParser\Node\Stmt\Break_; use PhpParser\Node\Stmt\Expression; use PhpParser\Node\Stmt\If_; use PhpParser\Node\Stmt\Namespace_; use PhpParser\Node\Stmt\Return_; use PhpParser\Node\Stmt\Switch_; /** * Add an implicit "return" to the last statement, provided it can be returned. */ class ImplicitReturnPass extends CodeCleanerPass { /** * @param array $nodes * * @return array */ public function beforeTraverse(array $nodes): array { return $this->addImplicitReturn($nodes); } /** * @param array $nodes * * @return array */ private function addImplicitReturn(array $nodes): array { // If nodes is empty, it can't have a return value. if (empty($nodes)) { return [new Return_(NoReturnValue::create())]; } $last = \end($nodes); // Special case a few types of statements to add an implicit return // value (even though they technically don't have any return value) // because showing a return value in these instances is useful and not // very surprising. if ($last instanceof If_) { $last->stmts = $this->addImplicitReturn($last->stmts); foreach ($last->elseifs as $elseif) { $elseif->stmts = $this->addImplicitReturn($elseif->stmts); } if ($last->else) { $last->else->stmts = $this->addImplicitReturn($last->else->stmts); } } elseif ($last instanceof Switch_) { foreach ($last->cases as $case) { // only add an implicit return to cases which end in break $caseLast = \end($case->stmts); if ($caseLast instanceof Break_) { $case->stmts = $this->addImplicitReturn(\array_slice($case->stmts, 0, -1)); $case->stmts[] = $caseLast; } } } elseif ($last instanceof Expr && !($last instanceof Exit_)) { // @codeCoverageIgnoreStart $nodes[\count($nodes) - 1] = new Return_($last, [ 'startLine' => $last->getStartLine(), 'endLine' => $last->getEndLine(), ]); // @codeCoverageIgnoreEnd } elseif ($last instanceof Expression && !($last->expr instanceof Exit_)) { $nodes[\count($nodes) - 1] = new Return_($last->expr, [ 'startLine' => $last->getStartLine(), 'endLine' => $last->getEndLine(), ]); } elseif ($last instanceof Namespace_) { $last->stmts = $this->addImplicitReturn($last->stmts); } // Return a "no return value" for all non-expression statements, so that // PsySH can suppress the `null` that `eval()` returns otherwise. // // Note that statements special cased above (if/elseif/else, switch) // _might_ implicitly return a value before this catch-all return is // reached. // // We're not adding a fallback return after namespace statements, // because code outside namespace statements doesn't really work, and // there's already an implicit return in the namespace statement anyway. if (self::isNonExpressionStmt($last)) { $nodes[] = new Return_(NoReturnValue::create()); } return $nodes; } /** * Check whether a given node is a non-expression statement. * * As of PHP Parser 4.x, Expressions are now instances of Stmt as well, so * we'll exclude them here. * * @param Node $node */ private static function isNonExpressionStmt(Node $node): bool { return $node instanceof Stmt && !$node instanceof Expression && !$node instanceof Return_ && !$node instanceof Namespace_; } } PK������*Z #��#����CodeCleaner/RequirePass.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\CodeCleaner; use PhpParser\Node; use PhpParser\Node\Arg; use PhpParser\Node\Expr\Include_; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Name\FullyQualified as FullyQualifiedName; use PhpParser\Node\Scalar\Int_; use PhpParser\Node\Scalar\LNumber; use Psy\Exception\ErrorException; use Psy\Exception\FatalErrorException; /** * Add runtime validation for `require` and `require_once` calls. */ class RequirePass extends CodeCleanerPass { private const REQUIRE_TYPES = [Include_::TYPE_REQUIRE, Include_::TYPE_REQUIRE_ONCE]; /** * {@inheritdoc} * * @return int|Node|null Replacement node (or special return value) */ public function enterNode(Node $origNode) { if (!$this->isRequireNode($origNode)) { return; } $node = clone $origNode; /* * rewrite * * $foo = require $bar * * to * * $foo = require \Psy\CodeCleaner\RequirePass::resolve($bar) */ // @todo Remove LNumber once we drop support for PHP-Parser 4.x $arg = \class_exists('PhpParser\Node\Scalar\Int_') ? new Int_($origNode->getStartLine()) : new LNumber($origNode->getStartLine()); $node->expr = new StaticCall( new FullyQualifiedName(self::class), 'resolve', [new Arg($origNode->expr), new Arg($arg)], $origNode->getAttributes() ); return $node; } /** * Runtime validation that $file can be resolved as an include path. * * If $file can be resolved, return $file. Otherwise throw a fatal error exception. * * If $file collides with a path in the currently running PsySH phar, it will be resolved * relative to the include path, to prevent PHP from grabbing the phar version of the file. * * @throws FatalErrorException when unable to resolve include path for $file * @throws ErrorException if $file is empty and E_WARNING is included in error_reporting level * * @param string $file * @param int $startLine Line number of the original require expression * * @return string Exactly the same as $file, unless $file collides with a path in the currently running phar */ public static function resolve($file, $startLine = null): string { $file = (string) $file; if ($file === '') { // @todo Shell::handleError would be better here, because we could // fake the file and line number, but we can't call it statically. // So we're duplicating some of the logics here. if (\E_WARNING & \error_reporting()) { ErrorException::throwException(\E_WARNING, 'Filename cannot be empty', null, $startLine); } // @todo trigger an error as fallback? this is pretty ugly… // trigger_error('Filename cannot be empty', E_USER_WARNING); } $resolvedPath = \stream_resolve_include_path($file); if ($file === '' || !$resolvedPath) { $msg = \sprintf("Failed opening required '%s'", $file); throw new FatalErrorException($msg, 0, \E_ERROR, null, $startLine); } // Special case: if the path is not already relative or absolute, and it would resolve to // something inside the currently running phar (e.g. `vendor/autoload.php`), we'll resolve // it relative to the include path so PHP won't grab the phar version. // // Note that this only works if the phar has `psysh` in the path. We might want to lift this // restriction and special case paths that would collide with any running phar? if ($resolvedPath !== $file && $file[0] !== '.') { $runningPhar = \Phar::running(); if (\strpos($runningPhar, 'psysh') !== false && \is_file($runningPhar.\DIRECTORY_SEPARATOR.$file)) { foreach (self::getIncludePath() as $prefix) { $resolvedPath = $prefix.\DIRECTORY_SEPARATOR.$file; if (\is_file($resolvedPath)) { return $resolvedPath; } } } } return $file; } private function isRequireNode(Node $node): bool { return $node instanceof Include_ && \in_array($node->type, self::REQUIRE_TYPES); } private static function getIncludePath(): array { if (\PATH_SEPARATOR === ':') { return \preg_split('#:(?!//)#', \get_include_path()); } return \explode(\PATH_SEPARATOR, \get_include_path()); } } PK������*ZFq��q�� ��Util/Json.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Util; /** * A static class to wrap JSON encoding/decoding with PsySH's default options. */ class Json { /** * Encode a value as JSON. * * @param mixed $val * @param int $opt */ public static function encode($val, int $opt = 0): string { $opt |= \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE; return \json_encode($val, $opt); } } PK������*ZRj������Util/Mirror.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Util; use Psy\Exception\RuntimeException; use Psy\Reflection\ReflectionConstant; use Psy\Reflection\ReflectionNamespace; /** * A utility class for getting Reflectors. */ class Mirror { const CONSTANT = 1; const METHOD = 2; const STATIC_PROPERTY = 4; const PROPERTY = 8; /** * Get a Reflector for a function, class or instance, constant, method or property. * * Optionally, pass a $filter param to restrict the types of members checked. For example, to only Reflectors for * static properties and constants, pass: * * $filter = Mirror::CONSTANT | Mirror::STATIC_PROPERTY * * @throws \Psy\Exception\RuntimeException when a $member specified but not present on $value * @throws \InvalidArgumentException if $value is something other than an object or class/function name * * @param mixed $value Class or function name, or variable instance * @param string $member Optional: property, constant or method name (default: null) * @param int $filter (default: CONSTANT | METHOD | PROPERTY | STATIC_PROPERTY) * * @return \Reflector */ public static function get($value, ?string $member = null, int $filter = 15): \Reflector { if ($member === null && \is_string($value)) { if (\function_exists($value)) { return new \ReflectionFunction($value); } elseif (\defined($value) || ReflectionConstant::isMagicConstant($value)) { return new ReflectionConstant($value); } } $class = self::getClass($value); if ($member === null) { return $class; } elseif ($filter & self::CONSTANT && $class->hasConstant($member)) { return new \ReflectionClassConstant($value, $member); } elseif ($filter & self::METHOD && $class->hasMethod($member)) { return $class->getMethod($member); } elseif ($filter & self::PROPERTY && $class->hasProperty($member)) { return $class->getProperty($member); } elseif ($filter & self::STATIC_PROPERTY && $class->hasProperty($member) && $class->getProperty($member)->isStatic()) { return $class->getProperty($member); } else { throw new RuntimeException(\sprintf('Unknown member %s on class %s', $member, \is_object($value) ? \get_class($value) : $value)); } } /** * Get a ReflectionClass (or ReflectionObject, or ReflectionNamespace) if possible. * * @throws \InvalidArgumentException if $value is not a namespace or class name or instance * * @param mixed $value * * @return \ReflectionClass|ReflectionNamespace */ private static function getClass($value) { if (\is_object($value)) { return new \ReflectionObject($value); } if (!\is_string($value)) { throw new \InvalidArgumentException('Mirror expects an object or class'); } if (\class_exists($value) || \interface_exists($value) || \trait_exists($value)) { return new \ReflectionClass($value); } $namespace = \preg_replace('/(^\\\\|\\\\$)/', '', $value); if (self::namespaceExists($namespace)) { return new ReflectionNamespace($namespace); } throw new \InvalidArgumentException('Unknown namespace, class or function: '.$value); } /** * Check declared namespaces for a given namespace. */ private static function namespaceExists(string $value): bool { return \in_array(\strtolower($value), self::getDeclaredNamespaces()); } /** * Get an array of all currently declared namespaces. * * Note that this relies on at least one function, class, interface, trait * or constant to have been declared in that namespace. */ private static function getDeclaredNamespaces(): array { $functions = \get_defined_functions(); $allNames = \array_merge( $functions['internal'], $functions['user'], \get_declared_classes(), \get_declared_interfaces(), \get_declared_traits(), \array_keys(\get_defined_constants()) ); $namespaces = []; foreach ($allNames as $name) { $chunks = \explode('\\', \strtolower($name)); // the last one is the function or class or whatever... \array_pop($chunks); while (!empty($chunks)) { $namespaces[\implode('\\', $chunks)] = true; \array_pop($chunks); } } $namespaceNames = \array_keys($namespaces); \sort($namespaceNames); return $namespaceNames; } } PK������*ZW<��<����Util/Docblock.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Util; /** * A docblock representation. * * Based on PHP-DocBlock-Parser by Paul Scott: * * {@link http://www.github.com/icio/PHP-DocBlock-Parser} * * @author Paul Scott <paul@duedil.com> * @author Justin Hileman <justin@justinhileman.info> */ class Docblock { /** * Tags in the docblock that have a whitespace-delimited number of parameters * (such as `@param type var desc` and `@return type desc`) and the names of * those parameters. * * @var array */ public static $vectors = [ 'throws' => ['type', 'desc'], 'param' => ['type', 'var', 'desc'], 'return' => ['type', 'desc'], ]; protected $reflector; /** * The description of the symbol. * * @var string */ public $desc; /** * The tags defined in the docblock. * * The array has keys which are the tag names (excluding the @) and values * that are arrays, each of which is an entry for the tag. * * In the case where the tag name is defined in {@see DocBlock::$vectors} the * value within the tag-value array is an array in itself with keys as * described by {@see DocBlock::$vectors}. * * @var array */ public $tags; /** * The entire DocBlock comment that was parsed. * * @var string */ public $comment; /** * Docblock constructor. * * @param \Reflector $reflector */ public function __construct(\Reflector $reflector) { $this->reflector = $reflector; if ($reflector instanceof \ReflectionClass || $reflector instanceof \ReflectionClassConstant || $reflector instanceof \ReflectionFunctionAbstract || $reflector instanceof \ReflectionProperty) { $this->setComment($reflector->getDocComment()); } } /** * Set and parse the docblock comment. * * @param string $comment The docblock */ protected function setComment(string $comment) { $this->desc = ''; $this->tags = []; $this->comment = $comment; $this->parseComment($comment); } /** * Find the length of the docblock prefix. * * @param array $lines * * @return int Prefix length */ protected static function prefixLength(array $lines): int { // find only lines with interesting things $lines = \array_filter($lines, function ($line) { return \substr($line, \strspn($line, "* \t\n\r\0\x0B")); }); // if we sort the lines, we only have to compare two items \sort($lines); $first = \reset($lines); $last = \end($lines); // Special case for single-line comments if (\count($lines) === 1) { return \strspn($first, "* \t\n\r\0\x0B"); } // find the longest common substring $count = \min(\strlen($first), \strlen($last)); for ($i = 0; $i < $count; $i++) { if ($first[$i] !== $last[$i]) { return $i; } } return $count; } /** * Parse the comment into the component parts and set the state of the object. * * @param string $comment The docblock */ protected function parseComment(string $comment) { // Strip the opening and closing tags of the docblock $comment = \substr($comment, 3, -2); // Split into arrays of lines $comment = \array_filter(\preg_split('/\r?\n\r?/', $comment)); // Trim asterisks and whitespace from the beginning and whitespace from the end of lines $prefixLength = self::prefixLength($comment); $comment = \array_map(function ($line) use ($prefixLength) { return \rtrim(\substr($line, $prefixLength)); }, $comment); // Group the lines together by @tags $blocks = []; $b = -1; foreach ($comment as $line) { if (self::isTagged($line)) { $b++; $blocks[] = []; } elseif ($b === -1) { $b = 0; $blocks[] = []; } $blocks[$b][] = $line; } // Parse the blocks foreach ($blocks as $block => $body) { $body = \trim(\implode("\n", $body)); if ($block === 0 && !self::isTagged($body)) { // This is the description block $this->desc = $body; } else { // This block is tagged $tag = \substr(self::strTag($body), 1); $body = \ltrim(\substr($body, \strlen($tag) + 2)); if (isset(self::$vectors[$tag])) { // The tagged block is a vector $count = \count(self::$vectors[$tag]); if ($body) { $parts = \preg_split('/\s+/', $body, $count); } else { $parts = []; } // Default the trailing values $parts = \array_pad($parts, $count, null); // Store as a mapped array $this->tags[$tag][] = \array_combine(self::$vectors[$tag], $parts); } else { // The tagged block is only text $this->tags[$tag][] = $body; } } } } /** * Whether or not a docblock contains a given @tag. * * @param string $tag The name of the @tag to check for */ public function hasTag(string $tag): bool { return \is_array($this->tags) && \array_key_exists($tag, $this->tags); } /** * The value of a tag. * * @param string $tag * * @return array|null */ public function tag(string $tag): ?array { return $this->hasTag($tag) ? $this->tags[$tag] : null; } /** * Whether or not a string begins with a @tag. * * @param string $str */ public static function isTagged(string $str): bool { return isset($str[1]) && $str[0] === '@' && !\preg_match('/[^A-Za-z]/', $str[1]); } /** * The tag at the beginning of a string. * * @param string $str * * @return string|null */ public static function strTag(string $str) { if (\preg_match('/^@[a-z0-9_]+/', $str, $matches)) { return $matches[0]; } } } PK������*Zژ �� �� ��Util/Str.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Util; use GrahamCampbell\ResultType\Error; use GrahamCampbell\ResultType\Success; use PhpOption\Option; /** * @internal */ final class Str { /** * This class is a singleton. * * @codeCoverageIgnore * * @return void */ private function __construct() { // } /** * Convert a string to UTF-8 from the given encoding. * * @param string $input * @param string|null $encoding * * @return \GrahamCampbell\ResultType\Result<string,string> */ public static function utf8(string $input, ?string $encoding = null) { if ($encoding !== null && !\in_array($encoding, \mb_list_encodings(), true)) { /** @var \GrahamCampbell\ResultType\Result<string,string> */ return Error::create( \sprintf('Illegal character encoding [%s] specified.', $encoding) ); } $converted = $encoding === null ? @\mb_convert_encoding($input, 'UTF-8') : @\mb_convert_encoding($input, 'UTF-8', $encoding); /** * this is for support UTF-8 with BOM encoding * @see https://en.wikipedia.org/wiki/Byte_order_mark * @see https://github.com/vlucas/phpdotenv/issues/500 */ if (\substr($converted, 0, 3) == "\xEF\xBB\xBF") { $converted = \substr($converted, 3); } /** @var \GrahamCampbell\ResultType\Result<string,string> */ return Success::create($converted); } /** * Search for a given substring of the input. * * @param string $haystack * @param string $needle * * @return \PhpOption\Option<int> */ public static function pos(string $haystack, string $needle) { /** @var \PhpOption\Option<int> */ return Option::fromValue(\mb_strpos($haystack, $needle, 0, 'UTF-8'), false); } /** * Grab the specified substring of the input. * * @param string $input * @param int $start * @param int|null $length * * @return string */ public static function substr(string $input, int $start, ?int $length = null) { return \mb_substr($input, $start, $length, 'UTF-8'); } /** * Compute the length of the given string. * * @param string $input * * @return int */ public static function len(string $input) { return \mb_strlen($input, 'UTF-8'); } } PK������*ZFtl��l����SuperglobalsEnv.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy; /** * Environment variables implementation via $_SERVER superglobal. */ class SuperglobalsEnv implements EnvInterface { /** * Get an environment variable by name. * * @return string|null */ public function get(string $key) { if (isset($_SERVER[$key]) && $_SERVER[$key]) { return $_SERVER[$key]; } return null; } } PK������*ZʤSc3��3����Formatter/DocblockFormatter.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Formatter; use Psy\Util\Docblock; use Symfony\Component\Console\Formatter\OutputFormatter; /** * A pretty-printer for docblocks. */ class DocblockFormatter implements ReflectorFormatter { private const VECTOR_PARAM_TEMPLATES = [ 'type' => 'info', 'var' => 'strong', ]; /** * Format a docblock. * * @param \Reflector $reflector * * @return string Formatted docblock */ public static function format(\Reflector $reflector): string { $docblock = new Docblock($reflector); $chunks = []; if (!empty($docblock->desc)) { $chunks[] = '<comment>Description:</comment>'; $chunks[] = self::indent(OutputFormatter::escape($docblock->desc), ' '); $chunks[] = ''; } if (!empty($docblock->tags)) { foreach ($docblock::$vectors as $name => $vector) { if (isset($docblock->tags[$name])) { $chunks[] = \sprintf('<comment>%s:</comment>', self::inflect($name)); $chunks[] = self::formatVector($vector, $docblock->tags[$name]); $chunks[] = ''; } } $tags = self::formatTags(\array_keys($docblock::$vectors), $docblock->tags); if (!empty($tags)) { $chunks[] = $tags; $chunks[] = ''; } } return \rtrim(\implode("\n", $chunks)); } /** * Format a docblock vector, for example, `@throws`, `@param`, or `@return`. * * @see DocBlock::$vectors * * @param array $vector * @param array $lines */ private static function formatVector(array $vector, array $lines): string { $template = [' ']; foreach ($vector as $type) { $max = 0; foreach ($lines as $line) { $chunk = $line[$type]; $cur = empty($chunk) ? 0 : \strlen($chunk) + 1; if ($cur > $max) { $max = $cur; } } $template[] = self::getVectorParamTemplate($type, $max); } $template = \implode(' ', $template); return \implode("\n", \array_map(function ($line) use ($template) { $escaped = \array_map(function ($l) { if ($l === null) { return ''; } return OutputFormatter::escape($l); }, $line); return \rtrim(\vsprintf($template, $escaped)); }, $lines)); } /** * Format docblock tags. * * @param array $skip Tags to exclude * @param array $tags Tags to format * * @return string formatted tags */ private static function formatTags(array $skip, array $tags): string { $chunks = []; foreach ($tags as $name => $values) { if (\in_array($name, $skip)) { continue; } foreach ($values as $value) { $chunks[] = \sprintf('<comment>%s%s</comment> %s', self::inflect($name), empty($value) ? '' : ':', OutputFormatter::escape($value)); } $chunks[] = ''; } return \implode("\n", $chunks); } /** * Get a docblock vector template. * * @param string $type Vector type * @param int $max Pad width */ private static function getVectorParamTemplate(string $type, int $max): string { if (!isset(self::VECTOR_PARAM_TEMPLATES[$type])) { return \sprintf('%%-%ds', $max); } return \sprintf('<%s>%%-%ds</%s>', self::VECTOR_PARAM_TEMPLATES[$type], $max, self::VECTOR_PARAM_TEMPLATES[$type]); } /** * Indent a string. * * @param string $text String to indent * @param string $indent (default: ' ') */ private static function indent(string $text, string $indent = ' '): string { return $indent.\str_replace("\n", "\n".$indent, $text); } /** * Convert underscored or whitespace separated words into sentence case. * * @param string $text */ private static function inflect(string $text): string { $words = \trim(\preg_replace('/[\s_-]+/', ' ', \preg_replace('/([a-z])([A-Z])/', '$1 $2', $text))); return \implode(' ', \array_map('ucfirst', \explode(' ', $words))); } } PK������*Z~ '�� '����Formatter/CodeFormatter.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Formatter; use Psy\Exception\RuntimeException; use Symfony\Component\Console\Formatter\OutputFormatter; /** * A pretty-printer for code. */ class CodeFormatter implements ReflectorFormatter { const LINE_MARKER = ' <urgent>></urgent> '; const NO_LINE_MARKER = ' '; const HIGHLIGHT_DEFAULT = 'default'; const HIGHLIGHT_KEYWORD = 'keyword'; const HIGHLIGHT_PUBLIC = 'public'; const HIGHLIGHT_PROTECTED = 'protected'; const HIGHLIGHT_PRIVATE = 'private'; const HIGHLIGHT_CONST = 'const'; const HIGHLIGHT_NUMBER = 'number'; const HIGHLIGHT_STRING = 'string'; const HIGHLIGHT_COMMENT = 'code_comment'; const HIGHLIGHT_INLINE_HTML = 'inline_html'; private const TOKEN_MAP = [ // Not highlighted \T_OPEN_TAG => self::HIGHLIGHT_DEFAULT, \T_OPEN_TAG_WITH_ECHO => self::HIGHLIGHT_DEFAULT, \T_CLOSE_TAG => self::HIGHLIGHT_DEFAULT, \T_STRING => self::HIGHLIGHT_DEFAULT, \T_VARIABLE => self::HIGHLIGHT_DEFAULT, \T_NS_SEPARATOR => self::HIGHLIGHT_DEFAULT, // Visibility \T_PUBLIC => self::HIGHLIGHT_PUBLIC, \T_PROTECTED => self::HIGHLIGHT_PROTECTED, \T_PRIVATE => self::HIGHLIGHT_PRIVATE, // Constants \T_DIR => self::HIGHLIGHT_CONST, \T_FILE => self::HIGHLIGHT_CONST, \T_METHOD_C => self::HIGHLIGHT_CONST, \T_NS_C => self::HIGHLIGHT_CONST, \T_LINE => self::HIGHLIGHT_CONST, \T_CLASS_C => self::HIGHLIGHT_CONST, \T_FUNC_C => self::HIGHLIGHT_CONST, \T_TRAIT_C => self::HIGHLIGHT_CONST, // Types \T_DNUMBER => self::HIGHLIGHT_NUMBER, \T_LNUMBER => self::HIGHLIGHT_NUMBER, \T_ENCAPSED_AND_WHITESPACE => self::HIGHLIGHT_STRING, \T_CONSTANT_ENCAPSED_STRING => self::HIGHLIGHT_STRING, // Comments \T_COMMENT => self::HIGHLIGHT_COMMENT, \T_DOC_COMMENT => self::HIGHLIGHT_COMMENT, // @todo something better here? \T_INLINE_HTML => self::HIGHLIGHT_INLINE_HTML, ]; /** * Format the code represented by $reflector for shell output. * * @param \Reflector $reflector * * @return string formatted code */ public static function format(\Reflector $reflector): string { if (self::isReflectable($reflector)) { if ($code = @\file_get_contents($reflector->getFileName())) { return self::formatCode($code, self::getStartLine($reflector), $reflector->getEndLine()); } } throw new RuntimeException('Source code unavailable'); } /** * Format code for shell output. * * Optionally, restrict by $startLine and $endLine line numbers, or pass $markLine to add a line marker. * * @param string $code * @param int $startLine * @param int|null $endLine * @param int|null $markLine * * @return string formatted code */ public static function formatCode(string $code, int $startLine = 1, ?int $endLine = null, ?int $markLine = null): string { $spans = self::tokenizeSpans($code); $lines = self::splitLines($spans, $startLine, $endLine); $lines = self::formatLines($lines); $lines = self::numberLines($lines, $markLine); return \implode('', \iterator_to_array($lines)); } /** * Get the start line for a given Reflector. * * Tries to incorporate doc comments if possible. * * This is typehinted as \Reflector but we've narrowed the input via self::isReflectable already. * * @param \ReflectionClass|\ReflectionFunctionAbstract $reflector */ private static function getStartLine(\Reflector $reflector): int { $startLine = $reflector->getStartLine(); if ($docComment = $reflector->getDocComment()) { $startLine -= \preg_match_all('/(\r\n?|\n)/', $docComment) + 1; } return \max($startLine, 1); } /** * Split code into highlight spans. * * Tokenize via \token_get_all, then map these tokens to internal highlight types, combining * adjacent spans of the same highlight type. * * @todo consider switching \token_get_all() out for PHP-Parser-based formatting at some point. * * @param string $code * * @return \Generator [$spanType, $spanText] highlight spans */ private static function tokenizeSpans(string $code): \Generator { $spanType = null; $buffer = ''; foreach (\token_get_all($code) as $token) { $nextType = self::nextHighlightType($token, $spanType); $spanType = $spanType ?: $nextType; if ($spanType !== $nextType) { yield [$spanType, $buffer]; $spanType = $nextType; $buffer = ''; } $buffer .= \is_array($token) ? $token[1] : $token; } if ($spanType !== null && $buffer !== '') { yield [$spanType, $buffer]; } } /** * Given a token and the current highlight span type, compute the next type. * * @param array|string $token \token_get_all token * @param string|null $currentType * * @return string|null */ private static function nextHighlightType($token, $currentType) { if ($token === '"') { return self::HIGHLIGHT_STRING; } if (\is_array($token)) { if ($token[0] === \T_WHITESPACE) { return $currentType; } if (\array_key_exists($token[0], self::TOKEN_MAP)) { return self::TOKEN_MAP[$token[0]]; } } return self::HIGHLIGHT_KEYWORD; } /** * Group highlight spans into an array of lines. * * Optionally, restrict by start and end line numbers. * * @param \Generator $spans as [$spanType, $spanText] pairs * @param int $startLine * @param int|null $endLine * * @return \Generator lines, each an array of [$spanType, $spanText] pairs */ private static function splitLines(\Generator $spans, int $startLine = 1, ?int $endLine = null): \Generator { $lineNum = 1; $buffer = []; foreach ($spans as list($spanType, $spanText)) { foreach (\preg_split('/(\r\n?|\n)/', $spanText) as $index => $spanLine) { if ($index > 0) { if ($lineNum >= $startLine) { yield $lineNum => $buffer; } $lineNum++; $buffer = []; if ($endLine !== null && $lineNum > $endLine) { return; } } if ($spanLine !== '') { $buffer[] = [$spanType, $spanLine]; } } } if (!empty($buffer)) { yield $lineNum => $buffer; } } /** * Format lines of highlight spans for shell output. * * @param \Generator $spanLines lines, each an array of [$spanType, $spanText] pairs * * @return \Generator Formatted lines */ private static function formatLines(\Generator $spanLines): \Generator { foreach ($spanLines as $lineNum => $spanLine) { $line = ''; foreach ($spanLine as list($spanType, $spanText)) { if ($spanType === self::HIGHLIGHT_DEFAULT) { $line .= OutputFormatter::escape($spanText); } else { $line .= \sprintf('<%s>%s</%s>', $spanType, OutputFormatter::escape($spanText), $spanType); } } yield $lineNum => $line.\PHP_EOL; } } /** * Prepend line numbers to formatted lines. * * Lines must be in an associative array with the correct keys in order to be numbered properly. * * Optionally, pass $markLine to add a line marker. * * @param \Generator $lines Formatted lines * @param int|null $markLine * * @return \Generator Numbered, formatted lines */ private static function numberLines(\Generator $lines, ?int $markLine = null): \Generator { $lines = \iterator_to_array($lines); // Figure out how much space to reserve for line numbers. \end($lines); $pad = \strlen(\key($lines)); // If $markLine is before or after our line range, don't bother reserving space for the marker. if ($markLine !== null) { if ($markLine > \key($lines)) { $markLine = null; } \reset($lines); if ($markLine < \key($lines)) { $markLine = null; } } foreach ($lines as $lineNum => $line) { $mark = ''; if ($markLine !== null) { $mark = ($markLine === $lineNum) ? self::LINE_MARKER : self::NO_LINE_MARKER; } yield \sprintf("%s<aside>%{$pad}s</aside>: %s", $mark, $lineNum, $line); } } /** * Check whether a Reflector instance is reflectable by this formatter. * * @phpstan-assert-if-true \ReflectionClass|\ReflectionFunctionAbstract $reflector * * @param \Reflector $reflector */ private static function isReflectable(\Reflector $reflector): bool { return ($reflector instanceof \ReflectionClass || $reflector instanceof \ReflectionFunctionAbstract) && \is_file($reflector->getFileName()); } } PK������*Zȑd,��,�� ��Formatter/SignatureFormatter.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Formatter; use Psy\Reflection\ReflectionConstant; use Psy\Reflection\ReflectionLanguageConstruct; use Psy\Util\Json; use Symfony\Component\Console\Formatter\OutputFormatter; /** * An abstract representation of a function, class or property signature. */ class SignatureFormatter implements ReflectorFormatter { /** * Format a signature for the given reflector. * * Defers to subclasses to do the actual formatting. * * @param \Reflector $reflector * * @return string Formatted signature */ public static function format(\Reflector $reflector): string { switch (true) { case $reflector instanceof \ReflectionFunction: case $reflector instanceof ReflectionLanguageConstruct: return self::formatFunction($reflector); case $reflector instanceof \ReflectionClass: // this case also covers \ReflectionObject return self::formatClass($reflector); case $reflector instanceof \ReflectionClassConstant: return self::formatClassConstant($reflector); case $reflector instanceof \ReflectionMethod: return self::formatMethod($reflector); case $reflector instanceof \ReflectionProperty: return self::formatProperty($reflector); case $reflector instanceof ReflectionConstant: return self::formatConstant($reflector); default: throw new \InvalidArgumentException('Unexpected Reflector class: '.\get_class($reflector)); } } /** * Print the signature name. * * @param \ReflectionClass|\ReflectionClassConstant|\ReflectionFunctionAbstract $reflector * * @return string Formatted name */ public static function formatName(\Reflector $reflector): string { return $reflector->getName(); } /** * Print the method, property or class modifiers. * * @param \ReflectionMethod|\ReflectionProperty|\ReflectionClass $reflector * * @return string Formatted modifiers */ private static function formatModifiers(\Reflector $reflector): string { return \implode(' ', \array_map(function ($modifier) { return \sprintf('<keyword>%s</keyword>', $modifier); }, \Reflection::getModifierNames($reflector->getModifiers()))); } /** * Format a class signature. * * @param \ReflectionClass $reflector * * @return string Formatted signature */ private static function formatClass(\ReflectionClass $reflector): string { $chunks = []; if ($modifiers = self::formatModifiers($reflector)) { $chunks[] = $modifiers; } if ($reflector->isTrait()) { $chunks[] = 'trait'; } else { $chunks[] = $reflector->isInterface() ? 'interface' : 'class'; } $chunks[] = \sprintf('<class>%s</class>', self::formatName($reflector)); if ($parent = $reflector->getParentClass()) { $chunks[] = 'extends'; $chunks[] = \sprintf('<class>%s</class>', $parent->getName()); } $interfaces = $reflector->getInterfaceNames(); if (!empty($interfaces)) { \sort($interfaces); $chunks[] = $reflector->isInterface() ? 'extends' : 'implements'; $chunks[] = \implode(', ', \array_map(function ($name) { return \sprintf('<class>%s</class>', $name); }, $interfaces)); } return \implode(' ', $chunks); } /** * Format a constant signature. * * @param \ReflectionClassConstant $reflector * * @return string Formatted signature */ private static function formatClassConstant($reflector): string { $value = $reflector->getValue(); $style = self::getTypeStyle($value); return \sprintf( '<keyword>const</keyword> <const>%s</const> = <%s>%s</%s>', self::formatName($reflector), $style, OutputFormatter::escape(Json::encode($value)), $style ); } /** * Format a constant signature. * * @param ReflectionConstant $reflector * * @return string Formatted signature */ private static function formatConstant(ReflectionConstant $reflector): string { $value = $reflector->getValue(); $style = self::getTypeStyle($value); return \sprintf( '<keyword>define</keyword>(<string>%s</string>, <%s>%s</%s>)', OutputFormatter::escape(Json::encode($reflector->getName())), $style, OutputFormatter::escape(Json::encode($value)), $style ); } /** * Helper for getting output style for a given value's type. * * @param mixed $value */ private static function getTypeStyle($value): string { if (\is_int($value) || \is_float($value)) { return 'number'; } elseif (\is_string($value)) { return 'string'; } elseif (\is_bool($value) || $value === null) { return 'bool'; } else { return 'strong'; // @codeCoverageIgnore } } /** * Format a property signature. * * @param \ReflectionProperty $reflector * * @return string Formatted signature */ private static function formatProperty(\ReflectionProperty $reflector): string { return \sprintf( '%s <strong>$%s</strong>', self::formatModifiers($reflector), $reflector->getName() ); } /** * Format a function signature. * * @param \ReflectionFunction $reflector * * @return string Formatted signature */ private static function formatFunction(\ReflectionFunctionAbstract $reflector): string { return \sprintf( '<keyword>function</keyword> %s<function>%s</function>(%s)%s', $reflector->returnsReference() ? '&' : '', self::formatName($reflector), \implode(', ', self::formatFunctionParams($reflector)), self::formatFunctionReturnType($reflector) ); } /** * Format a function signature's return type (if available). * * @param \ReflectionFunctionAbstract $reflector * * @return string Formatted return type */ private static function formatFunctionReturnType(\ReflectionFunctionAbstract $reflector): string { if (!\method_exists($reflector, 'hasReturnType') || !$reflector->hasReturnType()) { return ''; } return \sprintf(': %s', self::formatReflectionType($reflector->getReturnType(), true)); } /** * Format a method signature. * * @param \ReflectionMethod $reflector * * @return string Formatted signature */ private static function formatMethod(\ReflectionMethod $reflector): string { return \sprintf( '%s %s', self::formatModifiers($reflector), self::formatFunction($reflector) ); } /** * Print the function params. * * @param \ReflectionFunctionAbstract $reflector * * @return array */ private static function formatFunctionParams(\ReflectionFunctionAbstract $reflector): array { $params = []; foreach ($reflector->getParameters() as $param) { $hint = ''; try { if (\method_exists($param, 'getType')) { // Only include the inquisitive nullable type iff param default value is not null. $defaultIsNull = $param->isOptional() && $param->isDefaultValueAvailable() && $param->getDefaultValue() === null; $hint = self::formatReflectionType($param->getType(), !$defaultIsNull); } else { if ($param->isArray()) { $hint = '<keyword>array</keyword>'; } elseif ($class = $param->getClass()) { $hint = \sprintf('<class>%s</class>', $class->getName()); } } } catch (\Throwable $e) { // sometimes we just don't know... // bad class names, or autoloaded classes that haven't been loaded yet, or whathaveyou. // come to think of it, the only time I've seen this is with the intl extension. // Hax: we'll try to extract it :P // @codeCoverageIgnoreStart $chunks = \explode('$'.$param->getName(), (string) $param); $chunks = \explode(' ', \trim($chunks[0])); $guess = \end($chunks); $hint = \sprintf('<urgent>%s</urgent>', OutputFormatter::escape($guess)); // @codeCoverageIgnoreEnd } if ($param->isOptional()) { if (!$param->isDefaultValueAvailable()) { $value = 'unknown'; $typeStyle = 'urgent'; } else { $value = $param->getDefaultValue(); $typeStyle = self::getTypeStyle($value); $value = \is_array($value) ? '[]' : ($value === null ? 'null' : \var_export($value, true)); } $default = \sprintf(' = <%s>%s</%s>', $typeStyle, OutputFormatter::escape($value), $typeStyle); } else { $default = ''; } $params[] = \sprintf( '%s%s%s<strong>$%s</strong>%s', $param->isPassedByReference() ? '&' : '', $hint, $hint !== '' ? ' ' : '', $param->getName(), $default ); } return $params; } /** * Print function param or return type(s). * * @param \ReflectionType $type */ private static function formatReflectionType(?\ReflectionType $type, bool $indicateNullable): string { if ($type === null) { return ''; } if ($type instanceof \ReflectionUnionType) { $delimeter = '|'; } elseif ($type instanceof \ReflectionIntersectionType) { $delimeter = '&'; } else { return self::formatReflectionNamedType($type, $indicateNullable); } $formattedTypes = []; foreach ($type->getTypes() as $namedType) { $formattedTypes[] = self::formatReflectionNamedType($namedType, $indicateNullable); } return \implode($delimeter, $formattedTypes); } /** * Print a single named type. */ private static function formatReflectionNamedType(\ReflectionNamedType $type, bool $indicateNullable): string { $typeStyle = $type->isBuiltin() ? 'keyword' : 'class'; $nullable = $indicateNullable && $type->allowsNull() ? '?' : ''; return \sprintf('<%s>%s%s</%s>', $typeStyle, $nullable, OutputFormatter::escape($type->getName()), $typeStyle); } } PK������*Zqy]���� ��Formatter/ReflectorFormatter.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Formatter; /** * Reflector formatter interface. */ interface ReflectorFormatter { /** * @param \Reflector $reflector */ public static function format(\Reflector $reflector): string; } PK������*Z �� ����Formatter/TraceFormatter.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy\Formatter; use Psy\Input\FilterOptions; use Symfony\Component\Console\Formatter\OutputFormatter; /** * Output formatter for exception traces. */ class TraceFormatter { /** * Format the trace of the given exception. * * @param \Throwable $throwable The error or exception with a backtrace * @param FilterOptions $filter (default: null) * @param int $count (default: PHP_INT_MAX) * @param bool $includePsy (default: true) * * @return string[] Formatted stacktrace lines */ public static function formatTrace(\Throwable $throwable, ?FilterOptions $filter = null, ?int $count = null, bool $includePsy = true): array { if ($cwd = \getcwd()) { $cwd = \rtrim($cwd, \DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR; } if ($count === null) { $count = \PHP_INT_MAX; } $lines = []; $trace = $throwable->getTrace(); \array_unshift($trace, [ 'function' => '', 'file' => $throwable->getFile() !== null ? $throwable->getFile() : 'n/a', 'line' => $throwable->getLine() !== null ? $throwable->getLine() : 'n/a', 'args' => [], ]); if (!$includePsy) { for ($i = \count($trace) - 1; $i >= 0; $i--) { $thing = isset($trace[$i]['class']) ? $trace[$i]['class'] : $trace[$i]['function']; if (\preg_match('/\\\\?Psy\\\\/', $thing)) { $trace = \array_slice($trace, $i + 1); break; } } } for ($i = 0, $count = \min($count, \count($trace)); $i < $count; $i++) { $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : ''; $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : ''; $function = $trace[$i]['function']; $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a'; $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a'; // Make file paths relative to cwd if ($cwd !== false) { $file = \preg_replace('/^'.\preg_quote($cwd, '/').'/', '', $file); } // Leave execution loop out of the `eval()'d code` lines if (\preg_match("#/src/Execution(?:Loop)?Closure.php\(\d+\) : eval\(\)'d code$#", \str_replace('\\', '/', $file))) { $file = "eval()'d code"; } // Skip any lines that don't match our filter options if ($filter !== null && !$filter->match(\sprintf('%s%s%s() at %s:%s', $class, $type, $function, $file, $line))) { continue; } $lines[] = \sprintf( ' <class>%s</class>%s%s() at <info>%s:%s</info>', OutputFormatter::escape($class), OutputFormatter::escape($type), OutputFormatter::escape($function), OutputFormatter::escape($file), OutputFormatter::escape($line) ); } return $lines; } } PK������*Zș���� ��Shell.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy; use Psy\CodeCleaner\NoReturnValue; use Psy\Exception\BreakException; use Psy\Exception\ErrorException; use Psy\Exception\Exception as PsyException; use Psy\Exception\RuntimeException; use Psy\Exception\ThrowUpException; use Psy\ExecutionLoop\ProcessForker; use Psy\ExecutionLoop\RunkitReloader; use Psy\Formatter\TraceFormatter; use Psy\Input\ShellInput; use Psy\Input\SilentInput; use Psy\Output\ShellOutput; use Psy\Readline\Readline; use Psy\TabCompletion\AutoCompleter; use Psy\TabCompletion\Matcher; use Psy\TabCompletion\Matcher\CommandsMatcher; use Psy\VarDumper\PresenterAware; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command as BaseCommand; use Symfony\Component\Console\Exception\ExceptionInterface as SymfonyConsoleException; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\StringInput; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\OutputInterface; /** * The Psy Shell application. * * Usage: * * $shell = new Shell; * $shell->run(); * * @author Justin Hileman <justin@justinhileman.info> */ class Shell extends Application { const VERSION = 'v0.12.8'; private Configuration $config; private CodeCleaner $cleaner; private OutputInterface $output; private ?int $originalVerbosity = null; private Readline $readline; private array $inputBuffer; /** @var string|false|null */ private $code = null; private array $codeBuffer = []; private bool $codeBufferOpen = false; private array $codeStack; private string $stdoutBuffer; private Context $context; private array $includes; private bool $outputWantsNewline = false; private array $loopListeners; private ?AutoCompleter $autoCompleter = null; private array $matchers = []; private ?CommandsMatcher $commandsMatcher = null; private bool $lastExecSuccess = true; private bool $nonInteractive = false; private ?int $errorReporting = null; /** * Create a new Psy Shell. * * @param Configuration|null $config (default: null) */ public function __construct(?Configuration $config = null) { $this->config = $config ?: new Configuration(); $this->cleaner = $this->config->getCodeCleaner(); $this->context = new Context(); $this->includes = []; $this->readline = $this->config->getReadline(); $this->inputBuffer = []; $this->codeStack = []; $this->stdoutBuffer = ''; $this->loopListeners = $this->getDefaultLoopListeners(); parent::__construct('Psy Shell', self::VERSION); $this->config->setShell($this); // Register the current shell session's config with \Psy\info \Psy\info($this->config); } /** * Check whether the first thing in a backtrace is an include call. * * This is used by the psysh bin to decide whether to start a shell on boot, * or to simply autoload the library. */ public static function isIncluded(array $trace): bool { $isIncluded = isset($trace[0]['function']) && \in_array($trace[0]['function'], ['require', 'include', 'require_once', 'include_once']); // Detect Composer PHP bin proxies. if ($isIncluded && \array_key_exists('_composer_autoload_path', $GLOBALS) && \preg_match('{[\\\\/]psysh$}', $trace[0]['file'])) { // If we're in a bin proxy, we'll *always* see one include, but we // care if we see a second immediately after that. return isset($trace[1]['function']) && \in_array($trace[1]['function'], ['require', 'include', 'require_once', 'include_once']); } return $isIncluded; } /** * Check if the currently running PsySH bin is a phar archive. */ public static function isPhar(): bool { return \class_exists("\Phar") && \Phar::running() !== '' && \strpos(__FILE__, \Phar::running(true)) === 0; } /** * Invoke a Psy Shell from the current context. * * @see Psy\debug * @deprecated will be removed in 1.0. Use \Psy\debug instead * * @param array $vars Scope variables from the calling context (default: []) * @param object|string $bindTo Bound object ($this) or class (self) value for the shell * * @return array Scope variables from the debugger session */ public static function debug(array $vars = [], $bindTo = null): array { @\trigger_error('`Psy\\Shell::debug` is deprecated; call `Psy\\debug` instead.', \E_USER_DEPRECATED); return \Psy\debug($vars, $bindTo); } /** * Adds a command object. * * {@inheritdoc} * * @param BaseCommand $command A Symfony Console Command object * * @return BaseCommand The registered command */ public function add(BaseCommand $command): BaseCommand { if ($ret = parent::add($command)) { if ($ret instanceof ContextAware) { $ret->setContext($this->context); } if ($ret instanceof PresenterAware) { $ret->setPresenter($this->config->getPresenter()); } if (isset($this->commandsMatcher)) { $this->commandsMatcher->setCommands($this->all()); } } return $ret; } /** * Gets the default input definition. * * @return InputDefinition An InputDefinition instance */ protected function getDefaultInputDefinition(): InputDefinition { return new InputDefinition([ new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'), new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message.'), ]); } /** * Gets the default commands that should always be available. * * @return array An array of default Command instances */ protected function getDefaultCommands(): array { $sudo = new Command\SudoCommand(); $sudo->setReadline($this->readline); $hist = new Command\HistoryCommand(); $hist->setReadline($this->readline); return [ new Command\HelpCommand(), new Command\ListCommand(), new Command\DumpCommand(), new Command\DocCommand(), new Command\ShowCommand(), new Command\WtfCommand(), new Command\WhereamiCommand(), new Command\ThrowUpCommand(), new Command\TimeitCommand(), new Command\TraceCommand(), new Command\BufferCommand(), new Command\ClearCommand(), new Command\EditCommand($this->config->getRuntimeDir(false)), // new Command\PsyVersionCommand(), $sudo, $hist, new Command\ExitCommand(), ]; } /** * @return Matcher\AbstractMatcher[] */ protected function getDefaultMatchers(): array { // Store the Commands Matcher for later. If more commands are added, // we'll update the Commands Matcher too. $this->commandsMatcher = new CommandsMatcher($this->all()); return [ $this->commandsMatcher, new Matcher\KeywordsMatcher(), new Matcher\VariablesMatcher(), new Matcher\ConstantsMatcher(), new Matcher\FunctionsMatcher(), new Matcher\ClassNamesMatcher(), new Matcher\ClassMethodsMatcher(), new Matcher\ClassAttributesMatcher(), new Matcher\ObjectMethodsMatcher(), new Matcher\ObjectAttributesMatcher(), new Matcher\ClassMethodDefaultParametersMatcher(), new Matcher\ObjectMethodDefaultParametersMatcher(), new Matcher\FunctionDefaultParametersMatcher(), ]; } /** * Gets the default command loop listeners. * * @return array An array of Execution Loop Listener instances */ protected function getDefaultLoopListeners(): array { $listeners = []; if (ProcessForker::isSupported() && $this->config->usePcntl()) { $listeners[] = new ProcessForker(); } if (RunkitReloader::isSupported()) { $listeners[] = new RunkitReloader(); } return $listeners; } /** * Add tab completion matchers. * * @param array $matchers */ public function addMatchers(array $matchers) { $this->matchers = \array_merge($this->matchers, $matchers); if (isset($this->autoCompleter)) { $this->addMatchersToAutoCompleter($matchers); } } /** * @deprecated Call `addMatchers` instead * * @param array $matchers */ public function addTabCompletionMatchers(array $matchers) { @\trigger_error('`addTabCompletionMatchers` is deprecated; call `addMatchers` instead.', \E_USER_DEPRECATED); $this->addMatchers($matchers); } /** * Set the Shell output. * * @param OutputInterface $output */ public function setOutput(OutputInterface $output) { $this->output = $output; $this->originalVerbosity = $output->getVerbosity(); } /** * Runs PsySH. * * @param InputInterface|null $input An Input instance * @param OutputInterface|null $output An Output instance * * @return int 0 if everything went fine, or an error code */ public function run(?InputInterface $input = null, ?OutputInterface $output = null): int { // We'll just ignore the input passed in, and set up our own! $input = new ArrayInput([]); if ($output === null) { $output = $this->config->getOutput(); } $this->setAutoExit(false); $this->setCatchExceptions(false); try { return parent::run($input, $output); } catch (\Throwable $e) { $this->writeException($e); } return 1; } /** * Runs PsySH. * * @throws \Throwable if thrown via the `throw-up` command * * @param InputInterface $input An Input instance * @param OutputInterface $output An Output instance * * @return int 0 if everything went fine, or an error code */ public function doRun(InputInterface $input, OutputInterface $output): int { $this->setOutput($output); $this->resetCodeBuffer(); if ($input->isInteractive()) { // @todo should it be possible to have raw output in an interactive run? return $this->doInteractiveRun(); } else { return $this->doNonInteractiveRun($this->config->rawOutput()); } } /** * Run PsySH in interactive mode. * * Initializes tab completion and readline history, then spins up the * execution loop. * * @throws \Throwable if thrown via the `throw-up` command * * @return int 0 if everything went fine, or an error code */ private function doInteractiveRun(): int { $this->initializeTabCompletion(); $this->readline->readHistory(); $this->output->writeln($this->getHeader()); $this->writeVersionInfo(); $this->writeStartupMessage(); try { $this->beforeRun(); $this->loadIncludes(); $loop = new ExecutionLoopClosure($this); $loop->execute(); $this->afterRun(); } catch (ThrowUpException $e) { throw $e->getPrevious(); } catch (BreakException $e) { // The ProcessForker throws a BreakException to finish the main thread. } return 0; } /** * Run PsySH in non-interactive mode. * * Note that this isn't very useful unless you supply "include" arguments at * the command line, or code via stdin. * * @param bool $rawOutput * * @return int 0 if everything went fine, or an error code */ private function doNonInteractiveRun(bool $rawOutput): int { $this->nonInteractive = true; // If raw output is enabled (or output is piped) we don't want startup messages. if (!$rawOutput && !$this->config->outputIsPiped()) { $this->output->writeln($this->getHeader()); $this->writeVersionInfo(); $this->writeStartupMessage(); } $this->beforeRun(); $this->loadIncludes(); // For non-interactive execution, read only from the input buffer or from piped input. // Otherwise it'll try to readline and hang, waiting for user input with no indication of // what's holding things up. if (!empty($this->inputBuffer) || $this->config->inputIsPiped()) { $this->getInput(false); } if ($this->hasCode()) { $ret = $this->execute($this->flushCode()); $this->writeReturnValue($ret, $rawOutput); } $this->afterRun(); $this->nonInteractive = false; return 0; } /** * Configures the input and output instances based on the user arguments and options. */ protected function configureIO(InputInterface $input, OutputInterface $output): void { // @todo overrides via environment variables (or should these happen in config? ... probably config) $input->setInteractive($this->config->getInputInteractive()); if ($this->config->getOutputDecorated() !== null) { $output->setDecorated($this->config->getOutputDecorated()); } $output->setVerbosity($this->config->getOutputVerbosity()); } /** * Load user-defined includes. */ private function loadIncludes() { // Load user-defined includes $load = function (self $__psysh__) { \set_error_handler([$__psysh__, 'handleError']); foreach ($__psysh__->getIncludes() as $__psysh_include__) { try { include_once $__psysh_include__; } catch (\Exception $_e) { $__psysh__->writeException($_e); } } \restore_error_handler(); unset($__psysh_include__); // Override any new local variables with pre-defined scope variables \extract($__psysh__->getScopeVariables(false)); // ... then add the whole mess of variables back. $__psysh__->setScopeVariables(\get_defined_vars()); }; $load($this); } /** * Read user input. * * This will continue fetching user input until the code buffer contains * valid code. * * @throws BreakException if user hits Ctrl+D * * @param bool $interactive */ public function getInput(bool $interactive = true) { $this->codeBufferOpen = false; do { // reset output verbosity (in case it was altered by a subcommand) $this->output->setVerbosity($this->originalVerbosity); $input = $this->readline(); /* * Handle Ctrl+D. It behaves differently in different cases: * * 1) In an expression, like a function or "if" block, clear the input buffer * 2) At top-level session, behave like the exit command * 3) When non-interactive, return, because that's the end of stdin */ if ($input === false) { if (!$interactive) { return; } $this->output->writeln(''); if ($this->hasCode()) { $this->resetCodeBuffer(); } else { throw new BreakException('Ctrl+D'); } } // handle empty input if (\trim($input) === '' && !$this->codeBufferOpen) { continue; } $input = $this->onInput($input); // If the input isn't in an open string or comment, check for commands to run. if ($this->hasCommand($input) && !$this->inputInOpenStringOrComment($input)) { $this->addHistory($input); $this->runCommand($input); continue; } $this->addCode($input); } while (!$interactive || !$this->hasValidCode()); } /** * Check whether the code buffer (plus current input) is in an open string or comment. * * @param string $input current line of input * * @return bool true if the input is in an open string or comment */ private function inputInOpenStringOrComment(string $input): bool { if (!$this->hasCode()) { return false; } $code = $this->codeBuffer; $code[] = $input; $tokens = @\token_get_all('<?php '.\implode("\n", $code)); $last = \array_pop($tokens); return $last === '"' || $last === '`' || (\is_array($last) && \in_array($last[0], [\T_ENCAPSED_AND_WHITESPACE, \T_START_HEREDOC, \T_COMMENT])); } /** * Run execution loop listeners before the shell session. */ protected function beforeRun() { foreach ($this->loopListeners as $listener) { $listener->beforeRun($this); } } /** * Run execution loop listeners at the start of each loop. */ public function beforeLoop() { foreach ($this->loopListeners as $listener) { $listener->beforeLoop($this); } } /** * Run execution loop listeners on user input. * * @param string $input */ public function onInput(string $input): string { foreach ($this->loopListeners as $listeners) { if (($return = $listeners->onInput($this, $input)) !== null) { $input = $return; } } return $input; } /** * Run execution loop listeners on code to be executed. * * @param string $code */ public function onExecute(string $code): string { $this->errorReporting = \error_reporting(); foreach ($this->loopListeners as $listener) { if (($return = $listener->onExecute($this, $code)) !== null) { $code = $return; } } $output = $this->output; if ($output instanceof ConsoleOutput) { $output = $output->getErrorOutput(); } $output->writeln(\sprintf('<whisper>%s</whisper>', OutputFormatter::escape($code)), ConsoleOutput::VERBOSITY_DEBUG); return $code; } /** * Run execution loop listeners after each loop. */ public function afterLoop() { foreach ($this->loopListeners as $listener) { $listener->afterLoop($this); } } /** * Run execution loop listers after the shell session. */ protected function afterRun() { foreach ($this->loopListeners as $listener) { $listener->afterRun($this); } } /** * Set the variables currently in scope. * * @param array $vars */ public function setScopeVariables(array $vars) { $this->context->setAll($vars); } /** * Return the set of variables currently in scope. * * @param bool $includeBoundObject Pass false to exclude 'this'. If you're * passing the scope variables to `extract` * you _must_ exclude 'this' * * @return array Associative array of scope variables */ public function getScopeVariables(bool $includeBoundObject = true): array { $vars = $this->context->getAll(); if (!$includeBoundObject) { unset($vars['this']); } return $vars; } /** * Return the set of magic variables currently in scope. * * @param bool $includeBoundObject Pass false to exclude 'this'. If you're * passing the scope variables to `extract` * you _must_ exclude 'this' * * @return array Associative array of magic scope variables */ public function getSpecialScopeVariables(bool $includeBoundObject = true): array { $vars = $this->context->getSpecialVariables(); if (!$includeBoundObject) { unset($vars['this']); } return $vars; } /** * Return the set of variables currently in scope which differ from the * values passed as $currentVars. * * This is used inside the Execution Loop Closure to pick up scope variable * changes made by commands while the loop is running. * * @param array $currentVars * * @return array Associative array of scope variables which differ from $currentVars */ public function getScopeVariablesDiff(array $currentVars): array { $newVars = []; foreach ($this->getScopeVariables(false) as $key => $value) { if (!\array_key_exists($key, $currentVars) || $currentVars[$key] !== $value) { $newVars[$key] = $value; } } return $newVars; } /** * Get the set of unused command-scope variable names. * * @return array Array of unused variable names */ public function getUnusedCommandScopeVariableNames(): array { return $this->context->getUnusedCommandScopeVariableNames(); } /** * Get the set of variable names currently in scope. * * @return array Array of variable names */ public function getScopeVariableNames(): array { return \array_keys($this->context->getAll()); } /** * Get a scope variable value by name. * * @param string $name * * @return mixed */ public function getScopeVariable(string $name) { return $this->context->get($name); } /** * Set the bound object ($this variable) for the interactive shell. * * @param object|null $boundObject */ public function setBoundObject($boundObject) { $this->context->setBoundObject($boundObject); } /** * Get the bound object ($this variable) for the interactive shell. * * @return object|null */ public function getBoundObject() { return $this->context->getBoundObject(); } /** * Set the bound class (self) for the interactive shell. * * @param string|null $boundClass */ public function setBoundClass($boundClass) { $this->context->setBoundClass($boundClass); } /** * Get the bound class (self) for the interactive shell. * * @return string|null */ public function getBoundClass() { return $this->context->getBoundClass(); } /** * Add includes, to be parsed and executed before running the interactive shell. * * @param array $includes */ public function setIncludes(array $includes = []) { $this->includes = $includes; } /** * Get PHP files to be parsed and executed before running the interactive shell. * * @return string[] */ public function getIncludes(): array { return \array_merge($this->config->getDefaultIncludes(), $this->includes); } /** * Check whether this shell's code buffer contains code. * * @return bool True if the code buffer contains code */ public function hasCode(): bool { return !empty($this->codeBuffer); } /** * Check whether the code in this shell's code buffer is valid. * * If the code is valid, the code buffer should be flushed and evaluated. * * @return bool True if the code buffer content is valid */ protected function hasValidCode(): bool { return !$this->codeBufferOpen && $this->code !== false; } /** * Add code to the code buffer. * * @param string $code * @param bool $silent */ public function addCode(string $code, bool $silent = false) { try { // Code lines ending in \ keep the buffer open if (\substr(\rtrim($code), -1) === '\\') { $this->codeBufferOpen = true; $code = \substr(\rtrim($code), 0, -1); } else { $this->codeBufferOpen = false; } $this->codeBuffer[] = $silent ? new SilentInput($code) : $code; $this->code = $this->cleaner->clean($this->codeBuffer, $this->config->requireSemicolons()); } catch (\Throwable $e) { // Add failed code blocks to the readline history. $this->addCodeBufferToHistory(); throw $e; } } /** * Set the code buffer. * * This is mostly used by `Shell::execute`. Any existing code in the input * buffer is pushed onto a stack and will come back after this new code is * executed. * * @throws \InvalidArgumentException if $code isn't a complete statement * * @param string $code * @param bool $silent */ private function setCode(string $code, bool $silent = false) { if ($this->hasCode()) { $this->codeStack[] = [$this->codeBuffer, $this->codeBufferOpen, $this->code]; } $this->resetCodeBuffer(); try { $this->addCode($code, $silent); } catch (\Throwable $e) { $this->popCodeStack(); throw $e; } if (!$this->hasValidCode()) { $this->popCodeStack(); throw new \InvalidArgumentException('Unexpected end of input'); } } /** * Get the current code buffer. * * This is useful for commands which manipulate the buffer. * * @return string[] */ public function getCodeBuffer(): array { return $this->codeBuffer; } /** * Run a Psy Shell command given the user input. * * @throws \InvalidArgumentException if the input is not a valid command * * @param string $input User input string * * @return mixed Who knows? */ protected function runCommand(string $input) { $command = $this->getCommand($input); if (empty($command)) { throw new \InvalidArgumentException('Command not found: '.$input); } $input = new ShellInput(\str_replace('\\', '\\\\', \rtrim($input, " \t\n\r\0\x0B;"))); if (!$input->hasParameterOption(['--help', '-h'])) { try { return $command->run($input, $this->output); } catch (\Exception $e) { if (!self::needsInputHelp($e)) { throw $e; } $this->writeException($e); $this->output->writeln('--'); if (!$this->config->theme()->compact()) { $this->output->writeln(''); } } } $helpCommand = $this->get('help'); if (!$helpCommand instanceof Command\HelpCommand) { throw new RuntimeException('Invalid help command instance'); } $helpCommand->setCommand($command); return $helpCommand->run(new StringInput(''), $this->output); } /** * Check whether a given input error would benefit from --help. * * @return bool */ private static function needsInputHelp(\Exception $e): bool { if (!($e instanceof \RuntimeException || $e instanceof SymfonyConsoleException)) { return false; } $inputErrors = [ 'Not enough arguments', 'option does not accept a value', 'option does not exist', 'option requires a value', ]; $msg = $e->getMessage(); foreach ($inputErrors as $errorMsg) { if (\strpos($msg, $errorMsg) !== false) { return true; } } return false; } /** * Reset the current code buffer. * * This should be run after evaluating user input, catching exceptions, or * on demand by commands such as BufferCommand. */ public function resetCodeBuffer() { $this->codeBuffer = []; $this->code = false; } /** * Inject input into the input buffer. * * This is useful for commands which want to replay history. * * @param string|array $input * @param bool $silent */ public function addInput($input, bool $silent = false) { foreach ((array) $input as $line) { $this->inputBuffer[] = $silent ? new SilentInput($line) : $line; } } /** * Flush the current (valid) code buffer. * * If the code buffer is valid, resets the code buffer and returns the * current code. * * @return string|null PHP code buffer contents */ public function flushCode() { if ($this->hasValidCode()) { $this->addCodeBufferToHistory(); $code = $this->code; $this->popCodeStack(); return $code; } } /** * Reset the code buffer and restore any code pushed during `execute` calls. */ private function popCodeStack() { $this->resetCodeBuffer(); if (empty($this->codeStack)) { return; } list($codeBuffer, $codeBufferOpen, $code) = \array_pop($this->codeStack); $this->codeBuffer = $codeBuffer; $this->codeBufferOpen = $codeBufferOpen; $this->code = $code; } /** * (Possibly) add a line to the readline history. * * Like Bash, if the line starts with a space character, it will be omitted * from history. Note that an entire block multi-line code input will be * omitted iff the first line begins with a space. * * Additionally, if a line is "silent", i.e. it was initially added with the * silent flag, it will also be omitted. * * @param string|SilentInput $line */ private function addHistory($line) { if ($line instanceof SilentInput) { return; } // Skip empty lines and lines starting with a space if (\trim($line) !== '' && \substr($line, 0, 1) !== ' ') { $this->readline->addHistory($line); } } /** * Filter silent input from code buffer, write the rest to readline history. */ private function addCodeBufferToHistory() { $codeBuffer = \array_filter($this->codeBuffer, function ($line) { return !$line instanceof SilentInput; }); $this->addHistory(\implode("\n", $codeBuffer)); } /** * Get the current evaluation scope namespace. * * @see CodeCleaner::getNamespace * * @return string|null Current code namespace */ public function getNamespace() { if ($namespace = $this->cleaner->getNamespace()) { return \implode('\\', $namespace); } } /** * Write a string to stdout. * * This is used by the shell loop for rendering output from evaluated code. * * @param string $out * @param int $phase Output buffering phase */ public function writeStdout(string $out, int $phase = \PHP_OUTPUT_HANDLER_END) { if ($phase & \PHP_OUTPUT_HANDLER_START) { if ($this->output instanceof ShellOutput) { $this->output->startPaging(); } } $isCleaning = $phase & \PHP_OUTPUT_HANDLER_CLEAN; // Incremental flush if ($out !== '' && !$isCleaning) { $this->output->write($out, false, OutputInterface::OUTPUT_RAW); $this->outputWantsNewline = (\substr($out, -1) !== "\n"); $this->stdoutBuffer .= $out; } // Output buffering is done! if ($phase & \PHP_OUTPUT_HANDLER_END) { // Write an extra newline if stdout didn't end with one if ($this->outputWantsNewline) { if (!$this->config->rawOutput() && !$this->config->outputIsPiped()) { $this->output->writeln(\sprintf('<whisper>%s</whisper>', $this->config->useUnicode() ? '⏎' : '\\n')); } else { $this->output->writeln(''); } $this->outputWantsNewline = false; } // Save the stdout buffer as $__out if ($this->stdoutBuffer !== '') { $this->context->setLastStdout($this->stdoutBuffer); $this->stdoutBuffer = ''; } if ($this->output instanceof ShellOutput) { $this->output->stopPaging(); } } } /** * Write a return value to stdout. * * The return value is formatted or pretty-printed, and rendered in a * visibly distinct manner (in this case, as cyan). * * @see self::presentValue * * @param mixed $ret * @param bool $rawOutput Write raw var_export-style values */ public function writeReturnValue($ret, bool $rawOutput = false) { $this->lastExecSuccess = true; if ($ret instanceof NoReturnValue) { return; } $this->context->setReturnValue($ret); if ($rawOutput) { $formatted = \var_export($ret, true); } else { $prompt = $this->config->theme()->returnValue(); $indent = \str_repeat(' ', \strlen($prompt)); $formatted = $this->presentValue($ret); $formattedRetValue = \sprintf('<whisper>%s</whisper>', $prompt); $formatted = $formattedRetValue.\str_replace(\PHP_EOL, \PHP_EOL.$indent, $formatted); } if ($this->output instanceof ShellOutput) { $this->output->page($formatted.\PHP_EOL); } else { $this->output->writeln($formatted); } } /** * Renders a caught Exception or Error. * * Exceptions are formatted according to severity. ErrorExceptions which were * warnings or Strict errors aren't rendered as harshly as real errors. * * Stores $e as the last Exception in the Shell Context. * * @param \Throwable $e An exception or error instance */ public function writeException(\Throwable $e) { // No need to write the break exception during a non-interactive run. if ($e instanceof BreakException && $this->nonInteractive) { $this->resetCodeBuffer(); return; } // Break exceptions don't count :) if (!$e instanceof BreakException) { $this->lastExecSuccess = false; $this->context->setLastException($e); } $output = $this->output; if ($output instanceof ConsoleOutput) { $output = $output->getErrorOutput(); } if (!$this->config->theme()->compact()) { $output->writeln(''); } $output->writeln($this->formatException($e)); if (!$this->config->theme()->compact()) { $output->writeln(''); } // Include an exception trace (as long as this isn't a BreakException). if (!$e instanceof BreakException && $output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) { $trace = TraceFormatter::formatTrace($e); if (\count($trace) !== 0) { $output->writeln('--'); $output->write($trace, true); $output->writeln(''); } } $this->resetCodeBuffer(); } /** * Check whether the last exec was successful. * * Returns true if a return value was logged rather than an exception. */ public function getLastExecSuccess(): bool { return $this->lastExecSuccess; } /** * Helper for formatting an exception or error for writeException(). * * @todo extract this to somewhere it makes more sense * * @param \Throwable $e */ public function formatException(\Throwable $e): string { $indent = $this->config->theme()->compact() ? '' : ' '; if ($e instanceof BreakException) { return \sprintf('%s<info> INFO </info> %s.', $indent, \rtrim($e->getRawMessage(), '.')); } elseif ($e instanceof PsyException) { $message = $e->getLine() > 1 ? \sprintf('%s in %s on line %d', $e->getRawMessage(), $e->getFile(), $e->getLine()) : \sprintf('%s in %s', $e->getRawMessage(), $e->getFile()); $messageLabel = \strtoupper($this->getMessageLabel($e)); } else { $message = $e->getMessage(); $messageLabel = $this->getMessageLabel($e); } $message = \preg_replace( "#(\\w:)?([\\\\/]\\w+)*[\\\\/]src[\\\\/]Execution(?:Loop)?Closure.php\(\d+\) : eval\(\)'d code#", "eval()'d code", $message ); $message = \str_replace(" in eval()'d code", '', $message); $message = \trim($message); // Ensures the given string ends with punctuation... if (!empty($message) && !\in_array(\substr($message, -1), ['.', '?', '!', ':'])) { $message = "$message."; } // Ensures the given message only contains relative paths... $message = \str_replace(\getcwd().\DIRECTORY_SEPARATOR, '', $message); $severity = ($e instanceof \ErrorException) ? $this->getSeverity($e) : 'error'; return \sprintf('%s<%s> %s </%s> %s', $indent, $severity, $messageLabel, $severity, OutputFormatter::escape($message)); } /** * Helper for getting an output style for the given ErrorException's level. * * @param \ErrorException $e */ protected function getSeverity(\ErrorException $e): string { $severity = $e->getSeverity(); if ($severity & \error_reporting()) { switch ($severity) { case \E_WARNING: case \E_NOTICE: case \E_CORE_WARNING: case \E_COMPILE_WARNING: case \E_USER_WARNING: case \E_USER_NOTICE: case \E_USER_DEPRECATED: case \E_DEPRECATED: return 'warning'; default: if ((\PHP_VERSION_ID < 80400) && $severity === \E_STRICT) { return 'warning'; } return 'error'; } } else { // Since this is below the user's reporting threshold, it's always going to be a warning. return 'warning'; } } /** * Helper for getting an output style for the given ErrorException's level. * * @param \Throwable $e */ protected function getMessageLabel(\Throwable $e): string { if ($e instanceof \ErrorException) { $severity = $e->getSeverity(); if ($severity & \error_reporting()) { switch ($severity) { case \E_WARNING: return 'Warning'; case \E_NOTICE: return 'Notice'; case \E_CORE_WARNING: return 'Core Warning'; case \E_COMPILE_WARNING: return 'Compile Warning'; case \E_USER_WARNING: return 'User Warning'; case \E_USER_NOTICE: return 'User Notice'; case \E_USER_DEPRECATED: return 'User Deprecated'; case \E_DEPRECATED: return 'Deprecated'; case \E_STRICT: return 'Strict'; } } } if ($e instanceof PsyException || $e instanceof SymfonyConsoleException) { $exceptionShortName = (new \ReflectionClass($e))->getShortName(); $typeParts = \preg_split('/(?=[A-Z])/', $exceptionShortName); switch ($exceptionShortName) { case 'RuntimeException': case 'LogicException': // These ones look weird without 'Exception' break; default: if (\end($typeParts) === 'Exception') { \array_pop($typeParts); } break; } return \trim(\strtoupper(\implode(' ', $typeParts))); } return \get_class($e); } /** * Execute code in the shell execution context. * * @param string $code * @param bool $throwExceptions * * @return mixed */ public function execute(string $code, bool $throwExceptions = false) { $this->setCode($code, true); $closure = new ExecutionClosure($this); if ($throwExceptions) { return $closure->execute(); } try { return $closure->execute(); } catch (\Throwable $_e) { $this->writeException($_e); } } /** * Helper for throwing an ErrorException. * * This allows us to: * * set_error_handler([$psysh, 'handleError']); * * Unlike ErrorException::throwException, this error handler respects error * levels; i.e. it logs warnings and notices, but doesn't throw exceptions. * This should probably only be used in the inner execution loop of the * shell, as most of the time a thrown exception is much more useful. * * If the error type matches the `errorLoggingLevel` config, it will be * logged as well, regardless of the `error_reporting` level. * * @see \Psy\Exception\ErrorException::throwException * @see \Psy\Shell::writeException * * @throws \Psy\Exception\ErrorException depending on the error level * * @param int $errno Error type * @param string $errstr Message * @param string $errfile Filename * @param int $errline Line number */ public function handleError($errno, $errstr, $errfile, $errline) { // This is an error worth throwing. // // n.b. Technically we can't handle all of these in userland code, but // we'll list 'em all for good measure if ($errno & (\E_ERROR | \E_PARSE | \E_CORE_ERROR | \E_COMPILE_ERROR | \E_USER_ERROR | \E_RECOVERABLE_ERROR)) { ErrorException::throwException($errno, $errstr, $errfile, $errline); } // When errors are suppressed, the error_reporting value will differ // from when we started executing. In that case, we won't log errors. $errorsSuppressed = $this->errorReporting !== null && $this->errorReporting !== \error_reporting(); // Otherwise log it and continue. if ($errno & \error_reporting() || (!$errorsSuppressed && ($errno & $this->config->errorLoggingLevel()))) { $this->writeException(new ErrorException($errstr, 0, $errno, $errfile, $errline)); } } /** * Format a value for display. * * @see Presenter::present * * @param mixed $val * * @return string Formatted value */ protected function presentValue($val): string { return $this->config->getPresenter()->present($val); } /** * Get a command (if one exists) for the current input string. * * @param string $input * * @return BaseCommand|null */ protected function getCommand(string $input) { $input = new StringInput($input); if ($name = $input->getFirstArgument()) { return $this->get($name); } } /** * Check whether a command is set for the current input string. * * @param string $input * * @return bool True if the shell has a command for the given input */ protected function hasCommand(string $input): bool { if (\preg_match('/([^\s]+?)(?:\s|$)/A', \ltrim($input), $match)) { return $this->has($match[1]); } return false; } /** * Get the current input prompt. * * @return string|null */ protected function getPrompt() { if ($this->output->isQuiet()) { return null; } $theme = $this->config->theme(); if ($this->hasCode()) { return $theme->bufferPrompt(); } return $theme->prompt(); } /** * Read a line of user input. * * This will return a line from the input buffer (if any exist). Otherwise, * it will ask the user for input. * * If readline is enabled, this delegates to readline. Otherwise, it's an * ugly `fgets` call. * * @param bool $interactive * * @return string|false One line of user input */ protected function readline(bool $interactive = true) { $prompt = $this->config->theme()->replayPrompt(); if (!empty($this->inputBuffer)) { $line = \array_shift($this->inputBuffer); if (!$line instanceof SilentInput) { $this->output->writeln(\sprintf('<whisper>%s</whisper><aside>%s</aside>', $prompt, OutputFormatter::escape($line))); } return $line; } $bracketedPaste = $interactive && $this->config->useBracketedPaste(); if ($bracketedPaste) { \printf("\e[?2004h"); // Enable bracketed paste } $line = $this->readline->readline($this->getPrompt()); if ($bracketedPaste) { \printf("\e[?2004l"); // ... and disable it again } return $line; } /** * Get the shell output header. */ protected function getHeader(): string { return \sprintf('<whisper>%s by Justin Hileman</whisper>', self::getVersionHeader($this->config->useUnicode())); } /** * Get the current version of Psy Shell. * * @deprecated call self::getVersionHeader instead */ public function getVersion(): string { @\trigger_error('`getVersion` is deprecated; call `self::getVersionHeader` instead.', \E_USER_DEPRECATED); return self::getVersionHeader($this->config->useUnicode()); } /** * Get a pretty header including the current version of Psy Shell. * * @param bool $useUnicode */ public static function getVersionHeader(bool $useUnicode = false): string { $separator = $useUnicode ? '—' : '-'; return \sprintf('Psy Shell %s (PHP %s %s %s)', self::VERSION, \PHP_VERSION, $separator, \PHP_SAPI); } /** * Get a PHP manual database instance. * * @return \PDO|null */ public function getManualDb() { return $this->config->getManualDb(); } /** * Initialize tab completion matchers. * * If tab completion is enabled this adds tab completion matchers to the * auto completer and sets context if needed. */ protected function initializeTabCompletion() { if (!$this->config->useTabCompletion()) { return; } $this->autoCompleter = $this->config->getAutoCompleter(); // auto completer needs shell to be linked to configuration because of // the context aware matchers $this->addMatchersToAutoCompleter($this->getDefaultMatchers()); $this->addMatchersToAutoCompleter($this->matchers); $this->autoCompleter->activate(); } /** * Add matchers to the auto completer, setting context if needed. * * @param array $matchers */ private function addMatchersToAutoCompleter(array $matchers) { foreach ($matchers as $matcher) { if ($matcher instanceof ContextAware) { $matcher->setContext($this->context); } $this->autoCompleter->addMatcher($matcher); } } /** * @todo Implement prompt to start update * * @return void|string */ protected function writeVersionInfo() { if (\PHP_SAPI !== 'cli') { return; } try { $client = $this->config->getChecker(); if (!$client->isLatest()) { $this->output->writeln(\sprintf('<whisper>New version is available at psysh.org/psysh (current: %s, latest: %s)</whisper>', self::VERSION, $client->getLatest())); } } catch (\InvalidArgumentException $e) { $this->output->writeln($e->getMessage()); } } /** * Write a startup message if set. */ protected function writeStartupMessage() { $message = $this->config->getStartupMessage(); if ($message !== null && $message !== '') { $this->output->writeln($message); } } } PK������*Zbj(��(����ConfigPaths.phpnu�W+A��������<?php /* * This file is part of Psy Shell. * * (c) 2012-2023 Justin Hileman * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Psy; /** * A Psy Shell configuration path helper. */ class ConfigPaths { private ?string $configDir = null; private ?string $dataDir = null; private ?string $runtimeDir = null; private EnvInterface $env; /** * ConfigPaths constructor. * * Optionally provide `configDir`, `dataDir` and `runtimeDir` overrides. * * @see self::overrideDirs * * @param string[] $overrides Directory overrides * @param EnvInterface $env */ public function __construct(array $overrides = [], ?EnvInterface $env = null) { $this->overrideDirs($overrides); $this->env = $env ?: (\PHP_SAPI === 'cli-server' ? new SystemEnv() : new SuperglobalsEnv()); } /** * Provide `configDir`, `dataDir` and `runtimeDir` overrides. * * If a key is set but empty, the override will be removed. If it is not set * at all, any existing override will persist. * * @param string[] $overrides Directory overrides */ public function overrideDirs(array $overrides) { if (\array_key_exists('configDir', $overrides)) { $this->configDir = $overrides['configDir'] ?: null; } if (\array_key_exists('dataDir', $overrides)) { $this->dataDir = $overrides['dataDir'] ?: null; } if (\array_key_exists('runtimeDir', $overrides)) { $this->runtimeDir = $overrides['runtimeDir'] ?: null; } } /** * Get the current home directory. */ public function homeDir(): ?string { if ($homeDir = $this->getEnv('HOME') ?: $this->windowsHomeDir()) { return \strtr($homeDir, '\\', '/'); } return null; } private function windowsHomeDir(): ?string { if (\defined('PHP_WINDOWS_VERSION_MAJOR')) { $homeDrive = $this->getEnv('HOMEDRIVE'); $homePath = $this->getEnv('HOMEPATH'); if ($homeDrive && $homePath) { return $homeDrive.'/'.$homePath; } } return null; } private function homeConfigDir(): ?string { if ($homeConfigDir = $this->getEnv('XDG_CONFIG_HOME')) { return $homeConfigDir; } $homeDir = $this->homeDir(); if ($homeDir === null) { return null; } return $homeDir === '/' ? $homeDir.'.config' : $homeDir.'/.config'; } /** * Get potential config directory paths. * * Returns `~/.psysh`, `%APPDATA%/PsySH` (when on Windows), and all * XDG Base Directory config directories: * * http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html * * @return string[] */ public function configDirs(): array { if ($this->configDir !== null) { return [$this->configDir]; } $configDirs = $this->getEnvArray('XDG_CONFIG_DIRS') ?: ['/etc/xdg']; return $this->allDirNames(\array_merge([$this->homeConfigDir()], $configDirs)); } /** * Get the current home config directory. * * Returns the highest precedence home config directory which actually * exists. If none of them exists, returns the highest precedence home * config directory (`%APPDATA%/PsySH` on Windows, `~/.config/psysh` * everywhere else). * * @see self::homeConfigDir */ public function currentConfigDir(): ?string { if ($this->configDir !== null) { return $this->configDir; } $configDirs = $this->allDirNames([$this->homeConfigDir()]); foreach ($configDirs as $configDir) { if (@\is_dir($configDir)) { return $configDir; } } return $configDirs[0] ?? null; } /** * Find real config files in config directories. * * @param string[] $names Config file names * * @return string[] */ public function configFiles(array $names): array { return $this->allRealFiles($this->configDirs(), $names); } /** * Get potential data directory paths. * * If a `dataDir` option was explicitly set, returns an array containing * just that directory. * * Otherwise, it returns `~/.psysh` and all XDG Base Directory data directories: * * http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html * * @return string[] */ public function dataDirs(): array { if ($this->dataDir !== null) { return [$this->dataDir]; } $homeDataDir = $this->getEnv('XDG_DATA_HOME') ?: $this->homeDir().'/.local/share'; $dataDirs = $this->getEnvArray('XDG_DATA_DIRS') ?: ['/usr/local/share', '/usr/share']; return $this->allDirNames(\array_merge([$homeDataDir], $dataDirs)); } /** * Find real data files in config directories. * * @param string[] $names Config file names * * @return string[] */ public function dataFiles(array $names): array { return $this->allRealFiles($this->dataDirs(), $names); } /** * Get a runtime directory. * * Defaults to `/psysh` inside the system's temp dir. */ public function runtimeDir(): string { if ($this->runtimeDir !== null) { return $this->runtimeDir; } // Fallback to a boring old folder in the system temp dir. $runtimeDir = $this->getEnv('XDG_RUNTIME_DIR') ?: \sys_get_temp_dir(); return \strtr($runtimeDir, '\\', '/').'/psysh'; } /** * Get a list of directories in PATH. * * If $PATH is unset/empty it defaults to '/usr/sbin:/usr/bin:/sbin:/bin'. * * @return string[] */ public function pathDirs(): array { return $this->getEnvArray('PATH') ?: ['/usr/sbin', '/usr/bin', '/sbin', '/bin']; } /** * Locate a command (an executable) in $PATH. * * Behaves like 'command -v COMMAND' or 'which COMMAND'. * If $PATH is unset/empty it defaults to '/usr/sbin:/usr/bin:/sbin:/bin'. * * @param string $command the executable to locate */ public function which($command): ?string { if (!\is_string($command) || $command === '') { return null; } foreach ($this->pathDirs() as $path) { $fullpath = $path.\DIRECTORY_SEPARATOR.$command; if (@\is_file($fullpath) && @\is_executable($fullpath)) { return $fullpath; } } return null; } /** * Get all PsySH directory name candidates given a list of base directories. * * This expects that XDG-compatible directory paths will be passed in. * `psysh` will be added to each of $baseDirs, and we'll throw in `~/.psysh` * and a couple of Windows-friendly paths as well. * * @param string[] $baseDirs base directory paths * * @return string[] */ private function allDirNames(array $baseDirs): array { $baseDirs = \array_filter($baseDirs); $dirs = \array_map(function ($dir) { return \strtr($dir, '\\', '/').'/psysh'; }, $baseDirs); // Add ~/.psysh if ($home = $this->getEnv('HOME')) { $dirs[] = \strtr($home, '\\', '/').'/.psysh'; } // Add some Windows specific ones :) if (\defined('PHP_WINDOWS_VERSION_MAJOR')) { if ($appData = $this->getEnv('APPDATA')) { // AppData gets preference \array_unshift($dirs, \strtr($appData, '\\', '/').'/PsySH'); } if ($windowsHomeDir = $this->windowsHomeDir()) { $dir = \strtr($windowsHomeDir, '\\', '/').'/.psysh'; if (!\in_array($dir, $dirs)) { $dirs[] = $dir; } } } return $dirs; } /** * Given a list of directories, and a list of filenames, find the ones that * are real files. * * @return string[] */ private function allRealFiles(array $dirNames, array $fileNames): array { $files = []; foreach ($dirNames as $dir) { foreach ($fileNames as $name) { $file = $dir.'/'.$name; if (@\is_file($file)) { $files[] = $file; } } } return $files; } /** * Ensure that $dir exists and is writable. * * Generates E_USER_NOTICE error if the directory is not writable or creatable. * * @param string $dir * * @return bool False if directory exists but is not writeable, or cannot be created */ public static function ensureDir(string $dir): bool { if (!\is_dir($dir)) { // Just try making it and see if it works @\mkdir($dir, 0700, true); } if (!\is_dir($dir) || !\is_writable($dir)) { \trigger_error(\sprintf('Writing to directory %s is not allowed.', $dir), \E_USER_NOTICE); return false; } return true; } /** * Ensure that $file exists and is writable, make the parent directory if necessary. * * Generates E_USER_NOTICE error if either $file or its directory is not writable. * * @param string $file * * @return string|false Full path to $file, or false if file is not writable */ public static function touchFileWithMkdir(string $file) { if (\file_exists($file)) { if (\is_writable($file)) { return $file; } \trigger_error(\sprintf('Writing to %s is not allowed.', $file), \E_USER_NOTICE); return false; } if (!self::ensureDir(\dirname($file))) { return false; } \touch($file); return $file; } private function getEnv(string $key) { return $this->env->get($key); } private function getEnvArray(string $key) { if ($value = $this->getEnv($key)) { return \explode(\PATH_SEPARATOR, $value); } return null; } } PK������*ZӃ������exceptions/RuntimeException.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/comparator. * * (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\Comparator; final class RuntimeException extends \RuntimeException implements Exception { } PK������*ZU������ExceptionComparator.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/comparator. * * (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\Comparator; use Exception; /** * Compares Exception instances for equality. */ class ExceptionComparator extends ObjectComparator { /** * Returns whether the comparator can compare two values. * * @param mixed $expected The first value to compare * @param mixed $actual The second value to compare * * @return bool */ public function accepts($expected, $actual) { return $expected instanceof Exception && $actual instanceof Exception; } /** * Converts an object to an array containing all of its private, protected * and public properties. * * @param object $object * * @return array */ protected function toArray($object) { $array = parent::toArray($object); unset( $array['file'], $array['line'], $array['trace'], $array['string'], $array['xdebug_message'] ); return $array; } } PK������*Z^<pu ��u ����DateTimeComparator.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/comparator. * * (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\Comparator; use function abs; use function floor; use function sprintf; use DateInterval; use DateTime; use DateTimeInterface; use DateTimeZone; use Exception; /** * Compares DateTimeInterface instances for equality. */ class DateTimeComparator extends ObjectComparator { /** * Returns whether the comparator can compare two values. * * @param mixed $expected The first value to compare * @param mixed $actual The second value to compare * * @return bool */ public function accepts($expected, $actual) { return ($expected instanceof DateTime || $expected instanceof DateTimeInterface) && ($actual instanceof DateTime || $actual instanceof DateTimeInterface); } /** * Asserts that two values are equal. * * @param mixed $expected First value to compare * @param mixed $actual Second value to compare * @param float $delta Allowed numerical distance between two values to consider them equal * @param bool $canonicalize Arrays are sorted before comparison when set to true * @param bool $ignoreCase Case is ignored when set to true * @param array $processed List of already processed elements (used to prevent infinite recursion) * * @throws Exception * @throws ComparisonFailure */ public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = [])/*: void*/ { /** @var DateTimeInterface $expected */ /** @var DateTimeInterface $actual */ $absDelta = abs($delta); $delta = new DateInterval(sprintf('PT%dS', $absDelta)); $delta->f = $absDelta - floor($absDelta); $actualClone = (clone $actual) ->setTimezone(new DateTimeZone('UTC')); $expectedLower = (clone $expected) ->setTimezone(new DateTimeZone('UTC')) ->sub($delta); $expectedUpper = (clone $expected) ->setTimezone(new DateTimeZone('UTC')) ->add($delta); if ($actualClone < $expectedLower || $actualClone > $expectedUpper) { throw new ComparisonFailure( $expected, $actual, $this->dateTimeToString($expected), $this->dateTimeToString($actual), false, 'Failed asserting that two DateTime objects are equal.' ); } } /** * Returns an ISO 8601 formatted string representation of a datetime or * 'Invalid DateTimeInterface object' if the provided DateTimeInterface was not properly * initialized. */ private function dateTimeToString(DateTimeInterface $datetime): string { $string = $datetime->format('Y-m-d\TH:i:s.uO'); return $string ?: 'Invalid DateTimeInterface object'; } } PK������*Z������ObjectComparator.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/comparator. * * (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\Comparator; use function get_class; use function in_array; use function is_object; use function sprintf; use function substr_replace; /** * Compares objects for equality. */ class ObjectComparator extends ArrayComparator { /** * Returns whether the comparator can compare two values. * * @param mixed $expected The first value to compare * @param mixed $actual The second value to compare * * @return bool */ public function accepts($expected, $actual) { return is_object($expected) && is_object($actual); } /** * Asserts that two values are equal. * * @param mixed $expected First value to compare * @param mixed $actual Second value to compare * @param float $delta Allowed numerical distance between two values to consider them equal * @param bool $canonicalize Arrays are sorted before comparison when set to true * @param bool $ignoreCase Case is ignored when set to true * @param array $processed List of already processed elements (used to prevent infinite recursion) * * @throws ComparisonFailure */ public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = [])/*: void*/ { if (get_class($actual) !== get_class($expected)) { throw new ComparisonFailure( $expected, $actual, $this->exporter->export($expected), $this->exporter->export($actual), false, sprintf( '%s is not instance of expected class "%s".', $this->exporter->export($actual), get_class($expected) ) ); } // don't compare twice to allow for cyclic dependencies if (in_array([$actual, $expected], $processed, true) || in_array([$expected, $actual], $processed, true)) { return; } $processed[] = [$actual, $expected]; // don't compare objects if they are identical // this helps to avoid the error "maximum function nesting level reached" // CAUTION: this conditional clause is not tested if ($actual !== $expected) { try { parent::assertEquals( $this->toArray($expected), $this->toArray($actual), $delta, $canonicalize, $ignoreCase, $processed ); } catch (ComparisonFailure $e) { throw new ComparisonFailure( $expected, $actual, // replace "Array" with "MyClass object" substr_replace($e->getExpectedAsString(), get_class($expected) . ' Object', 0, 5), substr_replace($e->getActualAsString(), get_class($actual) . ' Object', 0, 5), false, 'Failed asserting that two objects are equal.' ); } } } /** * Converts an object to an array containing all of its private, protected * and public properties. * * @param object $object * * @return array */ protected function toArray($object) { return $this->exporter->toArray($object); } } PK������*Zw1<������ArrayComparator.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/comparator. * * (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\Comparator; use function array_key_exists; use function is_array; use function sort; use function sprintf; use function str_replace; use function trim; /** * Compares arrays for equality. * * Arrays are equal if they contain the same key-value pairs. * The order of the keys does not matter. * The types of key-value pairs do not matter. */ class ArrayComparator extends Comparator { /** * Returns whether the comparator can compare two values. * * @param mixed $expected The first value to compare * @param mixed $actual The second value to compare * * @return bool */ public function accepts($expected, $actual) { return is_array($expected) && is_array($actual); } /** * Asserts that two arrays are equal. * * @param mixed $expected First value to compare * @param mixed $actual Second value to compare * @param float $delta Allowed numerical distance between two values to consider them equal * @param bool $canonicalize Arrays are sorted before comparison when set to true * @param bool $ignoreCase Case is ignored when set to true * @param array $processed List of already processed elements (used to prevent infinite recursion) * * @throws ComparisonFailure */ public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = [])/*: void*/ { if ($canonicalize) { sort($expected); sort($actual); } $remaining = $actual; $actualAsString = "Array (\n"; $expectedAsString = "Array (\n"; $equal = true; foreach ($expected as $key => $value) { unset($remaining[$key]); if (!array_key_exists($key, $actual)) { $expectedAsString .= sprintf( " %s => %s\n", $this->exporter->export($key), $this->exporter->shortenedExport($value) ); $equal = false; continue; } try { $comparator = $this->factory->getComparatorFor($value, $actual[$key]); $comparator->assertEquals($value, $actual[$key], $delta, $canonicalize, $ignoreCase, $processed); $expectedAsString .= sprintf( " %s => %s\n", $this->exporter->export($key), $this->exporter->shortenedExport($value) ); $actualAsString .= sprintf( " %s => %s\n", $this->exporter->export($key), $this->exporter->shortenedExport($actual[$key]) ); } catch (ComparisonFailure $e) { $expectedAsString .= sprintf( " %s => %s\n", $this->exporter->export($key), $e->getExpectedAsString() ? $this->indent($e->getExpectedAsString()) : $this->exporter->shortenedExport($e->getExpected()) ); $actualAsString .= sprintf( " %s => %s\n", $this->exporter->export($key), $e->getActualAsString() ? $this->indent($e->getActualAsString()) : $this->exporter->shortenedExport($e->getActual()) ); $equal = false; } } foreach ($remaining as $key => $value) { $actualAsString .= sprintf( " %s => %s\n", $this->exporter->export($key), $this->exporter->shortenedExport($value) ); $equal = false; } $expectedAsString .= ')'; $actualAsString .= ')'; if (!$equal) { throw new ComparisonFailure( $expected, $actual, $expectedAsString, $actualAsString, false, 'Failed asserting that two arrays are equal.' ); } } protected function indent($lines) { return trim(str_replace("\n", "\n ", $lines)); } } PK������*Zw2��2����TypeComparator.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/comparator. * * (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\Comparator; use function gettype; use function sprintf; /** * Compares values for type equality. */ class TypeComparator extends Comparator { /** * Returns whether the comparator can compare two values. * * @param mixed $expected The first value to compare * @param mixed $actual The second value to compare * * @return bool */ public function accepts($expected, $actual) { return true; } /** * Asserts that two values are equal. * * @param mixed $expected First value to compare * @param mixed $actual Second value to compare * @param float $delta Allowed numerical distance between two values to consider them equal * @param bool $canonicalize Arrays are sorted before comparison when set to true * @param bool $ignoreCase Case is ignored when set to true * * @throws ComparisonFailure */ public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)/*: void*/ { if (gettype($expected) != gettype($actual)) { throw new ComparisonFailure( $expected, $actual, // we don't need a diff '', '', false, sprintf( '%s does not match expected type "%s".', $this->exporter->shortenedExport($actual), gettype($expected) ) ); } } } PK������*ZWpU ���� ��Factory.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/comparator. * * (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\Comparator; use function array_unshift; /** * Factory for comparators which compare values for equality. */ class Factory { /** * @var Factory */ private static $instance; /** * @var Comparator[] */ private $customComparators = []; /** * @var Comparator[] */ private $defaultComparators = []; /** * @return Factory */ public static function getInstance() { if (self::$instance === null) { self::$instance = new self; // @codeCoverageIgnore } return self::$instance; } /** * Constructs a new factory. */ public function __construct() { $this->registerDefaultComparators(); } /** * Returns the correct comparator for comparing two values. * * @param mixed $expected The first value to compare * @param mixed $actual The second value to compare * * @return Comparator */ public function getComparatorFor($expected, $actual) { foreach ($this->customComparators as $comparator) { if ($comparator->accepts($expected, $actual)) { return $comparator; } } foreach ($this->defaultComparators as $comparator) { if ($comparator->accepts($expected, $actual)) { return $comparator; } } throw new RuntimeException('No suitable Comparator implementation found'); } /** * Registers a new comparator. * * This comparator will be returned by getComparatorFor() if its accept() method * returns TRUE for the compared values. It has higher priority than the * existing comparators, meaning that its accept() method will be invoked * before those of the other comparators. * * @param Comparator $comparator The comparator to be registered */ public function register(Comparator $comparator)/*: void*/ { array_unshift($this->customComparators, $comparator); $comparator->setFactory($this); } /** * Unregisters a comparator. * * This comparator will no longer be considered by getComparatorFor(). * * @param Comparator $comparator The comparator to be unregistered */ public function unregister(Comparator $comparator)/*: void*/ { foreach ($this->customComparators as $key => $_comparator) { if ($comparator === $_comparator) { unset($this->customComparators[$key]); } } } /** * Unregisters all non-default comparators. */ public function reset()/*: void*/ { $this->customComparators = []; } private function registerDefaultComparators(): void { $this->registerDefaultComparator(new MockObjectComparator); $this->registerDefaultComparator(new DateTimeComparator); $this->registerDefaultComparator(new DOMNodeComparator); $this->registerDefaultComparator(new SplObjectStorageComparator); $this->registerDefaultComparator(new ExceptionComparator); $this->registerDefaultComparator(new ObjectComparator); $this->registerDefaultComparator(new ResourceComparator); $this->registerDefaultComparator(new ArrayComparator); $this->registerDefaultComparator(new NumericComparator); $this->registerDefaultComparator(new ScalarComparator); $this->registerDefaultComparator(new TypeComparator); } private function registerDefaultComparator(Comparator $comparator): void { $this->defaultComparators[] = $comparator; $comparator->setFactory($this); } } PK������*Zko �� ����NumericComparator.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/comparator. * * (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\Comparator; use function abs; use function is_float; use function is_infinite; use function is_nan; use function is_numeric; use function is_string; use function sprintf; /** * Compares numerical values for equality. */ class NumericComparator extends ScalarComparator { /** * Returns whether the comparator can compare two values. * * @param mixed $expected The first value to compare * @param mixed $actual The second value to compare * * @return bool */ public function accepts($expected, $actual) { // all numerical values, but not if both of them are strings return is_numeric($expected) && is_numeric($actual) && !(is_string($expected) && is_string($actual)); } /** * Asserts that two values are equal. * * @param mixed $expected First value to compare * @param mixed $actual Second value to compare * @param float $delta Allowed numerical distance between two values to consider them equal * @param bool $canonicalize Arrays are sorted before comparison when set to true * @param bool $ignoreCase Case is ignored when set to true * * @throws ComparisonFailure */ public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)/*: void*/ { if ($this->isInfinite($actual) && $this->isInfinite($expected)) { return; } if (($this->isInfinite($actual) xor $this->isInfinite($expected)) || ($this->isNan($actual) || $this->isNan($expected)) || abs($actual - $expected) > $delta) { throw new ComparisonFailure( $expected, $actual, '', '', false, sprintf( 'Failed asserting that %s matches expected %s.', $this->exporter->export($actual), $this->exporter->export($expected) ) ); } } private function isInfinite($value): bool { return is_float($value) && is_infinite($value); } private function isNan($value): bool { return is_float($value) && is_nan($value); } } PK������*ZI������DoubleComparator.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/comparator. * * (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\Comparator; use function is_float; use function is_numeric; /** * Compares doubles for equality. * * @deprecated since v3.0.5 and v4.0.8 */ class DoubleComparator extends NumericComparator { /** * Smallest value available in PHP. * * @var float */ public const EPSILON = 0.0000000001; /** * Returns whether the comparator can compare two values. * * @param mixed $expected The first value to compare * @param mixed $actual The second value to compare * * @return bool */ public function accepts($expected, $actual) { return (is_float($expected) || is_float($actual)) && is_numeric($expected) && is_numeric($actual); } /** * Asserts that two values are equal. * * @param mixed $expected First value to compare * @param mixed $actual Second value to compare * @param float $delta Allowed numerical distance between two values to consider them equal * @param bool $canonicalize Arrays are sorted before comparison when set to true * @param bool $ignoreCase Case is ignored when set to true * * @throws ComparisonFailure */ public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)/*: void*/ { if ($delta == 0) { $delta = self::EPSILON; } parent::assertEquals($expected, $actual, $delta, $canonicalize, $ignoreCase); } } PK������*ZFp������Comparator.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/comparator. * * (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\Comparator; use SebastianBergmann\Exporter\Exporter; /** * Abstract base class for comparators which compare values for equality. */ abstract class Comparator { /** * @var Factory */ protected $factory; /** * @var Exporter */ protected $exporter; public function __construct() { $this->exporter = new Exporter; } public function setFactory(Factory $factory)/*: void*/ { $this->factory = $factory; } /** * Returns whether the comparator can compare two values. * * @param mixed $expected The first value to compare * @param mixed $actual The second value to compare * * @return bool */ abstract public function accepts($expected, $actual); /** * Asserts that two values are equal. * * @param mixed $expected First value to compare * @param mixed $actual Second value to compare * @param float $delta Allowed numerical distance between two values to consider them equal * @param bool $canonicalize Arrays are sorted before comparison when set to true * @param bool $ignoreCase Case is ignored when set to true * * @throws ComparisonFailure */ abstract public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false); } PK������*ZJv �� ����ScalarComparator.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/comparator. * * (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\Comparator; use function is_bool; use function is_object; use function is_scalar; use function is_string; use function method_exists; use function sprintf; use function strtolower; /** * Compares scalar or NULL values for equality. */ class ScalarComparator extends Comparator { /** * Returns whether the comparator can compare two values. * * @param mixed $expected The first value to compare * @param mixed $actual The second value to compare * * @return bool * * @since Method available since Release 3.6.0 */ public function accepts($expected, $actual) { return ((is_scalar($expected) xor null === $expected) && (is_scalar($actual) xor null === $actual)) // allow comparison between strings and objects featuring __toString() || (is_string($expected) && is_object($actual) && method_exists($actual, '__toString')) || (is_object($expected) && method_exists($expected, '__toString') && is_string($actual)); } /** * Asserts that two values are equal. * * @param mixed $expected First value to compare * @param mixed $actual Second value to compare * @param float $delta Allowed numerical distance between two values to consider them equal * @param bool $canonicalize Arrays are sorted before comparison when set to true * @param bool $ignoreCase Case is ignored when set to true * * @throws ComparisonFailure */ public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)/*: void*/ { $expectedToCompare = $expected; $actualToCompare = $actual; // always compare as strings to avoid strange behaviour // otherwise 0 == 'Foobar' if ((is_string($expected) && !is_bool($actual)) || (is_string($actual) && !is_bool($expected))) { $expectedToCompare = (string) $expectedToCompare; $actualToCompare = (string) $actualToCompare; if ($ignoreCase) { $expectedToCompare = strtolower($expectedToCompare); $actualToCompare = strtolower($actualToCompare); } } if ($expectedToCompare !== $actualToCompare && is_string($expected) && is_string($actual)) { throw new ComparisonFailure( $expected, $actual, $this->exporter->export($expected), $this->exporter->export($actual), false, 'Failed asserting that two strings are equal.' ); } if ($expectedToCompare != $actualToCompare) { throw new ComparisonFailure( $expected, $actual, // no diff is required '', '', false, sprintf( 'Failed asserting that %s matches expected %s.', $this->exporter->export($actual), $this->exporter->export($expected) ) ); } } } PK������*Z8O �� ����ComparisonFailure.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/comparator. * * (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\Comparator; use RuntimeException; use SebastianBergmann\Diff\Differ; use SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder; /** * Thrown when an assertion for string equality failed. */ class ComparisonFailure extends RuntimeException { /** * Expected value of the retrieval which does not match $actual. * * @var mixed */ protected $expected; /** * Actually retrieved value which does not match $expected. * * @var mixed */ protected $actual; /** * The string representation of the expected value. * * @var string */ protected $expectedAsString; /** * The string representation of the actual value. * * @var string */ protected $actualAsString; /** * @var bool */ protected $identical; /** * Optional message which is placed in front of the first line * returned by toString(). * * @var string */ protected $message; /** * Initialises with the expected value and the actual value. * * @param mixed $expected expected value retrieved * @param mixed $actual actual value retrieved * @param string $expectedAsString * @param string $actualAsString * @param bool $identical * @param string $message a string which is prefixed on all returned lines * in the difference output */ public function __construct($expected, $actual, $expectedAsString, $actualAsString, $identical = false, $message = '') { $this->expected = $expected; $this->actual = $actual; $this->expectedAsString = $expectedAsString; $this->actualAsString = $actualAsString; $this->message = $message; } public function getActual() { return $this->actual; } public function getExpected() { return $this->expected; } /** * @return string */ public function getActualAsString() { return $this->actualAsString; } /** * @return string */ public function getExpectedAsString() { return $this->expectedAsString; } /** * @return string */ public function getDiff() { if (!$this->actualAsString && !$this->expectedAsString) { return ''; } $differ = new Differ(new UnifiedDiffOutputBuilder("\n--- Expected\n+++ Actual\n")); return $differ->diff($this->expectedAsString, $this->actualAsString); } /** * @return string */ public function toString() { return $this->message . $this->getDiff(); } } PK������*Z7 2 �� ����SplObjectStorageComparator.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/comparator. * * (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\Comparator; use SplObjectStorage; /** * Compares \SplObjectStorage instances for equality. */ class SplObjectStorageComparator extends Comparator { /** * Returns whether the comparator can compare two values. * * @param mixed $expected The first value to compare * @param mixed $actual The second value to compare * * @return bool */ public function accepts($expected, $actual) { return $expected instanceof SplObjectStorage && $actual instanceof SplObjectStorage; } /** * Asserts that two values are equal. * * @param mixed $expected First value to compare * @param mixed $actual Second value to compare * @param float $delta Allowed numerical distance between two values to consider them equal * @param bool $canonicalize Arrays are sorted before comparison when set to true * @param bool $ignoreCase Case is ignored when set to true * * @throws ComparisonFailure */ public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)/*: void*/ { foreach ($actual as $object) { if (!$expected->contains($object)) { throw new ComparisonFailure( $expected, $actual, $this->exporter->export($expected), $this->exporter->export($actual), false, 'Failed asserting that two objects are equal.' ); } } foreach ($expected as $object) { if (!$actual->contains($object)) { throw new ComparisonFailure( $expected, $actual, $this->exporter->export($expected), $this->exporter->export($actual), false, 'Failed asserting that two objects are equal.' ); } } } } PK������*Z f������MockObjectComparator.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/comparator. * * (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\Comparator; use PHPUnit\Framework\MockObject\MockObject; /** * Compares PHPUnit\Framework\MockObject\MockObject instances for equality. */ class MockObjectComparator extends ObjectComparator { /** * Returns whether the comparator can compare two values. * * @param mixed $expected The first value to compare * @param mixed $actual The second value to compare * * @return bool */ public function accepts($expected, $actual) { return $expected instanceof MockObject && $actual instanceof MockObject; } /** * Converts an object to an array containing all of its private, protected * and public properties. * * @param object $object * * @return array */ protected function toArray($object) { $array = parent::toArray($object); unset($array['__phpunit_invocationMocker']); return $array; } } PK������*Zi 7Zj��j����ResourceComparator.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/comparator. * * (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\Comparator; use function is_resource; /** * Compares resources for equality. */ class ResourceComparator extends Comparator { /** * Returns whether the comparator can compare two values. * * @param mixed $expected The first value to compare * @param mixed $actual The second value to compare * * @return bool */ public function accepts($expected, $actual) { return is_resource($expected) && is_resource($actual); } /** * Asserts that two values are equal. * * @param mixed $expected First value to compare * @param mixed $actual Second value to compare * @param float $delta Allowed numerical distance between two values to consider them equal * @param bool $canonicalize Arrays are sorted before comparison when set to true * @param bool $ignoreCase Case is ignored when set to true * * @throws ComparisonFailure */ public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)/*: void*/ { if ($actual != $expected) { throw new ComparisonFailure( $expected, $actual, $this->exporter->export($expected), $this->exporter->export($actual) ); } } } PK������*Zܓa �� ����DOMNodeComparator.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/comparator. * * (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\Comparator; use function sprintf; use function strtolower; use DOMDocument; use DOMNode; use ValueError; /** * Compares DOMNode instances for equality. */ class DOMNodeComparator extends ObjectComparator { /** * Returns whether the comparator can compare two values. * * @param mixed $expected The first value to compare * @param mixed $actual The second value to compare * * @return bool */ public function accepts($expected, $actual) { return $expected instanceof DOMNode && $actual instanceof DOMNode; } /** * Asserts that two values are equal. * * @param mixed $expected First value to compare * @param mixed $actual Second value to compare * @param float $delta Allowed numerical distance between two values to consider them equal * @param bool $canonicalize Arrays are sorted before comparison when set to true * @param bool $ignoreCase Case is ignored when set to true * @param array $processed List of already processed elements (used to prevent infinite recursion) * * @throws ComparisonFailure */ public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = [])/*: void*/ { $expectedAsString = $this->nodeToText($expected, true, $ignoreCase); $actualAsString = $this->nodeToText($actual, true, $ignoreCase); if ($expectedAsString !== $actualAsString) { $type = $expected instanceof DOMDocument ? 'documents' : 'nodes'; throw new ComparisonFailure( $expected, $actual, $expectedAsString, $actualAsString, false, sprintf("Failed asserting that two DOM %s are equal.\n", $type) ); } } /** * Returns the normalized, whitespace-cleaned, and indented textual * representation of a DOMNode. */ private function nodeToText(DOMNode $node, bool $canonicalize, bool $ignoreCase): string { if ($canonicalize) { $document = new DOMDocument; try { @$document->loadXML($node->C14N()); } catch (ValueError $e) { } $node = $document; } $document = $node instanceof DOMDocument ? $node : $node->ownerDocument; $document->formatOutput = true; $document->normalizeDocument(); $text = $node instanceof DOMDocument ? $node->saveXML() : $document->saveXML($node); return $ignoreCase ? strtolower($text) : $text; } } PK������*Z���� ��Handler.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision; use NunoMaduro\Collision\Contracts\Handler as HandlerContract; use NunoMaduro\Collision\Contracts\Writer as WriterContract; use Symfony\Component\Console\Output\OutputInterface; use Whoops\Handler\Handler as AbstractHandler; /** * @internal * * @see \Tests\Unit\HandlerTest */ final class Handler extends AbstractHandler implements HandlerContract { /** * Holds an instance of the writer. * * @var \NunoMaduro\Collision\Contracts\Writer */ protected $writer; /** * Creates an instance of the Handler. */ public function __construct(WriterContract $writer = null) { $this->writer = $writer ?: new Writer(); } /** * {@inheritdoc} */ public function handle() { $this->writer->write($this->getInspector()); return static::QUIT; } /** * {@inheritdoc} */ public function setOutput(OutputInterface $output): HandlerContract { $this->writer->setOutput($output); return $this; } /** * {@inheritdoc} */ public function getWriter(): WriterContract { return $this->writer; } } PK������*Z B&��&�� ��Writer.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision; use NunoMaduro\Collision\Contracts\ArgumentFormatter as ArgumentFormatterContract; use NunoMaduro\Collision\Contracts\Highlighter as HighlighterContract; use NunoMaduro\Collision\Contracts\RenderlessEditor; use NunoMaduro\Collision\Contracts\RenderlessTrace; use NunoMaduro\Collision\Contracts\SolutionsRepository; use NunoMaduro\Collision\Contracts\Writer as WriterContract; use NunoMaduro\Collision\SolutionsRepositories\NullSolutionsRepository; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\OutputInterface; use Whoops\Exception\Frame; use Whoops\Exception\Inspector; /** * @internal * * @see \Tests\Unit\WriterTest */ final class Writer implements WriterContract { /** * The number of frames if no verbosity is specified. */ public const VERBOSITY_NORMAL_FRAMES = 1; /** * Holds an instance of the solutions repository. * * @var \NunoMaduro\Collision\Contracts\SolutionsRepository */ private $solutionsRepository; /** * Holds an instance of the Output. * * @var \Symfony\Component\Console\Output\OutputInterface */ protected $output; /** * Holds an instance of the Argument Formatter. * * @var \NunoMaduro\Collision\Contracts\ArgumentFormatter */ protected $argumentFormatter; /** * Holds an instance of the Highlighter. * * @var \NunoMaduro\Collision\Contracts\Highlighter */ protected $highlighter; /** * Ignores traces where the file string matches one * of the provided regex expressions. * * @var string[] */ protected $ignore = []; /** * Declares whether or not the trace should appear. * * @var bool */ protected $showTrace = true; /** * Declares whether or not the title should appear. * * @var bool */ protected $showTitle = true; /** * Declares whether or not the editor should appear. * * @var bool */ protected $showEditor = true; /** * Creates an instance of the writer. */ public function __construct( SolutionsRepository $solutionsRepository = null, OutputInterface $output = null, ArgumentFormatterContract $argumentFormatter = null, HighlighterContract $highlighter = null ) { $this->solutionsRepository = $solutionsRepository ?: new NullSolutionsRepository(); $this->output = $output ?: new ConsoleOutput(); $this->argumentFormatter = $argumentFormatter ?: new ArgumentFormatter(); $this->highlighter = $highlighter ?: new Highlighter(); } /** * {@inheritdoc} */ public function write(Inspector $inspector): void { $this->renderTitleAndDescription($inspector); $frames = $this->getFrames($inspector); $editorFrame = array_shift($frames); $exception = $inspector->getException(); if ($this->showEditor && $editorFrame !== null && ! $exception instanceof RenderlessEditor ) { $this->renderEditor($editorFrame); } $this->renderSolution($inspector); if ($this->showTrace && ! empty($frames) && ! $exception instanceof RenderlessTrace) { $this->renderTrace($frames); } elseif (! $exception instanceof RenderlessEditor) { $this->output->writeln(''); } } /** * {@inheritdoc} */ public function ignoreFilesIn(array $ignore): WriterContract { $this->ignore = $ignore; return $this; } /** * {@inheritdoc} */ public function showTrace(bool $show): WriterContract { $this->showTrace = $show; return $this; } /** * {@inheritdoc} */ public function showTitle(bool $show): WriterContract { $this->showTitle = $show; return $this; } /** * {@inheritdoc} */ public function showEditor(bool $show): WriterContract { $this->showEditor = $show; return $this; } /** * {@inheritdoc} */ public function setOutput(OutputInterface $output): WriterContract { $this->output = $output; return $this; } /** * {@inheritdoc} */ public function getOutput(): OutputInterface { return $this->output; } /** * Returns pertinent frames. */ protected function getFrames(Inspector $inspector): array { return $inspector->getFrames() ->filter( function ($frame) { // If we are in verbose mode, we always // display the full stack trace. if ($this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) { return true; } foreach ($this->ignore as $ignore) { // Ensure paths are linux-style (like the ones on $this->ignore) // @phpstan-ignore-next-line $sanitizedPath = (string) str_replace('\\', '/', $frame->getFile()); if (preg_match($ignore, $sanitizedPath)) { return false; } } return true; } ) ->getArray(); } /** * Renders the title of the exception. */ protected function renderTitleAndDescription(Inspector $inspector): WriterContract { $exception = $inspector->getException(); $message = rtrim($exception->getMessage()); $class = $inspector->getExceptionName(); if ($this->showTitle) { $this->render("<bg=red;options=bold> $class </>"); $this->output->writeln(''); } $this->output->writeln("<fg=default;options=bold> $message</>"); return $this; } /** * Renders the solution of the exception, if any. */ protected function renderSolution(Inspector $inspector): WriterContract { $throwable = $inspector->getException(); $solutions = $this->solutionsRepository->getFromThrowable($throwable); foreach ($solutions as $solution) { /** @var \Spatie\Ignition\Contracts\Solution $solution */ $title = $solution->getSolutionTitle(); $description = $solution->getSolutionDescription(); $links = $solution->getDocumentationLinks(); $description = trim((string) preg_replace("/\n/", "\n ", $description)); $this->render(sprintf( '<fg=cyan;options=bold>i</> <fg=default;options=bold>%s</>: %s %s', rtrim($title, '.'), $description, implode(', ', array_map(function (string $link) { return sprintf("\n <fg=gray>%s</>", $link); }, $links)) )); } return $this; } /** * Renders the editor containing the code that was the * origin of the exception. */ protected function renderEditor(Frame $frame): WriterContract { if ($frame->getFile() !== 'Unknown') { $file = $this->getFileRelativePath((string) $frame->getFile()); // getLine() might return null so cast to int to get 0 instead $line = (int) $frame->getLine(); $this->render('at <fg=green>'.$file.'</>'.':<fg=green>'.$line.'</>'); $content = $this->highlighter->highlight((string) $frame->getFileContents(), (int) $frame->getLine()); $this->output->writeln($content); } return $this; } /** * Renders the trace of the exception. */ protected function renderTrace(array $frames): WriterContract { $vendorFrames = 0; $userFrames = 0; foreach ($frames as $i => $frame) { if ($this->output->getVerbosity() < OutputInterface::VERBOSITY_VERBOSE && strpos($frame->getFile(), '/vendor/') !== false) { $vendorFrames++; continue; } if ($userFrames > static::VERBOSITY_NORMAL_FRAMES && $this->output->getVerbosity() < OutputInterface::VERBOSITY_VERBOSE) { break; } $userFrames++; $file = $this->getFileRelativePath($frame->getFile()); $line = $frame->getLine(); $class = empty($frame->getClass()) ? '' : $frame->getClass().'::'; $function = $frame->getFunction(); $args = $this->argumentFormatter->format($frame->getArgs()); $pos = str_pad((string) ((int) $i + 1), 4, ' '); if ($vendorFrames > 0) { $this->output->write( sprintf("\n \e[2m+%s vendor frames \e[22m", $vendorFrames) ); $vendorFrames = 0; } $this->render("<fg=yellow>$pos</><fg=default;options=bold>$file</>:<fg=default;options=bold>$line</>"); $this->render("<fg=gray> $class$function($args)</>", false); } return $this; } /** * Renders an message into the console. * * @return $this */ protected function render(string $message, bool $break = true): WriterContract { if ($break) { $this->output->writeln(''); } $this->output->writeln(" $message"); return $this; } /** * Returns the relative path of the given file path. */ protected function getFileRelativePath(string $filePath): string { $cwd = (string) getcwd(); if (! empty($cwd)) { return str_replace("$cwd/", '', $filePath); } return $filePath; } } PK������*Z](/���� ��Provider.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision; use NunoMaduro\Collision\Contracts\Handler as HandlerContract; use NunoMaduro\Collision\Contracts\Provider as ProviderContract; use Whoops\Run; use Whoops\RunInterface; /** * @internal * * @see \Tests\Unit\ProviderTest */ final class Provider implements ProviderContract { /** * Holds an instance of the Run. * * @var \Whoops\RunInterface */ protected $run; /** * Holds an instance of the handler. * * @var \NunoMaduro\Collision\Contracts\Handler */ protected $handler; /** * Creates a new instance of the Provider. */ public function __construct(RunInterface $run = null, HandlerContract $handler = null) { $this->run = $run ?: new Run(); $this->handler = $handler ?: new Handler(); } /** * {@inheritdoc} */ public function register(): ProviderContract { $this->run->pushHandler($this->handler) ->register(); return $this; } /** * {@inheritdoc} */ public function getHandler(): HandlerContract { return $this->handler; } } PK������*Z8������$��Exceptions/InvalidStyleException.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Exceptions; use RuntimeException; /** * @internal */ final class InvalidStyleException extends RuntimeException { } PK������*Z5������Exceptions/ShouldNotHappen.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Exceptions; use RuntimeException; /** * @internal */ final class ShouldNotHappen extends RuntimeException { /** * @var string */ private const MESSAGE = 'This should not happen, please open an issue on collision repository: %s'; public function __construct() { parent::__construct(sprintf(self::MESSAGE, 'https://github.com/nunomaduro/collision/issues/new')); } } PK������*Zz<����1��SolutionsRepositories/NullSolutionsRepository.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\SolutionsRepositories; use NunoMaduro\Collision\Contracts\SolutionsRepository; use Throwable; /** * @internal */ final class NullSolutionsRepository implements SolutionsRepository { /** * {@inheritdoc} */ public function getFromThrowable(Throwable $throwable): array { return []; } } PK������*ZKM��M����ArgumentFormatter.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision; use NunoMaduro\Collision\Contracts\ArgumentFormatter as ArgumentFormatterContract; /** * @internal * * @see \Tests\Unit\ArgumentFormatterTest */ final class ArgumentFormatter implements ArgumentFormatterContract { private const MAX_STRING_LENGTH = 1000; /** * {@inheritdoc} */ public function format(array $arguments, bool $recursive = true): string { $result = []; foreach ($arguments as $argument) { switch (true) { case is_string($argument): $result[] = '"'.(mb_strlen($argument) > self::MAX_STRING_LENGTH ? mb_substr($argument, 0, self::MAX_STRING_LENGTH).'...' : $argument).'"'; break; case is_array($argument): $associative = array_keys($argument) !== range(0, count($argument) - 1); if ($recursive && $associative && count($argument) <= 5) { $result[] = '['.$this->format($argument, false).']'; } break; case is_object($argument): $class = get_class($argument); $result[] = "Object($class)"; break; } } return implode(', ', $result); } } PK������*Z d��d����Adapters/Phpunit/Timer.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Adapters\Phpunit; /** * @internal */ final class Timer { /** * @var float */ private $start; /** * Timer constructor. */ private function __construct(float $start) { $this->start = $start; } /** * Starts the timer. */ public static function start(): Timer { return new self(microtime(true)); } /** * Returns the elapsed time in microseconds. */ public function result(): float { return microtime(true) - $this->start; } } PK������*ZuDވ������Adapters/Phpunit/TestResult.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Adapters\Phpunit; use NunoMaduro\Collision\Contracts\Adapters\Phpunit\HasPrintableTestCaseName; use PHPUnit\Framework\TestCase; use Throwable; /** * @internal */ final class TestResult { public const FAIL = 'failed'; public const SKIPPED = 'skipped'; public const INCOMPLETE = 'incomplete'; public const RISKY = 'risky'; public const WARN = 'warnings'; public const RUNS = 'pending'; public const PASS = 'passed'; /** * @readonly * * @var string */ public $testCaseName; /** * @readonly * * @var string */ public $description; /** * @readonly * * @var string */ public $type; /** * @readonly * * @var string */ public $icon; /** * @readonly * * @var string */ public $color; /** * @readonly * * @var Throwable|null */ public $throwable; /** * @readonly * * @var string */ public $warning = ''; /** * Test constructor. */ private function __construct(string $testCaseName, string $description, string $type, string $icon, string $color, Throwable $throwable = null) { $this->testCaseName = $testCaseName; $this->description = $description; $this->type = $type; $this->icon = $icon; $this->color = $color; $this->throwable = $throwable; $asWarning = $this->type === TestResult::WARN || $this->type === TestResult::RISKY || $this->type === TestResult::SKIPPED || $this->type === TestResult::INCOMPLETE; if ($throwable instanceof Throwable && $asWarning) { $this->warning = trim((string) preg_replace("/\r|\n/", ' ', $throwable->getMessage())); } } /** * Creates a new test from the given test case. */ public static function fromTestCase(TestCase $testCase, string $type, Throwable $throwable = null): self { $testCaseName = State::getPrintableTestCaseName($testCase); $description = self::makeDescription($testCase); $icon = self::makeIcon($type); $color = self::makeColor($type); return new self($testCaseName, $description, $type, $icon, $color, $throwable); } /** * Get the test case description. */ public static function makeDescription(TestCase $testCase): string { $name = $testCase->getName(false); if ($testCase instanceof HasPrintableTestCaseName) { return $name; } // First, lets replace underscore by spaces. $name = str_replace('_', ' ', $name); // Then, replace upper cases by spaces. $name = (string) preg_replace('/([A-Z])/', ' $1', $name); // Finally, if it starts with `test`, we remove it. $name = (string) preg_replace('/^test/', '', $name); // Removes spaces $name = trim($name); // Lower case everything $name = mb_strtolower($name); // Add the dataset name if it has one if ($dataName = $testCase->dataName()) { if (is_int($dataName)) { $name .= sprintf(' with data set #%d', $dataName); } else { $name .= sprintf(' with data set "%s"', $dataName); } } return $name; } /** * Get the test case icon. */ public static function makeIcon(string $type): string { switch ($type) { case self::FAIL: return '⨯'; case self::SKIPPED: return '-'; case self::RISKY: return '!'; case self::INCOMPLETE: return '…'; case self::WARN: return '!'; case self::RUNS: return '•'; default: return '✓'; } } /** * Get the test case color. */ public static function makeColor(string $type): string { switch ($type) { case self::FAIL: return 'red'; case self::SKIPPED: case self::INCOMPLETE: case self::RISKY: case self::WARN: case self::RUNS: return 'yellow'; default: return 'green'; } } } PK������*Z~q���� ��Adapters/Phpunit/ConfigureIO.phpnu�W+A��������<?php declare(strict_types=1); /** * This file is part of Collision. * * (c) Nuno Maduro <enunomaduro@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace NunoMaduro\Collision\Adapters\Phpunit; use ReflectionObject; use Symfony\Component\Console\Application; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\Output; /** * @internal */ final class ConfigureIO { /** * Configures both given input and output with * options from the environment. * * @throws \ReflectionException */ public static function of(InputInterface $input, Output $output): void { $application = new Application(); $reflector = new ReflectionObject($application); $method = $reflector->getMethod('configureIO'); $method->setAccessible(true); $method->invoke($application, $input, $output); } } PK������*Z^0������Adapters/Phpunit/Printer.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Adapters\Phpunit; use NunoMaduro\Collision\Exceptions\ShouldNotHappen; use PHPUnit\Framework\AssertionFailedError; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestSuite; use PHPUnit\Framework\Warning; use ReflectionObject; use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Output\ConsoleOutput; use Throwable; /** * @internal */ final class Printer implements \PHPUnit\TextUI\ResultPrinter { /** * Holds an instance of the style. * * Style is a class we use to interact with output. * * @var Style */ private $style; /** * Holds the duration time of the test suite. * * @var Timer */ private $timer; /** * Holds the state of the test * suite. The number of tests, etc. * * @var State */ private $state; /** * If the test suite has failed. * * @var bool */ private $failed = false; /** * Creates a new instance of the listener. * * @param ConsoleOutput $output * * @throws \ReflectionException */ public function __construct(\Symfony\Component\Console\Output\ConsoleOutputInterface $output = null, bool $verbose = false, string $colors = 'always') { $this->timer = Timer::start(); $decorated = $colors === 'always' || $colors === 'auto'; $output = $output ?? new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, $decorated); ConfigureIO::of(new ArgvInput(), $output); $this->style = new Style($output); $dummyTest = new class() extends TestCase { }; $this->state = State::from($dummyTest); } /** * {@inheritdoc} */ public function addError(Test $testCase, Throwable $throwable, float $time): void { $this->failed = true; $testCase = $this->testCaseFromTest($testCase); $this->state->add(TestResult::fromTestCase($testCase, TestResult::FAIL, $throwable)); } /** * {@inheritdoc} */ public function addWarning(Test $testCase, Warning $warning, float $time): void { $testCase = $this->testCaseFromTest($testCase); $this->state->add(TestResult::fromTestCase($testCase, TestResult::WARN, $warning)); } /** * {@inheritdoc} */ public function addFailure(Test $testCase, AssertionFailedError $error, float $time): void { $this->failed = true; $testCase = $this->testCaseFromTest($testCase); $reflector = new ReflectionObject($error); if ($reflector->hasProperty('message')) { $message = trim((string) preg_replace("/\r|\n/", "\n ", $error->getMessage())); $property = $reflector->getProperty('message'); $property->setAccessible(true); $property->setValue($error, $message); } $this->state->add(TestResult::fromTestCase($testCase, TestResult::FAIL, $error)); } /** * {@inheritdoc} */ public function addIncompleteTest(Test $testCase, Throwable $throwable, float $time): void { $testCase = $this->testCaseFromTest($testCase); $this->state->add(TestResult::fromTestCase($testCase, TestResult::INCOMPLETE, $throwable)); } /** * {@inheritdoc} */ public function addRiskyTest(Test $testCase, Throwable $throwable, float $time): void { $testCase = $this->testCaseFromTest($testCase); $this->state->add(TestResult::fromTestCase($testCase, TestResult::RISKY, $throwable)); } /** * {@inheritdoc} */ public function addSkippedTest(Test $testCase, Throwable $throwable, float $time): void { $testCase = $this->testCaseFromTest($testCase); $this->state->add(TestResult::fromTestCase($testCase, TestResult::SKIPPED, $throwable)); } /** * {@inheritdoc} */ public function startTestSuite(TestSuite $suite): void { if ($this->state->suiteTotalTests === null) { $this->state->suiteTotalTests = $suite->count(); } } /** * {@inheritdoc} */ public function endTestSuite(TestSuite $suite): void { // .. } /** * {@inheritdoc} */ public function startTest(Test $testCase): void { $testCase = $this->testCaseFromTest($testCase); // Let's check first if the testCase is over. if ($this->state->testCaseHasChanged($testCase)) { $this->style->writeCurrentTestCaseSummary($this->state); $this->state->moveTo($testCase); } } /** * {@inheritdoc} */ public function endTest(Test $testCase, float $time): void { $testCase = $this->testCaseFromTest($testCase); if (! $this->state->existsInTestCase($testCase)) { $this->state->add(TestResult::fromTestCase($testCase, TestResult::PASS)); } if ($testCase instanceof TestCase && $testCase->getTestResultObject() instanceof \PHPUnit\Framework\TestResult && ! $testCase->getTestResultObject()->isStrictAboutOutputDuringTests() && ! $testCase->hasExpectationOnOutput()) { $this->style->write($testCase->getActualOutput()); } } /** * Intentionally left blank as we output things on events of the listener. */ public function write(string $content): void { // .. } /** * Returns a test case from the given test. * * Note: This printer is do not work with normal Test classes - only * with Test Case classes. Please report an issue if you think * this should work any other way. */ private function testCaseFromTest(Test $test): TestCase { if (! $test instanceof TestCase) { throw new ShouldNotHappen(); } return $test; } /** * Intentionally left blank as we output things on events of the listener. */ public function printResult(\PHPUnit\Framework\TestResult $result): void { if ($result->count() === 0) { $this->style->writeWarning('No tests executed!'); } $this->style->writeCurrentTestCaseSummary($this->state); if ($this->failed) { $onFailure = $this->state->suiteTotalTests !== $this->state->testSuiteTestsCount(); $this->style->writeErrorsSummary($this->state, $onFailure); } $this->style->writeRecap($this->state, $this->timer); } } PK������*Z~T ������Adapters/Phpunit/State.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Adapters\Phpunit; use NunoMaduro\Collision\Contracts\Adapters\Phpunit\HasPrintableTestCaseName; use PHPUnit\Framework\TestCase; /** * @internal */ final class State { /** * The complete test suite number of tests. * * @var int|null */ public $suiteTotalTests; /** * The complete test suite tests. * * @var array<int, TestResult> */ public $suiteTests = []; /** * The current test case class. * * @var string */ public $testCaseName; /** * The current test case tests. * * @var array<int, TestResult> */ public $testCaseTests = []; /** * The current test case tests. * * @var array<int, TestResult> */ public $toBePrintedCaseTests = []; /** * Header printed. * * @var bool */ public $headerPrinted = false; /** * The state constructor. */ private function __construct(string $testCaseName) { $this->testCaseName = $testCaseName; } /** * Creates a new State starting from the given test case. */ public static function from(TestCase $test): self { return new self(self::getPrintableTestCaseName($test)); } /** * Adds the given test to the State. */ public function add(TestResult $test): void { $this->testCaseTests[] = $test; $this->toBePrintedCaseTests[] = $test; $this->suiteTests[] = $test; } /** * Gets the test case title. */ public function getTestCaseTitle(): string { foreach ($this->testCaseTests as $test) { if ($test->type === TestResult::FAIL) { return 'FAIL'; } } foreach ($this->testCaseTests as $test) { if ($test->type !== TestResult::PASS) { return 'WARN'; } } return 'PASS'; } /** * Gets the test case title color. */ public function getTestCaseTitleColor(): string { foreach ($this->testCaseTests as $test) { if ($test->type === TestResult::FAIL) { return 'red'; } } foreach ($this->testCaseTests as $test) { if ($test->type !== TestResult::PASS) { return 'yellow'; } } return 'green'; } /** * Returns the number of tests on the current test case. */ public function testCaseTestsCount(): int { return count($this->testCaseTests); } /** * Returns the number of tests on the complete test suite. */ public function testSuiteTestsCount(): int { return count($this->suiteTests); } /** * Checks if the given test case is different from the current one. */ public function testCaseHasChanged(TestCase $testCase): bool { return self::getPrintableTestCaseName($testCase) !== $this->testCaseName; } /** * Moves the a new test case. */ public function moveTo(TestCase $testCase): void { $this->testCaseName = self::getPrintableTestCaseName($testCase); $this->testCaseTests = []; $this->headerPrinted = false; } /** * Foreach test in the test case. */ public function eachTestCaseTests(callable $callback): void { foreach ($this->toBePrintedCaseTests as $test) { $callback($test); } $this->toBePrintedCaseTests = []; } public function countTestsInTestSuiteBy(string $type): int { return count(array_filter($this->suiteTests, function (TestResult $testResult) use ($type) { return $testResult->type === $type; })); } /** * Checks if the given test already contains a result. */ public function existsInTestCase(TestCase $test): bool { foreach ($this->testCaseTests as $testResult) { if (TestResult::makeDescription($test) === $testResult->description) { return true; } } return false; } /** * Returns the printable test case name from the given `TestCase`. */ public static function getPrintableTestCaseName(TestCase $test): string { return $test instanceof HasPrintableTestCaseName ? $test->getPrintableTestCaseName() : get_class($test); } } PK������*Z������Adapters/Phpunit/Style.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Adapters\Phpunit; use NunoMaduro\Collision\Exceptions\ShouldNotHappen; use NunoMaduro\Collision\Writer; use PHPUnit\Framework\AssertionFailedError; use PHPUnit\Framework\ExceptionWrapper; use PHPUnit\Framework\ExpectationFailedException; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\ConsoleOutputInterface; use Throwable; use Whoops\Exception\Inspector; /** * @internal */ final class Style { /** * @var ConsoleOutput */ private $output; /** * Style constructor. */ public function __construct(ConsoleOutputInterface $output) { if (! $output instanceof ConsoleOutput) { throw new ShouldNotHappen(); } $this->output = $output; } /** * Prints the content. */ public function write(string $content): void { $this->output->write($content); } /** * Prints the content similar too:. * * ``` * PASS Unit\ExampleTest * ✓ basic test * ``` */ public function writeCurrentTestCaseSummary(State $state): void { if ($state->testCaseTestsCount() === 0) { return; } if (! $state->headerPrinted) { $this->output->writeln($this->titleLineFrom( $state->getTestCaseTitle() === 'FAIL' ? 'white' : 'black', $state->getTestCaseTitleColor(), $state->getTestCaseTitle(), $state->testCaseName )); $state->headerPrinted = true; } $state->eachTestCaseTests(function (TestResult $testResult) { $this->output->writeln($this->testLineFrom( $testResult->color, $testResult->icon, $testResult->description, $testResult->warning )); }); } /** * Prints the content similar too:. * * ``` * PASS Unit\ExampleTest * ✓ basic test * ``` */ public function writeErrorsSummary(State $state, bool $onFailure): void { $errors = array_filter($state->suiteTests, function (TestResult $testResult) { return $testResult->type === TestResult::FAIL; }); if (! $onFailure) { $this->output->writeln(['', " \e[2m---\e[22m", '']); } array_map(function (TestResult $testResult) use ($onFailure) { if (! $onFailure) { $this->output->write(sprintf( ' <fg=red;options=bold>• %s </>> <fg=red;options=bold>%s</>', $testResult->testCaseName, $testResult->description )); } if (! $testResult->throwable instanceof Throwable) { throw new ShouldNotHappen(); } $this->writeError($testResult->throwable); }, $errors); } /** * Writes the final recap. */ public function writeRecap(State $state, Timer $timer = null): void { $types = [TestResult::FAIL, TestResult::WARN, TestResult::RISKY, TestResult::INCOMPLETE, TestResult::SKIPPED, TestResult::PASS]; foreach ($types as $type) { if (($countTests = $state->countTestsInTestSuiteBy($type)) !== 0) { $color = TestResult::makeColor($type); $tests[] = "<fg=$color;options=bold>$countTests $type</>"; } } $pending = $state->suiteTotalTests - $state->testSuiteTestsCount(); if ($pending !== 0) { $tests[] = "\e[2m$pending pending\e[22m"; } if (! empty($tests)) { $this->output->write([ "\n", sprintf( ' <fg=white;options=bold>Tests: </><fg=default>%s</>', implode(', ', $tests) ), ]); } if ($timer !== null) { $timeElapsed = number_format($timer->result(), 2, '.', ''); $this->output->writeln([ '', sprintf( ' <fg=white;options=bold>Time: </><fg=default>%ss</>', $timeElapsed ), ] ); } $this->output->writeln(''); } /** * Displays a warning message. */ public function writeWarning(string $message): void { $this->output->writeln($this->testLineFrom('yellow', $message, '')); } /** * Displays the error using Collision's writer * and terminates with exit code === 1. */ public function writeError(Throwable $throwable): void { $writer = (new Writer())->setOutput($this->output); if ($throwable instanceof AssertionFailedError) { $writer->showTitle(false); $this->output->write('', true); } $writer->ignoreFilesIn([ '/vendor\/bin\/pest/', '/bin\/pest/', '/vendor\/pestphp\/pest/', '/vendor\/phpspec\/prophecy-phpunit/', '/vendor\/phpspec\/prophecy/', '/vendor\/phpunit\/phpunit\/src/', '/vendor\/mockery\/mockery/', '/vendor\/laravel\/dusk/', '/vendor\/laravel\/framework\/src\/Illuminate\/Testing/', '/vendor\/laravel\/framework\/src\/Illuminate\/Foundation\/Testing/', '/vendor\/symfony\/framework-bundle\/Test/', '/vendor\/symfony\/phpunit-bridge/', '/vendor\/symfony\/dom-crawler/', '/vendor\/symfony\/browser-kit/', '/vendor\/symfony\/css-selector/', '/vendor\/bin\/.phpunit/', '/bin\/.phpunit/', '/vendor\/bin\/simple-phpunit/', '/bin\/phpunit/', '/vendor\/coduo\/php-matcher\/src\/PHPUnit/', '/vendor\/sulu\/sulu\/src\/Sulu\/Bundle\/TestBundle\/Testing/', '/vendor\/webmozart\/assert/', ]); if ($throwable instanceof ExceptionWrapper && $throwable->getOriginalException() !== null) { $throwable = $throwable->getOriginalException(); } $inspector = new Inspector($throwable); $writer->write($inspector); if ($throwable instanceof ExpectationFailedException && $comparisionFailure = $throwable->getComparisonFailure()) { $diff = $comparisionFailure->getDiff(); $lines = explode(PHP_EOL, $diff); $diff = ''; foreach ($lines as $line) { if (0 === strpos($line, '-')) { $line = '<fg=red>'.$line.'</>'; } elseif (0 === strpos($line, '+')) { $line = '<fg=green>'.$line.'</>'; } $diff .= $line.PHP_EOL; } $diff = trim((string) preg_replace("/\r|\n/", "\n ", $diff)); $this->output->write(" $diff"); } $this->output->writeln(''); } /** * Returns the title contents. */ private function titleLineFrom(string $fg, string $bg, string $title, string $testCaseName): string { return sprintf( "\n <fg=%s;bg=%s;options=bold> %s </><fg=default> %s</>", $fg, $bg, $title, $testCaseName ); } /** * Returns the test contents. */ private function testLineFrom(string $fg, string $icon, string $description, string $warning = null): string { if (! empty($warning)) { $warning = sprintf( ' → %s', $warning ); } return sprintf( " <fg=%s;options=bold>%s</><fg=default> \e[2m%s\e[22m</><fg=yellow>%s</>", $fg, $icon, $description, $warning ); } } PK������*ZJ�����0��Adapters/Laravel/IgnitionSolutionsRepository.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Adapters\Laravel; use NunoMaduro\Collision\Contracts\SolutionsRepository; use Spatie\Ignition\Contracts\SolutionProviderRepository; use Throwable; /** * @internal */ final class IgnitionSolutionsRepository implements SolutionsRepository { /** * Holds an instance of ignition solutions provider repository. * * @var \Spatie\Ignition\Contracts\SolutionProviderRepository */ protected $solutionProviderRepository; /** * IgnitionSolutionsRepository constructor. */ public function __construct(SolutionProviderRepository $solutionProviderRepository) { $this->solutionProviderRepository = $solutionProviderRepository; } /** * {@inheritdoc} */ public function getFromThrowable(Throwable $throwable): array { return $this->solutionProviderRepository->getSolutionsForThrowable($throwable); } } PK������*ZvS������Adapters/Laravel/Inspector.phpnu�W+A��������<?php declare(strict_types=1); /** * This file is part of Collision. * * (c) Nuno Maduro <enunomaduro@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace NunoMaduro\Collision\Adapters\Laravel; use Whoops\Exception\Inspector as BaseInspector; /** * @internal */ final class Inspector extends BaseInspector { /** * {@inheritdoc} */ protected function getTrace($e) { return $e->getTrace(); } } PK������*Z]Gt �� ��-��Adapters/Laravel/CollisionServiceProvider.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Adapters\Laravel; use Illuminate\Contracts\Debug\ExceptionHandler as ExceptionHandlerContract; use Illuminate\Support\ServiceProvider; use NunoMaduro\Collision\Adapters\Laravel\Commands\TestCommand; use NunoMaduro\Collision\Contracts\Provider as ProviderContract; use NunoMaduro\Collision\Handler; use NunoMaduro\Collision\Provider; use NunoMaduro\Collision\SolutionsRepositories\NullSolutionsRepository; use NunoMaduro\Collision\Writer; /** * @internal * * @final */ class CollisionServiceProvider extends ServiceProvider { /** * {@inheritdoc} * * @var bool */ protected $defer = true; /** * Boots application services. * * @return void */ public function boot() { $this->commands([ TestCommand::class, ]); } /** * {@inheritdoc} */ public function register() { if ($this->app->runningInConsole() && ! $this->app->runningUnitTests()) { $this->app->bind(ProviderContract::class, function () { // @phpstan-ignore-next-line if ($this->app->has(\Spatie\Ignition\Contracts\SolutionProviderRepository::class)) { /** @var \Spatie\Ignition\Contracts\SolutionProviderRepository $solutionProviderRepository */ $solutionProviderRepository = $this->app->get(\Spatie\Ignition\Contracts\SolutionProviderRepository::class); $solutionsRepository = new IgnitionSolutionsRepository($solutionProviderRepository); } else { $solutionsRepository = new NullSolutionsRepository(); } $writer = new Writer($solutionsRepository); $handler = new Handler($writer); return new Provider(null, $handler); }); /** @var \Illuminate\Contracts\Debug\ExceptionHandler $appExceptionHandler */ $appExceptionHandler = $this->app->make(ExceptionHandlerContract::class); $this->app->singleton( ExceptionHandlerContract::class, function ($app) use ($appExceptionHandler) { return new ExceptionHandler($app, $appExceptionHandler); } ); } } /** * {@inheritdoc} */ public function provides() { return [ProviderContract::class]; } } PK������*ZJ_��_��5��Adapters/Laravel/Exceptions/RequirementsException.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Adapters\Laravel\Exceptions; use NunoMaduro\Collision\Contracts\RenderlessEditor; use NunoMaduro\Collision\Contracts\RenderlessTrace; use RuntimeException; /** * @internal */ final class RequirementsException extends RuntimeException implements RenderlessEditor, RenderlessTrace { } PK������*ZZ ,��,��)��Adapters/Laravel/Commands/TestCommand.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Adapters\Laravel\Commands; use Dotenv\Exception\InvalidPathException; use Dotenv\Parser\Parser; use Dotenv\Store\StoreBuilder; use Illuminate\Console\Command; use Illuminate\Support\Env; use Illuminate\Support\Str; use NunoMaduro\Collision\Adapters\Laravel\Exceptions\RequirementsException; use NunoMaduro\Collision\Coverage; use RuntimeException; use Symfony\Component\Process\Exception\ProcessSignaledException; use Symfony\Component\Process\Process; /** * @internal * * @final */ class TestCommand extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'test {--without-tty : Disable output to TTY} {--coverage : Indicates whether code coverage information should be collected} {--min= : Indicates the minimum threshold enforcement for code coverage} {--p|parallel : Indicates if the tests should run in parallel} {--recreate-databases : Indicates if the test databases should be re-created} {--drop-databases : Indicates if the test databases should be dropped} '; /** * The console command description. * * @var string */ protected $description = 'Run the application tests'; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); $this->ignoreValidationErrors(); } /** * Execute the console command. * * @return mixed */ public function handle() { $phpunitVersion = \PHPUnit\Runner\Version::id(); if ((int) $phpunitVersion[0] === 1) { throw new RequirementsException('Running PHPUnit 10.x or Pest 2.x requires Collision 7.x.'); } if ((int) $phpunitVersion[0] < 9) { throw new RequirementsException('Running Collision 6.x artisan test command requires at least PHPUnit 9.x.'); } $laravelVersion = (int) \Illuminate\Foundation\Application::VERSION; // @phpstan-ignore-next-line if ($laravelVersion < 9) { throw new RequirementsException('Running Collision 6.x artisan test command requires at least Laravel 9.x.'); } if ($this->option('coverage') && ! Coverage::isAvailable()) { $this->output->writeln(sprintf( "\n <fg=white;bg=red;options=bold> ERROR </> Code coverage driver not available.%s</>", Coverage::usingXdebug() ? " Did you set <href=https://xdebug.org/docs/code_coverage#mode>Xdebug's coverage mode</>?" : '' )); $this->newLine(); return 1; } if ($this->option('parallel') && ! $this->isParallelDependenciesInstalled()) { if (! $this->confirm('Running tests in parallel requires "brianium/paratest". Do you wish to install it as a dev dependency?')) { return 1; } $this->installParallelDependencies(); } $options = array_slice($_SERVER['argv'], $this->option('without-tty') ? 3 : 2); $this->clearEnv(); $parallel = $this->option('parallel'); $process = (new Process(array_merge( // Binary ... $this->binary(), // Arguments ... $parallel ? $this->paratestArguments($options) : $this->phpunitArguments($options) ), null, // Envs ... $parallel ? $this->paratestEnvironmentVariables() : $this->phpunitEnvironmentVariables(), ))->setTimeout(null); try { $process->setTty(! $this->option('without-tty')); } catch (RuntimeException $e) { $this->output->writeln('Warning: '.$e->getMessage()); } $exitCode = 1; try { $exitCode = $process->run(function ($type, $line) { $this->output->write($line); }); } catch (ProcessSignaledException $e) { if (extension_loaded('pcntl') && $e->getSignal() !== SIGINT) { throw $e; } } if ($exitCode === 0 && $this->option('coverage')) { if (! $this->usingPest() && $this->option('parallel')) { $this->newLine(); } $coverage = Coverage::report($this->output); $exitCode = (int) ($coverage < $this->option('min')); if ($exitCode === 1) { $this->output->writeln(sprintf( "\n <fg=white;bg=red;options=bold> FAIL </> Code coverage below expected:<fg=red;options=bold> %s %%</>. Minimum:<fg=white;options=bold> %s %%</>.", number_format($coverage, 1), number_format((float) $this->option('min'), 1) )); } } $this->newLine(); return $exitCode; } /** * Get the PHP binary to execute. * * @return array */ protected function binary() { if ($this->usingPest()) { $command = $this->option('parallel') ? ['vendor/pestphp/pest/bin/pest', '--parallel'] : ['vendor/pestphp/pest/bin/pest']; } else { $command = $this->option('parallel') ? ['vendor/brianium/paratest/bin/paratest'] : ['vendor/phpunit/phpunit/phpunit']; } if ('phpdbg' === PHP_SAPI) { return array_merge([PHP_BINARY, '-qrr'], $command); } return array_merge([PHP_BINARY], $command); } /** * Gets the common arguments of PHPUnit and Pest. * * @return array */ protected function commonArguments() { $arguments = []; if ($this->option('coverage')) { $arguments[] = '--coverage-php'; $arguments[] = Coverage::getPath(); } return $arguments; } /** * Determines if Pest is being used. * * @return bool */ protected function usingPest() { return class_exists(\Pest\Laravel\PestServiceProvider::class); } /** * Get the array of arguments for running PHPUnit. * * @param array $options * @return array */ protected function phpunitArguments($options) { $options = array_merge(['--printer=NunoMaduro\\Collision\\Adapters\\Phpunit\\Printer'], $options); $options = array_values(array_filter($options, function ($option) { return ! Str::startsWith($option, '--env=') && $option != '-q' && $option != '--quiet' && $option != '--coverage' && ! Str::startsWith($option, '--min'); })); if (! file_exists($file = base_path('phpunit.xml'))) { $file = base_path('phpunit.xml.dist'); } return array_merge($this->commonArguments(), ["--configuration=$file"], $options); } /** * Get the array of arguments for running Paratest. * * @param array $options * @return array */ protected function paratestArguments($options) { $options = array_values(array_filter($options, function ($option) { return ! Str::startsWith($option, '--env=') && $option != '--coverage' && $option != '-q' && $option != '--quiet' && ! Str::startsWith($option, '--min') && ! Str::startsWith($option, '-p') && ! Str::startsWith($option, '--parallel') && ! Str::startsWith($option, '--recreate-databases') && ! Str::startsWith($option, '--drop-databases'); })); if (! file_exists($file = base_path('phpunit.xml'))) { $file = base_path('phpunit.xml.dist'); } return array_merge($this->commonArguments(), [ "--configuration=$file", "--runner=\Illuminate\Testing\ParallelRunner", ], $options); } /** * Get the array of environment variables for running PHPUnit. * * @return array */ protected function phpunitEnvironmentVariables() { return []; } /** * Get the array of environment variables for running Paratest. * * @return array */ protected function paratestEnvironmentVariables() { return [ 'LARAVEL_PARALLEL_TESTING' => 1, 'LARAVEL_PARALLEL_TESTING_RECREATE_DATABASES' => $this->option('recreate-databases'), 'LARAVEL_PARALLEL_TESTING_DROP_DATABASES' => $this->option('drop-databases'), ]; } /** * Clears any set Environment variables set by Laravel if the --env option is empty. * * @return void */ protected function clearEnv() { if (! $this->option('env')) { $vars = self::getEnvironmentVariables( // @phpstan-ignore-next-line $this->laravel->environmentPath(), // @phpstan-ignore-next-line $this->laravel->environmentFile() ); $repository = Env::getRepository(); foreach ($vars as $name) { $repository->clear($name); } } } /** * @param string $path * @param string $file * @return array */ protected static function getEnvironmentVariables($path, $file) { try { $content = StoreBuilder::createWithNoNames() ->addPath($path) ->addName($file) ->make() ->read(); } catch (InvalidPathException $e) { return []; } $vars = []; foreach ((new Parser())->parse($content) as $entry) { $vars[] = $entry->getName(); } return $vars; } /** * Check if the parallel dependencies are installed. * * @return bool */ protected function isParallelDependenciesInstalled() { return class_exists(\ParaTest\Console\Commands\ParaTestCommand::class); } /** * Install parallel testing needed dependencies. * * @return void */ protected function installParallelDependencies() { $command = $this->findComposer().' require brianium/paratest --dev'; $process = Process::fromShellCommandline($command, null, null, null, null); if ('\\' !== DIRECTORY_SEPARATOR && file_exists('/dev/tty') && is_readable('/dev/tty')) { try { $process->setTty(true); } catch (RuntimeException $e) { $this->output->writeln('Warning: '.$e->getMessage()); } } try { $process->run(function ($type, $line) { $this->output->write($line); }); } catch (ProcessSignaledException $e) { if (extension_loaded('pcntl') && $e->getSignal() !== SIGINT) { throw $e; } } } /** * Get the composer command for the environment. * * @return string */ protected function findComposer() { $composerPath = getcwd().'/composer.phar'; if (file_exists($composerPath)) { return '"'.PHP_BINARY.'" '.$composerPath; } return 'composer'; } } PK������*Zrڵ����%��Adapters/Laravel/ExceptionHandler.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Adapters\Laravel; use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Debug\ExceptionHandler as ExceptionHandlerContract; use NunoMaduro\Collision\Contracts\Provider as ProviderContract; use Symfony\Component\Console\Exception\ExceptionInterface as SymfonyConsoleExceptionInterface; use Throwable; /** * @internal */ final class ExceptionHandler implements ExceptionHandlerContract { /** * Holds an instance of the application exception handler. * * @var \Illuminate\Contracts\Debug\ExceptionHandler */ protected $appExceptionHandler; /** * Holds an instance of the container. * * @var \Illuminate\Contracts\Container\Container */ protected $container; /** * Creates a new instance of the ExceptionHandler. */ public function __construct(Container $container, ExceptionHandlerContract $appExceptionHandler) { $this->container = $container; $this->appExceptionHandler = $appExceptionHandler; } /** * {@inheritdoc} */ public function report(Throwable $e) { $this->appExceptionHandler->report($e); } /** * {@inheritdoc} */ public function render($request, Throwable $e) { return $this->appExceptionHandler->render($request, $e); } /** * {@inheritdoc} */ public function renderForConsole($output, Throwable $e) { if ($e instanceof SymfonyConsoleExceptionInterface) { $this->appExceptionHandler->renderForConsole($output, $e); } else { /** @var \NunoMaduro\Collision\Contracts\Provider $provider */ $provider = $this->container->make(ProviderContract::class); $handler = $provider->register() ->getHandler() ->setOutput($output); $handler->setInspector((new Inspector($e))); $handler->handle(); } } /** * Determine if the exception should be reported. * * @return bool */ public function shouldReport(Throwable $e) { return $this->appExceptionHandler->shouldReport($e); } } PK������*ZGO%��%����Contracts/Handler.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Contracts; use Symfony\Component\Console\Output\OutputInterface; use Whoops\Handler\HandlerInterface; /** * @internal */ interface Handler extends HandlerInterface { /** * Sets the output. * * @return \NunoMaduro\Collision\Contracts\Handler */ public function setOutput(OutputInterface $output): Handler; /** * Returns the writer. * * @return \NunoMaduro\Collision\Contracts\Writer */ public function getWriter(): Writer; } PK������*Z,̀��������Contracts/RenderlessEditor.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Contracts; /** * @internal */ interface RenderlessEditor { } PK������*Z$��������Contracts/RenderlessTrace.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Contracts; /** * @internal */ interface RenderlessTrace { } PK������*Zl������Contracts/Writer.phpnu�W+A��������<?php declare(strict_types=1); /** * This file is part of Collision. * * (c) Nuno Maduro <enunomaduro@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace NunoMaduro\Collision\Contracts; use Symfony\Component\Console\Output\OutputInterface; use Whoops\Exception\Inspector; /** * @internal */ interface Writer { /** * Ignores traces where the file string matches one * of the provided regex expressions. * * @param string[] $ignore the regex expressions * @return \NunoMaduro\Collision\Contracts\Writer */ public function ignoreFilesIn(array $ignore): Writer; /** * Declares whether or not the Writer should show the trace. * * @return \NunoMaduro\Collision\Contracts\Writer */ public function showTrace(bool $show): Writer; /** * Declares whether or not the Writer should show the title. * * @return \NunoMaduro\Collision\Contracts\Writer */ public function showTitle(bool $show): Writer; /** * Declares whether or not the Writer should show the editor. * * @return \NunoMaduro\Collision\Contracts\Writer */ public function showEditor(bool $show): Writer; /** * Writes the details of the exception on the console. */ public function write(Inspector $inspector): void; /** * Sets the output. * * @return \NunoMaduro\Collision\Contracts\Writer */ public function setOutput(OutputInterface $output): Writer; /** * Gets the output. */ public function getOutput(): OutputInterface; } PK������*Zp��p��!��Contracts/SolutionsRepository.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Contracts; use Spatie\Ignition\Contracts\Solution; use Throwable; /** * @internal */ interface SolutionsRepository { /** * Gets the solutions from the given `$throwable`. * * @return array<int, Solution> */ public function getFromThrowable(Throwable $throwable): array; } PK������*ZrԾ������Contracts/Provider.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Contracts; /** * @internal */ interface Provider { /** * Registers the current Handler as Error Handler. * * @return \NunoMaduro\Collision\Contracts\Provider */ public function register(): Provider; /** * Returns the handler. * * @return \NunoMaduro\Collision\Contracts\Handler */ public function getHandler(): Handler; } PK������*ZS9��9����Contracts/ArgumentFormatter.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Contracts; /** * @internal */ interface ArgumentFormatter { /** * Formats the provided array of arguments into * an understandable description. */ public function format(array $arguments, bool $recursive = true): string; } PK������*Z_''��'��7��Contracts/Adapters/Phpunit/HasPrintableTestCaseName.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Contracts\Adapters\Phpunit; /** * @internal */ interface HasPrintableTestCaseName { /** * Returns the test case name that should be used by the printer. */ public function getPrintableTestCaseName(): string; } PK������*Zz��z��'��Contracts/Adapters/Phpunit/Listener.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Contracts\Adapters\Phpunit; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestListener; /** * @internal */ interface Listener extends TestListener { /** * Renders the provided error * on the console. * * @return void */ public function render(Test $test, \Throwable $t); } PK������*ZQ��������Contracts/Highlighter.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision\Contracts; /** * @internal */ interface Highlighter { /** * Highlights the provided content. */ public function highlight(string $content, int $line): string; } PK������*ZF h��h�� ��Coverage.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision; use SebastianBergmann\CodeCoverage\CodeCoverage; use SebastianBergmann\CodeCoverage\Node\Directory; use SebastianBergmann\CodeCoverage\Node\File; use SebastianBergmann\Environment\Runtime; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Terminal; /** * @internal */ final class Coverage { /** * Returns the coverage path. */ public static function getPath(): string { return implode(DIRECTORY_SEPARATOR, [ dirname(__DIR__), '.temp', 'coverage', ]); } /** * Runs true there is any code coverage driver available. */ public static function isAvailable(): bool { if (! (new Runtime())->canCollectCodeCoverage()) { return false; } if (static::usingXdebug()) { $mode = getenv('XDEBUG_MODE') ?: ini_get('xdebug.mode'); return $mode && in_array('coverage', explode(',', $mode), true); } return true; } /** * If the user is using Xdebug. */ public static function usingXdebug(): bool { return (new Runtime())->hasXdebug(); } /** * Reports the code coverage report to the * console and returns the result in float. */ public static function report(OutputInterface $output): float { if (! file_exists($reportPath = self::getPath())) { if (self::usingXdebug()) { $output->writeln( " <fg=black;bg=yellow;options=bold> WARN </> Unable to get coverage using Xdebug. Did you set <href=https://xdebug.org/docs/code_coverage#mode>Xdebug's coverage mode</>?</>", ); return 0.0; } $output->writeln( ' <fg=black;bg=yellow;options=bold> WARN </> No coverage driver detected.</>', ); return 0.0; } /** @var CodeCoverage $codeCoverage */ $codeCoverage = require $reportPath; unlink($reportPath); $totalCoverage = $codeCoverage->getReport()->percentageOfExecutedLines(); $totalWidth = (new Terminal())->getWidth(); $dottedLineLength = $totalWidth; /** @var Directory<File|Directory> $report */ $report = $codeCoverage->getReport(); foreach ($report->getIterator() as $file) { if (! $file instanceof File) { continue; } $dirname = dirname($file->id()); $basename = basename($file->id(), '.php'); $name = $dirname === '.' ? $basename : implode(DIRECTORY_SEPARATOR, [ $dirname, $basename, ]); $rawName = $dirname === '.' ? $basename : implode(DIRECTORY_SEPARATOR, [ $dirname, $basename, ]); $linesExecutedTakenSize = 0; if ($file->percentageOfExecutedLines()->asString() != '0.00%') { $linesExecutedTakenSize = strlen($uncoveredLines = trim(implode(', ', self::getMissingCoverage($file)))) + 1; $name .= sprintf(' <fg=red>%s</>', $uncoveredLines); } $percentage = $file->numberOfExecutableLines() === 0 ? '100.0' : number_format($file->percentageOfExecutedLines()->asFloat(), 1, '.', ''); $takenSize = strlen($rawName.$percentage) + 8 + $linesExecutedTakenSize; // adding 3 space and percent sign $percentage = sprintf( '<fg=%s%s>%s</>', $percentage === '100.0' ? 'green' : ($percentage === '0.0' ? 'red' : 'yellow'), $percentage === '100.0' ? ';options=bold' : '', $percentage ); $output->writeln(sprintf( ' <fg=white>%s</> <fg=#6C7280>%s</> %s <fg=#6C7280>%%</>', $name, str_repeat('.', max($dottedLineLength - $takenSize, 1)), $percentage )); } $output->writeln(''); $rawName = 'Total Coverage'; $takenSize = strlen($rawName.$totalCoverage->asString()) + 6; $output->writeln(sprintf( ' <fg=white;options=bold>%s</> <fg=#6C7280>%s</> %s <fg=#6C7280>%%</>', $rawName, str_repeat('.', max($dottedLineLength - $takenSize, 1)), number_format($totalCoverage->asFloat(), 1, '.', '') )); return $totalCoverage->asFloat(); } /** * Generates an array of missing coverage on the following format:. * * ``` * ['11', '20..25', '50', '60..80']; * ``` * * @param File $file * @return array<int, string> */ public static function getMissingCoverage($file): array { $shouldBeNewLine = true; $eachLine = function (array $array, array $tests, int $line) use (&$shouldBeNewLine): array { if (count($tests) > 0) { $shouldBeNewLine = true; return $array; } if ($shouldBeNewLine) { $array[] = (string) $line; $shouldBeNewLine = false; return $array; } $lastKey = count($array) - 1; if (array_key_exists($lastKey, $array) && str_contains($array[$lastKey], '..')) { [$from] = explode('..', $array[$lastKey]); $array[$lastKey] = $line > $from ? sprintf('%s..%s', $from, $line) : sprintf('%s..%s', $line, $from); return $array; } $array[$lastKey] = sprintf('%s..%s', $array[$lastKey], $line); return $array; }; $array = []; foreach (array_filter($file->lineCoverageData(), 'is_array') as $line => $tests) { $array = $eachLine($array, $tests, $line); } return $array; } } PK������*ZV#������ConsoleColor.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision; use NunoMaduro\Collision\Exceptions\InvalidStyleException; use NunoMaduro\Collision\Exceptions\ShouldNotHappen; /** * @internal */ final class ConsoleColor { public const FOREGROUND = 38; public const BACKGROUND = 48; public const COLOR256_REGEXP = '~^(bg_)?color_(\d{1,3})$~'; public const RESET_STYLE = 0; /** @var bool */ private $isSupported; /** @var bool */ private $forceStyle = false; /** @var array */ private const STYLES = [ 'none' => null, 'bold' => '1', 'dark' => '2', 'italic' => '3', 'underline' => '4', 'blink' => '5', 'reverse' => '7', 'concealed' => '8', 'default' => '39', 'black' => '30', 'red' => '31', 'green' => '32', 'yellow' => '33', 'blue' => '34', 'magenta' => '35', 'cyan' => '36', 'light_gray' => '37', 'dark_gray' => '90', 'light_red' => '91', 'light_green' => '92', 'light_yellow' => '93', 'light_blue' => '94', 'light_magenta' => '95', 'light_cyan' => '96', 'white' => '97', 'bg_default' => '49', 'bg_black' => '40', 'bg_red' => '41', 'bg_green' => '42', 'bg_yellow' => '43', 'bg_blue' => '44', 'bg_magenta' => '45', 'bg_cyan' => '46', 'bg_light_gray' => '47', 'bg_dark_gray' => '100', 'bg_light_red' => '101', 'bg_light_green' => '102', 'bg_light_yellow' => '103', 'bg_light_blue' => '104', 'bg_light_magenta' => '105', 'bg_light_cyan' => '106', 'bg_white' => '107', ]; /** @var array */ private $themes = []; public function __construct() { $this->isSupported = $this->isSupported(); } /** * @param string|array $style * @param string $text * @return string * * @throws InvalidStyleException * @throws \InvalidArgumentException */ public function apply($style, $text) { if (! $this->isStyleForced() && ! $this->isSupported()) { return $text; } if (is_string($style)) { $style = [$style]; } if (! is_array($style)) { throw new \InvalidArgumentException('Style must be string or array.'); } $sequences = []; foreach ($style as $s) { if (isset($this->themes[$s])) { $sequences = array_merge($sequences, $this->themeSequence($s)); } elseif ($this->isValidStyle($s)) { $sequences[] = $this->styleSequence($s); } else { throw new ShouldNotHappen(); } } $sequences = array_filter($sequences, function ($val) { return $val !== null; }); if (empty($sequences)) { return $text; } return $this->escSequence(implode(';', $sequences)).$text.$this->escSequence(self::RESET_STYLE); } /** * @param bool $forceStyle */ public function setForceStyle($forceStyle) { $this->forceStyle = $forceStyle; } /** * @return bool */ public function isStyleForced() { return $this->forceStyle; } public function setThemes(array $themes) { $this->themes = []; foreach ($themes as $name => $styles) { $this->addTheme($name, $styles); } } /** * @param string $name * @param array|string $styles */ public function addTheme($name, $styles) { if (is_string($styles)) { $styles = [$styles]; } if (! is_array($styles)) { throw new \InvalidArgumentException('Style must be string or array.'); } foreach ($styles as $style) { if (! $this->isValidStyle($style)) { throw new InvalidStyleException($style); } } $this->themes[$name] = $styles; } /** * @return array */ public function getThemes() { return $this->themes; } /** * @param string $name * @return bool */ public function hasTheme($name) { return isset($this->themes[$name]); } /** * @param string $name */ public function removeTheme($name) { unset($this->themes[$name]); } /** * @return bool */ public function isSupported() { // The COLLISION_FORCE_COLORS variable is for internal purposes only if (getenv('COLLISION_FORCE_COLORS') !== false) { return true; } if (DIRECTORY_SEPARATOR === '\\') { return getenv('ANSICON') !== false || getenv('ConEmuANSI') === 'ON'; } return function_exists('posix_isatty') && @posix_isatty(STDOUT); } /** * @return bool */ public function are256ColorsSupported() { if (DIRECTORY_SEPARATOR === '\\') { return function_exists('sapi_windows_vt100_support') && @sapi_windows_vt100_support(STDOUT); } return strpos(getenv('TERM'), '256color') !== false; } /** * @return array */ public function getPossibleStyles() { return array_keys(self::STYLES); } /** * @param string $name * @return string[] */ private function themeSequence($name) { $sequences = []; foreach ($this->themes[$name] as $style) { $sequences[] = $this->styleSequence($style); } return $sequences; } /** * @param string $style * @return string */ private function styleSequence($style) { if (array_key_exists($style, self::STYLES)) { return self::STYLES[$style]; } if (! $this->are256ColorsSupported()) { return null; } preg_match(self::COLOR256_REGEXP, $style, $matches); $type = $matches[1] === 'bg_' ? self::BACKGROUND : self::FOREGROUND; $value = $matches[2]; return "$type;5;$value"; } /** * @param string $style * @return bool */ private function isValidStyle($style) { return array_key_exists($style, self::STYLES) || preg_match(self::COLOR256_REGEXP, $style); } /** * @param string|int $value * @return string */ private function escSequence($value) { return "\033[{$value}m"; } } PK������*Z+q"��q"����Highlighter.phpnu�W+A��������<?php declare(strict_types=1); namespace NunoMaduro\Collision; use NunoMaduro\Collision\Contracts\Highlighter as HighlighterContract; /** * @internal */ final class Highlighter implements HighlighterContract { public const TOKEN_DEFAULT = 'token_default'; public const TOKEN_COMMENT = 'token_comment'; public const TOKEN_STRING = 'token_string'; public const TOKEN_HTML = 'token_html'; public const TOKEN_KEYWORD = 'token_keyword'; public const ACTUAL_LINE_MARK = 'actual_line_mark'; public const LINE_NUMBER = 'line_number'; private const ARROW_SYMBOL = '>'; private const DELIMITER = '|'; private const ARROW_SYMBOL_UTF8 = '➜'; private const DELIMITER_UTF8 = '▕'; // '▶'; private const LINE_NUMBER_DIVIDER = 'line_divider'; private const MARKED_LINE_NUMBER = 'marked_line'; private const WIDTH = 3; /** * Holds the theme. * * @var array */ private const THEME = [ self::TOKEN_STRING => ['light_gray'], self::TOKEN_COMMENT => ['dark_gray', 'italic'], self::TOKEN_KEYWORD => ['magenta', 'bold'], self::TOKEN_DEFAULT => ['default', 'bold'], self::TOKEN_HTML => ['blue', 'bold'], self::ACTUAL_LINE_MARK => ['red', 'bold'], self::LINE_NUMBER => ['dark_gray'], self::MARKED_LINE_NUMBER => ['italic', 'bold'], self::LINE_NUMBER_DIVIDER => ['dark_gray'], ]; /** @var ConsoleColor */ private $color; /** @var array */ private const DEFAULT_THEME = [ self::TOKEN_STRING => 'red', self::TOKEN_COMMENT => 'yellow', self::TOKEN_KEYWORD => 'green', self::TOKEN_DEFAULT => 'default', self::TOKEN_HTML => 'cyan', self::ACTUAL_LINE_MARK => 'dark_gray', self::LINE_NUMBER => 'dark_gray', self::MARKED_LINE_NUMBER => 'dark_gray', self::LINE_NUMBER_DIVIDER => 'dark_gray', ]; /** @var string */ private $delimiter = self::DELIMITER_UTF8; /** @var string */ private $arrow = self::ARROW_SYMBOL_UTF8; /** * @var string */ private const NO_MARK = ' '; /** * Creates an instance of the Highlighter. */ public function __construct(ConsoleColor $color = null, bool $UTF8 = true) { $this->color = $color ?: new ConsoleColor(); foreach (self::DEFAULT_THEME as $name => $styles) { if (! $this->color->hasTheme($name)) { $this->color->addTheme($name, $styles); } } foreach (self::THEME as $name => $styles) { $this->color->addTheme($name, $styles); } if (! $UTF8) { $this->delimiter = self::DELIMITER; $this->arrow = self::ARROW_SYMBOL; } $this->delimiter .= ' '; } /** * {@inheritdoc} */ public function highlight(string $content, int $line): string { return rtrim($this->getCodeSnippet($content, $line, 4, 4)); } /** * @param string $source * @param int $lineNumber * @param int $linesBefore * @param int $linesAfter */ public function getCodeSnippet($source, $lineNumber, $linesBefore = 2, $linesAfter = 2): string { $tokenLines = $this->getHighlightedLines($source); $offset = $lineNumber - $linesBefore - 1; $offset = max($offset, 0); $length = $linesAfter + $linesBefore + 1; $tokenLines = array_slice($tokenLines, $offset, $length, $preserveKeys = true); $lines = $this->colorLines($tokenLines); return $this->lineNumbers($lines, $lineNumber); } /** * @param string $source */ private function getHighlightedLines($source): array { $source = str_replace(["\r\n", "\r"], "\n", $source); $tokens = $this->tokenize($source); return $this->splitToLines($tokens); } /** * @param string $source */ private function tokenize($source): array { $tokens = token_get_all($source); $output = []; $currentType = null; $buffer = ''; foreach ($tokens as $token) { if (is_array($token)) { switch ($token[0]) { case T_WHITESPACE: break; case T_OPEN_TAG: case T_OPEN_TAG_WITH_ECHO: case T_CLOSE_TAG: case T_STRING: case T_VARIABLE: // Constants case T_DIR: case T_FILE: case T_METHOD_C: case T_DNUMBER: case T_LNUMBER: case T_NS_C: case T_LINE: case T_CLASS_C: case T_FUNC_C: case T_TRAIT_C: $newType = self::TOKEN_DEFAULT; break; case T_COMMENT: case T_DOC_COMMENT: $newType = self::TOKEN_COMMENT; break; case T_ENCAPSED_AND_WHITESPACE: case T_CONSTANT_ENCAPSED_STRING: $newType = self::TOKEN_STRING; break; case T_INLINE_HTML: $newType = self::TOKEN_HTML; break; default: $newType = self::TOKEN_KEYWORD; } } else { $newType = $token === '"' ? self::TOKEN_STRING : self::TOKEN_KEYWORD; } if ($currentType === null) { $currentType = $newType; } if ($currentType !== $newType) { $output[] = [$currentType, $buffer]; $buffer = ''; $currentType = $newType; } $buffer .= is_array($token) ? $token[1] : $token; } if (isset($newType)) { $output[] = [$newType, $buffer]; } return $output; } private function splitToLines(array $tokens): array { $lines = []; $line = []; foreach ($tokens as $token) { foreach (explode("\n", $token[1]) as $count => $tokenLine) { if ($count > 0) { $lines[] = $line; $line = []; } if ($tokenLine === '') { continue; } $line[] = [$token[0], $tokenLine]; } } $lines[] = $line; return $lines; } private function colorLines(array $tokenLines): array { $lines = []; foreach ($tokenLines as $lineCount => $tokenLine) { $line = ''; foreach ($tokenLine as $token) { [$tokenType, $tokenValue] = $token; if ($this->color->hasTheme($tokenType)) { $line .= $this->color->apply($tokenType, $tokenValue); } else { $line .= $tokenValue; } } $lines[$lineCount] = $line; } return $lines; } /** * @param int|null $markLine */ private function lineNumbers(array $lines, $markLine = null): string { $lineStrlen = strlen((string) (array_key_last($lines) + 1)); $lineStrlen = $lineStrlen < self::WIDTH ? self::WIDTH : $lineStrlen; $snippet = ''; $mark = ' '.$this->arrow.' '; foreach ($lines as $i => $line) { $coloredLineNumber = $this->coloredLineNumber(self::LINE_NUMBER, $i, $lineStrlen); if (null !== $markLine) { $snippet .= ($markLine === $i + 1 ? $this->color->apply(self::ACTUAL_LINE_MARK, $mark) : self::NO_MARK ); $coloredLineNumber = ($markLine === $i + 1 ? $this->coloredLineNumber(self::MARKED_LINE_NUMBER, $i, $lineStrlen) : $coloredLineNumber ); } $snippet .= $coloredLineNumber; $snippet .= $this->color->apply(self::LINE_NUMBER_DIVIDER, $this->delimiter); $snippet .= $line.PHP_EOL; } return $snippet; } /** * @param string $style * @param int $i * @param int $lineStrlen */ private function coloredLineNumber($style, $i, $lineStrlen): string { return $this->color->apply($style, str_pad((string) ($i + 1), $lineStrlen, ' ', STR_PAD_LEFT)); } } PK������,Zœ-��-�� ��Restorer.phpnu�W+A��������<?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 function_exists; use function get_defined_functions; use function in_array; use function is_array; use ReflectionClass; use ReflectionProperty; /** * Restorer of snapshots of global state. */ class Restorer { /** * Deletes function definitions that are not defined in a snapshot. * * @throws RuntimeException when the uopz_delete() function is not available * * @see https://github.com/krakjoe/uopz */ public function restoreFunctions(Snapshot $snapshot): void { if (!function_exists('uopz_delete')) { throw new RuntimeException('The uopz_delete() function is required for this operation'); } $functions = get_defined_functions(); foreach (array_diff($functions['user'], $snapshot->functions()) as $function) { uopz_delete($function); } } /** * Restores all global and super-global variables from a snapshot. */ 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]); } } } } /** * Restores all static attributes in user-defined classes from this snapshot. */ public function restoreStaticAttributes(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->staticAttributes() as $className => $staticAttributes) { foreach ($staticAttributes as $name => $value) { $reflector = new ReflectionProperty($className, $name); $reflector->setAccessible(true); $reflector->setValue(null, $value); } } foreach ($newClasses as $className) { $class = new ReflectionClass($className); $defaults = $class->getDefaultProperties(); foreach ($class->getProperties() as $attribute) { if (!$attribute->isStatic()) { continue; } $name = $attribute->getName(); if ($snapshot->excludeList()->isStaticAttributeExcluded($className, $name)) { continue; } if (!isset($defaults[$name])) { continue; } $attribute->setAccessible(true); $attribute->setValue(null, $defaults[$name]); } } } /** * Restores a super-global variable array from this snapshot. */ private function restoreSuperGlobalArray(Snapshot $snapshot, string $superGlobalArray): void { $superGlobalVariables = $snapshot->superGlobalVariables(); if (isset($GLOBALS[$superGlobalArray]) && is_array($GLOBALS[$superGlobalArray]) && isset($superGlobalVariables[$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]); } } } } } PK������,Z^4 �� ����ExcludeList.phpnu�W+A��������<?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 { /** * @var array */ private $globalVariables = []; /** * @var string[] */ private $classes = []; /** * @var string[] */ private $classNamePrefixes = []; /** * @var string[] */ private $parentClasses = []; /** * @var string[] */ private $interfaces = []; /** * @var array */ private $staticAttributes = []; 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 addStaticAttribute(string $className, string $attributeName): void { if (!isset($this->staticAttributes[$className])) { $this->staticAttributes[$className] = []; } $this->staticAttributes[$className][$attributeName] = true; } public function isGlobalVariableExcluded(string $variableName): bool { return isset($this->globalVariables[$variableName]); } public function isStaticAttributeExcluded(string $className, string $attributeName): 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; } } if (isset($this->staticAttributes[$className][$attributeName])) { return true; } return false; } } PK������,Zˮ +��+�� ��Snapshot.phpnu�W+A��������<?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_VERSION_ID; use function array_keys; use function array_merge; use function array_reverse; 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 { /** * @var ExcludeList */ private $excludeList; /** * @var array */ private $globalVariables = []; /** * @var array */ private $superGlobalArrays = []; /** * @var array */ private $superGlobalVariables = []; /** * @var array */ private $staticAttributes = []; /** * @var array */ private $iniSettings = []; /** * @var array */ private $includedFiles = []; /** * @var array */ private $constants = []; /** * @var array */ private $functions = []; /** * @var array */ private $interfaces = []; /** * @var array */ private $classes = []; /** * @var array */ private $traits = []; /** * Creates a snapshot of the current global state. */ public function __construct(?ExcludeList $excludeList = null, bool $includeGlobalVariables = true, bool $includeStaticAttributes = 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 || $includeStaticAttributes) { $this->snapshotClasses(); } if ($includeInterfaces) { $this->snapshotInterfaces(); } if ($includeGlobalVariables) { $this->setupSuperGlobalArrays(); $this->snapshotGlobals(); } if ($includeStaticAttributes) { $this->snapshotStaticAttributes(); } 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 staticAttributes(): array { return $this->staticAttributes; } 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; } /** * Creates a snapshot user-defined constants. */ private function snapshotConstants(): void { $constants = get_defined_constants(true); if (isset($constants['user'])) { $this->constants = $constants['user']; } } /** * Creates a snapshot user-defined functions. */ private function snapshotFunctions(): void { $functions = get_defined_functions(); $this->functions = $functions['user']; } /** * Creates a snapshot user-defined classes. */ 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); } /** * Creates a snapshot user-defined interfaces. */ 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); } /** * Creates a snapshot of all global and super-global variables. */ 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])); } } } /** * Creates a snapshot a super-global variable array. */ 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)); } } } /** * Creates a snapshot of all static attributes in user-defined classes. */ private function snapshotStaticAttributes(): void { foreach ($this->classes as $className) { $class = new ReflectionClass($className); $snapshot = []; foreach ($class->getProperties() as $attribute) { if ($attribute->isStatic()) { $name = $attribute->getName(); if ($this->excludeList->isStaticAttributeExcluded($className, $name)) { continue; } $attribute->setAccessible(true); if (PHP_VERSION_ID >= 70400 && !$attribute->isInitialized()) { continue; } $value = $attribute->getValue(); if ($this->canBeSerialized($value)) { /* @noinspection UnserializeExploitsInspection */ $snapshot[$name] = unserialize(serialize($value)); } } } if (!empty($snapshot)) { $this->staticAttributes[$className] = $snapshot; } } } /** * Returns a list of all super-global variable arrays. */ private function setupSuperGlobalArrays(): void { $this->superGlobalArrays = [ '_ENV', '_POST', '_GET', '_COOKIE', '_SERVER', '_FILES', '_REQUEST', ]; } private function canBeSerialized($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($variable): array { if (isset(func_get_args()[1])) { $processed = func_get_args()[1]; } else { $processed = new Context; } $result = []; if ($processed->contains($variable)) { return $result; } $array = $variable; $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)->getAttributes($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; } } PK������,Z#Vi ��i ����CodeExporter.phpnu�W+A��������<?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; /** * Exports parts of a Snapshot as PHP code. */ 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($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; } } PK������`.Zl(E��E��%��Exceptions/InvalidOptionException.phpnu�W+A��������<?php /* * This file is part of fruitcake/php-cors * * (c) Barryvdh <barryvdh@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Fruitcake\Cors\Exceptions; class InvalidOptionException extends \RuntimeException { } PK������`.Z5E&��&����CorsService.phpnu�W+A��������<?php /* * This file is part of fruitcake/php-cors and was originally part of asm89/stack-cors * * (c) Alexander <iam.asm89@gmail.com> * (c) Barryvdh <barryvdh@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Fruitcake\Cors; use Fruitcake\Cors\Exceptions\InvalidOptionException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * @phpstan-type CorsInputOptions array{ * 'allowedOrigins'?: string[], * 'allowedOriginsPatterns'?: string[], * 'supportsCredentials'?: bool, * 'allowedHeaders'?: string[], * 'allowedMethods'?: string[], * 'exposedHeaders'?: string[]|false, * 'maxAge'?: int|bool|null, * 'allowed_origins'?: string[], * 'allowed_origins_patterns'?: string[], * 'supports_credentials'?: bool, * 'allowed_headers'?: string[], * 'allowed_methods'?: string[], * 'exposed_headers'?: string[]|false, * 'max_age'?: int|bool|null * } * */ class CorsService { /** @var string[] */ private array $allowedOrigins = []; /** @var string[] */ private array $allowedOriginsPatterns = []; /** @var string[] */ private array $allowedMethods = []; /** @var string[] */ private array $allowedHeaders = []; /** @var string[] */ private array $exposedHeaders = []; private bool $supportsCredentials = false; private ?int $maxAge = 0; private bool $allowAllOrigins = false; private bool $allowAllMethods = false; private bool $allowAllHeaders = false; /** * @param CorsInputOptions $options */ public function __construct(array $options = []) { if ($options) { $this->setOptions($options); } } /** * @param CorsInputOptions $options */ public function setOptions(array $options): void { $this->allowedOrigins = $options['allowedOrigins'] ?? $options['allowed_origins'] ?? $this->allowedOrigins; $this->allowedOriginsPatterns = $options['allowedOriginsPatterns'] ?? $options['allowed_origins_patterns'] ?? $this->allowedOriginsPatterns; $this->allowedMethods = $options['allowedMethods'] ?? $options['allowed_methods'] ?? $this->allowedMethods; $this->allowedHeaders = $options['allowedHeaders'] ?? $options['allowed_headers'] ?? $this->allowedHeaders; $this->supportsCredentials = $options['supportsCredentials'] ?? $options['supports_credentials'] ?? $this->supportsCredentials; $maxAge = $this->maxAge; if (array_key_exists('maxAge', $options)) { $maxAge = $options['maxAge']; } elseif (array_key_exists('max_age', $options)) { $maxAge = $options['max_age']; } $this->maxAge = $maxAge === null ? null : (int)$maxAge; $exposedHeaders = $options['exposedHeaders'] ?? $options['exposed_headers'] ?? $this->exposedHeaders; $this->exposedHeaders = $exposedHeaders === false ? [] : $exposedHeaders; $this->normalizeOptions(); } private function normalizeOptions(): void { // Normalize case $this->allowedHeaders = array_map('strtolower', $this->allowedHeaders); $this->allowedMethods = array_map('strtoupper', $this->allowedMethods); // Normalize ['*'] to true $this->allowAllOrigins = in_array('*', $this->allowedOrigins); $this->allowAllHeaders = in_array('*', $this->allowedHeaders); $this->allowAllMethods = in_array('*', $this->allowedMethods); // Transform wildcard pattern if (!$this->allowAllOrigins) { foreach ($this->allowedOrigins as $origin) { if (strpos($origin, '*') !== false) { $this->allowedOriginsPatterns[] = $this->convertWildcardToPattern($origin); } } } } /** * Create a pattern for a wildcard, based on Str::is() from Laravel * * @see https://github.com/laravel/framework/blob/5.5/src/Illuminate/Support/Str.php * @param string $pattern * @return string */ private function convertWildcardToPattern($pattern) { $pattern = preg_quote($pattern, '#'); // Asterisks are translated into zero-or-more regular expression wildcards // to make it convenient to check if the strings starts with the given // pattern such as "*.example.com", making any string check convenient. $pattern = str_replace('\*', '.*', $pattern); return '#^' . $pattern . '\z#u'; } public function isCorsRequest(Request $request): bool { return $request->headers->has('Origin'); } public function isPreflightRequest(Request $request): bool { return $request->getMethod() === 'OPTIONS' && $request->headers->has('Access-Control-Request-Method'); } public function handlePreflightRequest(Request $request): Response { $response = new Response(); $response->setStatusCode(204); return $this->addPreflightRequestHeaders($response, $request); } public function addPreflightRequestHeaders(Response $response, Request $request): Response { $this->configureAllowedOrigin($response, $request); if ($response->headers->has('Access-Control-Allow-Origin')) { $this->configureAllowCredentials($response, $request); $this->configureAllowedMethods($response, $request); $this->configureAllowedHeaders($response, $request); $this->configureMaxAge($response, $request); } return $response; } public function isOriginAllowed(Request $request): bool { if ($this->allowAllOrigins === true) { return true; } $origin = (string) $request->headers->get('Origin'); if (in_array($origin, $this->allowedOrigins)) { return true; } foreach ($this->allowedOriginsPatterns as $pattern) { if (preg_match($pattern, $origin)) { return true; } } return false; } public function addActualRequestHeaders(Response $response, Request $request): Response { $this->configureAllowedOrigin($response, $request); if ($response->headers->has('Access-Control-Allow-Origin')) { $this->configureAllowCredentials($response, $request); $this->configureExposedHeaders($response, $request); } return $response; } private function configureAllowedOrigin(Response $response, Request $request): void { if ($this->allowAllOrigins === true && !$this->supportsCredentials) { // Safe+cacheable, allow everything $response->headers->set('Access-Control-Allow-Origin', '*'); } elseif ($this->isSingleOriginAllowed()) { // Single origins can be safely set $response->headers->set('Access-Control-Allow-Origin', array_values($this->allowedOrigins)[0]); } else { // For dynamic headers, set the requested Origin header when set and allowed if ($this->isCorsRequest($request) && $this->isOriginAllowed($request)) { $response->headers->set('Access-Control-Allow-Origin', (string) $request->headers->get('Origin')); } $this->varyHeader($response, 'Origin'); } } private function isSingleOriginAllowed(): bool { if ($this->allowAllOrigins === true || count($this->allowedOriginsPatterns) > 0) { return false; } return count($this->allowedOrigins) === 1; } private function configureAllowedMethods(Response $response, Request $request): void { if ($this->allowAllMethods === true) { $allowMethods = strtoupper((string) $request->headers->get('Access-Control-Request-Method')); $this->varyHeader($response, 'Access-Control-Request-Method'); } else { $allowMethods = implode(', ', $this->allowedMethods); } $response->headers->set('Access-Control-Allow-Methods', $allowMethods); } private function configureAllowedHeaders(Response $response, Request $request): void { if ($this->allowAllHeaders === true) { $allowHeaders = (string) $request->headers->get('Access-Control-Request-Headers'); $this->varyHeader($response, 'Access-Control-Request-Headers'); } else { $allowHeaders = implode(', ', $this->allowedHeaders); } $response->headers->set('Access-Control-Allow-Headers', $allowHeaders); } private function configureAllowCredentials(Response $response, Request $request): void { if ($this->supportsCredentials) { $response->headers->set('Access-Control-Allow-Credentials', 'true'); } } private function configureExposedHeaders(Response $response, Request $request): void { if ($this->exposedHeaders) { $response->headers->set('Access-Control-Expose-Headers', implode(', ', $this->exposedHeaders)); } } private function configureMaxAge(Response $response, Request $request): void { if ($this->maxAge !== null) { $response->headers->set('Access-Control-Max-Age', (string) $this->maxAge); } } public function varyHeader(Response $response, string $header): Response { if (!$response->headers->has('Vary')) { $response->headers->set('Vary', $header); } elseif (!in_array($header, explode(', ', (string) $response->headers->get('Vary')))) { $response->headers->set('Vary', ((string) $response->headers->get('Vary')) . ', ' . $header); } return $response; } } PK������<1Zg������Carbon/Language.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon; use JsonSerializable; use ReturnTypeWillChange; class Language implements JsonSerializable { /** * @var array */ protected static $languagesNames; /** * @var array */ protected static $regionsNames; /** * @var string */ protected $id; /** * @var string */ protected $code; /** * @var string|null */ protected $variant; /** * @var string|null */ protected $region; /** * @var array */ protected $names; /** * @var string */ protected $isoName; /** * @var string */ protected $nativeName; public function __construct(string $id) { $this->id = str_replace('-', '_', $id); $parts = explode('_', $this->id); $this->code = $parts[0]; if (isset($parts[1])) { if (!preg_match('/^[A-Z]+$/', $parts[1])) { $this->variant = $parts[1]; $parts[1] = $parts[2] ?? null; } if ($parts[1]) { $this->region = $parts[1]; } } } /** * Get the list of the known languages. * * @return array */ public static function all() { if (!static::$languagesNames) { static::$languagesNames = require __DIR__.'/List/languages.php'; } return static::$languagesNames; } /** * Get the list of the known regions. * * @return array */ public static function regions() { if (!static::$regionsNames) { static::$regionsNames = require __DIR__.'/List/regions.php'; } return static::$regionsNames; } /** * Get both isoName and nativeName as an array. * * @return array */ public function getNames(): array { if (!$this->names) { $this->names = static::all()[$this->code] ?? [ 'isoName' => $this->code, 'nativeName' => $this->code, ]; } return $this->names; } /** * Returns the original locale ID. * * @return string */ public function getId(): string { return $this->id; } /** * Returns the code of the locale "en"/"fr". * * @return string */ public function getCode(): string { return $this->code; } /** * Returns the variant code such as cyrl/latn. * * @return string|null */ public function getVariant(): ?string { return $this->variant; } /** * Returns the variant such as Cyrillic/Latin. * * @return string|null */ public function getVariantName(): ?string { if ($this->variant === 'Latn') { return 'Latin'; } if ($this->variant === 'Cyrl') { return 'Cyrillic'; } return $this->variant; } /** * Returns the region part of the locale. * * @return string|null */ public function getRegion(): ?string { return $this->region; } /** * Returns the region name for the current language. * * @return string|null */ public function getRegionName(): ?string { return $this->region ? (static::regions()[$this->region] ?? $this->region) : null; } /** * Returns the long ISO language name. * * @return string */ public function getFullIsoName(): string { if (!$this->isoName) { $this->isoName = $this->getNames()['isoName']; } return $this->isoName; } /** * Set the ISO language name. * * @param string $isoName */ public function setIsoName(string $isoName): self { $this->isoName = $isoName; return $this; } /** * Return the full name of the language in this language. * * @return string */ public function getFullNativeName(): string { if (!$this->nativeName) { $this->nativeName = $this->getNames()['nativeName']; } return $this->nativeName; } /** * Set the name of the language in this language. * * @param string $nativeName */ public function setNativeName(string $nativeName): self { $this->nativeName = $nativeName; return $this; } /** * Returns the short ISO language name. * * @return string */ public function getIsoName(): string { $name = $this->getFullIsoName(); return trim(strstr($name, ',', true) ?: $name); } /** * Get the short name of the language in this language. * * @return string */ public function getNativeName(): string { $name = $this->getFullNativeName(); return trim(strstr($name, ',', true) ?: $name); } /** * Get a string with short ISO name, region in parentheses if applicable, variant in parentheses if applicable. * * @return string */ public function getIsoDescription() { $region = $this->getRegionName(); $variant = $this->getVariantName(); return $this->getIsoName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : ''); } /** * Get a string with short native name, region in parentheses if applicable, variant in parentheses if applicable. * * @return string */ public function getNativeDescription() { $region = $this->getRegionName(); $variant = $this->getVariantName(); return $this->getNativeName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : ''); } /** * Get a string with long ISO name, region in parentheses if applicable, variant in parentheses if applicable. * * @return string */ public function getFullIsoDescription() { $region = $this->getRegionName(); $variant = $this->getVariantName(); return $this->getFullIsoName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : ''); } /** * Get a string with long native name, region in parentheses if applicable, variant in parentheses if applicable. * * @return string */ public function getFullNativeDescription() { $region = $this->getRegionName(); $variant = $this->getVariantName(); return $this->getFullNativeName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : ''); } /** * Returns the original locale ID. * * @return string */ public function __toString() { return $this->getId(); } /** * Get a string with short ISO name, region in parentheses if applicable, variant in parentheses if applicable. * * @return string */ #[ReturnTypeWillChange] public function jsonSerialize() { return $this->getIsoDescription(); } } PK������<1Z䪦������Carbon/Cli/Invoker.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Cli; class Invoker { public const CLI_CLASS_NAME = 'Carbon\\Cli'; protected function runWithCli(string $className, array $parameters): bool { $cli = new $className(); return $cli(...$parameters); } public function __invoke(...$parameters): bool { if (class_exists(self::CLI_CLASS_NAME)) { return $this->runWithCli(self::CLI_CLASS_NAME, $parameters); } $function = (($parameters[1] ?? '') === 'install' ? ($parameters[2] ?? null) : null) ?: 'shell_exec'; $function('composer require carbon-cli/carbon-cli --no-interaction'); echo 'Installation succeeded.'; return true; } } PK������<1Z3` �� ����Carbon/Lang/th_TH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/th.php'; PK������<1ZLO��O����Carbon/Lang/brx.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/brx_IN.php'; PK������<1ZՉN��N����Carbon/Lang/wo.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/wo_SN.php'; PK������<1Zd������Carbon/Lang/es_AR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]); PK������<1ZB������Carbon/Lang/bn_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/bn.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['জানুয়ারী', 'ফেব্রুয়ারী', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'], 'months_short' => ['জানু', 'ফেব', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'], 'weekdays' => ['রবিবার', 'সোমবার', 'মঙ্গলবার', 'বুধবার', 'বৃহস্পতিবার', 'শুক্রবার', 'শনিবার'], 'weekdays_short' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহস্পতি', 'শুক্র', 'শনি'], 'weekdays_min' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহস্পতি', 'শুক্র', 'শনি'], 'day_of_first_week_of_year' => 1, ]); PK������<1ZM������Carbon/Lang/cu.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'months' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'], 'months_short' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY-MM-DD', 'LL' => 'YYYY MMM D', 'LLL' => 'YYYY MMMM D HH:mm', 'LLLL' => 'YYYY MMMM D, dddd HH:mm', ], 'year' => ':count лѣто', 'y' => ':count лѣто', 'a_year' => ':count лѣто', 'month' => ':count мѣсѧць', 'm' => ':count мѣсѧць', 'a_month' => ':count мѣсѧць', 'week' => ':count сєдмица', 'w' => ':count сєдмица', 'a_week' => ':count сєдмица', 'day' => ':count дьнь', 'd' => ':count дьнь', 'a_day' => ':count дьнь', 'hour' => ':count година', 'h' => ':count година', 'a_hour' => ':count година', 'minute' => ':count малъ', // less reliable 'min' => ':count малъ', // less reliable 'a_minute' => ':count малъ', // less reliable 'second' => ':count въторъ', 's' => ':count въторъ', 'a_second' => ':count въторъ', ]); PK������<1ZUZj ��j ����Carbon/Lang/eo.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - François B * - Mia Nordentoft * - JD Isaacks */ return [ 'year' => ':count jaro|:count jaroj', 'a_year' => 'jaro|:count jaroj', 'y' => ':count j.', 'month' => ':count monato|:count monatoj', 'a_month' => 'monato|:count monatoj', 'm' => ':count mo.', 'week' => ':count semajno|:count semajnoj', 'a_week' => 'semajno|:count semajnoj', 'w' => ':count sem.', 'day' => ':count tago|:count tagoj', 'a_day' => 'tago|:count tagoj', 'd' => ':count t.', 'hour' => ':count horo|:count horoj', 'a_hour' => 'horo|:count horoj', 'h' => ':count h.', 'minute' => ':count minuto|:count minutoj', 'a_minute' => 'minuto|:count minutoj', 'min' => ':count min.', 'second' => ':count sekundo|:count sekundoj', 'a_second' => 'sekundoj|:count sekundoj', 's' => ':count sek.', 'ago' => 'antaŭ :time', 'from_now' => 'post :time', 'after' => ':time poste', 'before' => ':time antaŭe', 'diff_yesterday' => 'Hieraŭ', 'diff_yesterday_regexp' => 'Hieraŭ(?:\\s+je)?', 'diff_today' => 'Hodiaŭ', 'diff_today_regexp' => 'Hodiaŭ(?:\\s+je)?', 'diff_tomorrow' => 'Morgaŭ', 'diff_tomorrow_regexp' => 'Morgaŭ(?:\\s+je)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY-MM-DD', 'LL' => 'D[-a de] MMMM, YYYY', 'LLL' => 'D[-a de] MMMM, YYYY HH:mm', 'LLLL' => 'dddd, [la] D[-a de] MMMM, YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[Hodiaŭ je] LT', 'nextDay' => '[Morgaŭ je] LT', 'nextWeek' => 'dddd [je] LT', 'lastDay' => '[Hieraŭ je] LT', 'lastWeek' => '[pasinta] dddd [je] LT', 'sameElse' => 'L', ], 'ordinal' => ':numbera', 'meridiem' => ['a.t.m.', 'p.t.m.'], 'months' => ['januaro', 'februaro', 'marto', 'aprilo', 'majo', 'junio', 'julio', 'aŭgusto', 'septembro', 'oktobro', 'novembro', 'decembro'], 'months_short' => ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aŭg', 'sep', 'okt', 'nov', 'dec'], 'weekdays' => ['dimanĉo', 'lundo', 'mardo', 'merkredo', 'ĵaŭdo', 'vendredo', 'sabato'], 'weekdays_short' => ['dim', 'lun', 'mard', 'merk', 'ĵaŭ', 'ven', 'sab'], 'weekdays_min' => ['di', 'lu', 'ma', 'me', 'ĵa', 've', 'sa'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' kaj '], ]; PK������<1Z������Carbon/Lang/el.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Alessandro Di Felice * - François B * - Tim Fish * - Gabriel Monteagudo * - JD Isaacks * - yiannisdesp * - Ilias Kasmeridis (iliaskasm) */ use Carbon\CarbonInterface; return [ 'year' => ':count χρόνος|:count χρόνια', 'a_year' => 'ένας χρόνος|:count χρόνια', 'y' => ':count χρ.', 'month' => ':count μήνας|:count μήνες', 'a_month' => 'ένας μήνας|:count μήνες', 'm' => ':count μήν.', 'week' => ':count εβδομάδα|:count εβδομάδες', 'a_week' => 'μια εβδομάδα|:count εβδομάδες', 'w' => ':count εβδ.', 'day' => ':count μέρα|:count μέρες', 'a_day' => 'μία μέρα|:count μέρες', 'd' => ':count μέρ.', 'hour' => ':count ώρα|:count ώρες', 'a_hour' => 'μία ώρα|:count ώρες', 'h' => ':count ώρα|:count ώρες', 'minute' => ':count λεπτό|:count λεπτά', 'a_minute' => 'ένα λεπτό|:count λεπτά', 'min' => ':count λεπ.', 'second' => ':count δευτερόλεπτο|:count δευτερόλεπτα', 'a_second' => 'λίγα δευτερόλεπτα|:count δευτερόλεπτα', 's' => ':count δευ.', 'ago' => 'πριν :time', 'from_now' => 'σε :time', 'after' => ':time μετά', 'before' => ':time πριν', 'diff_now' => 'τώρα', 'diff_today' => 'Σήμερα', 'diff_today_regexp' => 'Σήμερα(?:\\s+{})?', 'diff_yesterday' => 'χθες', 'diff_yesterday_regexp' => 'Χθες(?:\\s+{})?', 'diff_tomorrow' => 'αύριο', 'diff_tomorrow_regexp' => 'Αύριο(?:\\s+{})?', 'formats' => [ 'LT' => 'h:mm A', 'LTS' => 'h:mm:ss A', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY h:mm A', 'LLLL' => 'dddd, D MMMM YYYY h:mm A', ], 'calendar' => [ 'sameDay' => '[Σήμερα {}] LT', 'nextDay' => '[Αύριο {}] LT', 'nextWeek' => 'dddd [{}] LT', 'lastDay' => '[Χθες {}] LT', 'lastWeek' => function (CarbonInterface $current) { switch ($current->dayOfWeek) { case 6: return '[το προηγούμενο] dddd [{}] LT'; default: return '[την προηγούμενη] dddd [{}] LT'; } }, 'sameElse' => 'L', ], 'ordinal' => ':numberη', 'meridiem' => ['ΠΜ', 'ΜΜ', 'πμ', 'μμ'], 'months' => ['Ιανουαρίου', 'Φεβρουαρίου', 'Μαρτίου', 'Απριλίου', 'Μαΐου', 'Ιουνίου', 'Ιουλίου', 'Αυγούστου', 'Σεπτεμβρίου', 'Οκτωβρίου', 'Νοεμβρίου', 'Δεκεμβρίου'], 'months_standalone' => ['Ιανουάριος', 'Φεβρουάριος', 'Μάρτιος', 'Απρίλιος', 'Μάιος', 'Ιούνιος', 'Ιούλιος', 'Αύγουστος', 'Σεπτέμβριος', 'Οκτώβριος', 'Νοέμβριος', 'Δεκέμβριος'], 'months_regexp' => '/(D[oD]?[\s,]+MMMM|L{2,4}|l{2,4})/', 'months_short' => ['Ιαν', 'Φεβ', 'Μαρ', 'Απρ', 'Μαϊ', 'Ιουν', 'Ιουλ', 'Αυγ', 'Σεπ', 'Οκτ', 'Νοε', 'Δεκ'], 'weekdays' => ['Κυριακή', 'Δευτέρα', 'Τρίτη', 'Τετάρτη', 'Πέμπτη', 'Παρασκευή', 'Σάββατο'], 'weekdays_short' => ['Κυρ', 'Δευ', 'Τρι', 'Τετ', 'Πεμ', 'Παρ', 'Σαβ'], 'weekdays_min' => ['Κυ', 'Δε', 'Τρ', 'Τε', 'Πε', 'Πα', 'Σα'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' και '], ]; PK������<1ZpG��G����Carbon/Lang/en_CK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z)��)����Carbon/Lang/ar_ER.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ar.php', [ ]); PK������<1Zr(������Carbon/Lang/sr_Latn_XK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Component\Translation\PluralizationRules; // @codeCoverageIgnoreStart if (class_exists(PluralizationRules::class)) { PluralizationRules::set(static function ($number) { return PluralizationRules::get($number, 'sr'); }, 'sr_Latn_XK'); } // @codeCoverageIgnoreEnd return array_replace_recursive(require __DIR__.'/sr_Latn_BA.php', [ 'weekdays' => ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak', 'subota'], ]); PK������<1ZpG��G����Carbon/Lang/en_TO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z8O��O����Carbon/Lang/gez.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/gez_ER.php'; PK������<1ZEA��A����Carbon/Lang/fr_DZ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/fr.php', [ 'first_day_of_week' => 6, 'weekend' => [5, 6], 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY h:mm a', 'LLLL' => 'dddd D MMMM YYYY h:mm a', ], ]); PK������<1Z% �� ����Carbon/Lang/so.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Author: * - Abdifatah Abdilahi(@abdifatahz) */ return [ 'year' => ':count sanad|:count sanadood', 'a_year' => 'sanad|:count sanadood', 'y' => '{1}:countsn|{0}:countsns|]1,Inf[:countsn', 'month' => ':count bil|:count bilood', 'a_month' => 'bil|:count bilood', 'm' => ':countbil', 'week' => ':count isbuuc', 'a_week' => 'isbuuc|:count isbuuc', 'w' => ':countis', 'day' => ':count maalin|:count maalmood', 'a_day' => 'maalin|:count maalmood', 'd' => ':countml', 'hour' => ':count saac', 'a_hour' => 'saacad|:count saac', 'h' => ':countsc', 'minute' => ':count daqiiqo', 'a_minute' => 'daqiiqo|:count daqiiqo', 'min' => ':countdq', 'second' => ':count ilbidhiqsi', 'a_second' => 'xooga ilbidhiqsiyo|:count ilbidhiqsi', 's' => ':countil', 'ago' => ':time kahor', 'from_now' => ':time gudahood', 'after' => ':time kedib', 'before' => ':time kahor', 'diff_now' => 'hada', 'diff_today' => 'maanta', 'diff_today_regexp' => 'maanta(?:\s+markay\s+(?:tahay|ahayd))?', 'diff_yesterday' => 'shalayto', 'diff_yesterday_regexp' => 'shalayto(?:\s+markay\s+ahayd)?', 'diff_tomorrow' => 'beri', 'diff_tomorrow_regexp' => 'beri(?:\s+markay\s+tahay)?', 'diff_before_yesterday' => 'doraato', 'diff_after_tomorrow' => 'saadanbe', 'period_recurrences' => 'mar|:count jeer', 'period_interval' => ':interval kasta', 'period_start_date' => 'laga bilaabo :date', 'period_end_date' => 'ilaa :date', 'months' => ['Janaayo', 'Febraayo', 'Abriil', 'Maajo', 'Juun', 'Luuliyo', 'Agoosto', 'Sebteembar', 'Oktoobar', 'Nofeembar', 'Diseembar'], 'months_short' => ['Jan', 'Feb', 'Mar', 'Abr', 'Mjo', 'Jun', 'Lyo', 'Agt', 'Seb', 'Okt', 'Nof', 'Dis'], 'weekdays' => ['Axad', 'Isniin', 'Talaada', 'Arbaca', 'Khamiis', 'Jimce', 'Sabti'], 'weekdays_short' => ['Axd', 'Isn', 'Tal', 'Arb', 'Kha', 'Jim', 'Sbt'], 'weekdays_min' => ['Ax', 'Is', 'Ta', 'Ar', 'Kh', 'Ji', 'Sa'], 'list' => [', ', ' and '], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'calendar' => [ 'sameDay' => '[Maanta markay tahay] LT', 'nextDay' => '[Beri markay tahay] LT', 'nextWeek' => 'dddd [markay tahay] LT', 'lastDay' => '[Shalay markay ahayd] LT', 'lastWeek' => '[Hore] dddd [Markay ahayd] LT', 'sameElse' => 'L', ], ]; PK������<1Z#z �� ����Carbon/Lang/ga.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Thanks to André Silva : https://github.com/askpt */ return [ 'year' => ':count bliain', 'a_year' => '{1}bliain|:count bliain', 'y' => ':countb', 'month' => ':count mí', 'a_month' => '{1}mí|:count mí', 'm' => ':countm', 'week' => ':count sheachtain', 'a_week' => '{1}sheachtain|:count sheachtain', 'w' => ':countsh', 'day' => ':count lá', 'a_day' => '{1}lá|:count lá', 'd' => ':countl', 'hour' => ':count uair an chloig', 'a_hour' => '{1}uair an chloig|:count uair an chloig', 'h' => ':countu', 'minute' => ':count nóiméad', 'a_minute' => '{1}nóiméad|:count nóiméad', 'min' => ':countn', 'second' => ':count soicind', 'a_second' => '{1}cúpla soicind|:count soicind', 's' => ':countso', 'ago' => ':time ó shin', 'from_now' => 'i :time', 'after' => ':time tar éis', 'before' => ':time roimh', 'diff_now' => 'anois', 'diff_today' => 'Inniu', 'diff_today_regexp' => 'Inniu(?:\\s+ag)?', 'diff_yesterday' => 'inné', 'diff_yesterday_regexp' => 'Inné(?:\\s+aig)?', 'diff_tomorrow' => 'amárach', 'diff_tomorrow_regexp' => 'Amárach(?:\\s+ag)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[Inniu ag] LT', 'nextDay' => '[Amárach ag] LT', 'nextWeek' => 'dddd [ag] LT', 'lastDay' => '[Inné aig] LT', 'lastWeek' => 'dddd [seo caite] [ag] LT', 'sameElse' => 'L', ], 'months' => ['Eanáir', 'Feabhra', 'Márta', 'Aibreán', 'Bealtaine', 'Méitheamh', 'Iúil', 'Lúnasa', 'Meán Fómhair', 'Deaireadh Fómhair', 'Samhain', 'Nollaig'], 'months_short' => ['Eaná', 'Feab', 'Márt', 'Aibr', 'Beal', 'Méit', 'Iúil', 'Lúna', 'Meán', 'Deai', 'Samh', 'Noll'], 'weekdays' => ['Dé Domhnaigh', 'Dé Luain', 'Dé Máirt', 'Dé Céadaoin', 'Déardaoin', 'Dé hAoine', 'Dé Satharn'], 'weekdays_short' => ['Dom', 'Lua', 'Mái', 'Céa', 'Déa', 'hAo', 'Sat'], 'weekdays_min' => ['Do', 'Lu', 'Má', 'Ce', 'Dé', 'hA', 'Sa'], 'ordinal' => function ($number) { return $number.($number === 1 ? 'd' : ($number % 10 === 2 ? 'na' : 'mh')); }, 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' agus '], 'meridiem' => ['r.n.', 'i.n.'], ]; PK������<1ZpG��G����Carbon/Lang/en_GI.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z})��)����Carbon/Lang/ca_IT.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ca.php', [ ]); PK������<1ZjtX��X����Carbon/Lang/twq.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ses.php', [ 'meridiem' => ['Subbaahi', 'Zaarikay b'], ]); PK������<1ZO?��?����Carbon/Lang/ht_HT.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Sugar Labs // OLPC sugarlabs.org libc-alpha@sourceware.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['janvye', 'fevriye', 'mas', 'avril', 'me', 'jen', 'jiyè', 'out', 'septanm', 'oktòb', 'novanm', 'desanm'], 'months_short' => ['jan', 'fev', 'mas', 'avr', 'me', 'jen', 'jiy', 'out', 'sep', 'okt', 'nov', 'des'], 'weekdays' => ['dimanch', 'lendi', 'madi', 'mèkredi', 'jedi', 'vandredi', 'samdi'], 'weekdays_short' => ['dim', 'len', 'mad', 'mèk', 'jed', 'van', 'sam'], 'weekdays_min' => ['dim', 'len', 'mad', 'mèk', 'jed', 'van', 'sam'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'year' => ':count lane', 'y' => ':count lane', 'a_year' => ':count lane', 'month' => 'mwa :count', 'm' => 'mwa :count', 'a_month' => 'mwa :count', 'week' => 'semèn :count', 'w' => 'semèn :count', 'a_week' => 'semèn :count', 'day' => ':count jou', 'd' => ':count jou', 'a_day' => ':count jou', 'hour' => ':count lè', 'h' => ':count lè', 'a_hour' => ':count lè', 'minute' => ':count minit', 'min' => ':count minit', 'a_minute' => ':count minit', 'second' => ':count segonn', 's' => ':count segonn', 'a_second' => ':count segonn', ]); PK������<1Z- �� ����Carbon/Lang/ff_GN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ff.php'; PK������<1Z>+ �� ����Carbon/Lang/lt_LT.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/lt.php'; PK������<1Z}*B �� ����Carbon/Lang/ha_NE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ha.php'; PK������<1ZpG��G����Carbon/Lang/en_SC.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZFI������Carbon/Lang/en_GB.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - Mayank Badola * - JD Isaacks */ return array_replace_recursive(require __DIR__.'/en.php', [ 'from_now' => 'in :time', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, ]); PK������<1Zh �� ����Carbon/Lang/se.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - Karamell */ return [ 'year' => '{1}:count jahki|:count jagit', 'a_year' => '{1}okta jahki|:count jagit', 'y' => ':count j.', 'month' => '{1}:count mánnu|:count mánut', 'a_month' => '{1}okta mánnu|:count mánut', 'm' => ':count mán.', 'week' => '{1}:count vahkku|:count vahkku', 'a_week' => '{1}okta vahkku|:count vahkku', 'w' => ':count v.', 'day' => '{1}:count beaivi|:count beaivvit', 'a_day' => '{1}okta beaivi|:count beaivvit', 'd' => ':count b.', 'hour' => '{1}:count diimmu|:count diimmut', 'a_hour' => '{1}okta diimmu|:count diimmut', 'h' => ':count d.', 'minute' => '{1}:count minuhta|:count minuhtat', 'a_minute' => '{1}okta minuhta|:count minuhtat', 'min' => ':count min.', 'second' => '{1}:count sekunddat|:count sekunddat', 'a_second' => '{1}moadde sekunddat|:count sekunddat', 's' => ':count s.', 'ago' => 'maŋit :time', 'from_now' => ':time geažes', 'diff_yesterday' => 'ikte', 'diff_yesterday_regexp' => 'ikte(?:\\s+ti)?', 'diff_today' => 'otne', 'diff_today_regexp' => 'otne(?:\\s+ti)?', 'diff_tomorrow' => 'ihttin', 'diff_tomorrow_regexp' => 'ihttin(?:\\s+ti)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'MMMM D. [b.] YYYY', 'LLL' => 'MMMM D. [b.] YYYY [ti.] HH:mm', 'LLLL' => 'dddd, MMMM D. [b.] YYYY [ti.] HH:mm', ], 'calendar' => [ 'sameDay' => '[otne ti] LT', 'nextDay' => '[ihttin ti] LT', 'nextWeek' => 'dddd [ti] LT', 'lastDay' => '[ikte ti] LT', 'lastWeek' => '[ovddit] dddd [ti] LT', 'sameElse' => 'L', ], 'ordinal' => ':number.', 'months' => ['ođđajagemánnu', 'guovvamánnu', 'njukčamánnu', 'cuoŋománnu', 'miessemánnu', 'geassemánnu', 'suoidnemánnu', 'borgemánnu', 'čakčamánnu', 'golggotmánnu', 'skábmamánnu', 'juovlamánnu'], 'months_short' => ['ođđj', 'guov', 'njuk', 'cuo', 'mies', 'geas', 'suoi', 'borg', 'čakč', 'golg', 'skáb', 'juov'], 'weekdays' => ['sotnabeaivi', 'vuossárga', 'maŋŋebárga', 'gaskavahkku', 'duorastat', 'bearjadat', 'lávvardat'], 'weekdays_short' => ['sotn', 'vuos', 'maŋ', 'gask', 'duor', 'bear', 'láv'], 'weekdays_min' => ['s', 'v', 'm', 'g', 'd', 'b', 'L'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' ja '], 'meridiem' => ['i.b.', 'e.b.'], ]; PK������<1ZpG��G����Carbon/Lang/en_LC.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZEA��A����Carbon/Lang/fr_SY.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/fr.php', [ 'first_day_of_week' => 6, 'weekend' => [5, 6], 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY h:mm a', 'LLLL' => 'dddd D MMMM YYYY h:mm a', ], ]); PK������<1ZŽ������Carbon/Lang/kln.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['krn', 'koosk'], 'weekdays' => ['Kotisap', 'Kotaai', 'Koaeng’', 'Kosomok', 'Koang’wan', 'Komuut', 'Kolo'], 'weekdays_short' => ['Kts', 'Kot', 'Koo', 'Kos', 'Koa', 'Kom', 'Kol'], 'weekdays_min' => ['Kts', 'Kot', 'Koo', 'Kos', 'Koa', 'Kom', 'Kol'], 'months' => ['Mulgul', 'Ng’atyaato', 'Kiptaamo', 'Iwootkuut', 'Mamuut', 'Paagi', 'Ng’eiyeet', 'Rooptui', 'Bureet', 'Epeeso', 'Kipsuunde ne taai', 'Kipsuunde nebo aeng’'], 'months_short' => ['Mul', 'Ngat', 'Taa', 'Iwo', 'Mam', 'Paa', 'Nge', 'Roo', 'Bur', 'Epe', 'Kpt', 'Kpa'], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'year' => ':count maghatiat', // less reliable 'y' => ':count maghatiat', // less reliable 'a_year' => ':count maghatiat', // less reliable ]); PK������<1Z, �� ����Carbon/Lang/km_KH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/km.php'; PK������<1Z8 �� ����Carbon/Lang/ne.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - nootanghimire * - Josh Soref * - Nj Subedi * - JD Isaacks */ return [ 'year' => 'एक बर्ष|:count बर्ष', 'y' => ':count वर्ष', 'month' => 'एक महिना|:count महिना', 'm' => ':count महिना', 'week' => ':count हप्ता', 'w' => ':count हप्ता', 'day' => 'एक दिन|:count दिन', 'd' => ':count दिन', 'hour' => 'एक घण्टा|:count घण्टा', 'h' => ':count घण्टा', 'minute' => 'एक मिनेट|:count मिनेट', 'min' => ':count मिनेट', 'second' => 'केही क्षण|:count सेकेण्ड', 's' => ':count सेकेण्ड', 'ago' => ':time अगाडि', 'from_now' => ':timeमा', 'after' => ':time पछि', 'before' => ':time अघि', 'diff_now' => 'अहिले', 'diff_today' => 'आज', 'diff_yesterday' => 'हिजो', 'diff_tomorrow' => 'भोलि', 'formats' => [ 'LT' => 'Aको h:mm बजे', 'LTS' => 'Aको h:mm:ss बजे', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY, Aको h:mm बजे', 'LLLL' => 'dddd, D MMMM YYYY, Aको h:mm बजे', ], 'calendar' => [ 'sameDay' => '[आज] LT', 'nextDay' => '[भोलि] LT', 'nextWeek' => '[आउँदो] dddd[,] LT', 'lastDay' => '[हिजो] LT', 'lastWeek' => '[गएको] dddd[,] LT', 'sameElse' => 'L', ], 'meridiem' => function ($hour) { if ($hour < 3) { return 'राति'; } if ($hour < 12) { return 'बिहान'; } if ($hour < 16) { return 'दिउँसो'; } if ($hour < 20) { return 'साँझ'; } return 'राति'; }, 'months' => ['जनवरी', 'फेब्रुवरी', 'मार्च', 'अप्रिल', 'मई', 'जुन', 'जुलाई', 'अगष्ट', 'सेप्टेम्बर', 'अक्टोबर', 'नोभेम्बर', 'डिसेम्बर'], 'months_short' => ['जन.', 'फेब्रु.', 'मार्च', 'अप्रि.', 'मई', 'जुन', 'जुलाई.', 'अग.', 'सेप्ट.', 'अक्टो.', 'नोभे.', 'डिसे.'], 'weekdays' => ['आइतबार', 'सोमबार', 'मङ्गलबार', 'बुधबार', 'बिहिबार', 'शुक्रबार', 'शनिबार'], 'weekdays_short' => ['आइत.', 'सोम.', 'मङ्गल.', 'बुध.', 'बिहि.', 'शुक्र.', 'शनि.'], 'weekdays_min' => ['आ.', 'सो.', 'मं.', 'बु.', 'बि.', 'शु.', 'श.'], 'list' => [', ', ' र '], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]; PK������<1Z''x �� ����Carbon/Lang/fr_BF.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Z4������Carbon/Lang/it_CH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Propaganistas */ return array_replace_recursive(require __DIR__.'/it.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], ]); PK������<1Z`N��N����Carbon/Lang/li.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/li_NL.php'; PK������<1Z5uO��O����Carbon/Lang/raj.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/raj_IN.php'; PK������<1ZpG��G����Carbon/Lang/en_DG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZNjG������Carbon/Lang/ku.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Unicode, Inc. */ return [ 'ago' => 'berî :time', 'from_now' => 'di :time de', 'after' => ':time piştî', 'before' => ':time berê', 'year' => ':count sal', 'year_ago' => ':count salê|:count salan', 'year_from_now' => 'salekê|:count salan', 'month' => ':count meh', 'week' => ':count hefte', 'day' => ':count roj', 'hour' => ':count saet', 'minute' => ':count deqîqe', 'second' => ':count saniye', 'months' => ['rêbendanê', 'reşemiyê', 'adarê', 'avrêlê', 'gulanê', 'pûşperê', 'tîrmehê', 'gelawêjê', 'rezberê', 'kewçêrê', 'sermawezê', 'berfanbarê'], 'months_standalone' => ['rêbendan', 'reşemî', 'adar', 'avrêl', 'gulan', 'pûşper', 'tîrmeh', 'gelawêj', 'rezber', 'kewçêr', 'sermawez', 'berfanbar'], 'months_short' => ['rêb', 'reş', 'ada', 'avr', 'gul', 'pûş', 'tîr', 'gel', 'rez', 'kew', 'ser', 'ber'], 'weekdays' => ['yekşem', 'duşem', 'sêşem', 'çarşem', 'pêncşem', 'în', 'şemî'], 'weekdays_short' => ['yş', 'dş', 'sş', 'çş', 'pş', 'în', 'ş'], 'weekdays_min' => ['Y', 'D', 'S', 'Ç', 'P', 'Î', 'Ş'], 'list' => [', ', ' û '], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, ]; PK������<1ZF������Carbon/Lang/os_RU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], 'months' => ['январы', 'февралы', 'мартъийы', 'апрелы', 'майы', 'июны', 'июлы', 'августы', 'сентябры', 'октябры', 'ноябры', 'декабры'], 'months_short' => ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'], 'weekdays' => ['Хуыцаубон', 'Къуырисæр', 'Дыццæг', 'Æртыццæг', 'Цыппæрæм', 'Майрæмбон', 'Сабат'], 'weekdays_short' => ['Хцб', 'Крс', 'Дцг', 'Æрт', 'Цпр', 'Мрб', 'Сбт'], 'weekdays_min' => ['Хцб', 'Крс', 'Дцг', 'Æрт', 'Цпр', 'Мрб', 'Сбт'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'minute' => ':count гыццыл', // less reliable 'min' => ':count гыццыл', // less reliable 'a_minute' => ':count гыццыл', // less reliable 'second' => ':count æндæр', // less reliable 's' => ':count æндæр', // less reliable 'a_second' => ':count æндæр', // less reliable 'year' => ':count аз', 'y' => ':count аз', 'a_year' => ':count аз', 'month' => ':count мӕй', 'm' => ':count мӕй', 'a_month' => ':count мӕй', 'week' => ':count къуыри', 'w' => ':count къуыри', 'a_week' => ':count къуыри', 'day' => ':count бон', 'd' => ':count бон', 'a_day' => ':count бон', 'hour' => ':count сахат', 'h' => ':count сахат', 'a_hour' => ':count сахат', ]); PK������<1Z$��$����Carbon/Lang/be.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Carbon\CarbonInterface; use Symfony\Component\Translation\PluralizationRules; // @codeCoverageIgnoreStart if (class_exists(PluralizationRules::class)) { PluralizationRules::set(static function ($number) { return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); }, 'be'); } // @codeCoverageIgnoreEnd /* * Authors: * - Josh Soref * - SobakaSlava * - François B * - Serhan Apaydın * - JD Isaacks * - AbadonnaAbbys * - Siomkin Alexander */ return [ 'year' => ':count год|:count гады|:count гадоў', 'a_year' => '{1}год|:count год|:count гады|:count гадоў', 'y' => ':count год|:count гады|:count гадоў', 'month' => ':count месяц|:count месяцы|:count месяцаў', 'a_month' => '{1}месяц|:count месяц|:count месяцы|:count месяцаў', 'm' => ':count месяц|:count месяцы|:count месяцаў', 'week' => ':count тыдзень|:count тыдні|:count тыдняў', 'a_week' => '{1}тыдзень|:count тыдзень|:count тыдні|:count тыдняў', 'w' => ':count тыдзень|:count тыдні|:count тыдняў', 'day' => ':count дзень|:count дні|:count дзён', 'a_day' => '{1}дзень|:count дзень|:count дні|:count дзён', 'd' => ':count дн', 'hour' => ':count гадзіну|:count гадзіны|:count гадзін', 'a_hour' => '{1}гадзіна|:count гадзіна|:count гадзіны|:count гадзін', 'h' => ':count гадзіна|:count гадзіны|:count гадзін', 'minute' => ':count хвіліна|:count хвіліны|:count хвілін', 'a_minute' => '{1}хвіліна|:count хвіліна|:count хвіліны|:count хвілін', 'min' => ':count хв', 'second' => ':count секунда|:count секунды|:count секунд', 'a_second' => '{1}некалькі секунд|:count секунда|:count секунды|:count секунд', 's' => ':count сек', 'hour_ago' => ':count гадзіну|:count гадзіны|:count гадзін', 'a_hour_ago' => '{1}гадзіну|:count гадзіну|:count гадзіны|:count гадзін', 'h_ago' => ':count гадзіну|:count гадзіны|:count гадзін', 'minute_ago' => ':count хвіліну|:count хвіліны|:count хвілін', 'a_minute_ago' => '{1}хвіліну|:count хвіліну|:count хвіліны|:count хвілін', 'min_ago' => ':count хвіліну|:count хвіліны|:count хвілін', 'second_ago' => ':count секунду|:count секунды|:count секунд', 'a_second_ago' => '{1}некалькі секунд|:count секунду|:count секунды|:count секунд', 's_ago' => ':count секунду|:count секунды|:count секунд', 'hour_from_now' => ':count гадзіну|:count гадзіны|:count гадзін', 'a_hour_from_now' => '{1}гадзіну|:count гадзіну|:count гадзіны|:count гадзін', 'h_from_now' => ':count гадзіну|:count гадзіны|:count гадзін', 'minute_from_now' => ':count хвіліну|:count хвіліны|:count хвілін', 'a_minute_from_now' => '{1}хвіліну|:count хвіліну|:count хвіліны|:count хвілін', 'min_from_now' => ':count хвіліну|:count хвіліны|:count хвілін', 'second_from_now' => ':count секунду|:count секунды|:count секунд', 'a_second_from_now' => '{1}некалькі секунд|:count секунду|:count секунды|:count секунд', 's_from_now' => ':count секунду|:count секунды|:count секунд', 'hour_after' => ':count гадзіну|:count гадзіны|:count гадзін', 'a_hour_after' => '{1}гадзіну|:count гадзіну|:count гадзіны|:count гадзін', 'h_after' => ':count гадзіну|:count гадзіны|:count гадзін', 'minute_after' => ':count хвіліну|:count хвіліны|:count хвілін', 'a_minute_after' => '{1}хвіліну|:count хвіліну|:count хвіліны|:count хвілін', 'min_after' => ':count хвіліну|:count хвіліны|:count хвілін', 'second_after' => ':count секунду|:count секунды|:count секунд', 'a_second_after' => '{1}некалькі секунд|:count секунду|:count секунды|:count секунд', 's_after' => ':count секунду|:count секунды|:count секунд', 'hour_before' => ':count гадзіну|:count гадзіны|:count гадзін', 'a_hour_before' => '{1}гадзіну|:count гадзіну|:count гадзіны|:count гадзін', 'h_before' => ':count гадзіну|:count гадзіны|:count гадзін', 'minute_before' => ':count хвіліну|:count хвіліны|:count хвілін', 'a_minute_before' => '{1}хвіліну|:count хвіліну|:count хвіліны|:count хвілін', 'min_before' => ':count хвіліну|:count хвіліны|:count хвілін', 'second_before' => ':count секунду|:count секунды|:count секунд', 'a_second_before' => '{1}некалькі секунд|:count секунду|:count секунды|:count секунд', 's_before' => ':count секунду|:count секунды|:count секунд', 'ago' => ':time таму', 'from_now' => 'праз :time', 'after' => ':time пасля', 'before' => ':time да', 'diff_now' => 'цяпер', 'diff_today' => 'Сёння', 'diff_today_regexp' => 'Сёння(?:\\s+ў)?', 'diff_yesterday' => 'учора', 'diff_yesterday_regexp' => 'Учора(?:\\s+ў)?', 'diff_tomorrow' => 'заўтра', 'diff_tomorrow_regexp' => 'Заўтра(?:\\s+ў)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D MMMM YYYY г.', 'LLL' => 'D MMMM YYYY г., HH:mm', 'LLLL' => 'dddd, D MMMM YYYY г., HH:mm', ], 'calendar' => [ 'sameDay' => '[Сёння ў] LT', 'nextDay' => '[Заўтра ў] LT', 'nextWeek' => '[У] dddd [ў] LT', 'lastDay' => '[Учора ў] LT', 'lastWeek' => function (CarbonInterface $current) { switch ($current->dayOfWeek) { case 1: case 2: case 4: return '[У мінулы] dddd [ў] LT'; default: return '[У мінулую] dddd [ў] LT'; } }, 'sameElse' => 'L', ], 'ordinal' => function ($number, $period) { switch ($period) { case 'M': case 'd': case 'DDD': case 'w': case 'W': return ($number % 10 === 2 || $number % 10 === 3) && ($number % 100 !== 12 && $number % 100 !== 13) ? $number.'-і' : $number.'-ы'; case 'D': return $number.'-га'; default: return $number; } }, 'meridiem' => function ($hour) { if ($hour < 4) { return 'ночы'; } if ($hour < 12) { return 'раніцы'; } if ($hour < 17) { return 'дня'; } return 'вечара'; }, 'months' => ['студзеня', 'лютага', 'сакавіка', 'красавіка', 'траўня', 'чэрвеня', 'ліпеня', 'жніўня', 'верасня', 'кастрычніка', 'лістапада', 'снежня'], 'months_standalone' => ['студзень', 'люты', 'сакавік', 'красавік', 'травень', 'чэрвень', 'ліпень', 'жнівень', 'верасень', 'кастрычнік', 'лістапад', 'снежань'], 'months_short' => ['студ', 'лют', 'сак', 'крас', 'трав', 'чэрв', 'ліп', 'жнів', 'вер', 'каст', 'ліст', 'снеж'], 'months_regexp' => '/(DD?o?\.?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/', 'weekdays' => ['нядзелю', 'панядзелак', 'аўторак', 'сераду', 'чацвер', 'пятніцу', 'суботу'], 'weekdays_standalone' => ['нядзеля', 'панядзелак', 'аўторак', 'серада', 'чацвер', 'пятніца', 'субота'], 'weekdays_short' => ['нд', 'пн', 'ат', 'ср', 'чц', 'пт', 'сб'], 'weekdays_min' => ['нд', 'пн', 'ат', 'ср', 'чц', 'пт', 'сб'], 'weekdays_regexp' => '/\[ ?[Ууў] ?(?:мінулую|наступную)? ?\] ?dddd/', 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' і '], 'months_short_standalone' => ['сту', 'лют', 'сак', 'кра', 'май', 'чэр', 'ліп', 'жні', 'вер', 'кас', 'ліс', 'сне'], ]; PK������<1ZX������Carbon/Lang/mag_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - bhashaghar@googlegroups.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'], 'months_short' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'], 'weekdays' => ['एतवार', 'सोमार', 'मंगर', 'बुध', 'बिफे', 'सूक', 'सनिचर'], 'weekdays_short' => ['एतवार', 'सोमार', 'मंगर', 'बुध', 'बिफे', 'सूक', 'सनिचर'], 'weekdays_min' => ['एतवार', 'सोमार', 'मंगर', 'बुध', 'बिफे', 'सूक', 'सनिचर'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['पूर्वाह्न', 'अपराह्न'], ]); PK������<1Z."N��N����Carbon/Lang/wa.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/wa_BE.php'; PK������<1ZSWN ��N ����Carbon/Lang/fy.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - Tim Fish * - JD Isaacks */ return [ 'year' => ':count jier|:count jierren', 'a_year' => 'ien jier|:count jierren', 'y' => ':count j', 'month' => ':count moanne|:count moannen', 'a_month' => 'ien moanne|:count moannen', 'm' => ':count moa.', 'week' => ':count wike|:count wiken', 'a_week' => 'in wike|:count wiken', 'a' => ':count w.', 'day' => ':count dei|:count dagen', 'a_day' => 'ien dei|:count dagen', 'd' => ':count d.', 'hour' => ':count oere|:count oeren', 'a_hour' => 'ien oere|:count oeren', 'h' => ':count o.', 'minute' => ':count minút|:count minuten', 'a_minute' => 'ien minút|:count minuten', 'min' => ':count min.', 'second' => ':count sekonde|:count sekonden', 'a_second' => 'in pear sekonden|:count sekonden', 's' => ':count s.', 'ago' => ':time lyn', 'from_now' => 'oer :time', 'diff_yesterday' => 'juster', 'diff_yesterday_regexp' => 'juster(?:\\s+om)?', 'diff_today' => 'hjoed', 'diff_today_regexp' => 'hjoed(?:\\s+om)?', 'diff_tomorrow' => 'moarn', 'diff_tomorrow_regexp' => 'moarn(?:\\s+om)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD-MM-YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[hjoed om] LT', 'nextDay' => '[moarn om] LT', 'nextWeek' => 'dddd [om] LT', 'lastDay' => '[juster om] LT', 'lastWeek' => '[ôfrûne] dddd [om] LT', 'sameElse' => 'L', ], 'ordinal' => function ($number) { return $number.(($number === 1 || $number === 8 || $number >= 20) ? 'ste' : 'de'); }, 'months' => ['jannewaris', 'febrewaris', 'maart', 'april', 'maaie', 'juny', 'july', 'augustus', 'septimber', 'oktober', 'novimber', 'desimber'], 'months_short' => ['jan', 'feb', 'mrt', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'], 'mmm_suffix' => '.', 'weekdays' => ['snein', 'moandei', 'tiisdei', 'woansdei', 'tongersdei', 'freed', 'sneon'], 'weekdays_short' => ['si.', 'mo.', 'ti.', 'wo.', 'to.', 'fr.', 'so.'], 'weekdays_min' => ['Si', 'Mo', 'Ti', 'Wo', 'To', 'Fr', 'So'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' en '], ]; PK������<1Z{9t������Carbon/Lang/hif_FJ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Samsung Electronics Co., Ltd. akhilesh.k@samsung.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'dddd DD MMM YYYY', ], 'months' => ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], 'weekdays' => ['Ravivar', 'Somvar', 'Mangalvar', 'Budhvar', 'Guruvar', 'Shukravar', 'Shanivar'], 'weekdays_short' => ['Ravi', 'Som', 'Mangal', 'Budh', 'Guru', 'Shukra', 'Shani'], 'weekdays_min' => ['Ravi', 'Som', 'Mangal', 'Budh', 'Guru', 'Shukra', 'Shani'], 'meridiem' => ['Purvahan', 'Aparaahna'], 'hour' => ':count minit', // less reliable 'h' => ':count minit', // less reliable 'a_hour' => ':count minit', // less reliable 'year' => ':count saal', 'y' => ':count saal', 'a_year' => ':count saal', 'month' => ':count Mahina', 'm' => ':count Mahina', 'a_month' => ':count Mahina', 'week' => ':count Hafta', 'w' => ':count Hafta', 'a_week' => ':count Hafta', 'day' => ':count Din', 'd' => ':count Din', 'a_day' => ':count Din', 'minute' => ':count Minit', 'min' => ':count Minit', 'a_minute' => ':count Minit', 'second' => ':count Second', 's' => ':count Second', 'a_second' => ':count Second', ]); PK������<1Zb �� ����Carbon/Lang/cs_CZ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/cs.php'; PK������<1Z )��)����Carbon/Lang/kkj.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ ]); PK������<1ZHv|������Carbon/Lang/bho_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - bhashaghar@googlegroups.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर"'], 'months_short' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर"'], 'weekdays' => ['रविवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'गुरुवार', 'शुक्रवार', 'शनिवार'], 'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र', 'शनि'], 'weekdays_min' => ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र', 'शनि'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['पूर्वाह्न', 'अपराह्न'], 'hour' => ':count मौसम', 'h' => ':count मौसम', 'a_hour' => ':count मौसम', 'minute' => ':count कला', 'min' => ':count कला', 'a_minute' => ':count कला', 'second' => ':count सोमार', 's' => ':count सोमार', 'a_second' => ':count सोमार', 'year' => ':count साल', 'y' => ':count साल', 'a_year' => ':count साल', 'month' => ':count महिना', 'm' => ':count महिना', 'a_month' => ':count महिना', 'week' => ':count सप्ताह', 'w' => ':count सप्ताह', 'a_week' => ':count सप्ताह', 'day' => ':count दिन', 'd' => ':count दिन', 'a_day' => ':count दिन', ]); PK������<1Z"������Carbon/Lang/kam.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['Ĩyakwakya', 'Ĩyawĩoo'], 'weekdays' => ['Wa kyumwa', 'Wa kwambĩlĩlya', 'Wa kelĩ', 'Wa katatũ', 'Wa kana', 'Wa katano', 'Wa thanthatũ'], 'weekdays_short' => ['Wky', 'Wkw', 'Wkl', 'Wtũ', 'Wkn', 'Wtn', 'Wth'], 'weekdays_min' => ['Wky', 'Wkw', 'Wkl', 'Wtũ', 'Wkn', 'Wtn', 'Wth'], 'months' => ['Mwai wa mbee', 'Mwai wa kelĩ', 'Mwai wa katatũ', 'Mwai wa kana', 'Mwai wa katano', 'Mwai wa thanthatũ', 'Mwai wa muonza', 'Mwai wa nyaanya', 'Mwai wa kenda', 'Mwai wa ĩkumi', 'Mwai wa ĩkumi na ĩmwe', 'Mwai wa ĩkumi na ilĩ'], 'months_short' => ['Mbe', 'Kel', 'Ktũ', 'Kan', 'Ktn', 'Tha', 'Moo', 'Nya', 'Knd', 'Ĩku', 'Ĩkm', 'Ĩkl'], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], // Too unreliable /* 'year' => ':count mbua', // less reliable 'y' => ':count mbua', // less reliable 'a_year' => ':count mbua', // less reliable 'month' => ':count ndakitali', // less reliable 'm' => ':count ndakitali', // less reliable 'a_month' => ':count ndakitali', // less reliable 'day' => ':count wia', // less reliable 'd' => ':count wia', // less reliable 'a_day' => ':count wia', // less reliable 'hour' => ':count orasan', // less reliable 'h' => ':count orasan', // less reliable 'a_hour' => ':count orasan', // less reliable 'minute' => ':count orasan', // less reliable 'min' => ':count orasan', // less reliable 'a_minute' => ':count orasan', // less reliable */ ]); PK������<1Z= �� ����Carbon/Lang/cy.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - JD Isaacks * - Daniel Monaghan */ return [ 'year' => '{1}blwyddyn|]1,Inf[:count flynedd', 'y' => ':countbl', 'month' => '{1}mis|]1,Inf[:count mis', 'm' => ':countmi', 'week' => ':count wythnos', 'w' => ':countw', 'day' => '{1}diwrnod|]1,Inf[:count diwrnod', 'd' => ':countd', 'hour' => '{1}awr|]1,Inf[:count awr', 'h' => ':counth', 'minute' => '{1}munud|]1,Inf[:count munud', 'min' => ':countm', 'second' => '{1}ychydig eiliadau|]1,Inf[:count eiliad', 's' => ':counts', 'ago' => ':time yn ôl', 'from_now' => 'mewn :time', 'after' => ':time ar ôl', 'before' => ':time o\'r blaen', 'diff_now' => 'nawr', 'diff_today' => 'Heddiw', 'diff_today_regexp' => 'Heddiw(?:\\s+am)?', 'diff_yesterday' => 'ddoe', 'diff_yesterday_regexp' => 'Ddoe(?:\\s+am)?', 'diff_tomorrow' => 'yfory', 'diff_tomorrow_regexp' => 'Yfory(?:\\s+am)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[Heddiw am] LT', 'nextDay' => '[Yfory am] LT', 'nextWeek' => 'dddd [am] LT', 'lastDay' => '[Ddoe am] LT', 'lastWeek' => 'dddd [diwethaf am] LT', 'sameElse' => 'L', ], 'ordinal' => function ($number) { return $number.( $number > 20 ? (\in_array((int) $number, [40, 50, 60, 80, 100], true) ? 'fed' : 'ain') : ([ '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed', // 11eg to 20fed ])[$number] ?? '' ); }, 'months' => ['Ionawr', 'Chwefror', 'Mawrth', 'Ebrill', 'Mai', 'Mehefin', 'Gorffennaf', 'Awst', 'Medi', 'Hydref', 'Tachwedd', 'Rhagfyr'], 'months_short' => ['Ion', 'Chwe', 'Maw', 'Ebr', 'Mai', 'Meh', 'Gor', 'Aws', 'Med', 'Hyd', 'Tach', 'Rhag'], 'weekdays' => ['Dydd Sul', 'Dydd Llun', 'Dydd Mawrth', 'Dydd Mercher', 'Dydd Iau', 'Dydd Gwener', 'Dydd Sadwrn'], 'weekdays_short' => ['Sul', 'Llun', 'Maw', 'Mer', 'Iau', 'Gwe', 'Sad'], 'weekdays_min' => ['Su', 'Ll', 'Ma', 'Me', 'Ia', 'Gw', 'Sa'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' a '], 'meridiem' => ['yb', 'yh'], ]; PK������<1ZT.C��C����Carbon/Lang/rwk.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['utuko', 'kyiukonyi'], 'weekdays' => ['Jumapilyi', 'Jumatatuu', 'Jumanne', 'Jumatanu', 'Alhamisi', 'Ijumaa', 'Jumamosi'], 'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'], 'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'], 'months' => ['Januari', 'Februari', 'Machi', 'Aprilyi', 'Mei', 'Junyi', 'Julyai', 'Agusti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'], 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], ]); PK������<1Zd������Carbon/Lang/es_PY.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]); PK������<1ZKNn��n����Carbon/Lang/no.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Daniel S. Billing * - Paul * - Jimmie Johansson * - Jens Herlevsen */ return array_replace_recursive(require __DIR__.'/nb.php', [ 'formats' => [ 'LLL' => 'D. MMMM YYYY HH:mm', 'LLLL' => 'dddd, D. MMMM YYYY [kl.] HH:mm', ], 'calendar' => [ 'nextWeek' => 'på dddd [kl.] LT', 'lastWeek' => '[i] dddd[s kl.] LT', ], ]); PK������<1Zw �� ����Carbon/Lang/fr_VU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/fr.php', [ 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY h:mm a', 'LLLL' => 'dddd D MMMM YYYY h:mm a', ], ]); PK������<1Z?Ej �� ����Carbon/Lang/en_BS.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1Z%������Carbon/Lang/rof.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['kang’ama', 'kingoto'], 'weekdays' => ['Ijumapili', 'Ijumatatu', 'Ijumanne', 'Ijumatano', 'Alhamisi', 'Ijumaa', 'Ijumamosi'], 'weekdays_short' => ['Ijp', 'Ijt', 'Ijn', 'Ijtn', 'Alh', 'Iju', 'Ijm'], 'weekdays_min' => ['Ijp', 'Ijt', 'Ijn', 'Ijtn', 'Alh', 'Iju', 'Ijm'], 'months' => ['Mweri wa kwanza', 'Mweri wa kaili', 'Mweri wa katatu', 'Mweri wa kaana', 'Mweri wa tanu', 'Mweri wa sita', 'Mweri wa saba', 'Mweri wa nane', 'Mweri wa tisa', 'Mweri wa ikumi', 'Mweri wa ikumi na moja', 'Mweri wa ikumi na mbili'], 'months_short' => ['M1', 'M2', 'M3', 'M4', 'M5', 'M6', 'M7', 'M8', 'M9', 'M10', 'M11', 'M12'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], ]); PK������<1Zx0N��N����Carbon/Lang/ts.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/ts_ZA.php'; PK������<1Z/������Carbon/Lang/ff.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM, YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'months' => ['siilo', 'colte', 'mbooy', 'seeɗto', 'duujal', 'korse', 'morso', 'juko', 'siilto', 'yarkomaa', 'jolal', 'bowte'], 'months_short' => ['sii', 'col', 'mbo', 'see', 'duu', 'kor', 'mor', 'juk', 'slt', 'yar', 'jol', 'bow'], 'weekdays' => ['dewo', 'aaɓnde', 'mawbaare', 'njeslaare', 'naasaande', 'mawnde', 'hoore-biir'], 'weekdays_short' => ['dew', 'aaɓ', 'maw', 'nje', 'naa', 'mwd', 'hbi'], 'weekdays_min' => ['dew', 'aaɓ', 'maw', 'nje', 'naa', 'mwd', 'hbi'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'meridiem' => ['subaka', 'kikiiɗe'], 'year' => ':count baret', // less reliable 'y' => ':count baret', // less reliable 'a_year' => ':count baret', // less reliable 'month' => ':count lewru', // less reliable 'm' => ':count lewru', // less reliable 'a_month' => ':count lewru', // less reliable 'week' => ':count naange', // less reliable 'w' => ':count naange', // less reliable 'a_week' => ':count naange', // less reliable 'day' => ':count dian', // less reliable 'd' => ':count dian', // less reliable 'a_day' => ':count dian', // less reliable 'hour' => ':count montor', // less reliable 'h' => ':count montor', // less reliable 'a_hour' => ':count montor', // less reliable 'minute' => ':count tokossuoum', // less reliable 'min' => ':count tokossuoum', // less reliable 'a_minute' => ':count tokossuoum', // less reliable 'second' => ':count tenen', // less reliable 's' => ':count tenen', // less reliable 'a_second' => ':count tenen', // less reliable ]); PK������<1Zv �� ����Carbon/Lang/bs_BA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/bs.php'; PK������<1ZVBO��O����Carbon/Lang/szl.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/szl_PL.php'; PK������<1ZڑQ��Q����Carbon/Lang/so_SO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ge'ez Frontier Foundation locales@geez.org */ return require __DIR__.'/so.php'; PK������<1Z'JN��N����Carbon/Lang/iu.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/iu_CA.php'; PK������<1ZA$������Carbon/Lang/ja.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Takuya Sawada * - Atsushi Tanaka * - François B * - Jason Katz-Brown * - Serhan Apaydın * - XueWei * - JD Isaacks * - toyama satoshi * - atakigawa */ use Carbon\CarbonInterface; return [ 'year' => ':count年', 'y' => ':count年', 'month' => ':countヶ月', 'm' => ':countヶ月', 'week' => ':count週間', 'w' => ':count週間', 'day' => ':count日', 'd' => ':count日', 'hour' => ':count時間', 'h' => ':count時間', 'minute' => ':count分', 'min' => ':count分', 'second' => ':count秒', 'a_second' => '{1}数秒|]1,Inf[:count秒', 's' => ':count秒', 'ago' => ':time前', 'from_now' => ':time後', 'after' => ':time後', 'before' => ':time前', 'diff_now' => '今', 'diff_today' => '今日', 'diff_yesterday' => '昨日', 'diff_tomorrow' => '明日', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY/MM/DD', 'LL' => 'YYYY年M月D日', 'LLL' => 'YYYY年M月D日 HH:mm', 'LLLL' => 'YYYY年M月D日 dddd HH:mm', ], 'calendar' => [ 'sameDay' => '[今日] LT', 'nextDay' => '[明日] LT', 'nextWeek' => function (CarbonInterface $current, CarbonInterface $other) { if ($other->week !== $current->week) { return '[来週]dddd LT'; } return 'dddd LT'; }, 'lastDay' => '[昨日] LT', 'lastWeek' => function (CarbonInterface $current, CarbonInterface $other) { if ($other->week !== $current->week) { return '[先週]dddd LT'; } return 'dddd LT'; }, 'sameElse' => 'L', ], 'ordinal' => function ($number, $period) { switch ($period) { case 'd': case 'D': case 'DDD': return $number.'日'; default: return $number; } }, 'meridiem' => ['午前', '午後'], 'months' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], 'months_short' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], 'weekdays' => ['日曜日', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日'], 'weekdays_short' => ['日', '月', '火', '水', '木', '金', '土'], 'weekdays_min' => ['日', '月', '火', '水', '木', '金', '土'], 'list' => '、', 'alt_numbers' => ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十', '二十一', '二十二', '二十三', '二十四', '二十五', '二十六', '二十七', '二十八', '二十九', '三十', '三十一', '三十二', '三十三', '三十四', '三十五', '三十六', '三十七', '三十八', '三十九', '四十', '四十一', '四十二', '四十三', '四十四', '四十五', '四十六', '四十七', '四十八', '四十九', '五十', '五十一', '五十二', '五十三', '五十四', '五十五', '五十六', '五十七', '五十八', '五十九', '六十', '六十一', '六十二', '六十三', '六十四', '六十五', '六十六', '六十七', '六十八', '六十九', '七十', '七十一', '七十二', '七十三', '七十四', '七十五', '七十六', '七十七', '七十八', '七十九', '八十', '八十一', '八十二', '八十三', '八十四', '八十五', '八十六', '八十七', '八十八', '八十九', '九十', '九十一', '九十二', '九十三', '九十四', '九十五', '九十六', '九十七', '九十八', '九十九'], 'alt_numbers_pow' => [ 10000 => '万', 1000 => '千', 100 => '百', ], ]; PK������<1Z ������Carbon/Lang/da_GL.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/da.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', 'LL' => 'D. MMM YYYY', 'LLL' => 'D. MMMM YYYY HH.mm', 'LLLL' => 'dddd [den] D. MMMM YYYY HH.mm', ], ]); PK������<1ZpG��G����Carbon/Lang/en_SE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZIt �� ����Carbon/Lang/cv.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - François B * - JD Isaacks */ return [ 'year' => ':count ҫул', 'a_year' => '{1}пӗр ҫул|:count ҫул', 'month' => ':count уйӑх', 'a_month' => '{1}пӗр уйӑх|:count уйӑх', 'week' => ':count эрне', 'a_week' => '{1}пӗр эрне|:count эрне', 'day' => ':count кун', 'a_day' => '{1}пӗр кун|:count кун', 'hour' => ':count сехет', 'a_hour' => '{1}пӗр сехет|:count сехет', 'minute' => ':count минут', 'a_minute' => '{1}пӗр минут|:count минут', 'second' => ':count ҫеккунт', 'a_second' => '{1}пӗр-ик ҫеккунт|:count ҫеккунт', 'ago' => ':time каялла', 'from_now' => function ($time) { return $time.(preg_match('/сехет$/u', $time) ? 'рен' : (preg_match('/ҫул/u', $time) ? 'тан' : 'ран')); }, 'diff_yesterday' => 'Ӗнер', 'diff_today' => 'Паян', 'diff_tomorrow' => 'Ыран', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD-MM-YYYY', 'LL' => 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]', 'LLL' => 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm', 'LLLL' => 'dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm', ], 'calendar' => [ 'sameDay' => '[Паян] LT [сехетре]', 'nextDay' => '[Ыран] LT [сехетре]', 'nextWeek' => '[Ҫитес] dddd LT [сехетре]', 'lastDay' => '[Ӗнер] LT [сехетре]', 'lastWeek' => '[Иртнӗ] dddd LT [сехетре]', 'sameElse' => 'L', ], 'ordinal' => ':number-мӗш', 'months' => ['кӑрлач', 'нарӑс', 'пуш', 'ака', 'май', 'ҫӗртме', 'утӑ', 'ҫурла', 'авӑн', 'юпа', 'чӳк', 'раштав'], 'months_short' => ['кӑр', 'нар', 'пуш', 'ака', 'май', 'ҫӗр', 'утӑ', 'ҫур', 'авн', 'юпа', 'чӳк', 'раш'], 'weekdays' => ['вырсарникун', 'тунтикун', 'ытларикун', 'юнкун', 'кӗҫнерникун', 'эрнекун', 'шӑматкун'], 'weekdays_short' => ['выр', 'тун', 'ытл', 'юн', 'кӗҫ', 'эрн', 'шӑм'], 'weekdays_min' => ['вр', 'тн', 'ыт', 'юн', 'кҫ', 'эр', 'шм'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' тата '], ]; PK������<1Z?Ej �� ����Carbon/Lang/en_UM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1Z^َ������Carbon/Lang/ln_CG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ln.php', [ 'weekdays' => ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé', 'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno', 'mpɔ́sɔ'], 'weekdays_short' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'], 'weekdays_min' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'], 'meridiem' => ['ntɔ́ngɔ́', 'mpókwa'], ]); PK������<1Z} �� ����Carbon/Lang/yo_NG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/yo.php'; PK������<1Z?Ej �� ����Carbon/Lang/en_ZW.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1Z)��)����Carbon/Lang/ar_MR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ar.php', [ ]); PK������<1Zi?#������Carbon/Lang/en_AG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'day_of_first_week_of_year' => 1, ]); PK������<1Zը������Carbon/Lang/fy_DE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - information from Kenneth Christiansen Kenneth Christiansen, Pablo Saratxaga kenneth@gnu.org, pablo@mandriva.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], 'months' => ['Jaunuwoa', 'Februwoa', 'Moaz', 'Aprell', 'Mai', 'Juni', 'Juli', 'August', 'Septamba', 'Oktoba', 'Nowamba', 'Dezamba'], 'months_short' => ['Jan', 'Feb', 'Moz', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Now', 'Dez'], 'weekdays' => ['Sinndag', 'Mondag', 'Dingsdag', 'Meddwäakj', 'Donnadag', 'Friedag', 'Sinnowend'], 'weekdays_short' => ['Sdg', 'Mdg', 'Dsg', 'Mwk', 'Ddg', 'Fdg', 'Swd'], 'weekdays_min' => ['Sdg', 'Mdg', 'Dsg', 'Mwk', 'Ddg', 'Fdg', 'Swd'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, ]); PK������<1Z㼦t.��.����Carbon/Lang/lt.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Philippe Vaucher * - Tsutomu Kuroda * - tjku * - valdas406 * - Justas Palumickas * - Max Melentiev * - Andrius Janauskas * - Juanito Fatas * - Akira Matsuda * - Christopher Dell * - Enrique Vidal * - Simone Carletti * - Aaron Patterson * - Nicolás Hock Isaza * - Laurynas Butkus * - Sven Fuchs * - Dominykas Tijūnaitis * - Justinas Bolys * - Ričardas * - Kirill Chalkin * - Rolandas * - Justinas (Gamesh) */ return [ 'year' => ':count metai|:count metai|:count metų', 'y' => ':count m.', 'month' => ':count mėnuo|:count mėnesiai|:count mėnesį', 'm' => ':count mėn.', 'week' => ':count savaitė|:count savaitės|:count savaitę', 'w' => ':count sav.', 'day' => ':count diena|:count dienos|:count dienų', 'd' => ':count d.', 'hour' => ':count valanda|:count valandos|:count valandų', 'h' => ':count val.', 'minute' => ':count minutė|:count minutės|:count minutę', 'min' => ':count min.', 'second' => ':count sekundė|:count sekundės|:count sekundžių', 's' => ':count sek.', 'year_ago' => ':count metus|:count metus|:count metų', 'month_ago' => ':count mėnesį|:count mėnesius|:count mėnesių', 'week_ago' => ':count savaitę|:count savaites|:count savaičių', 'day_ago' => ':count dieną|:count dienas|:count dienų', 'hour_ago' => ':count valandą|:count valandas|:count valandų', 'minute_ago' => ':count minutę|:count minutes|:count minučių', 'second_ago' => ':count sekundę|:count sekundes|:count sekundžių', 'year_from_now' => ':count metų', 'month_from_now' => ':count mėnesio|:count mėnesių|:count mėnesių', 'week_from_now' => ':count savaitės|:count savaičių|:count savaičių', 'day_from_now' => ':count dienos|:count dienų|:count dienų', 'hour_from_now' => ':count valandos|:count valandų|:count valandų', 'minute_from_now' => ':count minutės|:count minučių|:count minučių', 'second_from_now' => ':count sekundės|:count sekundžių|:count sekundžių', 'year_after' => ':count metų', 'month_after' => ':count mėnesio|:count mėnesių|:count mėnesių', 'week_after' => ':count savaitės|:count savaičių|:count savaičių', 'day_after' => ':count dienos|:count dienų|:count dienų', 'hour_after' => ':count valandos|:count valandų|:count valandų', 'minute_after' => ':count minutės|:count minučių|:count minučių', 'second_after' => ':count sekundės|:count sekundžių|:count sekundžių', 'ago' => 'prieš :time', 'from_now' => ':time nuo dabar', 'after' => 'po :time', 'before' => 'už :time', 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'diff_now' => 'ką tik', 'diff_today' => 'Šiandien', 'diff_yesterday' => 'vakar', 'diff_yesterday_regexp' => 'Vakar', 'diff_tomorrow' => 'rytoj', 'diff_tomorrow_regexp' => 'Rytoj', 'diff_before_yesterday' => 'užvakar', 'diff_after_tomorrow' => 'poryt', 'period_recurrences' => 'kartą|:count kartų', 'period_interval' => 'kiekvieną :interval', 'period_start_date' => 'nuo :date', 'period_end_date' => 'iki :date', 'months' => ['sausio', 'vasario', 'kovo', 'balandžio', 'gegužės', 'birželio', 'liepos', 'rugpjūčio', 'rugsėjo', 'spalio', 'lapkričio', 'gruodžio'], 'months_standalone' => ['sausis', 'vasaris', 'kovas', 'balandis', 'gegužė', 'birželis', 'liepa', 'rugpjūtis', 'rugsėjis', 'spalis', 'lapkritis', 'gruodis'], 'months_regexp' => '/(L{2,4}|D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|MMMM?(\[[^\[\]]*\]|\s)+D[oD]?)/', 'months_short' => ['sau', 'vas', 'kov', 'bal', 'geg', 'bir', 'lie', 'rgp', 'rgs', 'spa', 'lap', 'gru'], 'weekdays' => ['sekmadienį', 'pirmadienį', 'antradienį', 'trečiadienį', 'ketvirtadienį', 'penktadienį', 'šeštadienį'], 'weekdays_standalone' => ['sekmadienis', 'pirmadienis', 'antradienis', 'trečiadienis', 'ketvirtadienis', 'penktadienis', 'šeštadienis'], 'weekdays_short' => ['sek', 'pir', 'ant', 'tre', 'ket', 'pen', 'šeš'], 'weekdays_min' => ['se', 'pi', 'an', 'tr', 'ke', 'pe', 'še'], 'list' => [', ', ' ir '], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY-MM-DD', 'LL' => 'MMMM DD, YYYY', 'LLL' => 'DD MMM HH:mm', 'LLLL' => 'MMMM DD, YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[Šiandien] LT', 'nextDay' => '[Rytoj] LT', 'nextWeek' => 'dddd LT', 'lastDay' => '[Vakar] LT', 'lastWeek' => '[Paskutinį] dddd LT', 'sameElse' => 'L', ], 'ordinal' => function ($number) { switch ($number) { case 0: return '0-is'; case 3: return '3-ias'; default: return "$number-as"; } }, 'meridiem' => ['priešpiet', 'popiet'], ]; PK������<1Z;i������Carbon/Lang/yi_US.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - http://www.uyip.org/ Pablo Saratxaga pablo@mandrakesoft.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'months' => ['יאַנואַר', 'פֿעברואַר', 'מערץ', 'אַפּריל', 'מיי', 'יוני', 'יולי', 'אויגוסט', 'סעפּטעמבער', 'אקטאבער', 'נאוועמבער', 'דעצעמבער'], 'months_short' => ['יאַנ', 'פֿעב', 'מאַר', 'אַפּר', 'מײַ ', 'יונ', 'יול', 'אױג', 'סעפּ', 'אָקט', 'נאָװ', 'דעצ'], 'weekdays' => ['זונטיק', 'מאָנטיק', 'דינסטיק', 'מיטװאָך', 'דאָנערשטיק', 'פֿרײַטיק', 'שבת'], 'weekdays_short' => ['זונ\'', 'מאָנ\'', 'דינ\'', 'מיט\'', 'דאָנ\'', 'פֿרײַ\'', 'שבת'], 'weekdays_min' => ['זונ\'', 'מאָנ\'', 'דינ\'', 'מיט\'', 'דאָנ\'', 'פֿרײַ\'', 'שבת'], 'day_of_first_week_of_year' => 1, 'year' => ':count יאר', 'y' => ':count יאר', 'a_year' => ':count יאר', 'month' => ':count חודש', 'm' => ':count חודש', 'a_month' => ':count חודש', 'week' => ':count וואָך', 'w' => ':count וואָך', 'a_week' => ':count וואָך', 'day' => ':count טאָג', 'd' => ':count טאָג', 'a_day' => ':count טאָג', 'hour' => ':count שעה', 'h' => ':count שעה', 'a_hour' => ':count שעה', 'minute' => ':count מינוט', 'min' => ':count מינוט', 'a_minute' => ':count מינוט', 'second' => ':count סעקונדע', 's' => ':count סעקונדע', 'a_second' => ':count סעקונדע', ]); PK������<1ZpG��G����Carbon/Lang/en_SX.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z?b �� ����Carbon/Lang/da.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Rune Mønnike * - François B * - codenhagen * - JD Isaacks * - Jens Herlevsen * - Ulrik McArdle (mcardle) * - Frederik Sauer (FrittenKeeZ) * - Janus Bahs Jacquet (kokoshneta) */ return [ 'year' => ':count år|:count år', 'a_year' => 'et år|:count år', 'y' => ':count år|:count år', 'month' => ':count måned|:count måneder', 'a_month' => 'en måned|:count måneder', 'm' => ':count mdr.', 'week' => ':count uge|:count uger', 'a_week' => 'en uge|:count uger', 'w' => ':count u.', 'day' => ':count dag|:count dage', 'a_day' => ':count dag|:count dage', 'd' => ':count d.', 'hour' => ':count time|:count timer', 'a_hour' => 'en time|:count timer', 'h' => ':count t.', 'minute' => ':count minut|:count minutter', 'a_minute' => 'et minut|:count minutter', 'min' => ':count min.', 'second' => ':count sekund|:count sekunder', 'a_second' => 'få sekunder|:count sekunder', 's' => ':count s.', 'ago' => 'for :time siden', 'from_now' => 'om :time', 'after' => ':time efter', 'before' => ':time før', 'diff_now' => 'nu', 'diff_today' => 'i dag', 'diff_today_regexp' => 'i dag(?:\\s+kl.)?', 'diff_yesterday' => 'i går', 'diff_yesterday_regexp' => 'i går(?:\\s+kl.)?', 'diff_tomorrow' => 'i morgen', 'diff_tomorrow_regexp' => 'i morgen(?:\\s+kl.)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D. MMMM YYYY', 'LLL' => 'D. MMMM YYYY HH:mm', 'LLLL' => 'dddd [d.] D. MMMM YYYY [kl.] HH:mm', ], 'calendar' => [ 'sameDay' => '[i dag kl.] LT', 'nextDay' => '[i morgen kl.] LT', 'nextWeek' => 'på dddd [kl.] LT', 'lastDay' => '[i går kl.] LT', 'lastWeek' => '[i] dddd[s kl.] LT', 'sameElse' => 'L', ], 'ordinal' => ':number.', 'months' => ['januar', 'februar', 'marts', 'april', 'maj', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'december'], 'months_short' => ['jan.', 'feb.', 'mar.', 'apr.', 'maj.', 'jun.', 'jul.', 'aug.', 'sep.', 'okt.', 'nov.', 'dec.'], 'weekdays' => ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag'], 'weekdays_short' => ['søn.', 'man.', 'tir.', 'ons.', 'tor.', 'fre.', 'lør.'], 'weekdays_min' => ['sø', 'ma', 'ti', 'on', 'to', 'fr', 'lø'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' og '], ]; PK������<1Z ������Carbon/Lang/bem_ZM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - ANLoc Martin Benjamin locales@africanlocalization.net */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'MM/DD/YYYY', ], 'months' => ['Januari', 'Februari', 'Machi', 'Epreo', 'Mei', 'Juni', 'Julai', 'Ogasti', 'Septemba', 'Oktoba', 'Novemba', 'Disemba'], 'months_short' => ['Jan', 'Feb', 'Mac', 'Epr', 'Mei', 'Jun', 'Jul', 'Oga', 'Sep', 'Okt', 'Nov', 'Dis'], 'weekdays' => ['Pa Mulungu', 'Palichimo', 'Palichibuli', 'Palichitatu', 'Palichine', 'Palichisano', 'Pachibelushi'], 'weekdays_short' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], 'weekdays_min' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'meridiem' => ['uluchelo', 'akasuba'], 'year' => 'myaka :count', 'y' => 'myaka :count', 'a_year' => 'myaka :count', 'month' => 'myeshi :count', 'm' => 'myeshi :count', 'a_month' => 'myeshi :count', 'week' => 'umulungu :count', 'w' => 'umulungu :count', 'a_week' => 'umulungu :count', 'day' => 'inshiku :count', 'd' => 'inshiku :count', 'a_day' => 'inshiku :count', 'hour' => 'awala :count', 'h' => 'awala :count', 'a_hour' => 'awala :count', 'minute' => 'miniti :count', 'min' => 'miniti :count', 'a_minute' => 'miniti :count', 'second' => 'sekondi :count', 's' => 'sekondi :count', 'a_second' => 'sekondi :count', ]); PK������<1ZY^��^����Carbon/Lang/ff_SN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Pular-Fulfulde.org Ibrahima Sarr admin@pulaar-fulfulde.org */ return require __DIR__.'/ff.php'; PK������<1Z )��)����Carbon/Lang/jgo.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ ]); PK������<1ZO2aN��N����Carbon/Lang/am.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/am_ET.php'; PK������<1ZpG��G����Carbon/Lang/en_TC.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZC=5 �� ����Carbon/Lang/ru_RU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ru.php'; PK������<1ZO��O����Carbon/Lang/nan.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/nan_TW.php'; PK������<1Z=Y~��~����Carbon/Lang/sw_UG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/sw.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', ], ]); PK������<1ZpG��G����Carbon/Lang/en_TK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z''x �� ����Carbon/Lang/fr_BL.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Z"�������Carbon/Lang/de_LU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/de.php', [ 'formats' => [ 'L' => 'YYYY-MM-DD', ], ]); PK������<1ZhaK������Carbon/Lang/az_AZ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Pablo Saratxaga pablo@mandrakesoft.com */ return array_replace_recursive(require __DIR__.'/az.php', [ 'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'İyn', 'İyl', 'Avq', 'Sen', 'Okt', 'Noy', 'Dek'], 'weekdays' => ['bazar günü', 'bazar ertəsi', 'çərşənbə axşamı', 'çərşənbə', 'cümə axşamı', 'cümə', 'şənbə'], 'weekdays_short' => ['baz', 'ber', 'çax', 'çər', 'cax', 'cüm', 'şnb'], 'weekdays_min' => ['baz', 'ber', 'çax', 'çər', 'cax', 'cüm', 'şnb'], ]); PK������<1ZХ������Carbon/Lang/sr.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - François B * - shaishavgandhi05 * - Serhan Apaydın * - JD Isaacks * - Glavić * - Milos Sakovic */ use Carbon\CarbonInterface; return [ 'year' => ':count godina|:count godine|:count godina', 'y' => ':count g.', 'month' => ':count mesec|:count meseca|:count meseci', 'm' => ':count mj.', 'week' => ':count nedelja|:count nedelje|:count nedelja', 'w' => ':count ned.', 'day' => ':count dan|:count dana|:count dana', 'd' => ':count d.', 'hour' => ':count sat|:count sata|:count sati', 'h' => ':count č.', 'minute' => ':count minut|:count minuta|:count minuta', 'min' => ':count min.', 'second' => ':count sekundu|:count sekunde|:count sekundi', 's' => ':count sek.', 'ago' => 'pre :time', 'from_now' => 'za :time', 'after' => 'nakon :time', 'before' => 'pre :time', 'year_from_now' => ':count godinu|:count godine|:count godina', 'year_ago' => ':count godinu|:count godine|:count godina', 'week_from_now' => ':count nedelju|:count nedelje|:count nedelja', 'week_ago' => ':count nedelju|:count nedelje|:count nedelja', 'diff_now' => 'upravo sada', 'diff_today' => 'danas', 'diff_today_regexp' => 'danas(?:\\s+u)?', 'diff_yesterday' => 'juče', 'diff_yesterday_regexp' => 'juče(?:\\s+u)?', 'diff_tomorrow' => 'sutra', 'diff_tomorrow_regexp' => 'sutra(?:\\s+u)?', 'diff_before_yesterday' => 'prekjuče', 'diff_after_tomorrow' => 'preksutra', 'formats' => [ 'LT' => 'H:mm', 'LTS' => 'H:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D. MMMM YYYY', 'LLL' => 'D. MMMM YYYY H:mm', 'LLLL' => 'dddd, D. MMMM YYYY H:mm', ], 'calendar' => [ 'sameDay' => '[danas u] LT', 'nextDay' => '[sutra u] LT', 'nextWeek' => function (CarbonInterface $date) { switch ($date->dayOfWeek) { case 0: return '[u nedelju u] LT'; case 3: return '[u sredu u] LT'; case 6: return '[u subotu u] LT'; default: return '[u] dddd [u] LT'; } }, 'lastDay' => '[juče u] LT', 'lastWeek' => function (CarbonInterface $date) { switch ($date->dayOfWeek) { case 0: return '[prošle nedelje u] LT'; case 1: return '[prošlog ponedeljka u] LT'; case 2: return '[prošlog utorka u] LT'; case 3: return '[prošle srede u] LT'; case 4: return '[prošlog četvrtka u] LT'; case 5: return '[prošlog petka u] LT'; default: return '[prošle subote u] LT'; } }, 'sameElse' => 'L', ], 'ordinal' => ':number.', 'months' => ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'], 'months_short' => ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun', 'jul', 'avg.', 'sep.', 'okt.', 'nov.', 'dec.'], 'weekdays' => ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak', 'subota'], 'weekdays_short' => ['ned.', 'pon.', 'uto.', 'sre.', 'čet.', 'pet.', 'sub.'], 'weekdays_min' => ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' i '], ]; PK������<1Z�������Carbon/Lang/sq_XK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/sq.php', [ 'formats' => [ 'L' => 'D.M.YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY, HH:mm', 'LLLL' => 'dddd, D MMMM YYYY, HH:mm', ], ]); PK������<1Z,�������Carbon/Lang/ar_BH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org * - Abdullah-Alhariri */ return array_replace_recursive(require __DIR__.'/ar.php', [ 'formats' => [ 'L' => 'DD MMM, YYYY', ], 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'], 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'], 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'], ]); PK������<1ZpG��G����Carbon/Lang/en_BE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Zj\��\����Carbon/Lang/vo.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'months' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'], 'months_short' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY-MM-dd', 'LL' => 'YYYY MMM D', 'LLL' => 'YYYY MMMM D HH:mm', 'LLLL' => 'YYYY MMMM D, dddd HH:mm', ], 'year' => ':count yel', 'y' => ':count yel', 'a_year' => ':count yel', 'month' => ':count mul', 'm' => ':count mul', 'a_month' => ':count mul', 'week' => ':count vig', 'w' => ':count vig', 'a_week' => ':count vig', 'day' => ':count del', 'd' => ':count del', 'a_day' => ':count del', 'hour' => ':count düp', 'h' => ':count düp', 'a_hour' => ':count düp', 'minute' => ':count minut', 'min' => ':count minut', 'a_minute' => ':count minut', 'second' => ':count sekun', 's' => ':count sekun', 'a_second' => ':count sekun', ]); PK������<1Z?Ej �� ����Carbon/Lang/en_KE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1Zov2��2����Carbon/Lang/ce_RU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - ANCHR */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'YYYY.DD.MM', ], 'months' => ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'], 'months_short' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'], 'weekdays' => ['КӀиранан де', 'Оршотан де', 'Шинарин де', 'Кхаарин де', 'Еарин де', 'ПӀераскан де', 'Шот де'], 'weekdays_short' => ['КӀ', 'Ор', 'Ши', 'Кх', 'Еа', 'ПӀ', 'Шо'], 'weekdays_min' => ['КӀ', 'Ор', 'Ши', 'Кх', 'Еа', 'ПӀ', 'Шо'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'year' => ':count шо', 'y' => ':count шо', 'a_year' => ':count шо', 'month' => ':count бутт', 'm' => ':count бутт', 'a_month' => ':count бутт', 'week' => ':count кӏира', 'w' => ':count кӏира', 'a_week' => ':count кӏира', 'day' => ':count де', 'd' => ':count де', 'a_day' => ':count де', 'hour' => ':count сахьт', 'h' => ':count сахьт', 'a_hour' => ':count сахьт', 'minute' => ':count минот', 'min' => ':count минот', 'a_minute' => ':count минот', 'second' => ':count секунд', 's' => ':count секунд', 'a_second' => ':count секунд', ]); PK������<1ZM|UN��N����Carbon/Lang/tn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/tn_ZA.php'; PK������<1Z"�������Carbon/Lang/de_BE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/de.php', [ 'formats' => [ 'L' => 'YYYY-MM-DD', ], ]); PK������<1ZPש������Carbon/Lang/hak_TW.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'YYYY年MM月DD日', ], 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], 'months_short' => [' 1月', ' 2月', ' 3月', ' 4月', ' 5月', ' 6月', ' 7月', ' 8月', ' 9月', '10月', '11月', '12月'], 'weekdays' => ['禮拜日', '禮拜一', '禮拜二', '禮拜三', '禮拜四', '禮拜五', '禮拜六'], 'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'], 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['上晝', '下晝'], 'year' => ':count ngien11', 'y' => ':count ngien11', 'a_year' => ':count ngien11', 'month' => ':count ngie̍t', 'm' => ':count ngie̍t', 'a_month' => ':count ngie̍t', 'week' => ':count lî-pai', 'w' => ':count lî-pai', 'a_week' => ':count lî-pai', 'day' => ':count ngit', 'd' => ':count ngit', 'a_day' => ':count ngit', 'hour' => ':count sṳ̀', 'h' => ':count sṳ̀', 'a_hour' => ':count sṳ̀', 'minute' => ':count fûn', 'min' => ':count fûn', 'a_minute' => ':count fûn', 'second' => ':count miéu', 's' => ':count miéu', 'a_second' => ':count miéu', ]); PK������<1Z<-O��O����Carbon/Lang/bho.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/bho_IN.php'; PK������<1Z N��N����Carbon/Lang/sa.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/sa_IN.php'; PK������<1Z߬��������Carbon/Lang/ts_ZA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['Sunguti', 'Nyenyenyani', 'Nyenyankulu', 'Dzivamisoko', 'Mudyaxihi', 'Khotavuxika', 'Mawuwani', 'Mhawuri', 'Ndzhati', 'Nhlangula', 'Hukuri', 'N\'wendzamhala'], 'months_short' => ['Sun', 'Yan', 'Kul', 'Dzi', 'Mud', 'Kho', 'Maw', 'Mha', 'Ndz', 'Nhl', 'Huk', 'N\'w'], 'weekdays' => ['Sonto', 'Musumbhunuku', 'Ravumbirhi', 'Ravunharhu', 'Ravumune', 'Ravuntlhanu', 'Mugqivela'], 'weekdays_short' => ['Son', 'Mus', 'Bir', 'Har', 'Ne', 'Tlh', 'Mug'], 'weekdays_min' => ['Son', 'Mus', 'Bir', 'Har', 'Ne', 'Tlh', 'Mug'], 'day_of_first_week_of_year' => 1, 'year' => 'malembe ya :count', 'y' => 'malembe ya :count', 'a_year' => 'malembe ya :count', 'month' => 'tin’hweti ta :count', 'm' => 'tin’hweti ta :count', 'a_month' => 'tin’hweti ta :count', 'week' => 'mavhiki ya :count', 'w' => 'mavhiki ya :count', 'a_week' => 'mavhiki ya :count', 'day' => 'masiku :count', 'd' => 'masiku :count', 'a_day' => 'masiku :count', 'hour' => 'tiawara ta :count', 'h' => 'tiawara ta :count', 'a_hour' => 'tiawara ta :count', 'minute' => 'timinete ta :count', 'min' => 'timinete ta :count', 'a_minute' => 'timinete ta :count', 'second' => 'tisekoni ta :count', 's' => 'tisekoni ta :count', 'a_second' => 'tisekoni ta :count', ]); PK������<1ZpG��G����Carbon/Lang/en_SL.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z?Ej �� ����Carbon/Lang/en_AS.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1ZZ �� ����Carbon/Lang/ro_MD.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ro.php', [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY, HH:mm', 'LLLL' => 'dddd, D MMMM YYYY, HH:mm', ], ]); PK������<1ZC~sG��G����Carbon/Lang/pt_MZ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/pt.php', [ 'first_day_of_week' => 0, ]); PK������<1ZI V �� ����Carbon/Lang/fi.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Philippe Vaucher * - Janne Warén * - digitalfrost * - Tsutomu Kuroda * - Roope Salmi * - tjku * - Max Melentiev * - Sami Haahtinen * - Teemu Leisti * - Artem Ignatyev * - Akira Matsuda * - Christopher Dell * - Enrique Vidal * - Simone Carletti * - Robert Bjarnason * - Aaron Patterson * - Nicolás Hock Isaza * - Tom Hughes * - Sven Fuchs * - Petri Kivikangas * - Nizar Jouini * - Marko Seppae * - Tomi Mynttinen (Pikseli) * - Petteri (powergrip) */ return [ 'year' => ':count vuosi|:count vuotta', 'y' => ':count v', 'month' => ':count kuukausi|:count kuukautta', 'm' => ':count kk', 'week' => ':count viikko|:count viikkoa', 'w' => ':count vk', 'day' => ':count päivä|:count päivää', 'd' => ':count pv', 'hour' => ':count tunti|:count tuntia', 'h' => ':count t', 'minute' => ':count minuutti|:count minuuttia', 'min' => ':count min', 'second' => ':count sekunti|:count sekuntia', 'a_second' => 'muutama sekunti|:count sekuntia', 's' => ':count s', 'ago' => ':time sitten', 'from_now' => ':time päästä', 'year_from_now' => ':count vuoden', 'month_from_now' => ':count kuukauden', 'week_from_now' => ':count viikon', 'day_from_now' => ':count päivän', 'hour_from_now' => ':count tunnin', 'minute_from_now' => ':count minuutin', 'second_from_now' => ':count sekunnin', 'after' => ':time sen jälkeen', 'before' => ':time ennen', 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' ja '], 'diff_now' => 'nyt', 'diff_yesterday' => 'eilen', 'diff_tomorrow' => 'huomenna', 'formats' => [ 'LT' => 'HH.mm', 'LTS' => 'HH.mm:ss', 'L' => 'D.M.YYYY', 'LL' => 'dddd D. MMMM[ta] YYYY', 'll' => 'ddd D. MMM YYYY', 'LLL' => 'D.MM. HH.mm', 'LLLL' => 'D. MMMM[ta] YYYY HH.mm', 'llll' => 'D. MMM YY HH.mm', ], 'weekdays' => ['sunnuntai', 'maanantai', 'tiistai', 'keskiviikko', 'torstai', 'perjantai', 'lauantai'], 'weekdays_short' => ['su', 'ma', 'ti', 'ke', 'to', 'pe', 'la'], 'weekdays_min' => ['su', 'ma', 'ti', 'ke', 'to', 'pe', 'la'], 'months' => ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'], 'months_short' => ['tammi', 'helmi', 'maalis', 'huhti', 'touko', 'kesä', 'heinä', 'elo', 'syys', 'loka', 'marras', 'joulu'], 'meridiem' => ['aamupäivä', 'iltapäivä'], ]; PK������<1Z-|K������Carbon/Lang/es_PR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]); PK������<1Zۨr������Carbon/Lang/dyo.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'weekdays' => ['Dimas', 'Teneŋ', 'Talata', 'Alarbay', 'Aramisay', 'Arjuma', 'Sibiti'], 'weekdays_short' => ['Dim', 'Ten', 'Tal', 'Ala', 'Ara', 'Arj', 'Sib'], 'weekdays_min' => ['Dim', 'Ten', 'Tal', 'Ala', 'Ara', 'Arj', 'Sib'], 'months' => ['Sanvie', 'Fébirie', 'Mars', 'Aburil', 'Mee', 'Sueŋ', 'Súuyee', 'Ut', 'Settembar', 'Oktobar', 'Novembar', 'Disambar'], 'months_short' => ['Sa', 'Fe', 'Ma', 'Ab', 'Me', 'Su', 'Sú', 'Ut', 'Se', 'Ok', 'No', 'De'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], ]); PK������<1Z �� ����Carbon/Lang/mr_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/mr.php'; PK������<1ZpR������Carbon/Lang/zh.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - xuri * - sycuato * - bokideckonja * - Luo Ning * - William Yang (williamyang233) */ return array_merge(require __DIR__.'/zh_Hans.php', [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY/MM/DD', 'LL' => 'YYYY年M月D日', 'LLL' => 'YYYY年M月D日 A h点mm分', 'LLLL' => 'YYYY年M月D日dddd A h点mm分', ], ]); PK������<1Zb������Carbon/Lang/ti_ET.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ge'ez Frontier Foundation locales@geez.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች', 'ኤፕረል', 'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት', 'ሴፕቴምበር', 'ኦክተውበር', 'ኖቬምበር', 'ዲሴምበር'], 'months_short' => ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕረ', 'ሜይ ', 'ጁን ', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክተ', 'ኖቬም', 'ዲሴም'], 'weekdays' => ['ሰንበት', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'], 'weekdays_short' => ['ሰንበ', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'], 'weekdays_min' => ['ሰንበ', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['ንጉሆ ሰዓተ', 'ድሕር ሰዓት'], ]); PK������<1ZI ��I ����Carbon/Lang/as_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Amitakhya Phukan, Red Hat bug-glibc@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'D-MM-YYYY', ], 'months' => ['জানুৱাৰী', 'ফেব্ৰুৱাৰী', 'মাৰ্চ', 'এপ্ৰিল', 'মে', 'জুন', 'জুলাই', 'আগষ্ট', 'ছেপ্তেম্বৰ', 'অক্টোবৰ', 'নৱেম্বৰ', 'ডিচেম্বৰ'], 'months_short' => ['জানু', 'ফেব্ৰু', 'মাৰ্চ', 'এপ্ৰিল', 'মে', 'জুন', 'জুলাই', 'আগ', 'সেপ্ট', 'অক্টো', 'নভে', 'ডিসে'], 'weekdays' => ['দেওবাৰ', 'সোমবাৰ', 'মঙ্গলবাৰ', 'বুধবাৰ', 'বৃহষ্পতিবাৰ', 'শুক্ৰবাৰ', 'শনিবাৰ'], 'weekdays_short' => ['দেও', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহষ্পতি', 'শুক্ৰ', 'শনি'], 'weekdays_min' => ['দেও', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহষ্পতি', 'শুক্ৰ', 'শনি'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['পূৰ্ব্বাহ্ন', 'অপৰাহ্ন'], 'year' => ':count বছৰ', 'y' => ':count বছৰ', 'a_year' => ':count বছৰ', 'month' => ':count মাহ', 'm' => ':count মাহ', 'a_month' => ':count মাহ', 'week' => ':count সপ্তাহ', 'w' => ':count সপ্তাহ', 'a_week' => ':count সপ্তাহ', 'day' => ':count বাৰ', 'd' => ':count বাৰ', 'a_day' => ':count বাৰ', 'hour' => ':count ঘণ্টা', 'h' => ':count ঘণ্টা', 'a_hour' => ':count ঘণ্টা', 'minute' => ':count মিনিট', 'min' => ':count মিনিট', 'a_minute' => ':count মিনিট', 'second' => ':count দ্বিতীয়', 's' => ':count দ্বিতীয়', 'a_second' => ':count দ্বিতীয়', ]); PK������<1ZpG��G����Carbon/Lang/en_ER.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZpG��G����Carbon/Lang/en_GY.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z''x �� ����Carbon/Lang/fr_YT.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Z7$������Carbon/Lang/en_ZA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YY', 'LL' => 'MMMM DD, YYYY', 'LLL' => 'DD MMM HH:mm', 'LLLL' => 'MMMM DD, YYYY HH:mm', ], 'day_of_first_week_of_year' => 1, ]); PK������<1Z&$������Carbon/Lang/en_AU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Kunal Marwaha * - François B * - Mayank Badola * - JD Isaacks */ return array_replace_recursive(require __DIR__.'/en.php', [ 'from_now' => 'in :time', 'formats' => [ 'LT' => 'h:mm A', 'LTS' => 'h:mm:ss A', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY h:mm A', 'LLLL' => 'dddd, D MMMM YYYY h:mm A', ], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, ]); PK������<1Z}t������Carbon/Lang/ar_Shakl.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Abdellah Chadidi * - Atef Ben Ali (atefBB) * - Mohamed Sabil (mohamedsabil83) */ // Same for long and short $months = [ // @TODO add shakl to months 'يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر', ]; return [ 'year' => implode('|', ['{0}:count سَنَة', '{1}سَنَة', '{2}سَنَتَيْن', ']2,11[:count سَنَوَات', ']10,Inf[:count سَنَة']), 'a_year' => implode('|', ['{0}:count سَنَة', '{1}سَنَة', '{2}سَنَتَيْن', ']2,11[:count سَنَوَات', ']10,Inf[:count سَنَة']), 'month' => implode('|', ['{0}:count شَهْرَ', '{1}شَهْرَ', '{2}شَهْرَيْن', ']2,11[:count أَشْهُر', ']10,Inf[:count شَهْرَ']), 'a_month' => implode('|', ['{0}:count شَهْرَ', '{1}شَهْرَ', '{2}شَهْرَيْن', ']2,11[:count أَشْهُر', ']10,Inf[:count شَهْرَ']), 'week' => implode('|', ['{0}:count أُسْبُوع', '{1}أُسْبُوع', '{2}أُسْبُوعَيْن', ']2,11[:count أَسَابِيع', ']10,Inf[:count أُسْبُوع']), 'a_week' => implode('|', ['{0}:count أُسْبُوع', '{1}أُسْبُوع', '{2}أُسْبُوعَيْن', ']2,11[:count أَسَابِيع', ']10,Inf[:count أُسْبُوع']), 'day' => implode('|', ['{0}:count يَوْم', '{1}يَوْم', '{2}يَوْمَيْن', ']2,11[:count أَيَّام', ']10,Inf[:count يَوْم']), 'a_day' => implode('|', ['{0}:count يَوْم', '{1}يَوْم', '{2}يَوْمَيْن', ']2,11[:count أَيَّام', ']10,Inf[:count يَوْم']), 'hour' => implode('|', ['{0}:count سَاعَة', '{1}سَاعَة', '{2}سَاعَتَيْن', ']2,11[:count سَاعَات', ']10,Inf[:count سَاعَة']), 'a_hour' => implode('|', ['{0}:count سَاعَة', '{1}سَاعَة', '{2}سَاعَتَيْن', ']2,11[:count سَاعَات', ']10,Inf[:count سَاعَة']), 'minute' => implode('|', ['{0}:count دَقِيقَة', '{1}دَقِيقَة', '{2}دَقِيقَتَيْن', ']2,11[:count دَقَائِق', ']10,Inf[:count دَقِيقَة']), 'a_minute' => implode('|', ['{0}:count دَقِيقَة', '{1}دَقِيقَة', '{2}دَقِيقَتَيْن', ']2,11[:count دَقَائِق', ']10,Inf[:count دَقِيقَة']), 'second' => implode('|', ['{0}:count ثَانِيَة', '{1}ثَانِيَة', '{2}ثَانِيَتَيْن', ']2,11[:count ثَوَان', ']10,Inf[:count ثَانِيَة']), 'a_second' => implode('|', ['{0}:count ثَانِيَة', '{1}ثَانِيَة', '{2}ثَانِيَتَيْن', ']2,11[:count ثَوَان', ']10,Inf[:count ثَانِيَة']), 'ago' => 'مُنْذُ :time', 'from_now' => 'مِنَ الْآن :time', 'after' => 'بَعْدَ :time', 'before' => 'قَبْلَ :time', // @TODO add shakl to translations below 'diff_now' => 'الآن', 'diff_today' => 'اليوم', 'diff_today_regexp' => 'اليوم(?:\\s+عند)?(?:\\s+الساعة)?', 'diff_yesterday' => 'أمس', 'diff_yesterday_regexp' => 'أمس(?:\\s+عند)?(?:\\s+الساعة)?', 'diff_tomorrow' => 'غداً', 'diff_tomorrow_regexp' => 'غدًا(?:\\s+عند)?(?:\\s+الساعة)?', 'diff_before_yesterday' => 'قبل الأمس', 'diff_after_tomorrow' => 'بعد غد', 'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']), 'period_interval' => 'كل :interval', 'period_start_date' => 'من :date', 'period_end_date' => 'إلى :date', 'months' => $months, 'months_short' => $months, 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'], 'weekdays_min' => ['ح', 'اث', 'ثل', 'أر', 'خم', 'ج', 'س'], 'list' => ['، ', ' و '], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[اليوم عند الساعة] LT', 'nextDay' => '[غدًا عند الساعة] LT', 'nextWeek' => 'dddd [عند الساعة] LT', 'lastDay' => '[أمس عند الساعة] LT', 'lastWeek' => 'dddd [عند الساعة] LT', 'sameElse' => 'L', ], 'meridiem' => ['ص', 'م'], 'weekend' => [5, 6], ]; PK������<1Z:<������Carbon/Lang/sl.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Philippe Vaucher * - Tsutomu Kuroda * - tjku * - Max Melentiev * - Juanito Fatas * - Akira Matsuda * - Christopher Dell * - Enrique Vidal * - Simone Carletti * - Aaron Patterson * - Nicolás Hock Isaza * - Miha Rebernik * - Gal Jakič (morpheus7CS) * - Glavić * - Anže Časar * - Lovro Tramšek (Lovro1107) * - burut13 */ use Carbon\CarbonInterface; return [ 'year' => ':count leto|:count leti|:count leta|:count let', 'y' => ':count leto|:count leti|:count leta|:count let', 'month' => ':count mesec|:count meseca|:count mesece|:count mesecev', 'm' => ':count mes.', 'week' => ':count teden|:count tedna|:count tedne|:count tednov', 'w' => ':count ted.', 'day' => ':count dan|:count dni|:count dni|:count dni', 'd' => ':count dan|:count dni|:count dni|:count dni', 'hour' => ':count ura|:count uri|:count ure|:count ur', 'h' => ':count h', 'minute' => ':count minuta|:count minuti|:count minute|:count minut', 'min' => ':count min.', 'second' => ':count sekunda|:count sekundi|:count sekunde|:count sekund', 'a_second' => '{1}nekaj sekund|:count sekunda|:count sekundi|:count sekunde|:count sekund', 's' => ':count s', 'year_ago' => ':count letom|:count letoma|:count leti|:count leti', 'y_ago' => ':count letom|:count letoma|:count leti|:count leti', 'month_ago' => ':count mesecem|:count mesecema|:count meseci|:count meseci', 'week_ago' => ':count tednom|:count tednoma|:count tedni|:count tedni', 'day_ago' => ':count dnem|:count dnevoma|:count dnevi|:count dnevi', 'd_ago' => ':count dnem|:count dnevoma|:count dnevi|:count dnevi', 'hour_ago' => ':count uro|:count urama|:count urami|:count urami', 'minute_ago' => ':count minuto|:count minutama|:count minutami|:count minutami', 'second_ago' => ':count sekundo|:count sekundama|:count sekundami|:count sekundami', 'day_from_now' => ':count dan|:count dneva|:count dni|:count dni', 'd_from_now' => ':count dan|:count dneva|:count dni|:count dni', 'hour_from_now' => ':count uro|:count uri|:count ure|:count ur', 'minute_from_now' => ':count minuto|:count minuti|:count minute|:count minut', 'second_from_now' => ':count sekundo|:count sekundi|:count sekunde|:count sekund', 'ago' => 'pred :time', 'from_now' => 'čez :time', 'after' => ':time kasneje', 'before' => ':time prej', 'diff_now' => 'ravnokar', 'diff_today' => 'danes', 'diff_today_regexp' => 'danes(?:\\s+ob)?', 'diff_yesterday' => 'včeraj', 'diff_yesterday_regexp' => 'včeraj(?:\\s+ob)?', 'diff_tomorrow' => 'jutri', 'diff_tomorrow_regexp' => 'jutri(?:\\s+ob)?', 'diff_before_yesterday' => 'predvčerajšnjim', 'diff_after_tomorrow' => 'pojutrišnjem', 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'period_start_date' => 'od :date', 'period_end_date' => 'do :date', 'formats' => [ 'LT' => 'H:mm', 'LTS' => 'H:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D. MMMM YYYY', 'LLL' => 'D. MMMM YYYY H:mm', 'LLLL' => 'dddd, D. MMMM YYYY H:mm', ], 'calendar' => [ 'sameDay' => '[danes ob] LT', 'nextDay' => '[jutri ob] LT', 'nextWeek' => 'dddd [ob] LT', 'lastDay' => '[včeraj ob] LT', 'lastWeek' => function (CarbonInterface $date) { switch ($date->dayOfWeek) { case 0: return '[preteklo] [nedeljo] [ob] LT'; case 1: return '[pretekli] [ponedeljek] [ob] LT'; case 2: return '[pretekli] [torek] [ob] LT'; case 3: return '[preteklo] [sredo] [ob] LT'; case 4: return '[pretekli] [četrtek] [ob] LT'; case 5: return '[pretekli] [petek] [ob] LT'; case 6: return '[preteklo] [soboto] [ob] LT'; } }, 'sameElse' => 'L', ], 'months' => ['januar', 'februar', 'marec', 'april', 'maj', 'junij', 'julij', 'avgust', 'september', 'oktober', 'november', 'december'], 'months_short' => ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'avg', 'sep', 'okt', 'nov', 'dec'], 'weekdays' => ['nedelja', 'ponedeljek', 'torek', 'sreda', 'četrtek', 'petek', 'sobota'], 'weekdays_short' => ['ned', 'pon', 'tor', 'sre', 'čet', 'pet', 'sob'], 'weekdays_min' => ['ne', 'po', 'to', 'sr', 'če', 'pe', 'so'], 'list' => [', ', ' in '], 'meridiem' => ['dopoldan', 'popoldan'], ]; PK������<1Z(N��N����Carbon/Lang/mg.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/mg_MG.php'; PK������<1Z&5 �� ����Carbon/Lang/nl_SX.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/nl.php'; PK������<1Z㚸 �� ����Carbon/Lang/ml_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ml.php'; PK������<1Zx$������Carbon/Lang/ee_TG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ee.php', [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'LLL' => 'HH:mm MMMM D [lia] YYYY', 'LLLL' => 'HH:mm dddd, MMMM D [lia] YYYY', ], ]); PK������<1ZD������Carbon/Lang/niu_NU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RockET Systems Emani Fakaotimanava-Lui emani@niue.nu */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'months' => ['Ianuali', 'Fepuali', 'Masi', 'Apelila', 'Me', 'Iuni', 'Iulai', 'Aokuso', 'Sepetema', 'Oketopa', 'Novema', 'Tesemo'], 'months_short' => ['Ian', 'Fep', 'Mas', 'Ape', 'Me', 'Iun', 'Iul', 'Aok', 'Sep', 'Oke', 'Nov', 'Tes'], 'weekdays' => ['Aho Tapu', 'Aho Gofua', 'Aho Ua', 'Aho Lotu', 'Aho Tuloto', 'Aho Falaile', 'Aho Faiumu'], 'weekdays_short' => ['Tapu', 'Gofua', 'Ua', 'Lotu', 'Tuloto', 'Falaile', 'Faiumu'], 'weekdays_min' => ['Tapu', 'Gofua', 'Ua', 'Lotu', 'Tuloto', 'Falaile', 'Faiumu'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'year' => ':count tau', 'y' => ':count tau', 'a_year' => ':count tau', 'month' => ':count mahina', 'm' => ':count mahina', 'a_month' => ':count mahina', 'week' => ':count faahi tapu', 'w' => ':count faahi tapu', 'a_week' => ':count faahi tapu', 'day' => ':count aho', 'd' => ':count aho', 'a_day' => ':count aho', 'hour' => ':count e tulā', 'h' => ':count e tulā', 'a_hour' => ':count e tulā', 'minute' => ':count minuti', 'min' => ':count minuti', 'a_minute' => ':count minuti', 'second' => ':count sekone', 's' => ':count sekone', 'a_second' => ':count sekone', ]); PK������<1Z\G��G����Carbon/Lang/qu_EC.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/qu.php', [ 'first_day_of_week' => 1, ]); PK������<1Z|=}������Carbon/Lang/yav.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['kiɛmɛ́ɛm', 'kisɛ́ndɛ'], 'weekdays' => ['sɔ́ndiɛ', 'móndie', 'muányáŋmóndie', 'metúkpíápɛ', 'kúpélimetúkpiapɛ', 'feléte', 'séselé'], 'weekdays_short' => ['sd', 'md', 'mw', 'et', 'kl', 'fl', 'ss'], 'weekdays_min' => ['sd', 'md', 'mw', 'et', 'kl', 'fl', 'ss'], 'months' => ['pikítíkítie, oólí ú kutúan', 'siɛyɛ́, oóli ú kándíɛ', 'ɔnsúmbɔl, oóli ú kátátúɛ', 'mesiŋ, oóli ú kénie', 'ensil, oóli ú kátánuɛ', 'ɔsɔn', 'efute', 'pisuyú', 'imɛŋ i puɔs', 'imɛŋ i putúk,oóli ú kátíɛ', 'makandikɛ', 'pilɔndɔ́'], 'months_short' => ['o.1', 'o.2', 'o.3', 'o.4', 'o.5', 'o.6', 'o.7', 'o.8', 'o.9', 'o.10', 'o.11', 'o.12'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], ]); PK������<1ZZ7$��$����Carbon/Lang/luy.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'weekdays' => ['Jumapiri', 'Jumatatu', 'Jumanne', 'Jumatano', 'Murwa wa Kanne', 'Murwa wa Katano', 'Jumamosi'], 'weekdays_short' => ['J2', 'J3', 'J4', 'J5', 'Al', 'Ij', 'J1'], 'weekdays_min' => ['J2', 'J3', 'J4', 'J5', 'Al', 'Ij', 'J1'], 'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'], 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], // Too unreliable /* 'year' => ':count liliino', // less reliable 'y' => ':count liliino', // less reliable 'a_year' => ':count liliino', // less reliable 'month' => ':count kumwesi', // less reliable 'm' => ':count kumwesi', // less reliable 'a_month' => ':count kumwesi', // less reliable 'week' => ':count olutambi', // less reliable 'w' => ':count olutambi', // less reliable 'a_week' => ':count olutambi', // less reliable 'day' => ':count luno', // less reliable 'd' => ':count luno', // less reliable 'a_day' => ':count luno', // less reliable 'hour' => ':count ekengele', // less reliable 'h' => ':count ekengele', // less reliable 'a_hour' => ':count ekengele', // less reliable 'minute' => ':count omundu', // less reliable 'min' => ':count omundu', // less reliable 'a_minute' => ':count omundu', // less reliable 'second' => ':count liliino', // less reliable 's' => ':count liliino', // less reliable 'a_second' => ':count liliino', // less reliable */ ]); PK������<1Z?Ej �� ����Carbon/Lang/en_US_Posix.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1ZpG��G����Carbon/Lang/en_CM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Zr �� ����Carbon/Lang/tg_TJ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/tg.php'; PK������<1Zeѡ������Carbon/Lang/szl_PL.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - szl_PL locale Przemyslaw Buczkowski libc-alpha@sourceware.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], 'months' => ['styczyń', 'luty', 'merc', 'kwjeciyń', 'moj', 'czyrwjyń', 'lipjyń', 'siyrpjyń', 'wrzesiyń', 'październik', 'listopad', 'grudziyń'], 'months_short' => ['sty', 'lut', 'mer', 'kwj', 'moj', 'czy', 'lip', 'siy', 'wrz', 'paź', 'lis', 'gru'], 'weekdays' => ['niydziela', 'pyńdziŏek', 'wtŏrek', 'strzŏda', 'sztwortek', 'pjōntek', 'sobŏta'], 'weekdays_short' => ['niy', 'pyń', 'wtŏ', 'str', 'szt', 'pjō', 'sob'], 'weekdays_min' => ['niy', 'pyń', 'wtŏ', 'str', 'szt', 'pjō', 'sob'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'year' => ':count rok', 'y' => ':count rok', 'a_year' => ':count rok', 'month' => ':count mjeśůnc', 'm' => ':count mjeśůnc', 'a_month' => ':count mjeśůnc', 'week' => ':count tydźyń', 'w' => ':count tydźyń', 'a_week' => ':count tydźyń', 'day' => ':count dźyń', 'd' => ':count dźyń', 'a_day' => ':count dźyń', 'hour' => ':count godzina', 'h' => ':count godzina', 'a_hour' => ':count godzina', 'minute' => ':count minuta', 'min' => ':count minuta', 'a_minute' => ':count minuta', 'second' => ':count sekůnda', 's' => ':count sekůnda', 'a_second' => ':count sekůnda', ]); PK������<1Z!k������Carbon/Lang/ru_UA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RFC 2319 bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/ru.php', [ 'weekdays' => ['воскресенье', 'понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота'], 'weekdays_short' => ['вск', 'пнд', 'вто', 'срд', 'чтв', 'птн', 'суб'], 'weekdays_min' => ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'су'], ]); PK������<1Z''x �� ����Carbon/Lang/fr_CI.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Z,�������Carbon/Lang/ar_QA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org * - Abdullah-Alhariri */ return array_replace_recursive(require __DIR__.'/ar.php', [ 'formats' => [ 'L' => 'DD MMM, YYYY', ], 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'], 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'], 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'], ]); PK������<1Z+v0% �� ����Carbon/Lang/br_FR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/br.php'; PK������<1Z*痖������Carbon/Lang/nso_ZA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['Janaware', 'Febereware', 'Matšhe', 'Aprele', 'Mei', 'June', 'Julae', 'Agostose', 'Setemere', 'Oktobere', 'Nofemere', 'Disemere'], 'months_short' => ['Jan', 'Feb', 'Mat', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Set', 'Okt', 'Nof', 'Dis'], 'weekdays' => ['LaMorena', 'Mošupologo', 'Labobedi', 'Laboraro', 'Labone', 'Labohlano', 'Mokibelo'], 'weekdays_short' => ['Son', 'Moš', 'Bed', 'Rar', 'Ne', 'Hla', 'Mok'], 'weekdays_min' => ['Son', 'Moš', 'Bed', 'Rar', 'Ne', 'Hla', 'Mok'], 'day_of_first_week_of_year' => 1, 'year' => ':count ngwaga', 'y' => ':count ngwaga', 'a_year' => ':count ngwaga', 'month' => ':count Kgwedi', 'm' => ':count Kgwedi', 'a_month' => ':count Kgwedi', 'week' => ':count Beke', 'w' => ':count Beke', 'a_week' => ':count Beke', 'day' => ':count Letšatši', 'd' => ':count Letšatši', 'a_day' => ':count Letšatši', 'hour' => ':count Iri', 'h' => ':count Iri', 'a_hour' => ':count Iri', 'minute' => ':count Motsotso', 'min' => ':count Motsotso', 'a_minute' => ':count Motsotso', 'second' => ':count motsotswana', 's' => ':count motsotswana', 'a_second' => ':count motsotswana', ]); PK������<1ZUp��p����Carbon/Lang/lv.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Carbon\CarbonInterface; /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Philippe Vaucher * - pirminis * - Tsutomu Kuroda * - tjku * - Andris Zāģeris * - Max Melentiev * - Edgars Beigarts * - Juanito Fatas * - Vitauts Stočka * - Akira Matsuda * - Christopher Dell * - Enrique Vidal * - Simone Carletti * - Aaron Patterson * - Kaspars Bankovskis * - Nicolás Hock Isaza * - Viesturs Kavacs (Kavacky) * - zakse * - Janis Eglitis (janiseglitis) * - Guntars * - Juris Sudmalis */ $daysOfWeek = ['svētdiena', 'pirmdiena', 'otrdiena', 'trešdiena', 'ceturtdiena', 'piektdiena', 'sestdiena']; $daysOfWeekLocativum = ['svētdien', 'pirmdien', 'otrdien', 'trešdien', 'ceturtdien', 'piektdien', 'sestdien']; $transformDiff = function ($input) { return strtr($input, [ // Nominative => "pirms/pēc" Dative 'gads' => 'gada', 'gadi' => 'gadiem', 'gadu' => 'gadiem', 'mēnesis' => 'mēneša', 'mēneši' => 'mēnešiem', 'mēnešu' => 'mēnešiem', 'nedēļa' => 'nedēļas', 'nedēļas' => 'nedēļām', 'nedēļu' => 'nedēļām', 'diena' => 'dienas', 'dienas' => 'dienām', 'dienu' => 'dienām', 'stunda' => 'stundas', 'stundas' => 'stundām', 'stundu' => 'stundām', 'minūte' => 'minūtes', 'minūtes' => 'minūtēm', 'minūšu' => 'minūtēm', 'sekunde' => 'sekundes', 'sekundes' => 'sekundēm', 'sekunžu' => 'sekundēm', ]); }; return [ 'ago' => function ($time) use ($transformDiff) { return 'pirms '.$transformDiff($time); }, 'from_now' => function ($time) use ($transformDiff) { return 'pēc '.$transformDiff($time); }, 'year' => '0 gadu|:count gads|:count gadi', 'y' => ':count g.', 'a_year' => '{1}gads|0 gadu|:count gads|:count gadi', 'month' => '0 mēnešu|:count mēnesis|:count mēneši', 'm' => ':count mēn.', 'a_month' => '{1}mēnesis|0 mēnešu|:count mēnesis|:count mēneši', 'week' => '0 nedēļu|:count nedēļa|:count nedēļas', 'w' => ':count ned.', 'a_week' => '{1}nedēļa|0 nedēļu|:count nedēļa|:count nedēļas', 'day' => '0 dienu|:count diena|:count dienas', 'd' => ':count d.', 'a_day' => '{1}diena|0 dienu|:count diena|:count dienas', 'hour' => '0 stundu|:count stunda|:count stundas', 'h' => ':count st.', 'a_hour' => '{1}stunda|0 stundu|:count stunda|:count stundas', 'minute' => '0 minūšu|:count minūte|:count minūtes', 'min' => ':count min.', 'a_minute' => '{1}minūte|0 minūšu|:count minūte|:count minūtes', 'second' => '0 sekunžu|:count sekunde|:count sekundes', 's' => ':count sek.', 'a_second' => '{1}sekunde|0 sekunžu|:count sekunde|:count sekundes', 'after' => ':time vēlāk', 'year_after' => '0 gadus|:count gadu|:count gadus', 'a_year_after' => '{1}gadu|0 gadus|:count gadu|:count gadus', 'month_after' => '0 mēnešus|:count mēnesi|:count mēnešus', 'a_month_after' => '{1}mēnesi|0 mēnešus|:count mēnesi|:count mēnešus', 'week_after' => '0 nedēļas|:count nedēļu|:count nedēļas', 'a_week_after' => '{1}nedēļu|0 nedēļas|:count nedēļu|:count nedēļas', 'day_after' => '0 dienas|:count dienu|:count dienas', 'a_day_after' => '{1}dienu|0 dienas|:count dienu|:count dienas', 'hour_after' => '0 stundas|:count stundu|:count stundas', 'a_hour_after' => '{1}stundu|0 stundas|:count stundu|:count stundas', 'minute_after' => '0 minūtes|:count minūti|:count minūtes', 'a_minute_after' => '{1}minūti|0 minūtes|:count minūti|:count minūtes', 'second_after' => '0 sekundes|:count sekundi|:count sekundes', 'a_second_after' => '{1}sekundi|0 sekundes|:count sekundi|:count sekundes', 'before' => ':time agrāk', 'year_before' => '0 gadus|:count gadu|:count gadus', 'a_year_before' => '{1}gadu|0 gadus|:count gadu|:count gadus', 'month_before' => '0 mēnešus|:count mēnesi|:count mēnešus', 'a_month_before' => '{1}mēnesi|0 mēnešus|:count mēnesi|:count mēnešus', 'week_before' => '0 nedēļas|:count nedēļu|:count nedēļas', 'a_week_before' => '{1}nedēļu|0 nedēļas|:count nedēļu|:count nedēļas', 'day_before' => '0 dienas|:count dienu|:count dienas', 'a_day_before' => '{1}dienu|0 dienas|:count dienu|:count dienas', 'hour_before' => '0 stundas|:count stundu|:count stundas', 'a_hour_before' => '{1}stundu|0 stundas|:count stundu|:count stundas', 'minute_before' => '0 minūtes|:count minūti|:count minūtes', 'a_minute_before' => '{1}minūti|0 minūtes|:count minūti|:count minūtes', 'second_before' => '0 sekundes|:count sekundi|:count sekundes', 'a_second_before' => '{1}sekundi|0 sekundes|:count sekundi|:count sekundes', 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' un '], 'diff_now' => 'tagad', 'diff_today' => 'šodien', 'diff_yesterday' => 'vakar', 'diff_before_yesterday' => 'aizvakar', 'diff_tomorrow' => 'rīt', 'diff_after_tomorrow' => 'parīt', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY.', 'LL' => 'YYYY. [gada] D. MMMM', 'LLL' => 'DD.MM.YYYY., HH:mm', 'LLLL' => 'YYYY. [gada] D. MMMM, HH:mm', ], 'calendar' => [ 'sameDay' => '[šodien] [plkst.] LT', 'nextDay' => '[rīt] [plkst.] LT', 'nextWeek' => function (CarbonInterface $current, CarbonInterface $other) use ($daysOfWeekLocativum) { if ($current->week !== $other->week) { return '[nākošo] ['.$daysOfWeekLocativum[$current->dayOfWeek].'] [plkst.] LT'; } return '['.$daysOfWeekLocativum[$current->dayOfWeek].'] [plkst.] LT'; }, 'lastDay' => '[vakar] [plkst.] LT', 'lastWeek' => function (CarbonInterface $current) use ($daysOfWeekLocativum) { return '[pagājušo] ['.$daysOfWeekLocativum[$current->dayOfWeek].'] [plkst.] LT'; }, 'sameElse' => 'L', ], 'weekdays' => $daysOfWeek, 'weekdays_short' => ['Sv.', 'P.', 'O.', 'T.', 'C.', 'Pk.', 'S.'], 'weekdays_min' => ['Sv.', 'P.', 'O.', 'T.', 'C.', 'Pk.', 'S.'], 'months' => ['janvāris', 'februāris', 'marts', 'aprīlis', 'maijs', 'jūnijs', 'jūlijs', 'augusts', 'septembris', 'oktobris', 'novembris', 'decembris'], 'months_standalone' => ['janvārī', 'februārī', 'martā', 'aprīlī', 'maijā', 'jūnijā', 'jūlijā', 'augustā', 'septembrī', 'oktobrī', 'novembrī', 'decembrī'], 'months_short' => ['janv.', 'febr.', 'martā', 'apr.', 'maijā', 'jūn.', 'jūl.', 'aug.', 'sept.', 'okt.', 'nov.', 'dec.'], 'meridiem' => ['priekšpusdiena', 'pēcpusdiena'], ]; PK������<1Z K��K����Carbon/Lang/hsb_DE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Information from Michael Wolf Andrzej Krzysztofowicz ankry@mif.pg.gda.pl */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'DD. MMMM YYYY', 'LLL' => 'DD. MMMM, HH:mm [hodź.]', 'LLLL' => 'dddd, DD. MMMM YYYY, HH:mm [hodź.]', ], 'months' => ['januara', 'februara', 'měrca', 'apryla', 'meje', 'junija', 'julija', 'awgusta', 'septembra', 'oktobra', 'nowembra', 'decembra'], 'months_short' => ['Jan', 'Feb', 'Měr', 'Apr', 'Mej', 'Jun', 'Jul', 'Awg', 'Sep', 'Okt', 'Now', 'Dec'], 'weekdays' => ['Njedźela', 'Póndźela', 'Wutora', 'Srjeda', 'Štvórtk', 'Pjatk', 'Sobota'], 'weekdays_short' => ['Nj', 'Pó', 'Wu', 'Sr', 'Št', 'Pj', 'So'], 'weekdays_min' => ['Nj', 'Pó', 'Wu', 'Sr', 'Št', 'Pj', 'So'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'year' => ':count lěto', 'y' => ':count lěto', 'a_year' => ':count lěto', 'month' => ':count měsac', 'm' => ':count měsac', 'a_month' => ':count měsac', 'week' => ':count tydźeń', 'w' => ':count tydźeń', 'a_week' => ':count tydźeń', 'day' => ':count dźeń', 'd' => ':count dźeń', 'a_day' => ':count dźeń', 'hour' => ':count hodźina', 'h' => ':count hodźina', 'a_hour' => ':count hodźina', 'minute' => ':count chwila', 'min' => ':count chwila', 'a_minute' => ':count chwila', 'second' => ':count druhi', 's' => ':count druhi', 'a_second' => ':count druhi', ]); PK������<1Z?7 �� ����Carbon/Lang/pl_PL.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/pl.php'; PK������<1Z^dL������Carbon/Lang/zh_MO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - tarunvelli * - Eddie * - KID * - shankesgk2 */ return array_replace_recursive(require __DIR__.'/zh_Hant.php', [ 'after' => ':time后', ]); PK������<1Z''x �� ����Carbon/Lang/fr_NE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Z<H��H����Carbon/Lang/teo_KE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/teo.php', [ 'first_day_of_week' => 0, ]); PK������<1ZK}O��O����Carbon/Lang/nds.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/nds_DE.php'; PK������<1Z:ZS��S����Carbon/Lang/mk.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Sashko Todorov * - Josh Soref * - François B * - Serhan Apaydın * - Borislav Mickov * - JD Isaacks * - Tomi Atanasoski */ use Carbon\CarbonInterface; return [ 'year' => ':count година|:count години', 'a_year' => 'година|:count години', 'y' => ':count год.', 'month' => ':count месец|:count месеци', 'a_month' => 'месец|:count месеци', 'm' => ':count месец|:count месеци', 'week' => ':count седмица|:count седмици', 'a_week' => 'седмица|:count седмици', 'w' => ':count седмица|:count седмици', 'day' => ':count ден|:count дена', 'a_day' => 'ден|:count дена', 'd' => ':count ден|:count дена', 'hour' => ':count час|:count часа', 'a_hour' => 'час|:count часа', 'h' => ':count час|:count часа', 'minute' => ':count минута|:count минути', 'a_minute' => 'минута|:count минути', 'min' => ':count мин.', 'second' => ':count секунда|:count секунди', 'a_second' => 'неколку секунди|:count секунди', 's' => ':count сек.', 'ago' => 'пред :time', 'from_now' => 'после :time', 'after' => 'по :time', 'before' => 'пред :time', 'diff_now' => 'сега', 'diff_today' => 'Денес', 'diff_today_regexp' => 'Денес(?:\\s+во)?', 'diff_yesterday' => 'вчера', 'diff_yesterday_regexp' => 'Вчера(?:\\s+во)?', 'diff_tomorrow' => 'утре', 'diff_tomorrow_regexp' => 'Утре(?:\\s+во)?', 'formats' => [ 'LT' => 'H:mm', 'LTS' => 'H:mm:ss', 'L' => 'D.MM.YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY H:mm', 'LLLL' => 'dddd, D MMMM YYYY H:mm', ], 'calendar' => [ 'sameDay' => '[Денес во] LT', 'nextDay' => '[Утре во] LT', 'nextWeek' => '[Во] dddd [во] LT', 'lastDay' => '[Вчера во] LT', 'lastWeek' => function (CarbonInterface $date) { switch ($date->dayOfWeek) { case 0: case 3: case 6: return '[Изминатата] dddd [во] LT'; default: return '[Изминатиот] dddd [во] LT'; } }, 'sameElse' => 'L', ], 'ordinal' => function ($number) { $lastDigit = $number % 10; $last2Digits = $number % 100; if ($number === 0) { return $number.'-ев'; } if ($last2Digits === 0) { return $number.'-ен'; } if ($last2Digits > 10 && $last2Digits < 20) { return $number.'-ти'; } if ($lastDigit === 1) { return $number.'-ви'; } if ($lastDigit === 2) { return $number.'-ри'; } if ($lastDigit === 7 || $lastDigit === 8) { return $number.'-ми'; } return $number.'-ти'; }, 'months' => ['јануари', 'февруари', 'март', 'април', 'мај', 'јуни', 'јули', 'август', 'септември', 'октомври', 'ноември', 'декември'], 'months_short' => ['јан', 'фев', 'мар', 'апр', 'мај', 'јун', 'јул', 'авг', 'сеп', 'окт', 'ное', 'дек'], 'weekdays' => ['недела', 'понеделник', 'вторник', 'среда', 'четврток', 'петок', 'сабота'], 'weekdays_short' => ['нед', 'пон', 'вто', 'сре', 'чет', 'пет', 'саб'], 'weekdays_min' => ['нe', 'пo', 'вт', 'ср', 'че', 'пе', 'сa'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' и '], 'meridiem' => ['АМ', 'ПМ'], ]; PK������<1Z ������Carbon/Lang/pa_Guru.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/pa.php', [ 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'D/M/yy', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY, h:mm a', 'LLLL' => 'dddd, D MMMM YYYY, h:mm a', ], 'months' => ['ਜਨਵਰੀ', 'ਫ਼ਰਵਰੀ', 'ਮਾਰਚ', 'ਅਪ੍ਰੈਲ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾਈ', 'ਅਗਸਤ', 'ਸਤੰਬਰ', 'ਅਕਤੂਬਰ', 'ਨਵੰਬਰ', 'ਦਸੰਬਰ'], 'months_short' => ['ਜਨ', 'ਫ਼ਰ', 'ਮਾਰਚ', 'ਅਪ੍ਰੈ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾ', 'ਅਗ', 'ਸਤੰ', 'ਅਕਤੂ', 'ਨਵੰ', 'ਦਸੰ'], 'weekdays' => ['ਐਤਵਾਰ', 'ਸੋਮਵਾਰ', 'ਮੰਗਲਵਾਰ', 'ਬੁੱਧਵਾਰ', 'ਵੀਰਵਾਰ', 'ਸ਼ੁੱਕਰਵਾਰ', 'ਸ਼ਨਿੱਚਰਵਾਰ'], 'weekdays_short' => ['ਐਤ', 'ਸੋਮ', 'ਮੰਗਲ', 'ਬੁੱਧ', 'ਵੀਰ', 'ਸ਼ੁੱਕਰ', 'ਸ਼ਨਿੱਚਰ'], 'weekdays_min' => ['ਐਤ', 'ਸੋਮ', 'ਮੰਗ', 'ਬੁੱਧ', 'ਵੀਰ', 'ਸ਼ੁੱਕ', 'ਸ਼ਨਿੱ'], 'weekend' => [0, 0], ]); PK������<1Z !R �� ����Carbon/Lang/ss_ZA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ss.php'; PK������<1Z-!b>��>����Carbon/Lang/ar_IQ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org * - Abdullah-Alhariri */ return array_replace_recursive(require __DIR__.'/ar.php', [ 'formats' => [ 'L' => 'DD MMM, YYYY', ], 'months' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'], 'months_short' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'], 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'], ]); PK������<1Z������Carbon/Lang/ne_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ne.php', [ 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'yy/M/d', 'LL' => 'YYYY MMM D', 'LLL' => 'YYYY MMMM D, h:mm a', 'LLLL' => 'YYYY MMMM D, dddd, h:mm a', ], 'months' => ['जनवरी', 'फेब्रुअरी', 'मार्च', 'अप्रिल', 'मे', 'जुन', 'जुलाई', 'अगस्ट', 'सेप्टेम्बर', 'अक्टोबर', 'नोभेम्बर', 'डिसेम्बर'], 'months_short' => ['जनवरी', 'फेब्रुअरी', 'मार्च', 'अप्रिल', 'मे', 'जुन', 'जुलाई', 'अगस्ट', 'सेप्टेम्बर', 'अक्टोबर', 'नोभेम्बर', 'डिसेम्बर'], 'weekend' => [0, 0], 'meridiem' => ['पूर्वाह्न', 'अपराह्न'], ]); PK������<1Z,}s` ��` ����Carbon/Lang/he.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Daniel Cohen Gindi * - JD Isaacks * - Itai Nathaniel * - GabMic * - Yaakov Dahan (yakidahan) */ return [ 'year' => 'שנה|{2}שנתיים|:count שנים', 'y' => 'שנה|:count שנ׳', 'month' => 'חודש|{2}חודשיים|:count חודשים', 'm' => 'חודש|:count חו׳', 'week' => 'שבוע|{2}שבועיים|:count שבועות', 'w' => 'שבוע|:count שב׳', 'day' => 'יום|{2}יומיים|:count ימים', 'd' => 'יום|:count ימ׳', 'hour' => 'שעה|{2}שעתיים|:count שעות', 'h' => 'שעה|:count שע׳', 'minute' => 'דקה|{2}שתי דקות|:count דקות', 'min' => 'דקה|:count דק׳', 'second' => 'שנייה|:count שניות', 'a_second' => 'כמה שניות|:count שניות', 's' => 'שניה|:count שנ׳', 'ago' => 'לפני :time', 'from_now' => 'בעוד :time מעכשיו', 'after' => 'אחרי :time', 'before' => 'לפני :time', 'diff_now' => 'עכשיו', 'diff_today' => 'היום', 'diff_today_regexp' => 'היום(?:\\s+ב־)?', 'diff_yesterday' => 'אתמול', 'diff_yesterday_regexp' => 'אתמול(?:\\s+ב־)?', 'diff_tomorrow' => 'מחר', 'diff_tomorrow_regexp' => 'מחר(?:\\s+ב־)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D [ב]MMMM YYYY', 'LLL' => 'D [ב]MMMM YYYY HH:mm', 'LLLL' => 'dddd, D [ב]MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[היום ב־]LT', 'nextDay' => '[מחר ב־]LT', 'nextWeek' => 'dddd [בשעה] LT', 'lastDay' => '[אתמול ב־]LT', 'lastWeek' => '[ביום] dddd [האחרון בשעה] LT', 'sameElse' => 'L', ], 'meridiem' => function ($hour, $minute, $isLower) { if ($hour < 5) { return 'לפנות בוקר'; } if ($hour < 10) { return 'בבוקר'; } if ($hour < 12) { return $isLower ? 'לפנה"צ' : 'לפני הצהריים'; } if ($hour < 18) { return $isLower ? 'אחה"צ' : 'אחרי הצהריים'; } return 'בערב'; }, 'months' => ['ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר'], 'months_short' => ['ינו׳', 'פבר׳', 'מרץ', 'אפר׳', 'מאי', 'יוני', 'יולי', 'אוג׳', 'ספט׳', 'אוק׳', 'נוב׳', 'דצמ׳'], 'weekdays' => ['ראשון', 'שני', 'שלישי', 'רביעי', 'חמישי', 'שישי', 'שבת'], 'weekdays_short' => ['א׳', 'ב׳', 'ג׳', 'ד׳', 'ה׳', 'ו׳', 'ש׳'], 'weekdays_min' => ['א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ש'], 'list' => [', ', ' ו -'], 'weekend' => [5, 6], ]; PK������<1ZpG��G����Carbon/Lang/en_NF.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZӾ6������Carbon/Lang/zh_Hans_MO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/zh_Hans.php'; PK������<1Zd������Carbon/Lang/es_419.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]); PK������<1Z$�rl��l����Carbon/Lang/gsw_FR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/gsw.php', [ 'meridiem' => ['vorm.', 'nam.'], 'months' => ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'Auguscht', 'Septämber', 'Oktoober', 'Novämber', 'Dezämber'], 'first_day_of_week' => 1, 'formats' => [ 'LLL' => 'Do MMMM YYYY HH:mm', 'LLLL' => 'dddd, Do MMMM YYYY HH:mm', ], ]); PK������<1Z/{PO��O����Carbon/Lang/hak.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/hak_TW.php'; PK������<1Z''x �� ����Carbon/Lang/fr_GN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1ZW������Carbon/Lang/seh.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'weekdays' => ['Dimingu', 'Chiposi', 'Chipiri', 'Chitatu', 'Chinai', 'Chishanu', 'Sabudu'], 'weekdays_short' => ['Dim', 'Pos', 'Pir', 'Tat', 'Nai', 'Sha', 'Sab'], 'weekdays_min' => ['Dim', 'Pos', 'Pir', 'Tat', 'Nai', 'Sha', 'Sab'], 'months' => ['Janeiro', 'Fevreiro', 'Marco', 'Abril', 'Maio', 'Junho', 'Julho', 'Augusto', 'Setembro', 'Otubro', 'Novembro', 'Decembro'], 'months_short' => ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Aug', 'Set', 'Otu', 'Nov', 'Dec'], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'd [de] MMM [de] YYYY', 'LLL' => 'd [de] MMMM [de] YYYY HH:mm', 'LLLL' => 'dddd, d [de] MMMM [de] YYYY HH:mm', ], ]); PK������<1Z]������Carbon/Lang/wal_ET.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ge'ez Frontier Foundation locales@geez.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች', 'ኤፕረል', 'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት', 'ሴፕቴምበር', 'ኦክተውበር', 'ኖቬምበር', 'ዲሴምበር'], 'months_short' => ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕረ', 'ሜይ ', 'ጁን ', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክተ', 'ኖቬም', 'ዲሴም'], 'weekdays' => ['ወጋ', 'ሳይኖ', 'ማቆሳኛ', 'አሩዋ', 'ሃሙሳ', 'አርባ', 'ቄራ'], 'weekdays_short' => ['ወጋ ', 'ሳይኖ', 'ማቆሳ', 'አሩዋ', 'ሃሙሳ', 'አርባ', 'ቄራ '], 'weekdays_min' => ['ወጋ ', 'ሳይኖ', 'ማቆሳ', 'አሩዋ', 'ሃሙሳ', 'አርባ', 'ቄራ '], 'day_of_first_week_of_year' => 1, 'meridiem' => ['ማለዶ', 'ቃማ'], ]); PK������<1Zw �� ����Carbon/Lang/fr_TD.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/fr.php', [ 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY h:mm a', 'LLLL' => 'dddd D MMMM YYYY h:mm a', ], ]); PK������<1ZpG��G����Carbon/Lang/en_001.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZM4��4����Carbon/Lang/az_IR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Mousa Moradi mousamk@gmail.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'OY/OM/OD', ], 'months' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مئی', 'ژوئن', 'جولای', 'آقۇست', 'سپتامبر', 'اوْکتوْبر', 'نوْوامبر', 'دسامبر'], 'months_short' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مئی', 'ژوئن', 'جولای', 'آقۇست', 'سپتامبر', 'اوْکتوْبر', 'نوْوامبر', 'دسامبر'], 'weekdays' => ['یکشنبه', 'دوشنبه', 'سه‌شنبه', 'چارشنبه', 'جۆمعه آخشامی', 'جۆمعه', 'شنبه'], 'weekdays_short' => ['یکشنبه', 'دوشنبه', 'سه‌شنبه', 'چارشنبه', 'جۆمعه آخشامی', 'جۆمعه', 'شنبه'], 'weekdays_min' => ['یکشنبه', 'دوشنبه', 'سه‌شنبه', 'چارشنبه', 'جۆمعه آخشامی', 'جۆمعه', 'شنبه'], 'first_day_of_week' => 6, 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰۴', '۰۵', '۰۶', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱۴', '۱۵', '۱۶', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲۴', '۲۵', '۲۶', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳۴', '۳۵', '۳۶', '۳۷', '۳۸', '۳۹', '۴۰', '۴۱', '۴۲', '۴۳', '۴۴', '۴۵', '۴۶', '۴۷', '۴۸', '۴۹', '۵۰', '۵۱', '۵۲', '۵۳', '۵۴', '۵۵', '۵۶', '۵۷', '۵۸', '۵۹', '۶۰', '۶۱', '۶۲', '۶۳', '۶۴', '۶۵', '۶۶', '۶۷', '۶۸', '۶۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷۴', '۷۵', '۷۶', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸۴', '۸۵', '۸۶', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹۴', '۹۵', '۹۶', '۹۷', '۹۸', '۹۹'], ]); PK������<1Z(|@zG��G����Carbon/Lang/es_GQ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 1, ]); PK������<1Z )v������Carbon/Lang/mua.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['comme', 'lilli'], 'weekdays' => ['Com’yakke', 'Comlaaɗii', 'Comzyiiɗii', 'Comkolle', 'Comkaldǝɓlii', 'Comgaisuu', 'Comzyeɓsuu'], 'weekdays_short' => ['Cya', 'Cla', 'Czi', 'Cko', 'Cka', 'Cga', 'Cze'], 'weekdays_min' => ['Cya', 'Cla', 'Czi', 'Cko', 'Cka', 'Cga', 'Cze'], 'months' => ['Fĩi Loo', 'Cokcwaklaŋne', 'Cokcwaklii', 'Fĩi Marfoo', 'Madǝǝuutǝbijaŋ', 'Mamǝŋgwãafahbii', 'Mamǝŋgwãalii', 'Madǝmbii', 'Fĩi Dǝɓlii', 'Fĩi Mundaŋ', 'Fĩi Gwahlle', 'Fĩi Yuru'], 'months_short' => ['FLO', 'CLA', 'CKI', 'FMF', 'MAD', 'MBI', 'MLI', 'MAM', 'FDE', 'FMU', 'FGW', 'FYU'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], ]); PK������<1Zj������Carbon/Lang/ber_DZ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Pablo Saratxaga pablo@mandrakesoft.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], 'months' => ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust', 'sentyabr', 'oktyabr', 'noyabr', 'dekabr'], 'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'İyn', 'İyl', 'Avq', 'Sen', 'Okt', 'Noy', 'Dek'], 'weekdays' => ['bazar günü', 'birinci gün', 'ikinci gün', 'üçüncü gün', 'dördüncü gün', 'beşinci gün', 'altıncı gün'], 'weekdays_short' => ['baz', 'bir', 'iki', 'üçü', 'dör', 'beş', 'alt'], 'weekdays_min' => ['baz', 'bir', 'iki', 'üçü', 'dör', 'beş', 'alt'], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, ]); PK������<1Za �� ����Carbon/Lang/ccp.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'weekdays' => ['𑄢𑄧𑄝𑄨𑄝𑄢𑄴', '𑄥𑄧𑄟𑄴𑄝𑄢𑄴', '𑄟𑄧𑄁𑄉𑄧𑄣𑄴𑄝𑄢𑄴', '𑄝𑄪𑄖𑄴𑄝𑄢𑄴', '𑄝𑄳𑄢𑄨𑄥𑄪𑄛𑄴𑄝𑄢𑄴', '𑄥𑄪𑄇𑄴𑄇𑄮𑄢𑄴𑄝𑄢𑄴', '𑄥𑄧𑄚𑄨𑄝𑄢𑄴'], 'weekdays_short' => ['𑄢𑄧𑄝𑄨', '𑄥𑄧𑄟𑄴', '𑄟𑄧𑄁𑄉𑄧𑄣𑄴', '𑄝𑄪𑄖𑄴', '𑄝𑄳𑄢𑄨𑄥𑄪𑄛𑄴', '𑄥𑄪𑄇𑄴𑄇𑄮𑄢𑄴', '𑄥𑄧𑄚𑄨'], 'weekdays_min' => ['𑄢𑄧𑄝𑄨', '𑄥𑄧𑄟𑄴', '𑄟𑄧𑄁𑄉𑄧𑄣𑄴', '𑄝𑄪𑄖𑄴', '𑄝𑄳𑄢𑄨𑄥𑄪𑄛𑄴', '𑄥𑄪𑄇𑄴𑄇𑄮𑄢𑄴', '𑄥𑄧𑄚𑄨'], 'months' => ['𑄎𑄚𑄪𑄠𑄢𑄨', '𑄜𑄬𑄛𑄴𑄝𑄳𑄢𑄪𑄠𑄢𑄨', '𑄟𑄢𑄴𑄌𑄧', '𑄃𑄬𑄛𑄳𑄢𑄨𑄣𑄴', '𑄟𑄬', '𑄎𑄪𑄚𑄴', '𑄎𑄪𑄣𑄭', '𑄃𑄉𑄧𑄌𑄴𑄑𑄴', '𑄥𑄬𑄛𑄴𑄑𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄃𑄧𑄇𑄴𑄑𑄬𑄝𑄧𑄢𑄴', '𑄚𑄧𑄞𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄓𑄨𑄥𑄬𑄟𑄴𑄝𑄧𑄢𑄴'], 'months_short' => ['𑄎𑄚𑄪', '𑄜𑄬𑄛𑄴', '𑄟𑄢𑄴𑄌𑄧', '𑄃𑄬𑄛𑄳𑄢𑄨𑄣𑄴', '𑄟𑄬', '𑄎𑄪𑄚𑄴', '𑄎𑄪𑄣𑄭', '𑄃𑄉𑄧𑄌𑄴𑄑𑄴', '𑄥𑄬𑄛𑄴𑄑𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄃𑄧𑄇𑄴𑄑𑄮𑄝𑄧𑄢𑄴', '𑄚𑄧𑄞𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄓𑄨𑄥𑄬𑄟𑄴𑄝𑄢𑄴'], 'months_short_standalone' => ['𑄎𑄚𑄪𑄠𑄢𑄨', '𑄜𑄬𑄛𑄴𑄝𑄳𑄢𑄪𑄠𑄢𑄨', '𑄟𑄢𑄴𑄌𑄧', '𑄃𑄬𑄛𑄳𑄢𑄨𑄣𑄴', '𑄟𑄬', '𑄎𑄪𑄚𑄴', '𑄎𑄪𑄣𑄭', '𑄃𑄉𑄧𑄌𑄴𑄑𑄴', '𑄥𑄬𑄛𑄴𑄑𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄃𑄧𑄇𑄴𑄑𑄮𑄝𑄧𑄢𑄴', '𑄚𑄧𑄞𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄓𑄨𑄥𑄬𑄟𑄴𑄝𑄧𑄢𑄴'], 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'D/M/YYYY', 'LL' => 'D MMM, YYYY', 'LLL' => 'D MMMM, YYYY h:mm a', 'LLLL' => 'dddd, D MMMM, YYYY h:mm a', ], ]); PK������<1Z+hk{ ��{ ����Carbon/Lang/dv.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ $months = [ 'ޖެނުއަރީ', 'ފެބްރުއަރީ', 'މާރިޗު', 'އޭޕްރީލު', 'މޭ', 'ޖޫން', 'ޖުލައި', 'އޯގަސްޓު', 'ސެޕްޓެމްބަރު', 'އޮކްޓޯބަރު', 'ނޮވެމްބަރު', 'ޑިސެމްބަރު', ]; $weekdays = [ 'އާދިއްތަ', 'ހޯމަ', 'އަންގާރަ', 'ބުދަ', 'ބުރާސްފަތި', 'ހުކުރު', 'ހޮނިހިރު', ]; /* * Authors: * - Josh Soref * - Jawish Hameed */ return [ 'year' => ':count '.'އަހަރު', 'a_year' => '{1}'.'އަހަރެއް'.'|:count '.'އަހަރު', 'month' => ':count '.'މަސް', 'a_month' => '{1}'.'މަހެއް'.'|:count '.'މަސް', 'week' => ':count '.'ހަފްތާ', 'a_week' => '{1}'.'ސިކުންތުކޮޅެއް'.'|:count '.'ހަފްތާ', 'day' => ':count '.'ދުވަސް', 'a_day' => '{1}'.'ދުވަހެއް'.'|:count '.'ދުވަސް', 'hour' => ':count '.'ގަޑިއިރު', 'a_hour' => '{1}'.'ގަޑިއިރެއް'.'|:count '.'ގަޑިއިރު', 'minute' => ':count '.'މިނިޓު', 'a_minute' => '{1}'.'މިނިޓެއް'.'|:count '.'މިނިޓު', 'second' => ':count '.'ސިކުންތު', 'a_second' => '{1}'.'ސިކުންތުކޮޅެއް'.'|:count '.'ސިކުންތު', 'ago' => 'ކުރިން :time', 'from_now' => 'ތެރޭގައި :time', 'after' => ':time ފަހުން', 'before' => ':time ކުރި', 'diff_yesterday' => 'އިއްޔެ', 'diff_today' => 'މިއަދު', 'diff_tomorrow' => 'މާދަމާ', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[މިއަދު] LT', 'nextDay' => '[މާދަމާ] LT', 'nextWeek' => 'dddd LT', 'lastDay' => '[އިއްޔެ] LT', 'lastWeek' => '[ފާއިތުވި] dddd LT', 'sameElse' => 'L', ], 'meridiem' => ['މކ', 'މފ'], 'months' => $months, 'months_short' => $months, 'weekdays' => $weekdays, 'weekdays_short' => $weekdays, 'weekdays_min' => ['އާދި', 'ހޯމަ', 'އަން', 'ބުދަ', 'ބުރާ', 'ހުކު', 'ހޮނި'], 'list' => [', ', ' އަދި '], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]; PK������<1Z Pc��c����Carbon/Lang/pa_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Guo Xiang Tan * - Josh Soref * - Ash * - harpreetkhalsagtbit */ return require __DIR__.'/pa.php'; PK������<1Za O��O����Carbon/Lang/mni.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/mni_IN.php'; PK������<1ZWW��W����Carbon/Lang/ln_CD.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ubuntu René Manassé GALEKWA renemanasse@gmail.com */ return require __DIR__.'/ln.php'; PK������<1Zا4l4��4����Carbon/Lang/zu_ZA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['Januwari', 'Februwari', 'Mashi', 'Ephreli', 'Meyi', 'Juni', 'Julayi', 'Agasti', 'Septhemba', 'Okthoba', 'Novemba', 'Disemba'], 'months_short' => ['Jan', 'Feb', 'Mas', 'Eph', 'Mey', 'Jun', 'Jul', 'Aga', 'Sep', 'Okt', 'Nov', 'Dis'], 'weekdays' => ['iSonto', 'uMsombuluko', 'uLwesibili', 'uLwesithathu', 'uLwesine', 'uLwesihlanu', 'uMgqibelo'], 'weekdays_short' => ['Son', 'Mso', 'Bil', 'Tha', 'Sin', 'Hla', 'Mgq'], 'weekdays_min' => ['Son', 'Mso', 'Bil', 'Tha', 'Sin', 'Hla', 'Mgq'], 'day_of_first_week_of_year' => 1, 'year' => 'kweminyaka engu-:count', 'y' => 'kweminyaka engu-:count', 'a_year' => 'kweminyaka engu-:count', 'month' => 'izinyanga ezingu-:count', 'm' => 'izinyanga ezingu-:count', 'a_month' => 'izinyanga ezingu-:count', 'week' => 'lwamasonto angu-:count', 'w' => 'lwamasonto angu-:count', 'a_week' => 'lwamasonto angu-:count', 'day' => 'ezingaba ngu-:count', 'd' => 'ezingaba ngu-:count', 'a_day' => 'ezingaba ngu-:count', 'hour' => 'amahora angu-:count', 'h' => 'amahora angu-:count', 'a_hour' => 'amahora angu-:count', 'minute' => 'ngemizuzu engu-:count', 'min' => 'ngemizuzu engu-:count', 'a_minute' => 'ngemizuzu engu-:count', 'second' => 'imizuzwana engu-:count', 's' => 'imizuzwana engu-:count', 'a_second' => 'imizuzwana engu-:count', ]); PK������<1ZpG��G����Carbon/Lang/en_IO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z+ �� ����Carbon/Lang/se_NO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/se.php'; PK������<1ZpG��G����Carbon/Lang/en_JE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z''x �� ����Carbon/Lang/fr_MC.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1ZndN��N����Carbon/Lang/dz.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/dz_BT.php'; PK������<1Zw7G��G����Carbon/Lang/es_BZ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 0, ]); PK������<1Z.{��{����Carbon/Lang/ca.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - mestremuten * - François B * - Marc Ordinas i Llopis * - Pere Orga * - JD Isaacks * - Quentí * - Víctor Díaz * - Xavi * - qcardona */ use Carbon\CarbonInterface; return [ 'year' => ':count any|:count anys', 'a_year' => 'un any|:count anys', 'y' => ':count any|:count anys', 'month' => ':count mes|:count mesos', 'a_month' => 'un mes|:count mesos', 'm' => ':count mes|:count mesos', 'week' => ':count setmana|:count setmanes', 'a_week' => 'una setmana|:count setmanes', 'w' => ':count setmana|:count setmanes', 'day' => ':count dia|:count dies', 'a_day' => 'un dia|:count dies', 'd' => ':count d', 'hour' => ':count hora|:count hores', 'a_hour' => 'una hora|:count hores', 'h' => ':count h', 'minute' => ':count minut|:count minuts', 'a_minute' => 'un minut|:count minuts', 'min' => ':count min', 'second' => ':count segon|:count segons', 'a_second' => 'uns segons|:count segons', 's' => ':count s', 'ago' => 'fa :time', 'from_now' => 'd\'aquí a :time', 'after' => ':time després', 'before' => ':time abans', 'diff_now' => 'ara mateix', 'diff_today' => 'avui', 'diff_today_regexp' => 'avui(?:\\s+a)?(?:\\s+les)?', 'diff_yesterday' => 'ahir', 'diff_yesterday_regexp' => 'ahir(?:\\s+a)?(?:\\s+les)?', 'diff_tomorrow' => 'demà', 'diff_tomorrow_regexp' => 'demà(?:\\s+a)?(?:\\s+les)?', 'diff_before_yesterday' => 'abans d\'ahir', 'diff_after_tomorrow' => 'demà passat', 'period_recurrences' => ':count cop|:count cops', 'period_interval' => 'cada :interval', 'period_start_date' => 'de :date', 'period_end_date' => 'fins a :date', 'formats' => [ 'LT' => 'H:mm', 'LTS' => 'H:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM [de] YYYY', 'LLL' => 'D MMMM [de] YYYY [a les] H:mm', 'LLLL' => 'dddd D MMMM [de] YYYY [a les] H:mm', ], 'calendar' => [ 'sameDay' => function (CarbonInterface $current) { return '[avui a '.($current->hour !== 1 ? 'les' : 'la').'] LT'; }, 'nextDay' => function (CarbonInterface $current) { return '[demà a '.($current->hour !== 1 ? 'les' : 'la').'] LT'; }, 'nextWeek' => function (CarbonInterface $current) { return 'dddd [a '.($current->hour !== 1 ? 'les' : 'la').'] LT'; }, 'lastDay' => function (CarbonInterface $current) { return '[ahir a '.($current->hour !== 1 ? 'les' : 'la').'] LT'; }, 'lastWeek' => function (CarbonInterface $current) { return '[el] dddd [passat a '.($current->hour !== 1 ? 'les' : 'la').'] LT'; }, 'sameElse' => 'L', ], 'ordinal' => function ($number, $period) { return $number.( ($period === 'w' || $period === 'W') ? 'a' : ( ($number === 1) ? 'r' : ( ($number === 2) ? 'n' : ( ($number === 3) ? 'r' : ( ($number === 4) ? 't' : 'è' ) ) ) ) ); }, 'months' => ['de gener', 'de febrer', 'de març', 'd\'abril', 'de maig', 'de juny', 'de juliol', 'd\'agost', 'de setembre', 'd\'octubre', 'de novembre', 'de desembre'], 'months_standalone' => ['gener', 'febrer', 'març', 'abril', 'maig', 'juny', 'juliol', 'agost', 'setembre', 'octubre', 'novembre', 'desembre'], 'months_short' => ['de gen.', 'de febr.', 'de març', 'd\'abr.', 'de maig', 'de juny', 'de jul.', 'd\'ag.', 'de set.', 'd\'oct.', 'de nov.', 'de des.'], 'months_short_standalone' => ['gen.', 'febr.', 'març', 'abr.', 'maig', 'juny', 'jul.', 'ag.', 'set.', 'oct.', 'nov.', 'des.'], 'months_regexp' => '/(D[oD]?[\s,]+MMMM?|L{2,4}|l{2,4})/', 'weekdays' => ['diumenge', 'dilluns', 'dimarts', 'dimecres', 'dijous', 'divendres', 'dissabte'], 'weekdays_short' => ['dg.', 'dl.', 'dt.', 'dc.', 'dj.', 'dv.', 'ds.'], 'weekdays_min' => ['dg', 'dl', 'dt', 'dc', 'dj', 'dv', 'ds'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' i '], 'meridiem' => ['a. m.', 'p. m.'], ]; PK������<1Z(|@zG��G����Carbon/Lang/es_CU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 1, ]); PK������<1Z/;)( ��( ����Carbon/Lang/tig_ER.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ge'ez Frontier Foundation locales@geez.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['ጥሪ', 'ለካቲት', 'መጋቢት', 'ሚያዝያ', 'ግንቦት', 'ሰነ', 'ሓምለ', 'ነሓሰ', 'መስከረም', 'ጥቅምቲ', 'ሕዳር', 'ታሕሳስ'], 'months_short' => ['ጥሪ ', 'ለካቲ', 'መጋቢ', 'ሚያዝ', 'ግንቦ', 'ሰነ ', 'ሓምለ', 'ነሓሰ', 'መስከ', 'ጥቅም', 'ሕዳር', 'ታሕሳ'], 'weekdays' => ['ሰንበት ዓባይ', 'ሰኖ', 'ታላሸኖ', 'ኣረርባዓ', 'ከሚሽ', 'ጅምዓት', 'ሰንበት ንኢሽ'], 'weekdays_short' => ['ሰ//ዓ', 'ሰኖ ', 'ታላሸ', 'ኣረር', 'ከሚሽ', 'ጅምዓ', 'ሰ//ን'], 'weekdays_min' => ['ሰ//ዓ', 'ሰኖ ', 'ታላሸ', 'ኣረር', 'ከሚሽ', 'ጅምዓ', 'ሰ//ን'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'meridiem' => ['ቀደም ሰር ምዕል', 'ሓቆ ሰር ምዕል'], 'year' => ':count ማይ', // less reliable 'y' => ':count ማይ', // less reliable 'a_year' => ':count ማይ', // less reliable 'month' => ':count ሸምሽ', // less reliable 'm' => ':count ሸምሽ', // less reliable 'a_month' => ':count ሸምሽ', // less reliable 'week' => ':count ሰቡዕ', // less reliable 'w' => ':count ሰቡዕ', // less reliable 'a_week' => ':count ሰቡዕ', // less reliable 'day' => ':count ዎሮ', // less reliable 'd' => ':count ዎሮ', // less reliable 'a_day' => ':count ዎሮ', // less reliable 'hour' => ':count ሰዓት', // less reliable 'h' => ':count ሰዓት', // less reliable 'a_hour' => ':count ሰዓት', // less reliable 'minute' => ':count ካልኣይት', // less reliable 'min' => ':count ካልኣይት', // less reliable 'a_minute' => ':count ካልኣይት', // less reliable 'second' => ':count ካልኣይ', 's' => ':count ካልኣይ', 'a_second' => ':count ካልኣይ', ]); PK������<1Ze> �� ����Carbon/Lang/et_EE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/et.php'; PK������<1Z&������Carbon/Lang/dje.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['Subbaahi', 'Zaarikay b'], 'weekdays' => ['Alhadi', 'Atinni', 'Atalaata', 'Alarba', 'Alhamisi', 'Alzuma', 'Asibti'], 'weekdays_short' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'], 'weekdays_min' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'], 'months' => ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me', 'Žuweŋ', 'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur', 'Deesanbur'], 'months_short' => ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy', 'Ut', 'Sek', 'Okt', 'Noo', 'Dee'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM, YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'year' => ':count hari', // less reliable 'y' => ':count hari', // less reliable 'a_year' => ':count hari', // less reliable 'week' => ':count alzuma', // less reliable 'w' => ':count alzuma', // less reliable 'a_week' => ':count alzuma', // less reliable 'second' => ':count atinni', // less reliable 's' => ':count atinni', // less reliable 'a_second' => ':count atinni', // less reliable ]); PK������<1ZEV?D��D����Carbon/Lang/es_ES.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return require __DIR__.'/es.php'; PK������<1Zj������Carbon/Lang/ber_MA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Pablo Saratxaga pablo@mandrakesoft.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], 'months' => ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust', 'sentyabr', 'oktyabr', 'noyabr', 'dekabr'], 'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'İyn', 'İyl', 'Avq', 'Sen', 'Okt', 'Noy', 'Dek'], 'weekdays' => ['bazar günü', 'birinci gün', 'ikinci gün', 'üçüncü gün', 'dördüncü gün', 'beşinci gün', 'altıncı gün'], 'weekdays_short' => ['baz', 'bir', 'iki', 'üçü', 'dör', 'beş', 'alt'], 'weekdays_min' => ['baz', 'bir', 'iki', 'üçü', 'dör', 'beş', 'alt'], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, ]); PK������<1Zif)O��O����Carbon/Lang/fil.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/fil_PH.php'; PK������<1Z �� ����Carbon/Lang/tlh.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - Serhan Apaydın * - Dominika */ return [ 'year' => '{1}wa’ DIS|:count DIS', 'month' => '{1}wa’ jar|:count jar', 'week' => '{1}wa’ hogh|:count hogh', 'day' => '{1}wa’ jaj|:count jaj', 'hour' => '{1}wa’ rep|:count rep', 'minute' => '{1}wa’ tup|:count tup', 'second' => '{1}puS lup|:count lup', 'ago' => function ($time) { $output = strtr($time, [ 'jaj' => 'Hu’', 'jar' => 'wen', 'DIS' => 'ben', ]); return $output === $time ? "$time ret" : $output; }, 'from_now' => function ($time) { $output = strtr($time, [ 'jaj' => 'leS', 'jar' => 'waQ', 'DIS' => 'nem', ]); return $output === $time ? "$time pIq" : $output; }, 'diff_yesterday' => 'wa’Hu’', 'diff_today' => 'DaHjaj', 'diff_tomorrow' => 'wa’leS', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[DaHjaj] LT', 'nextDay' => '[wa’leS] LT', 'nextWeek' => 'LLL', 'lastDay' => '[wa’Hu’] LT', 'lastWeek' => 'LLL', 'sameElse' => 'L', ], 'ordinal' => ':number.', 'months' => ['tera’ jar wa’', 'tera’ jar cha’', 'tera’ jar wej', 'tera’ jar loS', 'tera’ jar vagh', 'tera’ jar jav', 'tera’ jar Soch', 'tera’ jar chorgh', 'tera’ jar Hut', 'tera’ jar wa’maH', 'tera’ jar wa’maH wa’', 'tera’ jar wa’maH cha’'], 'months_short' => ['jar wa’', 'jar cha’', 'jar wej', 'jar loS', 'jar vagh', 'jar jav', 'jar Soch', 'jar chorgh', 'jar Hut', 'jar wa’maH', 'jar wa’maH wa’', 'jar wa’maH cha’'], 'weekdays' => ['lojmItjaj', 'DaSjaj', 'povjaj', 'ghItlhjaj', 'loghjaj', 'buqjaj', 'ghInjaj'], 'weekdays_short' => ['lojmItjaj', 'DaSjaj', 'povjaj', 'ghItlhjaj', 'loghjaj', 'buqjaj', 'ghInjaj'], 'weekdays_min' => ['lojmItjaj', 'DaSjaj', 'povjaj', 'ghItlhjaj', 'loghjaj', 'buqjaj', 'ghInjaj'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' ’ej '], ]; PK������<1Z>ڰ �� ����Carbon/Lang/hi.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - abhimanyu003 * - Josh Soref * - JD Isaacks */ return [ 'year' => 'एक वर्ष|:count वर्ष', 'y' => '1 वर्ष|:count वर्षों', 'month' => 'एक महीने|:count महीने', 'm' => '1 माह|:count महीने', 'week' => '1 सप्ताह|:count सप्ताह', 'w' => '1 सप्ताह|:count सप्ताह', 'day' => 'एक दिन|:count दिन', 'd' => '1 दिन|:count दिनों', 'hour' => 'एक घंटा|:count घंटे', 'h' => '1 घंटा|:count घंटे', 'minute' => 'एक मिनट|:count मिनट', 'min' => '1 मिनट|:count मिनटों', 'second' => 'कुछ ही क्षण|:count सेकंड', 's' => '1 सेकंड|:count सेकंड', 'ago' => ':time पहले', 'from_now' => ':time में', 'after' => ':time के बाद', 'before' => ':time के पहले', 'diff_now' => 'अब', 'diff_today' => 'आज', 'diff_yesterday' => 'कल', 'diff_tomorrow' => 'कल', 'formats' => [ 'LT' => 'A h:mm बजे', 'LTS' => 'A h:mm:ss बजे', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY, A h:mm बजे', 'LLLL' => 'dddd, D MMMM YYYY, A h:mm बजे', ], 'calendar' => [ 'sameDay' => '[आज] LT', 'nextDay' => '[कल] LT', 'nextWeek' => 'dddd, LT', 'lastDay' => '[कल] LT', 'lastWeek' => '[पिछले] dddd, LT', 'sameElse' => 'L', ], 'meridiem' => function ($hour) { if ($hour < 4) { return 'रात'; } if ($hour < 10) { return 'सुबह'; } if ($hour < 17) { return 'दोपहर'; } if ($hour < 20) { return 'शाम'; } return 'रात'; }, 'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'], 'months_short' => ['जन.', 'फ़र.', 'मार्च', 'अप्रै.', 'मई', 'जून', 'जुल.', 'अग.', 'सित.', 'अक्टू.', 'नव.', 'दिस.'], 'weekdays' => ['रविवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'गुरूवार', 'शुक्रवार', 'शनिवार'], 'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरू', 'शुक्र', 'शनि'], 'weekdays_min' => ['र', 'सो', 'मं', 'बु', 'गु', 'शु', 'श'], 'list' => [', ', ' और '], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, 'weekend' => [0, 0], ]; PK������<1Z-'O��O����Carbon/Lang/doi.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/doi_IN.php'; PK������<1Zk0 ��0 ����Carbon/Lang/ug.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Philippe Vaucher * - Tsutomu Kuroda * - yasinn */ return [ 'year' => '{1}'.'بىر يىل'.'|:count '.'يىل', 'month' => '{1}'.'بىر ئاي'.'|:count '.'ئاي', 'week' => '{1}'.'بىر ھەپتە'.'|:count '.'ھەپتە', 'day' => '{1}'.'بىر كۈن'.'|:count '.'كۈن', 'hour' => '{1}'.'بىر سائەت'.'|:count '.'سائەت', 'minute' => '{1}'.'بىر مىنۇت'.'|:count '.'مىنۇت', 'second' => '{1}'.'نەچچە سېكونت'.'|:count '.'سېكونت', 'ago' => ':time بۇرۇن', 'from_now' => ':time كېيىن', 'diff_today' => 'بۈگۈن', 'diff_yesterday' => 'تۆنۈگۈن', 'diff_tomorrow' => 'ئەتە', 'diff_tomorrow_regexp' => 'ئەتە(?:\\s+سائەت)?', 'diff_today_regexp' => 'بۈگۈن(?:\\s+سائەت)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY-MM-DD', 'LL' => 'YYYY-يىلىM-ئاينىڭD-كۈنى', 'LLL' => 'YYYY-يىلىM-ئاينىڭD-كۈنى، HH:mm', 'LLLL' => 'dddd، YYYY-يىلىM-ئاينىڭD-كۈنى، HH:mm', ], 'calendar' => [ 'sameDay' => '[بۈگۈن سائەت] LT', 'nextDay' => '[ئەتە سائەت] LT', 'nextWeek' => '[كېلەركى] dddd [سائەت] LT', 'lastDay' => '[تۆنۈگۈن] LT', 'lastWeek' => '[ئالدىنقى] dddd [سائەت] LT', 'sameElse' => 'L', ], 'ordinal' => function ($number, $period) { switch ($period) { case 'd': case 'D': case 'DDD': return $number.'-كۈنى'; case 'w': case 'W': return $number.'-ھەپتە'; default: return $number; } }, 'meridiem' => function ($hour, $minute) { $time = $hour * 100 + $minute; if ($time < 600) { return 'يېرىم كېچە'; } if ($time < 900) { return 'سەھەر'; } if ($time < 1130) { return 'چۈشتىن بۇرۇن'; } if ($time < 1230) { return 'چۈش'; } if ($time < 1800) { return 'چۈشتىن كېيىن'; } return 'كەچ'; }, 'months' => ['يانۋار', 'فېۋرال', 'مارت', 'ئاپرېل', 'ماي', 'ئىيۇن', 'ئىيۇل', 'ئاۋغۇست', 'سېنتەبىر', 'ئۆكتەبىر', 'نويابىر', 'دېكابىر'], 'months_short' => ['يانۋار', 'فېۋرال', 'مارت', 'ئاپرېل', 'ماي', 'ئىيۇن', 'ئىيۇل', 'ئاۋغۇست', 'سېنتەبىر', 'ئۆكتەبىر', 'نويابىر', 'دېكابىر'], 'weekdays' => ['يەكشەنبە', 'دۈشەنبە', 'سەيشەنبە', 'چارشەنبە', 'پەيشەنبە', 'جۈمە', 'شەنبە'], 'weekdays_short' => ['يە', 'دۈ', 'سە', 'چا', 'پە', 'جۈ', 'شە'], 'weekdays_min' => ['يە', 'دۈ', 'سە', 'چا', 'پە', 'جۈ', 'شە'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' ۋە '], ]; PK������<1Z �� ����Carbon/Lang/mn_MN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/mn.php'; PK������<1Z8������Carbon/Lang/csb_PL.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - csb_PL locale Michal Ostrowski bug-glibc-locales@gnu.org */ return [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY-MM-DD', 'LL' => 'MMMM DD, YYYY', 'LLL' => 'DD MMM HH:mm', 'LLLL' => 'MMMM DD, YYYY HH:mm', ], 'months' => ['stëcznika', 'gromicznika', 'strëmiannika', 'łżëkwiata', 'maja', 'czerwińca', 'lëpińca', 'zélnika', 'séwnika', 'rujana', 'lëstopadnika', 'gòdnika'], 'months_short' => ['stë', 'gro', 'str', 'łżë', 'maj', 'cze', 'lëp', 'zél', 'séw', 'ruj', 'lës', 'gòd'], 'weekdays' => ['niedzela', 'pòniedzôłk', 'wtórk', 'strzoda', 'czwiôrtk', 'piątk', 'sobòta'], 'weekdays_short' => ['nie', 'pòn', 'wtó', 'str', 'czw', 'pią', 'sob'], 'weekdays_min' => ['nie', 'pòn', 'wtó', 'str', 'czw', 'pią', 'sob'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' a téż '], 'two_words_connector' => ' a téż ', 'year' => ':count rok', 'month' => ':count miesiąc', 'week' => ':count tidzéń', 'day' => ':count dzéń', 'hour' => ':count gòdzëna', 'minute' => ':count minuta', 'second' => ':count sekunda', ]; PK������<1ZJBm������Carbon/Lang/aa_DJ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ge'ez Frontier Foundation locales@geez.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], 'months' => ['Qunxa Garablu', 'Kudo', 'Ciggilta Kudo', 'Agda Baxisso', 'Caxah Alsa', 'Qasa Dirri', 'Qado Dirri', 'Liiqen', 'Waysu', 'Diteli', 'Ximoli', 'Kaxxa Garablu'], 'months_short' => ['qun', 'nah', 'cig', 'agd', 'cax', 'qas', 'qad', 'leq', 'way', 'dit', 'xim', 'kax'], 'weekdays' => ['Acaada', 'Etleeni', 'Talaata', 'Arbaqa', 'Kamiisi', 'Gumqata', 'Sabti'], 'weekdays_short' => ['aca', 'etl', 'tal', 'arb', 'kam', 'gum', 'sab'], 'weekdays_min' => ['aca', 'etl', 'tal', 'arb', 'kam', 'gum', 'sab'], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'meridiem' => ['saaku', 'carra'], 'year' => ':count gaqambo', // less reliable 'y' => ':count gaqambo', // less reliable 'a_year' => ':count gaqambo', // less reliable 'month' => ':count àlsa', 'm' => ':count àlsa', 'a_month' => ':count àlsa', 'day' => ':count saaku', // less reliable 'd' => ':count saaku', // less reliable 'a_day' => ':count saaku', // less reliable 'hour' => ':count ayti', // less reliable 'h' => ':count ayti', // less reliable 'a_hour' => ':count ayti', // less reliable ]); PK������<1ZcNz������Carbon/Lang/uz_Cyrl.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/uz.php', [ 'formats' => [ 'L' => 'DD/MM/yy', 'LL' => 'D MMM, YYYY', 'LLL' => 'D MMMM, YYYY HH:mm', 'LLLL' => 'dddd, DD MMMM, YYYY HH:mm', ], 'meridiem' => ['ТО', 'ТК'], ]); PK������<1Z3I1O��O����Carbon/Lang/agr.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/agr_PE.php'; PK������<1Zp������Carbon/Lang/sr_ME.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/sr_Latn_ME.php'; PK������<1ZN��N����Carbon/Lang/xh.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/xh_ZA.php'; PK������<1Z{kO��O����Carbon/Lang/tpi.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/tpi_PG.php'; PK������<1Z!~P �� ����Carbon/Lang/nb.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - Alexander Tømmerås * - Sigurd Gartmann * - JD Isaacks */ return [ 'year' => ':count år|:count år', 'a_year' => 'ett år|:count år', 'y' => ':count år|:count år', 'month' => ':count måned|:count måneder', 'a_month' => 'en måned|:count måneder', 'm' => ':count md.', 'week' => ':count uke|:count uker', 'a_week' => 'en uke|:count uker', 'w' => ':count u.', 'day' => ':count dag|:count dager', 'a_day' => 'en dag|:count dager', 'd' => ':count d.', 'hour' => ':count time|:count timer', 'a_hour' => 'en time|:count timer', 'h' => ':count t', 'minute' => ':count minutt|:count minutter', 'a_minute' => 'ett minutt|:count minutter', 'min' => ':count min', 'second' => ':count sekund|:count sekunder', 'a_second' => 'noen sekunder|:count sekunder', 's' => ':count sek', 'ago' => ':time siden', 'from_now' => 'om :time', 'after' => ':time etter', 'before' => ':time før', 'diff_now' => 'akkurat nå', 'diff_today' => 'i dag', 'diff_today_regexp' => 'i dag(?:\\s+kl.)?', 'diff_yesterday' => 'i går', 'diff_yesterday_regexp' => 'i går(?:\\s+kl.)?', 'diff_tomorrow' => 'i morgen', 'diff_tomorrow_regexp' => 'i morgen(?:\\s+kl.)?', 'diff_before_yesterday' => 'i forgårs', 'diff_after_tomorrow' => 'i overmorgen', 'period_recurrences' => 'en gang|:count ganger', 'period_interval' => 'hver :interval', 'period_start_date' => 'fra :date', 'period_end_date' => 'til :date', 'months' => ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember'], 'months_short' => ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'], 'weekdays' => ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag'], 'weekdays_short' => ['søn', 'man', 'tir', 'ons', 'tor', 'fre', 'lør'], 'weekdays_min' => ['sø', 'ma', 'ti', 'on', 'to', 'fr', 'lø'], 'ordinal' => ':number.', 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D. MMMM YYYY', 'LLL' => 'D. MMMM YYYY [kl.] HH:mm', 'LLLL' => 'dddd D. MMMM YYYY [kl.] HH:mm', ], 'calendar' => [ 'sameDay' => '[i dag kl.] LT', 'nextDay' => '[i morgen kl.] LT', 'nextWeek' => 'dddd [kl.] LT', 'lastDay' => '[i går kl.] LT', 'lastWeek' => '[forrige] dddd [kl.] LT', 'sameElse' => 'L', ], 'list' => [', ', ' og '], 'meridiem' => ['a.m.', 'p.m.'], ]; PK������<1ZM������Carbon/Lang/ve_ZA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['Phando', 'Luhuhi', 'Ṱhafamuhwe', 'Lambamai', 'Shundunthule', 'Fulwi', 'Fulwana', 'Ṱhangule', 'Khubvumedzi', 'Tshimedzi', 'Ḽara', 'Nyendavhusiku'], 'months_short' => ['Pha', 'Luh', 'Fam', 'Lam', 'Shu', 'Lwi', 'Lwa', 'Ngu', 'Khu', 'Tsh', 'Ḽar', 'Nye'], 'weekdays' => ['Swondaha', 'Musumbuluwo', 'Ḽavhuvhili', 'Ḽavhuraru', 'Ḽavhuṋa', 'Ḽavhuṱanu', 'Mugivhela'], 'weekdays_short' => ['Swo', 'Mus', 'Vhi', 'Rar', 'ṋa', 'Ṱan', 'Mug'], 'weekdays_min' => ['Swo', 'Mus', 'Vhi', 'Rar', 'ṋa', 'Ṱan', 'Mug'], 'day_of_first_week_of_year' => 1, // Too unreliable /* 'day' => ':count vhege', // less reliable 'd' => ':count vhege', // less reliable 'a_day' => ':count vhege', // less reliable 'hour' => ':count watshi', // less reliable 'h' => ':count watshi', // less reliable 'a_hour' => ':count watshi', // less reliable 'minute' => ':count watshi', // less reliable 'min' => ':count watshi', // less reliable 'a_minute' => ':count watshi', // less reliable 'second' => ':count Mu', // less reliable 's' => ':count Mu', // less reliable 'a_second' => ':count Mu', // less reliable 'week' => ':count vhege', 'w' => ':count vhege', 'a_week' => ':count vhege', */ ]); PK������<1ZpG��G����Carbon/Lang/en_LR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z5O��O����Carbon/Lang/sgs.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/sgs_LT.php'; PK������<1Z+H �� ����Carbon/Lang/vi_VN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/vi.php'; PK������<1Z~@O��O����Carbon/Lang/hne.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/hne_IN.php'; PK������<1ZlW������Carbon/Lang/naq.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['ǁgoagas', 'ǃuias'], 'weekdays' => ['Sontaxtsees', 'Mantaxtsees', 'Denstaxtsees', 'Wunstaxtsees', 'Dondertaxtsees', 'Fraitaxtsees', 'Satertaxtsees'], 'weekdays_short' => ['Son', 'Ma', 'De', 'Wu', 'Do', 'Fr', 'Sat'], 'weekdays_min' => ['Son', 'Ma', 'De', 'Wu', 'Do', 'Fr', 'Sat'], 'months' => ['ǃKhanni', 'ǃKhanǀgôab', 'ǀKhuuǁkhâb', 'ǃHôaǂkhaib', 'ǃKhaitsâb', 'Gamaǀaeb', 'ǂKhoesaob', 'Aoǁkhuumûǁkhâb', 'Taraǀkhuumûǁkhâb', 'ǂNûǁnâiseb', 'ǀHooǂgaeb', 'Hôasoreǁkhâb'], 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY h:mm a', 'LLLL' => 'dddd, D MMMM YYYY h:mm a', ], 'year' => ':count kurigu', 'y' => ':count kurigu', 'a_year' => ':count kurigu', 'month' => ':count ǁaub', // less reliable 'm' => ':count ǁaub', // less reliable 'a_month' => ':count ǁaub', // less reliable 'week' => ':count hû', // less reliable 'w' => ':count hû', // less reliable 'a_week' => ':count hû', // less reliable 'day' => ':count ǀhobas', // less reliable 'd' => ':count ǀhobas', // less reliable 'a_day' => ':count ǀhobas', // less reliable 'hour' => ':count ǂgaes', // less reliable 'h' => ':count ǂgaes', // less reliable 'a_hour' => ':count ǂgaes', // less reliable 'minute' => ':count minutga', // less reliable 'min' => ':count minutga', // less reliable 'a_minute' => ':count minutga', // less reliable ]); PK������<1Z%.��.����Carbon/Lang/zh_SG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/zh.php', [ 'formats' => [ 'L' => 'YYYY年MM月DD日', ], 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], 'months_short' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], 'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'], 'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'], 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'], 'day_of_first_week_of_year' => 1, ]); PK������<1Zf8 �� ����Carbon/Lang/sv.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - Kristoffer Snabb * - JD Isaacks * - Jens Herlevsen * - Nightpine * - Anders Nygren (litemerafrukt) */ return [ 'year' => ':count år', 'a_year' => 'ett år|:count år', 'y' => ':count år', 'month' => ':count månad|:count månader', 'a_month' => 'en månad|:count månader', 'm' => ':count mån', 'week' => ':count vecka|:count veckor', 'a_week' => 'en vecka|:count veckor', 'w' => ':count v', 'day' => ':count dag|:count dagar', 'a_day' => 'en dag|:count dagar', 'd' => ':count dgr', 'hour' => ':count timme|:count timmar', 'a_hour' => 'en timme|:count timmar', 'h' => ':count tim', 'minute' => ':count minut|:count minuter', 'a_minute' => 'en minut|:count minuter', 'min' => ':count min', 'second' => ':count sekund|:count sekunder', 'a_second' => 'några sekunder|:count sekunder', 's' => ':count s', 'ago' => 'för :time sedan', 'from_now' => 'om :time', 'after' => ':time efter', 'before' => ':time före', 'diff_now' => 'nu', 'diff_today' => 'I dag', 'diff_yesterday' => 'i går', 'diff_yesterday_regexp' => 'I går', 'diff_tomorrow' => 'i morgon', 'diff_tomorrow_regexp' => 'I morgon', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY-MM-DD', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY [kl.] HH:mm', 'LLLL' => 'dddd D MMMM YYYY [kl.] HH:mm', ], 'calendar' => [ 'sameDay' => '[I dag] LT', 'nextDay' => '[I morgon] LT', 'nextWeek' => '[På] dddd LT', 'lastDay' => '[I går] LT', 'lastWeek' => '[I] dddd[s] LT', 'sameElse' => 'L', ], 'ordinal' => function ($number) { $lastDigit = $number % 10; return $number.( ((int) ($number % 100 / 10) === 1) ? 'e' : ( ($lastDigit === 1 || $lastDigit === 2) ? 'a' : 'e' ) ); }, 'months' => ['januari', 'februari', 'mars', 'april', 'maj', 'juni', 'juli', 'augusti', 'september', 'oktober', 'november', 'december'], 'months_short' => ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'], 'weekdays' => ['söndag', 'måndag', 'tisdag', 'onsdag', 'torsdag', 'fredag', 'lördag'], 'weekdays_short' => ['sön', 'mån', 'tis', 'ons', 'tors', 'fre', 'lör'], 'weekdays_min' => ['sö', 'må', 'ti', 'on', 'to', 'fr', 'lö'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' och '], 'meridiem' => ['fm', 'em'], ]; PK������<1Z''x �� ����Carbon/Lang/fr_GF.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Za= �� ����Carbon/Lang/ps.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Muhammad Nasir Rahimi * - Nassim Nasibullah (spinzar) */ return [ 'year' => ':count کال|:count کاله', 'y' => ':countکال|:countکاله', 'month' => ':count مياشت|:count مياشتي', 'm' => ':countمياشت|:countمياشتي', 'week' => ':count اونۍ|:count اونۍ', 'w' => ':countاونۍ|:countاونۍ', 'day' => ':count ورځ|:count ورځي', 'd' => ':countورځ|:countورځي', 'hour' => ':count ساعت|:count ساعته', 'h' => ':countساعت|:countساعته', 'minute' => ':count دقيقه|:count دقيقې', 'min' => ':countدقيقه|:countدقيقې', 'second' => ':count ثانيه|:count ثانيې', 's' => ':countثانيه|:countثانيې', 'ago' => ':time دمخه', 'from_now' => ':time له اوس څخه', 'after' => ':time وروسته', 'before' => ':time دمخه', 'list' => ['، ', ' او '], 'meridiem' => ['غ.م.', 'غ.و.'], 'weekdays' => ['اتوار', 'ګل', 'نهه', 'شورو', 'زيارت', 'جمعه', 'خالي'], 'weekdays_short' => ['ا', 'ګ', 'ن', 'ش', 'ز', 'ج', 'خ'], 'weekdays_min' => ['ا', 'ګ', 'ن', 'ش', 'ز', 'ج', 'خ'], 'months' => ['جنوري', 'فبروري', 'مارچ', 'اپریل', 'مۍ', 'جون', 'جولای', 'اگست', 'سېپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'], 'months_short' => ['جنوري', 'فبروري', 'مارچ', 'اپریل', 'مۍ', 'جون', 'جولای', 'اگست', 'سېپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'], 'months_standalone' => ['جنوري', 'فېبروري', 'مارچ', 'اپریل', 'مۍ', 'جون', 'جولای', 'اگست', 'سپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'], 'months_short_standalone' => ['جنوري', 'فبروري', 'مارچ', 'اپریل', 'مۍ', 'جون', 'جولای', 'اگست', 'سپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'], 'first_day_of_week' => 6, 'weekend' => [4, 5], 'formats' => [ 'LT' => 'H:mm', 'LTS' => 'H:mm:ss', 'L' => 'YYYY/M/d', 'LL' => 'YYYY MMM D', 'LLL' => 'د YYYY د MMMM D H:mm', 'LLLL' => 'dddd د YYYY د MMMM D H:mm', ], ]; PK������<1Z)��)����Carbon/Lang/ar_TD.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ar.php', [ ]); PK������<1Z+\��\����Carbon/Lang/teo.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ta.php', [ 'meridiem' => ['Taparachu', 'Ebongi'], 'weekdays' => ['Nakaejuma', 'Nakaebarasa', 'Nakaare', 'Nakauni', 'Nakaung’on', 'Nakakany', 'Nakasabiti'], 'weekdays_short' => ['Jum', 'Bar', 'Aar', 'Uni', 'Ung', 'Kan', 'Sab'], 'weekdays_min' => ['Jum', 'Bar', 'Aar', 'Uni', 'Ung', 'Kan', 'Sab'], 'months' => ['Orara', 'Omuk', 'Okwamg’', 'Odung’el', 'Omaruk', 'Omodok’king’ol', 'Ojola', 'Opedel', 'Osokosokoma', 'Otibar', 'Olabor', 'Opoo'], 'months_short' => ['Rar', 'Muk', 'Kwa', 'Dun', 'Mar', 'Mod', 'Jol', 'Ped', 'Sok', 'Tib', 'Lab', 'Poo'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], ]); PK������<1Z^<��<����Carbon/Lang/khq.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['Adduha', 'Aluula'], 'weekdays' => ['Alhadi', 'Atini', 'Atalata', 'Alarba', 'Alhamiisa', 'Aljuma', 'Assabdu'], 'weekdays_short' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alj', 'Ass'], 'weekdays_min' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alj', 'Ass'], 'months' => ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me', 'Žuweŋ', 'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur', 'Deesanbur'], 'months_short' => ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy', 'Ut', 'Sek', 'Okt', 'Noo', 'Dee'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM, YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], ]); PK������<1Z.z/������Carbon/Lang/quz_PE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Sugar Labs // OLPC sugarlabs.org libc-alpha@sourceware.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'months' => ['iniru', 'phiwriru', 'marsu', 'awril', 'mayu', 'huniyu', 'huliyu', 'agustu', 'siptiyimri', 'uktuwri', 'nuwiyimri', 'tisiyimri'], 'months_short' => ['ini', 'phi', 'mar', 'awr', 'may', 'hun', 'hul', 'agu', 'sip', 'ukt', 'nuw', 'tis'], 'weekdays' => ['tuminku', 'lunis', 'martis', 'miyirkulis', 'juywis', 'wiyirnis', 'sawatu'], 'weekdays_short' => ['tum', 'lun', 'mar', 'miy', 'juy', 'wiy', 'saw'], 'weekdays_min' => ['tum', 'lun', 'mar', 'miy', 'juy', 'wiy', 'saw'], 'day_of_first_week_of_year' => 1, 'minute' => ':count uchuy', // less reliable 'min' => ':count uchuy', // less reliable 'a_minute' => ':count uchuy', // less reliable 'year' => ':count wata', 'y' => ':count wata', 'a_year' => ':count wata', 'month' => ':count killa', 'm' => ':count killa', 'a_month' => ':count killa', 'week' => ':count simana', 'w' => ':count simana', 'a_week' => ':count simana', 'day' => ':count pʼunchaw', 'd' => ':count pʼunchaw', 'a_day' => ':count pʼunchaw', 'hour' => ':count ura', 'h' => ':count ura', 'a_hour' => ':count ura', 'second' => ':count iskay ñiqin', 's' => ':count iskay ñiqin', 'a_second' => ':count iskay ñiqin', ]); PK������<1Z'Ht̽������Carbon/Lang/nus.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['RW', 'TŊ'], 'weekdays' => ['Cäŋ kuɔth', 'Jiec la̱t', 'Rɛw lätni', 'Diɔ̱k lätni', 'Ŋuaan lätni', 'Dhieec lätni', 'Bäkɛl lätni'], 'weekdays_short' => ['Cäŋ', 'Jiec', 'Rɛw', 'Diɔ̱k', 'Ŋuaan', 'Dhieec', 'Bäkɛl'], 'weekdays_min' => ['Cäŋ', 'Jiec', 'Rɛw', 'Diɔ̱k', 'Ŋuaan', 'Dhieec', 'Bäkɛl'], 'months' => ['Tiop thar pɛt', 'Pɛt', 'Duɔ̱ɔ̱ŋ', 'Guak', 'Duät', 'Kornyoot', 'Pay yie̱tni', 'Tho̱o̱r', 'Tɛɛr', 'Laath', 'Kur', 'Tio̱p in di̱i̱t'], 'months_short' => ['Tiop', 'Pɛt', 'Duɔ̱ɔ̱', 'Guak', 'Duä', 'Kor', 'Pay', 'Thoo', 'Tɛɛ', 'Laa', 'Kur', 'Tid'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'D/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY h:mm a', 'LLLL' => 'dddd D MMMM YYYY h:mm a', ], 'year' => ':count jiök', // less reliable 'y' => ':count jiök', // less reliable 'a_year' => ':count jiök', // less reliable 'month' => ':count pay', // less reliable 'm' => ':count pay', // less reliable 'a_month' => ':count pay', // less reliable ]); PK������<1Zjߎ������Carbon/Lang/fr.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Dieter Sting * - François B * - Maxime VALY * - JD Isaacks * - Dieter Sting * - François B * - JD Isaacks * - Sebastian Thierer * - Fastfuel * - Pete Scopes (pdscopes) */ return [ 'year' => ':count an|:count ans', 'a_year' => 'un an|:count ans', 'y' => ':count an|:count ans', 'month' => ':count mois|:count mois', 'a_month' => 'un mois|:count mois', 'm' => ':count mois', 'week' => ':count semaine|:count semaines', 'a_week' => 'une semaine|:count semaines', 'w' => ':count sem.', 'day' => ':count jour|:count jours', 'a_day' => 'un jour|:count jours', 'd' => ':count j', 'hour' => ':count heure|:count heures', 'a_hour' => 'une heure|:count heures', 'h' => ':count h', 'minute' => ':count minute|:count minutes', 'a_minute' => 'une minute|:count minutes', 'min' => ':count min', 'second' => ':count seconde|:count secondes', 'a_second' => 'quelques secondes|:count secondes', 's' => ':count s', 'millisecond' => ':count milliseconde|:count millisecondes', 'a_millisecond' => 'une milliseconde|:count millisecondes', 'ms' => ':countms', 'microsecond' => ':count microseconde|:count microsecondes', 'a_microsecond' => 'une microseconde|:count microsecondes', 'µs' => ':countµs', 'ago' => 'il y a :time', 'from_now' => 'dans :time', 'after' => ':time après', 'before' => ':time avant', 'diff_now' => "à l'instant", 'diff_today' => "aujourd'hui", 'diff_today_regexp' => "aujourd'hui(?:\s+à)?", 'diff_yesterday' => 'hier', 'diff_yesterday_regexp' => 'hier(?:\s+à)?', 'diff_tomorrow' => 'demain', 'diff_tomorrow_regexp' => 'demain(?:\s+à)?', 'diff_before_yesterday' => 'avant-hier', 'diff_after_tomorrow' => 'après-demain', 'period_recurrences' => ':count fois', 'period_interval' => 'tous les :interval', 'period_start_date' => 'de :date', 'period_end_date' => 'à :date', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[Aujourd’hui à] LT', 'nextDay' => '[Demain à] LT', 'nextWeek' => 'dddd [à] LT', 'lastDay' => '[Hier à] LT', 'lastWeek' => 'dddd [dernier à] LT', 'sameElse' => 'L', ], 'months' => ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'], 'months_short' => ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.', 'août', 'sept.', 'oct.', 'nov.', 'déc.'], 'weekdays' => ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'], 'weekdays_short' => ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'], 'weekdays_min' => ['di', 'lu', 'ma', 'me', 'je', 've', 'sa'], 'ordinal' => function ($number, $period) { switch ($period) { // In French, only the first has to be ordinal, other number remains cardinal // @link https://fr.wikihow.com/%C3%A9crire-la-date-en-fran%C3%A7ais case 'D': return $number.($number === 1 ? 'er' : ''); default: case 'M': case 'Q': case 'DDD': case 'd': return $number.($number === 1 ? 'er' : 'e'); // Words with feminine grammatical gender: semaine case 'w': case 'W': return $number.($number === 1 ? 're' : 'e'); } }, 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' et '], 'ordinal_words' => [ 'of' => 'de', 'first' => 'premier', 'second' => 'deuxième', 'third' => 'troisième', 'fourth' => 'quatrième', 'fifth' => 'cinquième', 'last' => 'dernier', ], ]; PK������<1Zz������Carbon/Lang/shn_MM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - ubuntu Myanmar LoCo Team https://ubuntu-mm.net Bone Pyae Sone bone.burma@mail.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'OY MMM OD dddd', ], 'months' => ['လိူၼ်ၵမ်', 'လိူၼ်သၢမ်', 'လိူၼ်သီ', 'လိူၼ်ႁႃႈ', 'လိူၼ်ႁူၵ်း', 'လိူၼ်ၸဵတ်း', 'လိူၼ်ပႅတ်ႇ', 'လိူၼ်ၵဝ်ႈ', 'လိူၼ်သိပ်း', 'လိူၼ်သိပ်းဢိတ်း', 'လိူၼ်သိပ်းဢိတ်းသွင်', 'လိူၼ်ၸဵင်'], 'months_short' => ['လိူၼ်ၵမ်', 'လိူၼ်သၢမ်', 'လိူၼ်သီ', 'လိူၼ်ႁႃႈ', 'လိူၼ်ႁူၵ်း', 'လိူၼ်ၸဵတ်း', 'လိူၼ်ပႅတ်ႇ', 'လိူၼ်ၵဝ်ႈ', 'လိူၼ်သိပ်း', 'လိူၼ်သိပ်းဢိတ်း', 'လိူၼ်သိပ်းဢိတ်းသွင်', 'လိူၼ်ၸဵင်'], 'weekdays' => ['ဝၼ်းဢႃးတိတ်ႉ', 'ဝၼ်းၸၼ်', 'ဝၼ်း​ဢၢင်း​ၵၢၼ်း', 'ဝၼ်းပူတ်ႉ', 'ဝၼ်းၽတ်း', 'ဝၼ်းသုၵ်း', 'ဝၼ်းသဝ်'], 'weekdays_short' => ['တိတ့်', 'ၸၼ်', 'ၵၢၼ်း', 'ပုတ့်', 'ၽတ်း', 'သုၵ်း', 'သဝ်'], 'weekdays_min' => ['တိတ့်', 'ၸၼ်', 'ၵၢၼ်း', 'ပုတ့်', 'ၽတ်း', 'သုၵ်း', 'သဝ်'], 'alt_numbers' => ['႐႐', '႐႑', '႐႒', '႐႓', '႐႔', '႐႕', '႐႖', '႐႗', '႐႘', '႐႙', '႑႐', '႑႑', '႑႒', '႑႓', '႑႔', '႑႕', '႑႖', '႑႗', '႑႘', '႑႙', '႒႐', '႒႑', '႒႒', '႒႓', '႒႔', '႒႕', '႒႖', '႒႗', '႒႘', '႒႙', '႓႐', '႓႑', '႓႒', '႓႓', '႓႔', '႓႕', '႓႖', '႓႗', '႓႘', '႓႙', '႔႐', '႔႑', '႔႒', '႔႓', '႔႔', '႔႕', '႔႖', '႔႗', '႔႘', '႔႙', '႕႐', '႕႑', '႕႒', '႕႓', '႕႔', '႕႕', '႕႖', '႕႗', '႕႘', '႕႙', '႖႐', '႖႑', '႖႒', '႖႓', '႖႔', '႖႕', '႖႖', '႖႗', '႖႘', '႖႙', '႗႐', '႗႑', '႗႒', '႗႓', '႗႔', '႗႕', '႗႖', '႗႗', '႗႘', '႗႙', '႘႐', '႘႑', '႘႒', '႘႓', '႘႔', '႘႕', '႘႖', '႘႗', '႘႘', '႘႙', '႙႐', '႙႑', '႙႒', '႙႓', '႙႔', '႙႕', '႙႖', '႙႗', '႙႘', '႙႙'], 'meridiem' => ['ၵၢင်ၼႂ်', 'တၢမ်းၶမ်ႈ'], 'month' => ':count လိူၼ်', // less reliable 'm' => ':count လိူၼ်', // less reliable 'a_month' => ':count လိူၼ်', // less reliable 'week' => ':count ဝၼ်း', // less reliable 'w' => ':count ဝၼ်း', // less reliable 'a_week' => ':count ဝၼ်း', // less reliable 'hour' => ':count ຕີ', // less reliable 'h' => ':count ຕີ', // less reliable 'a_hour' => ':count ຕີ', // less reliable 'minute' => ':count ເດັກ', // less reliable 'min' => ':count ເດັກ', // less reliable 'a_minute' => ':count ເດັກ', // less reliable 'second' => ':count ဢိုၼ်ႇ', // less reliable 's' => ':count ဢိုၼ်ႇ', // less reliable 'a_second' => ':count ဢိုၼ်ႇ', // less reliable 'year' => ':count ပီ', 'y' => ':count ပီ', 'a_year' => ':count ပီ', 'day' => ':count ກາງວັນ', 'd' => ':count ກາງວັນ', 'a_day' => ':count ກາງວັນ', ]); PK������<1ZC������Carbon/Lang/bhb_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Samsung Electronics Co., Ltd. alexey.merzlyakov@samsung.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], 'weekdays' => ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], 'weekdays_short' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], 'weekdays_min' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], 'day_of_first_week_of_year' => 1, ]); PK������<1Z?щ������Carbon/Lang/sw_KE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Kamusi Project Martin Benjamin locales@kamusi.org */ return array_replace_recursive(require __DIR__.'/sw.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'], 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'], 'weekdays' => ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi', 'Ijumaa', 'Jumamosi'], 'weekdays_short' => ['J2', 'J3', 'J4', 'J5', 'Alh', 'Ij', 'J1'], 'weekdays_min' => ['J2', 'J3', 'J4', 'J5', 'Alh', 'Ij', 'J1'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['asubuhi', 'alasiri'], ]); PK������<1Z:*������Carbon/Lang/sm_WS.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Samsung Electronics Co., Ltd. akhilesh.k@samsung.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['Ianuari', 'Fepuari', 'Mati', 'Aperila', 'Me', 'Iuni', 'Iulai', 'Auguso', 'Setema', 'Oketopa', 'Novema', 'Tesema'], 'months_short' => ['Ian', 'Fep', 'Mat', 'Ape', 'Me', 'Iun', 'Iul', 'Aug', 'Set', 'Oke', 'Nov', 'Tes'], 'weekdays' => ['Aso Sa', 'Aso Gafua', 'Aso Lua', 'Aso Lulu', 'Aso Tofi', 'Aso Farail', 'Aso To\'ana\'i'], 'weekdays_short' => ['Aso Sa', 'Aso Gaf', 'Aso Lua', 'Aso Lul', 'Aso Tof', 'Aso Far', 'Aso To\''], 'weekdays_min' => ['Aso Sa', 'Aso Gaf', 'Aso Lua', 'Aso Lul', 'Aso Tof', 'Aso Far', 'Aso To\''], 'hour' => ':count uati', // less reliable 'h' => ':count uati', // less reliable 'a_hour' => ':count uati', // less reliable 'minute' => ':count itiiti', // less reliable 'min' => ':count itiiti', // less reliable 'a_minute' => ':count itiiti', // less reliable 'second' => ':count lua', // less reliable 's' => ':count lua', // less reliable 'a_second' => ':count lua', // less reliable 'year' => ':count tausaga', 'y' => ':count tausaga', 'a_year' => ':count tausaga', 'month' => ':count māsina', 'm' => ':count māsina', 'a_month' => ':count māsina', 'week' => ':count vaiaso', 'w' => ':count vaiaso', 'a_week' => ':count vaiaso', 'day' => ':count aso', 'd' => ':count aso', 'a_day' => ':count aso', ]); PK������<1Z������Carbon/Lang/ki.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['Kiroko', 'Hwaĩ-inĩ'], 'weekdays' => ['Kiumia', 'Njumatatũ', 'Njumaine', 'Njumatana', 'Aramithi', 'Njumaa', 'Njumamothi'], 'weekdays_short' => ['KMA', 'NTT', 'NMN', 'NMT', 'ART', 'NMA', 'NMM'], 'weekdays_min' => ['KMA', 'NTT', 'NMN', 'NMT', 'ART', 'NMA', 'NMM'], 'months' => ['Njenuarĩ', 'Mwere wa kerĩ', 'Mwere wa gatatũ', 'Mwere wa kana', 'Mwere wa gatano', 'Mwere wa gatandatũ', 'Mwere wa mũgwanja', 'Mwere wa kanana', 'Mwere wa kenda', 'Mwere wa ikũmi', 'Mwere wa ikũmi na ũmwe', 'Ndithemba'], 'months_short' => ['JEN', 'WKR', 'WGT', 'WKN', 'WTN', 'WTD', 'WMJ', 'WNN', 'WKD', 'WIK', 'WMW', 'DIT'], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'year' => ':count mĩaka', // less reliable 'y' => ':count mĩaka', // less reliable 'a_year' => ':count mĩaka', // less reliable 'month' => ':count mweri', // less reliable 'm' => ':count mweri', // less reliable 'a_month' => ':count mweri', // less reliable 'week' => ':count kiumia', // less reliable 'w' => ':count kiumia', // less reliable 'a_week' => ':count kiumia', // less reliable 'day' => ':count mũthenya', // less reliable 'd' => ':count mũthenya', // less reliable 'a_day' => ':count mũthenya', // less reliable 'hour' => ':count thaa', // less reliable 'h' => ':count thaa', // less reliable 'a_hour' => ':count thaa', // less reliable 'minute' => ':count mundu', // less reliable 'min' => ':count mundu', // less reliable 'a_minute' => ':count mundu', // less reliable 'second' => ':count igego', // less reliable 's' => ':count igego', // less reliable 'a_second' => ':count igego', // less reliable ]); PK������<1Z  �� ����Carbon/Lang/or_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM AP Linux Technology Center, Yamato Software Laboratory bug-glibc@gnu.org */ return [ 'diff_now' => 'ବର୍ତ୍ତମାନ', 'diff_yesterday' => 'ଗତକାଲି', 'diff_tomorrow' => 'ଆସନ୍ତାକାଲି', 'formats' => [ 'LT' => 'Oh:Om A', 'LTS' => 'Oh:Om:Os A', 'L' => 'OD-OM-OY', 'LL' => 'OD MMMM OY', 'LLL' => 'OD MMMM OY Oh:Om A', 'LLLL' => 'dddd OD MMMM OY Oh:Om A', ], 'months' => ['ଜାନୁଆରୀ', 'ଫେବୃଆରୀ', 'ମାର୍ଚ୍ଚ', 'ଅପ୍ରେଲ', 'ମଇ', 'ଜୁନ', 'ଜୁଲାଇ', 'ଅଗଷ୍ଟ', 'ସେପ୍ଟେମ୍ବର', 'ଅକ୍ଟୋବର', 'ନଭେମ୍ବର', 'ଡିସେମ୍ବର'], 'months_short' => ['ଜାନୁଆରୀ', 'ଫେବୃଆରୀ', 'ମାର୍ଚ୍ଚ', 'ଅପ୍ରେଲ', 'ମଇ', 'ଜୁନ', 'ଜୁଲାଇ', 'ଅଗଷ୍ଟ', 'ସେପ୍ଟେମ୍ବର', 'ଅକ୍ଟୋବର', 'ନଭେମ୍ବର', 'ଡିସେମ୍ବର'], 'weekdays' => ['ରବିବାର', 'ସୋମବାର', 'ମଙ୍ଗଳବାର', 'ବୁଧବାର', 'ଗୁରୁବାର', 'ଶୁକ୍ରବାର', 'ଶନିବାର'], 'weekdays_short' => ['ରବି', 'ସୋମ', 'ମଙ୍ଗଳ', 'ବୁଧ', 'ଗୁରୁ', 'ଶୁକ୍ର', 'ଶନି'], 'weekdays_min' => ['ରବି', 'ସୋମ', 'ମଙ୍ଗଳ', 'ବୁଧ', 'ଗୁରୁ', 'ଶୁକ୍ର', 'ଶନି'], 'day_of_first_week_of_year' => 1, 'alt_numbers' => ['୦', '୧', '୨', '୩', '୪', '୫', '୬', '୭', '୮', '୯', '୧୦', '୧୧', '୧୨', '୧୩', '୧୪', '୧୫', '୧୬', '୧୭', '୧୮', '୧୯', '୨୦', '୨୧', '୨୨', '୨୩', '୨୪', '୨୫', '୨୬', '୨୭', '୨୮', '୨୯', '୩୦', '୩୧', '୩୨', '୩୩', '୩୪', '୩୫', '୩୬', '୩୭', '୩୮', '୩୯', '୪୦', '୪୧', '୪୨', '୪୩', '୪୪', '୪୫', '୪୬', '୪୭', '୪୮', '୪୯', '୫୦', '୫୧', '୫୨', '୫୩', '୫୪', '୫୫', '୫୬', '୫୭', '୫୮', '୫୯', '୬୦', '୬୧', '୬୨', '୬୩', '୬୪', '୬୫', '୬୬', '୬୭', '୬୮', '୬୯', '୭୦', '୭୧', '୭୨', '୭୩', '୭୪', '୭୫', '୭୬', '୭୭', '୭୮', '୭୯', '୮୦', '୮୧', '୮୨', '୮୩', '୮୪', '୮୫', '୮୬', '୮୭', '୮୮', '୮୯', '୯୦', '୯୧', '୯୨', '୯୩', '୯୪', '୯୫', '୯୬', '୯୭', '୯୮', '୯୯'], 'year' => ':count ବର୍ଷ', 'y' => ':count ବ.', 'month' => ':count ମାସ', 'm' => ':count ମା.', 'week' => ':count ସପ୍ତାହ', 'w' => ':count ସପ୍ତା.', 'day' => ':count ଦିନ', 'd' => ':count ଦିନ', 'hour' => ':count ଘଣ୍ତ', 'h' => ':count ଘ.', 'minute' => ':count ମିନଟ', 'min' => ':count ମି.', 'second' => ':count ସେକଣ୍ଢ', 's' => ':count ସେ.', 'ago' => ':time ପୂର୍ବେ', 'from_now' => ':timeରେ', ]; PK������<1Z?Ej �� ����Carbon/Lang/en_JM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1ZNn �� ����Carbon/Lang/ro_RO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ro.php'; PK������<1Zq a �� ����Carbon/Lang/it_VA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/it.php'; PK������<1Z������Carbon/Lang/bs_Cyrl.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/bs.php', [ 'meridiem' => ['пре подне', 'поподне'], 'weekdays' => ['недјеља', 'понедјељак', 'уторак', 'сриједа', 'четвртак', 'петак', 'субота'], 'weekdays_short' => ['нед', 'пон', 'уто', 'сри', 'чет', 'пет', 'суб'], 'weekdays_min' => ['нед', 'пон', 'уто', 'сри', 'чет', 'пет', 'суб'], 'months' => ['јануар', 'фебруар', 'март', 'април', 'мај', 'јуни', 'јули', 'аугуст', 'септембар', 'октобар', 'новембар', 'децембар'], 'months_short' => ['јан', 'феб', 'мар', 'апр', 'мај', 'јун', 'јул', 'ауг', 'сеп', 'окт', 'нов', 'дец'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D.M.YYYY.', 'LL' => 'DD.MM.YYYY.', 'LLL' => 'DD. MMMM YYYY. HH:mm', 'LLLL' => 'dddd, DD. MMMM YYYY. HH:mm', ], ]); PK������<1Z>�KN��N����Carbon/Lang/sc.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/sc_IT.php'; PK������<1Zd������Carbon/Lang/es_GT.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]); PK������<1ZV ��V ����Carbon/Lang/sq.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - JD Isaacks * - Fadion Dashi */ return [ 'year' => ':count vit|:count vjet', 'a_year' => 'një vit|:count vite', 'y' => ':count v.', 'month' => ':count muaj', 'a_month' => 'një muaj|:count muaj', 'm' => ':count muaj', 'week' => ':count javë', 'a_week' => ':count javë|:count javë', 'w' => ':count j.', 'day' => ':count ditë', 'a_day' => 'një ditë|:count ditë', 'd' => ':count d.', 'hour' => ':count orë', 'a_hour' => 'një orë|:count orë', 'h' => ':count o.', 'minute' => ':count minutë|:count minuta', 'a_minute' => 'një minutë|:count minuta', 'min' => ':count min.', 'second' => ':count sekondë|:count sekonda', 'a_second' => 'disa sekonda|:count sekonda', 's' => ':count s.', 'ago' => ':time më parë', 'from_now' => 'në :time', 'after' => ':time pas', 'before' => ':time para', 'diff_now' => 'tani', 'diff_today' => 'Sot', 'diff_today_regexp' => 'Sot(?:\\s+në)?', 'diff_yesterday' => 'dje', 'diff_yesterday_regexp' => 'Dje(?:\\s+në)?', 'diff_tomorrow' => 'nesër', 'diff_tomorrow_regexp' => 'Nesër(?:\\s+në)?', 'diff_before_yesterday' => 'pardje', 'diff_after_tomorrow' => 'pasnesër', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[Sot në] LT', 'nextDay' => '[Nesër në] LT', 'nextWeek' => 'dddd [në] LT', 'lastDay' => '[Dje në] LT', 'lastWeek' => 'dddd [e kaluar në] LT', 'sameElse' => 'L', ], 'ordinal' => ':number.', 'meridiem' => ['PD', 'MD'], 'months' => ['janar', 'shkurt', 'mars', 'prill', 'maj', 'qershor', 'korrik', 'gusht', 'shtator', 'tetor', 'nëntor', 'dhjetor'], 'months_short' => ['jan', 'shk', 'mar', 'pri', 'maj', 'qer', 'kor', 'gus', 'sht', 'tet', 'nën', 'dhj'], 'weekdays' => ['e diel', 'e hënë', 'e martë', 'e mërkurë', 'e enjte', 'e premte', 'e shtunë'], 'weekdays_short' => ['die', 'hën', 'mar', 'mër', 'enj', 'pre', 'sht'], 'weekdays_min' => ['d', 'h', 'ma', 'më', 'e', 'p', 'sh'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' dhe '], ]; PK������<1Z+k��k����Carbon/Lang/ig_NG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - pablo@mandriva.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'months' => ['Jenụwarị', 'Febrụwarị', 'Maachị', 'Eprel', 'Mee', 'Juun', 'Julaị', 'Ọgọọst', 'Septemba', 'Ọktoba', 'Novemba', 'Disemba'], 'months_short' => ['Jen', 'Feb', 'Maa', 'Epr', 'Mee', 'Juu', 'Jul', 'Ọgọ', 'Sep', 'Ọkt', 'Nov', 'Dis'], 'weekdays' => ['sọnde', 'mọnde', 'tuzde', 'wenzde', 'tọsde', 'fraịde', 'satọde'], 'weekdays_short' => ['sọn', 'mọn', 'tuz', 'wen', 'tọs', 'fra', 'sat'], 'weekdays_min' => ['sọn', 'mọn', 'tuz', 'wen', 'tọs', 'fra', 'sat'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'year' => 'afo :count', 'y' => 'afo :count', 'a_year' => 'afo :count', 'month' => 'önwa :count', 'm' => 'önwa :count', 'a_month' => 'önwa :count', 'week' => 'izu :count', 'w' => 'izu :count', 'a_week' => 'izu :count', 'day' => 'ụbọchị :count', 'd' => 'ụbọchị :count', 'a_day' => 'ụbọchị :count', 'hour' => 'awa :count', 'h' => 'awa :count', 'a_hour' => 'awa :count', 'minute' => 'minit :count', 'min' => 'minit :count', 'a_minute' => 'minit :count', 'second' => 'sekọnd :count', 's' => 'sekọnd :count', 'a_second' => 'sekọnd :count', ]); PK������<1ZO \��\����Carbon/Lang/xog.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['Munkyo', 'Eigulo'], 'weekdays' => ['Sabiiti', 'Balaza', 'Owokubili', 'Owokusatu', 'Olokuna', 'Olokutaanu', 'Olomukaaga'], 'weekdays_short' => ['Sabi', 'Bala', 'Kubi', 'Kusa', 'Kuna', 'Kuta', 'Muka'], 'weekdays_min' => ['Sabi', 'Bala', 'Kubi', 'Kusa', 'Kuna', 'Kuta', 'Muka'], 'months' => ['Janwaliyo', 'Febwaliyo', 'Marisi', 'Apuli', 'Maayi', 'Juuni', 'Julaayi', 'Agusito', 'Sebuttemba', 'Okitobba', 'Novemba', 'Desemba'], 'months_short' => ['Jan', 'Feb', 'Mar', 'Apu', 'Maa', 'Juu', 'Jul', 'Agu', 'Seb', 'Oki', 'Nov', 'Des'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], ]); PK������<1Z(RHk��k����Carbon/Lang/es_US.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Kunal Marwaha * - Josh Soref * - Jørn Ølmheim * - Craig Patik * - bustta * - François B * - Tim Fish * - Claire Coloma * - Steven Heinrich * - JD Isaacks * - Raphael Amorim */ return array_replace_recursive(require __DIR__.'/es.php', [ 'diff_before_yesterday' => 'anteayer', 'formats' => [ 'LT' => 'h:mm A', 'LTS' => 'h:mm:ss A', 'L' => 'MM/DD/YYYY', 'LL' => 'MMMM [de] D [de] YYYY', 'LLL' => 'MMMM [de] D [de] YYYY h:mm A', 'LLLL' => 'dddd, MMMM [de] D [de] YYYY h:mm A', ], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]); PK������<1Zr9������Carbon/Lang/tt_RU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Rinat Norkin Pablo Saratxaga, Rinat Norkin pablo@mandrakesoft.com, rinat@taif.ru */ return [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'DD MMM, HH:mm', 'LLLL' => 'DD MMMM YYYY, HH:mm', ], 'months' => ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'], 'months_short' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'], 'weekdays' => ['якшәмбе', 'дышәмбе', 'сишәмбе', 'чәршәәмбе', 'пәнҗешмбе', 'җомга', 'шимбә'], 'weekdays_short' => ['якш', 'дыш', 'сиш', 'чәрш', 'пәнҗ', 'җом', 'шим'], 'weekdays_min' => ['якш', 'дыш', 'сиш', 'чәрш', 'пәнҗ', 'җом', 'шим'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'year' => ':count ел', 'month' => ':count ай', 'week' => ':count атна', 'day' => ':count көн', 'hour' => ':count сәгать', 'minute' => ':count минут', 'second' => ':count секунд', ]; PK������<1Z[Ƀ������Carbon/Lang/es_SV.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/es.php', [ 'months' => ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'], 'months_short' => ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic'], 'day_of_first_week_of_year' => 1, ]); PK������<1ZnRO��O����Carbon/Lang/crh.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/crh_UA.php'; PK������<1Z$Z���� ��Carbon/Lang/sd_IN@devanagari.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Red Hat, Pune bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/sd.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['जनवरी', 'फबरवरी', 'मार्चि', 'अप्रेल', 'मे', 'जूनि', 'जूलाइ', 'आगस्टु', 'सेप्टेंबरू', 'आक्टूबरू', 'नवंबरू', 'ॾिसंबरू'], 'months_short' => ['जनवरी', 'फबरवरी', 'मार्चि', 'अप्रेल', 'मे', 'जूनि', 'जूलाइ', 'आगस्टु', 'सेप्टेंबरू', 'आक्टूबरू', 'नवंबरू', 'ॾिसंबरू'], 'weekdays' => ['आर्तवारू', 'सूमरू', 'मंगलू', 'ॿुधरू', 'विस्पति', 'जुमो', 'छंछस'], 'weekdays_short' => ['आर्तवारू', 'सूमरू', 'मंगलू', 'ॿुधरू', 'विस्पति', 'जुमो', 'छंछस'], 'weekdays_min' => ['आर्तवारू', 'सूमरू', 'मंगलू', 'ॿुधरू', 'विस्पति', 'जुमो', 'छंछस'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['म.पू.', 'म.नं.'], ]); PK������<1Zl`PO��O����Carbon/Lang/ayc.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/ayc_PE.php'; PK������<1Zkf'������Carbon/Lang/az_Cyrl.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/az.php', [ 'weekdays' => ['базар', 'базар ертәси', 'чәршәнбә ахшамы', 'чәршәнбә', 'ҹүмә ахшамы', 'ҹүмә', 'шәнбә'], 'weekdays_short' => ['Б.', 'Б.Е.', 'Ч.А.', 'Ч.', 'Ҹ.А.', 'Ҹ.', 'Ш.'], 'weekdays_min' => ['Б.', 'Б.Е.', 'Ч.А.', 'Ч.', 'Ҹ.А.', 'Ҹ.', 'Ш.'], 'months' => ['јанвар', 'феврал', 'март', 'апрел', 'май', 'ијун', 'ијул', 'август', 'сентјабр', 'октјабр', 'нојабр', 'декабр'], 'months_short' => ['јан', 'фев', 'мар', 'апр', 'май', 'ијн', 'ијл', 'авг', 'сен', 'окт', 'ној', 'дек'], 'months_standalone' => ['Јанвар', 'Феврал', 'Март', 'Апрел', 'Май', 'Ијун', 'Ијул', 'Август', 'Сентјабр', 'Октјабр', 'Нојабр', 'Декабр'], 'meridiem' => ['а', 'п'], ]); PK������<1Z!N��N����Carbon/Lang/os.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/os_RU.php'; PK������<1Zz������Carbon/Lang/zh_HK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/zh_Hant_HK.php'; PK������<1Zh������Carbon/Lang/ar_MA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /** * Authors: * - Josh Soref * - JD Isaacks * - Atef Ben Ali (atefBB) * - Mohamed Sabil (mohamedsabil83) */ $months = [ 'يناير', 'فبراير', 'مارس', 'أبريل', 'ماي', 'يونيو', 'يوليوز', 'غشت', 'شتنبر', 'أكتوبر', 'نونبر', 'دجنبر', ]; return [ 'year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']), 'a_year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']), 'month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']), 'a_month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']), 'week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']), 'a_week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']), 'day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']), 'a_day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']), 'hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']), 'a_hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']), 'minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']), 'a_minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']), 'second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']), 'a_second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']), 'ago' => 'منذ :time', 'from_now' => 'في :time', 'after' => 'بعد :time', 'before' => 'قبل :time', 'diff_now' => 'الآن', 'diff_today' => 'اليوم', 'diff_today_regexp' => 'اليوم(?:\\s+على)?(?:\\s+الساعة)?', 'diff_yesterday' => 'أمس', 'diff_yesterday_regexp' => 'أمس(?:\\s+على)?(?:\\s+الساعة)?', 'diff_tomorrow' => 'غداً', 'diff_tomorrow_regexp' => 'غدا(?:\\s+على)?(?:\\s+الساعة)?', 'diff_before_yesterday' => 'قبل الأمس', 'diff_after_tomorrow' => 'بعد غد', 'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']), 'period_interval' => 'كل :interval', 'period_start_date' => 'من :date', 'period_end_date' => 'إلى :date', 'months' => $months, 'months_short' => $months, 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'], 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'list' => ['، ', ' و '], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[اليوم على الساعة] LT', 'nextDay' => '[غدا على الساعة] LT', 'nextWeek' => 'dddd [على الساعة] LT', 'lastDay' => '[أمس على الساعة] LT', 'lastWeek' => 'dddd [على الساعة] LT', 'sameElse' => 'L', ], 'meridiem' => ['ص', 'م'], 'weekend' => [5, 6], ]; PK������<1Z?Ej �� ����Carbon/Lang/en_MT.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1ZO%ėO��O����Carbon/Lang/cmn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/cmn_TW.php'; PK������<1Z������Carbon/Lang/gez_ER.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ge'ez Frontier Foundation locales@geez.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['ጠሐረ', 'ከተተ', 'መገበ', 'አኀዘ', 'ግንባት', 'ሠንየ', 'ሐመለ', 'ነሐሰ', 'ከረመ', 'ጠቀመ', 'ኀደረ', 'ኀሠሠ'], 'months_short' => ['ጠሐረ', 'ከተተ', 'መገበ', 'አኀዘ', 'ግንባ', 'ሠንየ', 'ሐመለ', 'ነሐሰ', 'ከረመ', 'ጠቀመ', 'ኀደረ', 'ኀሠሠ'], 'weekdays' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚት'], 'weekdays_short' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚ'], 'weekdays_min' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚ'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'meridiem' => ['ጽባሕ', 'ምሴት'], 'month' => ':count ወርሕ', // less reliable 'm' => ':count ወርሕ', // less reliable 'a_month' => ':count ወርሕ', // less reliable 'week' => ':count ሰብዑ', // less reliable 'w' => ':count ሰብዑ', // less reliable 'a_week' => ':count ሰብዑ', // less reliable 'hour' => ':count አንትሙ', // less reliable 'h' => ':count አንትሙ', // less reliable 'a_hour' => ':count አንትሙ', // less reliable 'minute' => ':count ንኡስ', // less reliable 'min' => ':count ንኡስ', // less reliable 'a_minute' => ':count ንኡስ', // less reliable 'year' => ':count ዓመት', 'y' => ':count ዓመት', 'a_year' => ':count ዓመት', 'day' => ':count ዕለት', 'd' => ':count ዕለት', 'a_day' => ':count ዕለት', 'second' => ':count ካልእ', 's' => ':count ካልእ', 'a_second' => ':count ካልእ', ]); PK������<1Zb������Carbon/Lang/ha.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - pablo@mandriva.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM, YYYY', 'LLL' => 'D MMMM, YYYY HH:mm', 'LLLL' => 'dddd, D MMMM, YYYY HH:mm', ], 'months' => ['Janairu', 'Faburairu', 'Maris', 'Afirilu', 'Mayu', 'Yuni', 'Yuli', 'Agusta', 'Satumba', 'Oktoba', 'Nuwamba', 'Disamba'], 'months_short' => ['Jan', 'Fab', 'Mar', 'Afi', 'May', 'Yun', 'Yul', 'Agu', 'Sat', 'Okt', 'Nuw', 'Dis'], 'weekdays' => ['Lahadi', 'Litini', 'Talata', 'Laraba', 'Alhamis', 'Jumaʼa', 'Asabar'], 'weekdays_short' => ['Lah', 'Lit', 'Tal', 'Lar', 'Alh', 'Jum', 'Asa'], 'weekdays_min' => ['Lh', 'Li', 'Ta', 'Lr', 'Al', 'Ju', 'As'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'year' => 'shekara :count', 'y' => 'shekara :count', 'a_year' => 'shekara :count', 'month' => ':count wátàa', 'm' => ':count wátàa', 'a_month' => ':count wátàa', 'week' => ':count mako', 'w' => ':count mako', 'a_week' => ':count mako', 'day' => ':count rana', 'd' => ':count rana', 'a_day' => ':count rana', 'hour' => ':count áwàa', 'h' => ':count áwàa', 'a_hour' => ':count áwàa', 'minute' => 'minti :count', 'min' => 'minti :count', 'a_minute' => 'minti :count', 'second' => ':count ná bíyú', 's' => ':count ná bíyú', 'a_second' => ':count ná bíyú', ]); PK������<1Z-n �� ����Carbon/Lang/ko_KR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ko.php'; PK������<1Z3@%��@%����Carbon/Lang/uk.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Carbon\CarbonInterface; $processHoursFunction = function (CarbonInterface $date, string $format) { return $format.'о'.($date->hour === 11 ? 'б' : '').'] LT'; }; /* * Authors: * - Kunal Marwaha * - Josh Soref * - François B * - Tim Fish * - Serhan Apaydın * - Max Mykhailenko * - JD Isaacks * - Max Kovpak * - AucT * - Philippe Vaucher * - Ilya Shaplyko * - Vadym Ievsieiev * - Denys Kurets * - Igor Kasyanchuk * - Tsutomu Kuroda * - tjku * - Max Melentiev * - Oleh * - epaminond * - Juanito Fatas * - Vitalii Khustochka * - Akira Matsuda * - Christopher Dell * - Enrique Vidal * - Simone Carletti * - Aaron Patterson * - Andriy Tyurnikov * - Nicolás Hock Isaza * - Iwakura Taro * - Andrii Ponomarov * - alecrabbit * - vystepanenko * - AlexWalkerson * - Andre Havryliuk (Andrend) * - Max Datsenko (datsenko-md) */ return [ 'year' => ':count рік|:count роки|:count років', 'y' => ':countр|:countрр|:countрр', 'a_year' => '{1}рік|:count рік|:count роки|:count років', 'month' => ':count місяць|:count місяці|:count місяців', 'm' => ':countм', 'a_month' => '{1}місяць|:count місяць|:count місяці|:count місяців', 'week' => ':count тиждень|:count тижні|:count тижнів', 'w' => ':countт', 'a_week' => '{1}тиждень|:count тиждень|:count тижні|:count тижнів', 'day' => ':count день|:count дні|:count днів', 'd' => ':countд', 'a_day' => '{1}день|:count день|:count дні|:count днів', 'hour' => ':count година|:count години|:count годин', 'h' => ':countг', 'a_hour' => '{1}година|:count година|:count години|:count годин', 'minute' => ':count хвилина|:count хвилини|:count хвилин', 'min' => ':countхв', 'a_minute' => '{1}хвилина|:count хвилина|:count хвилини|:count хвилин', 'second' => ':count секунда|:count секунди|:count секунд', 's' => ':countсек', 'a_second' => '{1}декілька секунд|:count секунда|:count секунди|:count секунд', 'hour_ago' => ':count годину|:count години|:count годин', 'a_hour_ago' => '{1}годину|:count годину|:count години|:count годин', 'minute_ago' => ':count хвилину|:count хвилини|:count хвилин', 'a_minute_ago' => '{1}хвилину|:count хвилину|:count хвилини|:count хвилин', 'second_ago' => ':count секунду|:count секунди|:count секунд', 'a_second_ago' => '{1}декілька секунд|:count секунду|:count секунди|:count секунд', 'hour_from_now' => ':count годину|:count години|:count годин', 'a_hour_from_now' => '{1}годину|:count годину|:count години|:count годин', 'minute_from_now' => ':count хвилину|:count хвилини|:count хвилин', 'a_minute_from_now' => '{1}хвилину|:count хвилину|:count хвилини|:count хвилин', 'second_from_now' => ':count секунду|:count секунди|:count секунд', 'a_second_from_now' => '{1}декілька секунд|:count секунду|:count секунди|:count секунд', 'hour_after' => ':count годину|:count години|:count годин', 'a_hour_after' => '{1}годину|:count годину|:count години|:count годин', 'minute_after' => ':count хвилину|:count хвилини|:count хвилин', 'a_minute_after' => '{1}хвилину|:count хвилину|:count хвилини|:count хвилин', 'second_after' => ':count секунду|:count секунди|:count секунд', 'a_second_after' => '{1}декілька секунд|:count секунду|:count секунди|:count секунд', 'hour_before' => ':count годину|:count години|:count годин', 'a_hour_before' => '{1}годину|:count годину|:count години|:count годин', 'minute_before' => ':count хвилину|:count хвилини|:count хвилин', 'a_minute_before' => '{1}хвилину|:count хвилину|:count хвилини|:count хвилин', 'second_before' => ':count секунду|:count секунди|:count секунд', 'a_second_before' => '{1}декілька секунд|:count секунду|:count секунди|:count секунд', 'ago' => ':time тому', 'from_now' => 'за :time', 'after' => ':time після', 'before' => ':time до', 'diff_now' => 'щойно', 'diff_today' => 'Сьогодні', 'diff_today_regexp' => 'Сьогодні(?:\\s+о)?', 'diff_yesterday' => 'вчора', 'diff_yesterday_regexp' => 'Вчора(?:\\s+о)?', 'diff_tomorrow' => 'завтра', 'diff_tomorrow_regexp' => 'Завтра(?:\\s+о)?', 'diff_before_yesterday' => 'позавчора', 'diff_after_tomorrow' => 'післязавтра', 'period_recurrences' => 'один раз|:count рази|:count разів', 'period_interval' => 'кожні :interval', 'period_start_date' => 'з :date', 'period_end_date' => 'до :date', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY, HH:mm', 'LLLL' => 'dddd, D MMMM YYYY, HH:mm', ], 'calendar' => [ 'sameDay' => function (CarbonInterface $date) use ($processHoursFunction) { return $processHoursFunction($date, '[Сьогодні '); }, 'nextDay' => function (CarbonInterface $date) use ($processHoursFunction) { return $processHoursFunction($date, '[Завтра '); }, 'nextWeek' => function (CarbonInterface $date) use ($processHoursFunction) { return $processHoursFunction($date, '[У] dddd ['); }, 'lastDay' => function (CarbonInterface $date) use ($processHoursFunction) { return $processHoursFunction($date, '[Вчора '); }, 'lastWeek' => function (CarbonInterface $date) use ($processHoursFunction) { switch ($date->dayOfWeek) { case 0: case 3: case 5: case 6: return $processHoursFunction($date, '[Минулої] dddd ['); default: return $processHoursFunction($date, '[Минулого] dddd ['); } }, 'sameElse' => 'L', ], 'ordinal' => function ($number, $period) { switch ($period) { case 'M': case 'd': case 'DDD': case 'w': case 'W': return $number.'-й'; case 'D': return $number.'-го'; default: return $number; } }, 'meridiem' => function ($hour) { if ($hour < 4) { return 'ночі'; } if ($hour < 12) { return 'ранку'; } if ($hour < 17) { return 'дня'; } return 'вечора'; }, 'months' => ['січня', 'лютого', 'березня', 'квітня', 'травня', 'червня', 'липня', 'серпня', 'вересня', 'жовтня', 'листопада', 'грудня'], 'months_standalone' => ['січень', 'лютий', 'березень', 'квітень', 'травень', 'червень', 'липень', 'серпень', 'вересень', 'жовтень', 'листопад', 'грудень'], 'months_short' => ['січ', 'лют', 'бер', 'кві', 'тра', 'чер', 'лип', 'сер', 'вер', 'жов', 'лис', 'гру'], 'months_regexp' => '/(D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/', 'weekdays' => function (CarbonInterface $date, $format, $index) { static $words = [ 'nominative' => ['неділя', 'понеділок', 'вівторок', 'середа', 'четвер', 'п’ятниця', 'субота'], 'accusative' => ['неділю', 'понеділок', 'вівторок', 'середу', 'четвер', 'п’ятницю', 'суботу'], 'genitive' => ['неділі', 'понеділка', 'вівторка', 'середи', 'четверга', 'п’ятниці', 'суботи'], ]; $format = $format ?? ''; $nounCase = preg_match('/(\[(В|в|У|у)\])\s+dddd/u', $format) ? 'accusative' : ( preg_match('/\[?(?:минулої|наступної)?\s*\]\s+dddd/u', $format) ? 'genitive' : 'nominative' ); return $words[$nounCase][$index] ?? null; }, 'weekdays_short' => ['нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'], 'weekdays_min' => ['нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' i '], ]; PK������<1Z)��)����Carbon/Lang/be_BY.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/be.php', [ 'months' => ['студзеня', 'лютага', 'сакавіка', 'красавіка', 'мая', 'чэрвеня', 'ліпеня', 'жніўня', 'верасня', 'кастрычніка', 'лістапада', 'снежня'], 'months_short' => ['сту', 'лют', 'сак', 'кра', 'мая', 'чэр', 'ліп', 'жні', 'вер', 'кас', 'ліс', 'сне'], 'weekdays' => ['Нядзеля', 'Панядзелак', 'Аўторак', 'Серада', 'Чацвер', 'Пятніца', 'Субота'], 'weekdays_short' => ['Няд', 'Пан', 'Аўт', 'Срд', 'Чцв', 'Пят', 'Суб'], 'weekdays_min' => ['Няд', 'Пан', 'Аўт', 'Срд', 'Чцв', 'Пят', 'Суб'], ]); PK������<1Z^َ������Carbon/Lang/ln_AO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ln.php', [ 'weekdays' => ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé', 'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno', 'mpɔ́sɔ'], 'weekdays_short' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'], 'weekdays_min' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'], 'meridiem' => ['ntɔ́ngɔ́', 'mpókwa'], ]); PK������<1Z,�������Carbon/Lang/ar_OM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org * - Abdullah-Alhariri */ return array_replace_recursive(require __DIR__.'/ar.php', [ 'formats' => [ 'L' => 'DD MMM, YYYY', ], 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'], 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'], 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'], ]); PK������<1ZpG��G����Carbon/Lang/en_FM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZV���� ��Carbon/Lang/ks_IN@devanagari.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - ks-gnome-trans-commits@lists.code.indlinux.net */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'M/D/YY', ], 'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'], 'months_short' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'], 'weekdays' => ['आथवार', 'चॅ़दुरवार', 'बोमवार', 'ब्वदवार', 'ब्रसवार', 'शोकुरवार', 'बटुवार'], 'weekdays_short' => ['आथ ', 'चॅ़दुर', 'बोम', 'ब्वद', 'ब्रस', 'शोकुर', 'बटु'], 'weekdays_min' => ['आथ ', 'चॅ़दुर', 'बोम', 'ब्वद', 'ब्रस', 'शोकुर', 'बटु'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['पूर्वाह्न', 'अपराह्न'], ]); PK������<1Z8��8����Carbon/Lang/dsb_DE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Information from Michael Wolf bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'DD. MMMM YYYY', 'LLL' => 'DD. MMMM, HH:mm [góź.]', 'LLLL' => 'dddd, DD. MMMM YYYY, HH:mm [góź.]', ], 'months' => ['januara', 'februara', 'měrca', 'apryla', 'maja', 'junija', 'julija', 'awgusta', 'septembra', 'oktobra', 'nowembra', 'decembra'], 'months_short' => ['Jan', 'Feb', 'Měr', 'Apr', 'Maj', 'Jun', 'Jul', 'Awg', 'Sep', 'Okt', 'Now', 'Dec'], 'weekdays' => ['Njeźela', 'Pónjeźele', 'Wałtora', 'Srjoda', 'Stwórtk', 'Pětk', 'Sobota'], 'weekdays_short' => ['Nj', 'Pó', 'Wa', 'Sr', 'St', 'Pě', 'So'], 'weekdays_min' => ['Nj', 'Pó', 'Wa', 'Sr', 'St', 'Pě', 'So'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'year' => ':count lěto', 'y' => ':count lěto', 'a_year' => ':count lěto', 'month' => ':count mjasec', 'm' => ':count mjasec', 'a_month' => ':count mjasec', 'week' => ':count tyźeń', 'w' => ':count tyźeń', 'a_week' => ':count tyźeń', 'day' => ':count źeń', 'd' => ':count źeń', 'a_day' => ':count źeń', 'hour' => ':count góźina', 'h' => ':count góźina', 'a_hour' => ':count góźina', 'minute' => ':count minuta', 'min' => ':count minuta', 'a_minute' => ':count minuta', 'second' => ':count drugi', 's' => ':count drugi', 'a_second' => ':count drugi', ]); PK������<1Zs!��!����Carbon/Lang/mn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Philippe Vaucher * - Tsutomu Kuroda * - tjku * - Max Melentiev * - Zolzaya Erdenebaatar * - Tom Hughes * - Akira Matsuda * - Christopher Dell * - Michael Kessler * - Enrique Vidal * - Simone Carletti * - Aaron Patterson * - Nicolás Hock Isaza * - Ochirkhuyag * - Batmandakh * - lucifer-crybaby */ return [ 'year' => ':count жил', 'y' => ':count жил', 'month' => ':count сар', 'm' => ':count сар', 'week' => ':count долоо хоног', 'w' => ':count долоо хоног', 'day' => ':count өдөр', 'd' => ':count өдөр', 'hour' => ':count цаг', 'h' => ':countц', 'minute' => ':count минут', 'min' => ':countм', 'second' => ':count секунд', 's' => ':countс', 'ago_mode' => 'last', 'ago' => ':time өмнө', 'year_ago' => ':count жилийн', 'y_ago' => ':count жилийн', 'month_ago' => ':count сарын', 'm_ago' => ':count сарын', 'day_ago' => ':count хоногийн', 'd_ago' => ':count хоногийн', 'week_ago' => ':count долоо хоногийн', 'w_ago' => ':count долоо хоногийн', 'hour_ago' => ':count цагийн', 'minute_ago' => ':count минутын', 'second_ago' => ':count секундын', 'from_now_mode' => 'last', 'from_now' => 'одоогоос :time', 'year_from_now' => ':count жилийн дараа', 'y_from_now' => ':count жилийн дараа', 'month_from_now' => ':count сарын дараа', 'm_from_now' => ':count сарын дараа', 'day_from_now' => ':count хоногийн дараа', 'd_from_now' => ':count хоногийн дараа', 'hour_from_now' => ':count цагийн дараа', 'minute_from_now' => ':count минутын дараа', 'second_from_now' => ':count секундын дараа', 'after_mode' => 'last', 'after' => ':time дараа', 'year_after' => ':count жилийн', 'y_after' => ':count жилийн', 'month_after' => ':count сарын', 'm_after' => ':count сарын', 'day_after' => ':count хоногийн', 'd_after' => ':count хоногийн', 'hour_after' => ':count цагийн', 'minute_after' => ':count минутын', 'second_after' => ':count секундын', 'before_mode' => 'last', 'before' => ':time өмнө', 'year_before' => ':count жилийн', 'y_before' => ':count жилийн', 'month_before' => ':count сарын', 'm_before' => ':count сарын', 'day_before' => ':count хоногийн', 'd_before' => ':count хоногийн', 'hour_before' => ':count цагийн', 'minute_before' => ':count минутын', 'second_before' => ':count секундын', 'list' => ', ', 'diff_now' => 'одоо', 'diff_yesterday' => 'өчигдөр', 'diff_tomorrow' => 'маргааш', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY-MM-DD', 'LL' => 'YYYY MMMM DD', 'LLL' => 'YY-MM-DD, HH:mm', 'LLLL' => 'YYYY MMMM DD, HH:mm', ], 'weekdays' => ['Ням', 'Даваа', 'Мягмар', 'Лхагва', 'Пүрэв', 'Баасан', 'Бямба'], 'weekdays_short' => ['Ня', 'Да', 'Мя', 'Лх', 'Пү', 'Ба', 'Бя'], 'weekdays_min' => ['Ня', 'Да', 'Мя', 'Лх', 'Пү', 'Ба', 'Бя'], 'months' => ['1 сар', '2 сар', '3 сар', '4 сар', '5 сар', '6 сар', '7 сар', '8 сар', '9 сар', '10 сар', '11 сар', '12 сар'], 'months_short' => ['1 сар', '2 сар', '3 сар', '4 сар', '5 сар', '6 сар', '7 сар', '8 сар', '9 сар', '10 сар', '11 сар', '12 сар'], 'meridiem' => ['өглөө', 'орой'], 'first_day_of_week' => 1, ]; PK������<1Z�SS��S����Carbon/Lang/tl_PH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - Ian De La Cruz * - JD Isaacks */ return require __DIR__.'/tl.php'; PK������<1Zb3Z��Z����Carbon/Lang/de_IT.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Matthias Dieter Wallno:fer libc-locales@sourceware.org */ return require __DIR__.'/de.php'; PK������<1Zse �� ����Carbon/Lang/uk_UA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/uk.php'; PK������<1Z=Y~��~����Carbon/Lang/sw_CD.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/sw.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', ], ]); PK������<1Z~` �� ����Carbon/Lang/sa_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - The Debian project Christian Perrier bubulle@debian.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'D-MM-YY', ], 'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'], 'months_short' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'], 'weekdays' => ['रविवासर:', 'सोमवासर:', 'मंगलवासर:', 'बुधवासर:', 'बृहस्पतिवासरः', 'शुक्रवासर', 'शनिवासर:'], 'weekdays_short' => ['रविः', 'सोम:', 'मंगल:', 'बुध:', 'बृहस्पतिः', 'शुक्र', 'शनि:'], 'weekdays_min' => ['रविः', 'सोम:', 'मंगल:', 'बुध:', 'बृहस्पतिः', 'शुक्र', 'शनि:'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['पूर्वाह्न', 'अपराह्न'], 'minute' => ':count होरा', // less reliable 'min' => ':count होरा', // less reliable 'a_minute' => ':count होरा', // less reliable 'year' => ':count वर्ष', 'y' => ':count वर्ष', 'a_year' => ':count वर्ष', 'month' => ':count मास', 'm' => ':count मास', 'a_month' => ':count मास', 'week' => ':count सप्ताहः saptahaĥ', 'w' => ':count सप्ताहः saptahaĥ', 'a_week' => ':count सप्ताहः saptahaĥ', 'day' => ':count दिन', 'd' => ':count दिन', 'a_day' => ':count दिन', 'hour' => ':count घण्टा', 'h' => ':count घण्टा', 'a_hour' => ':count घण्टा', 'second' => ':count द्वितीयः', 's' => ':count द्वितीयः', 'a_second' => ':count द्वितीयः', ]); PK������<1ZW]FN��N����Carbon/Lang/an.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/an_ES.php'; PK������<1Z&oq|��|����Carbon/Lang/en_IL.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Yoav Amit * - François B * - Mayank Badola * - JD Isaacks */ return array_replace_recursive(require __DIR__.'/en.php', [ 'from_now' => 'in :time', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], ]); PK������<1Z''x �� ����Carbon/Lang/fr_WF.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1ZwO��O����Carbon/Lang/ber.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/ber_DZ.php'; PK������<1Z������Carbon/Lang/aa_ET.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ge'ez Frontier Foundation locales@geez.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['Qunxa Garablu', 'Kudo', 'Ciggilta Kudo', 'Agda Baxisso', 'Caxah Alsa', 'Qasa Dirri', 'Qado Dirri', 'Liiqen', 'Waysu', 'Diteli', 'Ximoli', 'Kaxxa Garablu'], 'months_short' => ['Qun', 'Kud', 'Cig', 'Agd', 'Cax', 'Qas', 'Qad', 'Leq', 'Way', 'Dit', 'Xim', 'Kax'], 'weekdays' => ['Acaada', 'Etleeni', 'Talaata', 'Arbaqa', 'Kamiisi', 'Gumqata', 'Sabti'], 'weekdays_short' => ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'], 'weekdays_min' => ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['saaku', 'carra'], ]); PK������<1Zx^ �� ����Carbon/Lang/ms.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - Azri Jamil * - JD Isaacks * - Josh Soref * - Azri Jamil * - Hariadi Hinta * - Ashraf Kamarudin */ return [ 'year' => ':count tahun', 'a_year' => '{1}setahun|]1,Inf[:count tahun', 'y' => ':count tahun', 'month' => ':count bulan', 'a_month' => '{1}sebulan|]1,Inf[:count bulan', 'm' => ':count bulan', 'week' => ':count minggu', 'a_week' => '{1}seminggu|]1,Inf[:count minggu', 'w' => ':count minggu', 'day' => ':count hari', 'a_day' => '{1}sehari|]1,Inf[:count hari', 'd' => ':count hari', 'hour' => ':count jam', 'a_hour' => '{1}sejam|]1,Inf[:count jam', 'h' => ':count jam', 'minute' => ':count minit', 'a_minute' => '{1}seminit|]1,Inf[:count minit', 'min' => ':count minit', 'second' => ':count saat', 'a_second' => '{1}beberapa saat|]1,Inf[:count saat', 'millisecond' => ':count milisaat', 'a_millisecond' => '{1}semilisaat|]1,Inf[:count milliseconds', 'microsecond' => ':count mikrodetik', 'a_microsecond' => '{1}semikrodetik|]1,Inf[:count mikrodetik', 's' => ':count saat', 'ago' => ':time yang lepas', 'from_now' => ':time dari sekarang', 'after' => ':time kemudian', 'before' => ':time sebelum', 'diff_now' => 'sekarang', 'diff_today' => 'Hari', 'diff_today_regexp' => 'Hari(?:\\s+ini)?(?:\\s+pukul)?', 'diff_yesterday' => 'semalam', 'diff_yesterday_regexp' => 'Semalam(?:\\s+pukul)?', 'diff_tomorrow' => 'esok', 'diff_tomorrow_regexp' => 'Esok(?:\\s+pukul)?', 'diff_before_yesterday' => 'kelmarin', 'diff_after_tomorrow' => 'lusa', 'formats' => [ 'LT' => 'HH.mm', 'LTS' => 'HH.mm.ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY [pukul] HH.mm', 'LLLL' => 'dddd, D MMMM YYYY [pukul] HH.mm', ], 'calendar' => [ 'sameDay' => '[Hari ini pukul] LT', 'nextDay' => '[Esok pukul] LT', 'nextWeek' => 'dddd [pukul] LT', 'lastDay' => '[Kelmarin pukul] LT', 'lastWeek' => 'dddd [lepas pukul] LT', 'sameElse' => 'L', ], 'meridiem' => function ($hour) { if ($hour < 1) { return 'tengah malam'; } if ($hour < 12) { return 'pagi'; } if ($hour < 13) { return 'tengah hari'; } if ($hour < 19) { return 'petang'; } return 'malam'; }, 'months' => ['Januari', 'Februari', 'Mac', 'April', 'Mei', 'Jun', 'Julai', 'Ogos', 'September', 'Oktober', 'November', 'Disember'], 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ogs', 'Sep', 'Okt', 'Nov', 'Dis'], 'weekdays' => ['Ahad', 'Isnin', 'Selasa', 'Rabu', 'Khamis', 'Jumaat', 'Sabtu'], 'weekdays_short' => ['Ahd', 'Isn', 'Sel', 'Rab', 'Kha', 'Jum', 'Sab'], 'weekdays_min' => ['Ah', 'Is', 'Sl', 'Rb', 'Km', 'Jm', 'Sb'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' dan '], ]; PK������<1Z''x �� ����Carbon/Lang/fr_CF.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Z?uL �� ����Carbon/Lang/af_ZA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/af.php'; PK������<1ZL-xVO��O����Carbon/Lang/shn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/shn_MM.php'; PK������<1Z7,������Carbon/Lang/brx_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Red Hat Pune bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'M/D/YY', ], 'months' => ['जानुवारी', 'फेब्रुवारी', 'मार्स', 'एफ्रिल', 'मे', 'जुन', 'जुलाइ', 'आगस्थ', 'सेबथेज्ब़र', 'अखथबर', 'नबेज्ब़र', 'दिसेज्ब़र'], 'months_short' => ['जानुवारी', 'फेब्रुवारी', 'मार्स', 'एप्रिल', 'मे', 'जुन', 'जुलाइ', 'आगस्थ', 'सेबथेज्ब़र', 'अखथबर', 'नबेज्ब़र', 'दिसेज्ब़र'], 'weekdays' => ['रबिबार', 'सोबार', 'मंगलबार', 'बुदबार', 'बिसथिबार', 'सुखुरबार', 'सुनिबार'], 'weekdays_short' => ['रबि', 'सम', 'मंगल', 'बुद', 'बिसथि', 'सुखुर', 'सुनि'], 'weekdays_min' => ['रबि', 'सम', 'मंगल', 'बुद', 'बिसथि', 'सुखुर', 'सुनि'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['फुं.', 'बेलासे.'], ]); PK������<1Zߴ/w��w����Carbon/Lang/se_FI.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/se.php', [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'months' => ['ođđajagemánnu', 'guovvamánnu', 'njukčamánnu', 'cuoŋománnu', 'miessemánnu', 'geassemánnu', 'suoidnemánnu', 'borgemánnu', 'čakčamánnu', 'golggotmánnu', 'skábmamánnu', 'juovlamánnu'], 'months_short' => ['ođđj', 'guov', 'njuk', 'cuoŋ', 'mies', 'geas', 'suoi', 'borg', 'čakč', 'golg', 'skáb', 'juov'], 'weekdays' => ['sotnabeaivi', 'mánnodat', 'disdat', 'gaskavahkku', 'duorastat', 'bearjadat', 'lávvordat'], 'weekdays_short' => ['so', 'má', 'di', 'ga', 'du', 'be', 'lá'], 'weekdays_min' => ['so', 'má', 'di', 'ga', 'du', 'be', 'lá'], 'meridiem' => ['i', 'e'], ]); PK������<1Z>1������Carbon/Lang/zh_YUE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/zh.php', [ 'formats' => [ 'L' => 'YYYY-MM-DD', ], ]); PK������<1ZڑQ��Q����Carbon/Lang/so_KE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ge'ez Frontier Foundation locales@geez.org */ return require __DIR__.'/so.php'; PK������<1Z^O��O����Carbon/Lang/sid.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/sid_ET.php'; PK������<1Z N��N����Carbon/Lang/ig.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/ig_NG.php'; PK������<1Zl �� ����Carbon/Lang/ja_JP.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ja.php'; PK������<1ZW?������Carbon/Lang/ar_PS.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Abdullah-Alhariri */ return array_replace_recursive(require __DIR__.'/ar.php', [ 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'], ]); PK������<1Z)��)����Carbon/Lang/ar_IL.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ar.php', [ ]); PK������<1ZpN��N����Carbon/Lang/kl.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/kl_GL.php'; PK������<1ZCi �� ����Carbon/Lang/lv_LV.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/lv.php'; PK������<1ZG������Carbon/Lang/is.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Kristján Ingi Geirsson */ return [ 'year' => '1 ár|:count ár', 'y' => '1 ár|:count ár', 'month' => '1 mánuður|:count mánuðir', 'm' => '1 mánuður|:count mánuðir', 'week' => '1 vika|:count vikur', 'w' => '1 vika|:count vikur', 'day' => '1 dagur|:count dagar', 'd' => '1 dagur|:count dagar', 'hour' => '1 klukkutími|:count klukkutímar', 'h' => '1 klukkutími|:count klukkutímar', 'minute' => '1 mínúta|:count mínútur', 'min' => '1 mínúta|:count mínútur', 'second' => '1 sekúnda|:count sekúndur', 's' => '1 sekúnda|:count sekúndur', 'ago' => ':time síðan', 'from_now' => ':time síðan', 'after' => ':time eftir', 'before' => ':time fyrir', 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' og '], 'meridiem' => ['fh', 'eh'], 'diff_now' => 'núna', 'diff_yesterday' => 'í gær', 'diff_tomorrow' => 'á morgun', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D. MMMM YYYY', 'LLL' => 'D. MMMM [kl.] HH:mm', 'LLLL' => 'dddd D. MMMM YYYY [kl.] HH:mm', ], 'weekdays' => ['sunnudaginn', 'mánudaginn', 'þriðjudaginn', 'miðvikudaginn', 'fimmtudaginn', 'föstudaginn', 'laugardaginn'], 'weekdays_short' => ['sun', 'mán', 'þri', 'mið', 'fim', 'fös', 'lau'], 'weekdays_min' => ['sun', 'mán', 'þri', 'mið', 'fim', 'fös', 'lau'], 'months' => ['janúar', 'febrúar', 'mars', 'apríl', 'maí', 'júní', 'júlí', 'ágúst', 'september', 'október', 'nóvember', 'desember'], 'months_short' => ['jan', 'feb', 'mar', 'apr', 'maí', 'jún', 'júl', 'ágú', 'sep', 'okt', 'nóv', 'des'], ]; PK������<1Z&5 �� ����Carbon/Lang/nl_SR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/nl.php'; PK������<1Z^َ������Carbon/Lang/ln_CF.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ln.php', [ 'weekdays' => ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé', 'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno', 'mpɔ́sɔ'], 'weekdays_short' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'], 'weekdays_min' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'], 'meridiem' => ['ntɔ́ngɔ́', 'mpókwa'], ]); PK������<1Z|������Carbon/Lang/ar_KW.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /** * Authors: * - Josh Soref * - Nusret Parlak * - JD Isaacks * - Atef Ben Ali (atefBB) * - Mohamed Sabil (mohamedsabil83) * - Abdullah-Alhariri */ $months = [ 'يناير', 'فبراير', 'مارس', 'أبريل', 'ماي', 'يونيو', 'يوليوز', 'غشت', 'شتنبر', 'أكتوبر', 'نونبر', 'دجنبر', ]; return [ 'year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']), 'a_year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']), 'month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']), 'a_month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']), 'week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']), 'a_week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']), 'day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']), 'a_day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']), 'hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']), 'a_hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']), 'minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']), 'a_minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']), 'second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']), 'a_second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']), 'ago' => 'منذ :time', 'from_now' => 'في :time', 'after' => 'بعد :time', 'before' => 'قبل :time', 'diff_now' => 'الآن', 'diff_today' => 'اليوم', 'diff_today_regexp' => 'اليوم(?:\\s+على)?(?:\\s+الساعة)?', 'diff_yesterday' => 'أمس', 'diff_yesterday_regexp' => 'أمس(?:\\s+على)?(?:\\s+الساعة)?', 'diff_tomorrow' => 'غداً', 'diff_tomorrow_regexp' => 'غدا(?:\\s+على)?(?:\\s+الساعة)?', 'diff_before_yesterday' => 'قبل الأمس', 'diff_after_tomorrow' => 'بعد غد', 'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']), 'period_interval' => 'كل :interval', 'period_start_date' => 'من :date', 'period_end_date' => 'إلى :date', 'months' => $months, 'months_short' => $months, 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'], 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'list' => ['، ', ' و '], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[اليوم على الساعة] LT', 'nextDay' => '[غدا على الساعة] LT', 'nextWeek' => 'dddd [على الساعة] LT', 'lastDay' => '[أمس على الساعة] LT', 'lastWeek' => 'dddd [على الساعة] LT', 'sameElse' => 'L', ], 'meridiem' => ['ص', 'م'], 'weekend' => [5, 6], 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'], ]; PK������<1ZZ Y �� ����Carbon/Lang/fi_FI.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fi.php'; PK������<1Z=N��N����Carbon/Lang/lg.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/lg_UG.php'; PK������<1Z` �� ����Carbon/Lang/he_IL.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/he.php'; PK������<1Z': �� ����Carbon/Lang/uz.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Dmitriy Shabanov * - JD Isaacks * - Inoyatulloh * - Jamshid * - aarkhipov * - Philippe Vaucher * - felixthemagnificent * - Tsutomu Kuroda * - tjku * - Max Melentiev * - Juanito Fatas * - Alisher Ulugbekov * - Ergashev Adizbek */ return [ 'year' => ':count йил', 'a_year' => '{1}бир йил|:count йил', 'y' => ':count й', 'month' => ':count ой', 'a_month' => '{1}бир ой|:count ой', 'm' => ':count о', 'week' => ':count ҳафта', 'a_week' => '{1}бир ҳафта|:count ҳафта', 'w' => ':count ҳ', 'day' => ':count кун', 'a_day' => '{1}бир кун|:count кун', 'd' => ':count к', 'hour' => ':count соат', 'a_hour' => '{1}бир соат|:count соат', 'h' => ':count с', 'minute' => ':count дақиқа', 'a_minute' => '{1}бир дақиқа|:count дақиқа', 'min' => ':count д', 'second' => ':count сония', 'a_second' => '{1}сония|:count сония', 's' => ':count с', 'ago' => ':time аввал', 'from_now' => 'Якин :time ичида', 'after' => ':timeдан кейин', 'before' => ':time олдин', 'diff_now' => 'ҳозир', 'diff_today' => 'Бугун', 'diff_today_regexp' => 'Бугун(?:\\s+соат)?', 'diff_yesterday' => 'Кеча', 'diff_yesterday_regexp' => 'Кеча(?:\\s+соат)?', 'diff_tomorrow' => 'Эртага', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'D MMMM YYYY, dddd HH:mm', ], 'calendar' => [ 'sameDay' => '[Бугун соат] LT [да]', 'nextDay' => '[Эртага] LT [да]', 'nextWeek' => 'dddd [куни соат] LT [да]', 'lastDay' => '[Кеча соат] LT [да]', 'lastWeek' => '[Утган] dddd [куни соат] LT [да]', 'sameElse' => 'L', ], 'months' => ['январ', 'феврал', 'март', 'апрел', 'май', 'июн', 'июл', 'август', 'сентябр', 'октябр', 'ноябр', 'декабр'], 'months_short' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'], 'weekdays' => ['якшанба', 'душанба', 'сешанба', 'чоршанба', 'пайшанба', 'жума', 'шанба'], 'weekdays_short' => ['якш', 'душ', 'сеш', 'чор', 'пай', 'жум', 'шан'], 'weekdays_min' => ['як', 'ду', 'се', 'чо', 'па', 'жу', 'ша'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'meridiem' => ['эрталаб', 'кечаси'], 'list' => [', ', ' ва '], ]; PK������<1Z�������Carbon/Lang/sq_MK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/sq.php', [ 'formats' => [ 'L' => 'D.M.YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY, HH:mm', 'LLLL' => 'dddd, D MMMM YYYY, HH:mm', ], ]); PK������<1Zv}V ��V ����Carbon/Lang/gom_Latn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return [ 'year' => ':count voros|:count vorsam', 'y' => ':countv', 'month' => ':count mhoino|:count mhoine', 'm' => ':countmh', 'week' => ':count satolleacho|:count satolleache', 'w' => ':countsa|:countsa', 'day' => ':count dis', 'd' => ':countd', 'hour' => ':count hor|:count horam', 'h' => ':counth', 'minute' => ':count minute|:count mintam', 'min' => ':countm', 'second' => ':count second', 's' => ':counts', 'diff_today' => 'Aiz', 'diff_yesterday' => 'Kal', 'diff_tomorrow' => 'Faleam', 'formats' => [ 'LT' => 'A h:mm [vazta]', 'LTS' => 'A h:mm:ss [vazta]', 'L' => 'DD-MM-YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY A h:mm [vazta]', 'LLLL' => 'dddd, MMMM[achea] Do, YYYY, A h:mm [vazta]', 'llll' => 'ddd, D MMM YYYY, A h:mm [vazta]', ], 'calendar' => [ 'sameDay' => '[Aiz] LT', 'nextDay' => '[Faleam] LT', 'nextWeek' => '[Ieta to] dddd[,] LT', 'lastDay' => '[Kal] LT', 'lastWeek' => '[Fatlo] dddd[,] LT', 'sameElse' => 'L', ], 'months' => ['Janer', 'Febrer', 'Mars', 'Abril', 'Mai', 'Jun', 'Julai', 'Agost', 'Setembr', 'Otubr', 'Novembr', 'Dezembr'], 'months_short' => ['Jan.', 'Feb.', 'Mars', 'Abr.', 'Mai', 'Jun', 'Jul.', 'Ago.', 'Set.', 'Otu.', 'Nov.', 'Dez.'], 'weekdays' => ['Aitar', 'Somar', 'Mongllar', 'Budvar', 'Brestar', 'Sukrar', 'Son\'var'], 'weekdays_short' => ['Ait.', 'Som.', 'Mon.', 'Bud.', 'Bre.', 'Suk.', 'Son.'], 'weekdays_min' => ['Ai', 'Sm', 'Mo', 'Bu', 'Br', 'Su', 'Sn'], 'ordinal' => function ($number, $period) { return $number.($period === 'D' ? 'er' : ''); }, 'meridiem' => function ($hour) { if ($hour < 4) { return 'rati'; } if ($hour < 12) { return 'sokalli'; } if ($hour < 16) { return 'donparam'; } if ($hour < 20) { return 'sanje'; } return 'rati'; }, 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' ani '], ]; PK������<1ZߟW� ��� ����Carbon/Lang/pa.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Philippe Vaucher * - Tsutomu Kuroda * - Punjab */ return [ 'year' => 'ਇੱਕ ਸਾਲ|:count ਸਾਲ', 'month' => 'ਇੱਕ ਮਹੀਨਾ|:count ਮਹੀਨੇ', 'week' => 'ਹਫਤਾ|:count ਹਫ਼ਤੇ', 'day' => 'ਇੱਕ ਦਿਨ|:count ਦਿਨ', 'hour' => 'ਇੱਕ ਘੰਟਾ|:count ਘੰਟੇ', 'minute' => 'ਇਕ ਮਿੰਟ|:count ਮਿੰਟ', 'second' => 'ਕੁਝ ਸਕਿੰਟ|:count ਸਕਿੰਟ', 'ago' => ':time ਪਹਿਲਾਂ', 'from_now' => ':time ਵਿੱਚ', 'before' => ':time ਤੋਂ ਪਹਿਲਾਂ', 'after' => ':time ਤੋਂ ਬਾਅਦ', 'diff_now' => 'ਹੁਣ', 'diff_today' => 'ਅਜ', 'diff_yesterday' => 'ਕਲ', 'diff_tomorrow' => 'ਕਲ', 'formats' => [ 'LT' => 'A h:mm ਵਜੇ', 'LTS' => 'A h:mm:ss ਵਜੇ', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY, A h:mm ਵਜੇ', 'LLLL' => 'dddd, D MMMM YYYY, A h:mm ਵਜੇ', ], 'calendar' => [ 'sameDay' => '[ਅਜ] LT', 'nextDay' => '[ਕਲ] LT', 'nextWeek' => '[ਅਗਲਾ] dddd, LT', 'lastDay' => '[ਕਲ] LT', 'lastWeek' => '[ਪਿਛਲੇ] dddd, LT', 'sameElse' => 'L', ], 'meridiem' => function ($hour) { if ($hour < 4) { return 'ਰਾਤ'; } if ($hour < 10) { return 'ਸਵੇਰ'; } if ($hour < 17) { return 'ਦੁਪਹਿਰ'; } if ($hour < 20) { return 'ਸ਼ਾਮ'; } return 'ਰਾਤ'; }, 'months' => ['ਜਨਵਰੀ', 'ਫ਼ਰਵਰੀ', 'ਮਾਰਚ', 'ਅਪ੍ਰੈਲ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾਈ', 'ਅਗਸਤ', 'ਸਤੰਬਰ', 'ਅਕਤੂਬਰ', 'ਨਵੰਬਰ', 'ਦਸੰਬਰ'], 'months_short' => ['ਜਨਵਰੀ', 'ਫ਼ਰਵਰੀ', 'ਮਾਰਚ', 'ਅਪ੍ਰੈਲ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾਈ', 'ਅਗਸਤ', 'ਸਤੰਬਰ', 'ਅਕਤੂਬਰ', 'ਨਵੰਬਰ', 'ਦਸੰਬਰ'], 'weekdays' => ['ਐਤਵਾਰ', 'ਸੋਮਵਾਰ', 'ਮੰਗਲਵਾਰ', 'ਬੁਧਵਾਰ', 'ਵੀਰਵਾਰ', 'ਸ਼ੁੱਕਰਵਾਰ', 'ਸ਼ਨੀਚਰਵਾਰ'], 'weekdays_short' => ['ਐਤ', 'ਸੋਮ', 'ਮੰਗਲ', 'ਬੁਧ', 'ਵੀਰ', 'ਸ਼ੁਕਰ', 'ਸ਼ਨੀ'], 'weekdays_min' => ['ਐਤ', 'ਸੋਮ', 'ਮੰਗਲ', 'ਬੁਧ', 'ਵੀਰ', 'ਸ਼ੁਕਰ', 'ਸ਼ਨੀ'], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' ਅਤੇ '], 'weekend' => [0, 0], 'alt_numbers' => ['੦', '੧', '੨', '੩', '੪', '੫', '੬', '੭', '੮', '੯'], ]; PK������<1Z9v��v����Carbon/Lang/nd.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'weekdays' => ['Sonto', 'Mvulo', 'Sibili', 'Sithathu', 'Sine', 'Sihlanu', 'Mgqibelo'], 'weekdays_short' => ['Son', 'Mvu', 'Sib', 'Sit', 'Sin', 'Sih', 'Mgq'], 'weekdays_min' => ['Son', 'Mvu', 'Sib', 'Sit', 'Sin', 'Sih', 'Mgq'], 'months' => ['Zibandlela', 'Nhlolanja', 'Mbimbitho', 'Mabasa', 'Nkwenkwezi', 'Nhlangula', 'Ntulikazi', 'Ncwabakazi', 'Mpandula', 'Mfumfu', 'Lwezi', 'Mpalakazi'], 'months_short' => ['Zib', 'Nhlo', 'Mbi', 'Mab', 'Nkw', 'Nhla', 'Ntu', 'Ncw', 'Mpan', 'Mfu', 'Lwe', 'Mpal'], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'year' => 'okweminyaka engu-:count', // less reliable 'y' => 'okweminyaka engu-:count', // less reliable 'a_year' => 'okweminyaka engu-:count', // less reliable 'month' => 'inyanga ezingu-:count', 'm' => 'inyanga ezingu-:count', 'a_month' => 'inyanga ezingu-:count', 'week' => 'amaviki angu-:count', 'w' => 'amaviki angu-:count', 'a_week' => 'amaviki angu-:count', 'day' => 'kwamalanga angu-:count', 'd' => 'kwamalanga angu-:count', 'a_day' => 'kwamalanga angu-:count', 'hour' => 'amahola angu-:count', 'h' => 'amahola angu-:count', 'a_hour' => 'amahola angu-:count', 'minute' => 'imizuzu engu-:count', 'min' => 'imizuzu engu-:count', 'a_minute' => 'imizuzu engu-:count', 'second' => 'imizuzwana engu-:count', 's' => 'imizuzwana engu-:count', 'a_second' => 'imizuzwana engu-:count', ]); PK������<1ZO��O����Carbon/Lang/csb.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/csb_PL.php'; PK������<1ZL(O��O����Carbon/Lang/wal.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/wal_ET.php'; PK������<1Z7O��O����Carbon/Lang/tcy.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/tcy_IN.php'; PK������<1ZO %������Carbon/Lang/haw.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'months' => ['Ianuali', 'Pepeluali', 'Malaki', 'ʻApelila', 'Mei', 'Iune', 'Iulai', 'ʻAukake', 'Kepakemapa', 'ʻOkakopa', 'Nowemapa', 'Kekemapa'], 'months_short' => ['Ian.', 'Pep.', 'Mal.', 'ʻAp.', 'Mei', 'Iun.', 'Iul.', 'ʻAu.', 'Kep.', 'ʻOk.', 'Now.', 'Kek.'], 'weekdays' => ['Lāpule', 'Poʻakahi', 'Poʻalua', 'Poʻakolu', 'Poʻahā', 'Poʻalima', 'Poʻaono'], 'weekdays_short' => ['LP', 'P1', 'P2', 'P3', 'P4', 'P5', 'P6'], 'weekdays_min' => ['S', 'M', 'T', 'W', 'T', 'F', 'S'], 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'D/M/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY h:mm a', 'LLLL' => 'dddd, D MMMM YYYY h:mm a', ], 'year' => ':count makahiki', 'y' => ':count makahiki', 'a_year' => ':count makahiki', 'month' => ':count mahina', 'm' => ':count mahina', 'a_month' => ':count mahina', 'week' => ':count pule', 'w' => ':count pule', 'a_week' => ':count pule', 'day' => ':count lā', 'd' => ':count lā', 'a_day' => ':count lā', 'hour' => ':count hola', 'h' => ':count hola', 'a_hour' => ':count hola', 'minute' => ':count minuke', 'min' => ':count minuke', 'a_minute' => ':count minuke', 'second' => ':count lua', 's' => ':count lua', 'a_second' => ':count lua', ]); PK������<1Z{O��O����Carbon/Lang/miq.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/miq_NI.php'; PK������<1Z(|@zG��G����Carbon/Lang/es_IC.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 1, ]); PK������<1Z} �� ����Carbon/Lang/mk_MK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/mk.php'; PK������<1Z/kO��O����Carbon/Lang/wae.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/wae_CH.php'; PK������<1Z������Carbon/Lang/sg.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['ND', 'LK'], 'weekdays' => ['Bikua-ôko', 'Bïkua-ûse', 'Bïkua-ptâ', 'Bïkua-usïö', 'Bïkua-okü', 'Lâpôsö', 'Lâyenga'], 'weekdays_short' => ['Bk1', 'Bk2', 'Bk3', 'Bk4', 'Bk5', 'Lâp', 'Lây'], 'weekdays_min' => ['Bk1', 'Bk2', 'Bk3', 'Bk4', 'Bk5', 'Lâp', 'Lây'], 'months' => ['Nyenye', 'Fulundïgi', 'Mbängü', 'Ngubùe', 'Bêläwü', 'Föndo', 'Lengua', 'Kükürü', 'Mvuka', 'Ngberere', 'Nabändüru', 'Kakauka'], 'months_short' => ['Nye', 'Ful', 'Mbä', 'Ngu', 'Bêl', 'Fön', 'Len', 'Kük', 'Mvu', 'Ngb', 'Nab', 'Kak'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM, YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'year' => ':count dā', // less reliable 'y' => ':count dā', // less reliable 'a_year' => ':count dā', // less reliable 'week' => ':count bïkua-okü', // less reliable 'w' => ':count bïkua-okü', // less reliable 'a_week' => ':count bïkua-okü', // less reliable 'day' => ':count ziggawâ', // less reliable 'd' => ':count ziggawâ', // less reliable 'a_day' => ':count ziggawâ', // less reliable 'hour' => ':count yângâködörö', // less reliable 'h' => ':count yângâködörö', // less reliable 'a_hour' => ':count yângâködörö', // less reliable 'second' => ':count bïkua-ôko', // less reliable 's' => ':count bïkua-ôko', // less reliable 'a_second' => ':count bïkua-ôko', // less reliable 'month' => ':count Nze tî ngu', 'm' => ':count Nze tî ngu', 'a_month' => ':count Nze tî ngu', ]); PK������<1ZӾ6������Carbon/Lang/zh_Hans_HK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/zh_Hans.php'; PK������<1ZՊ.������Carbon/Lang/ar.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Atef Ben Ali (atefBB) * - Ibrahim AshShohail * - MLTDev * - Mohamed Sabil (mohamedsabil83) * - Yazan Alnugnugh (yazan-alnugnugh) */ $months = [ 'يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر', ]; return [ 'year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']), 'a_year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']), 'month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']), 'a_month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']), 'week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']), 'a_week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']), 'day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']), 'a_day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']), 'hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']), 'a_hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']), 'minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']), 'a_minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']), 'second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']), 'a_second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']), 'ago' => 'منذ :time', 'from_now' => ':time من الآن', 'after' => 'بعد :time', 'before' => 'قبل :time', 'diff_now' => 'الآن', 'diff_today' => 'اليوم', 'diff_today_regexp' => 'اليوم(?:\\s+عند)?(?:\\s+الساعة)?', 'diff_yesterday' => 'أمس', 'diff_yesterday_regexp' => 'أمس(?:\\s+عند)?(?:\\s+الساعة)?', 'diff_tomorrow' => 'غداً', 'diff_tomorrow_regexp' => 'غدًا(?:\\s+عند)?(?:\\s+الساعة)?', 'diff_before_yesterday' => 'قبل الأمس', 'diff_after_tomorrow' => 'بعد غد', 'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']), 'period_interval' => 'كل :interval', 'period_start_date' => 'من :date', 'period_end_date' => 'إلى :date', 'months' => $months, 'months_short' => $months, 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'], 'weekdays_min' => ['ح', 'اث', 'ثل', 'أر', 'خم', 'ج', 'س'], 'list' => ['، ', ' و '], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[اليوم عند الساعة] LT', 'nextDay' => '[غدًا عند الساعة] LT', 'nextWeek' => 'dddd [عند الساعة] LT', 'lastDay' => '[أمس عند الساعة] LT', 'lastWeek' => 'dddd [عند الساعة] LT', 'sameElse' => 'L', ], 'meridiem' => ['ص', 'م'], 'weekend' => [5, 6], ]; PK������<1Z mN��N����Carbon/Lang/st.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/st_ZA.php'; PK������<1ZƢ: �� ����Carbon/Lang/br.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - Serhan Apaydın * - JD Isaacks */ return [ 'year' => '{1}:count bloaz|{3,4,5,9}:count bloaz|[0,Inf[:count vloaz', 'a_year' => '{1}ur bloaz|{3,4,5,9}:count bloaz|[0,Inf[:count vloaz', 'month' => '{1}:count miz|{2}:count viz|[0,Inf[:count miz', 'a_month' => '{1}ur miz|{2}:count viz|[0,Inf[:count miz', 'week' => ':count sizhun', 'a_week' => '{1}ur sizhun|:count sizhun', 'day' => '{1}:count devezh|{2}:count zevezh|[0,Inf[:count devezh', 'a_day' => '{1}un devezh|{2}:count zevezh|[0,Inf[:count devezh', 'hour' => ':count eur', 'a_hour' => '{1}un eur|:count eur', 'minute' => '{1}:count vunutenn|{2}:count vunutenn|[0,Inf[:count munutenn', 'a_minute' => '{1}ur vunutenn|{2}:count vunutenn|[0,Inf[:count munutenn', 'second' => ':count eilenn', 'a_second' => '{1}un nebeud segondennoù|[0,Inf[:count eilenn', 'ago' => ':time \'zo', 'from_now' => 'a-benn :time', 'diff_now' => 'bremañ', 'diff_today' => 'Hiziv', 'diff_today_regexp' => 'Hiziv(?:\\s+da)?', 'diff_yesterday' => 'decʼh', 'diff_yesterday_regexp' => 'Dec\'h(?:\\s+da)?', 'diff_tomorrow' => 'warcʼhoazh', 'diff_tomorrow_regexp' => 'Warc\'hoazh(?:\\s+da)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D [a viz] MMMM YYYY', 'LLL' => 'D [a viz] MMMM YYYY HH:mm', 'LLLL' => 'dddd, D [a viz] MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[Hiziv da] LT', 'nextDay' => '[Warc\'hoazh da] LT', 'nextWeek' => 'dddd [da] LT', 'lastDay' => '[Dec\'h da] LT', 'lastWeek' => 'dddd [paset da] LT', 'sameElse' => 'L', ], 'ordinal' => function ($number) { return $number.($number === 1 ? 'añ' : 'vet'); }, 'months' => ['Genver', 'C\'hwevrer', 'Meurzh', 'Ebrel', 'Mae', 'Mezheven', 'Gouere', 'Eost', 'Gwengolo', 'Here', 'Du', 'Kerzu'], 'months_short' => ['Gen', 'C\'hwe', 'Meu', 'Ebr', 'Mae', 'Eve', 'Gou', 'Eos', 'Gwe', 'Her', 'Du', 'Ker'], 'weekdays' => ['Sul', 'Lun', 'Meurzh', 'Merc\'her', 'Yaou', 'Gwener', 'Sadorn'], 'weekdays_short' => ['Sul', 'Lun', 'Meu', 'Mer', 'Yao', 'Gwe', 'Sad'], 'weekdays_min' => ['Su', 'Lu', 'Me', 'Mer', 'Ya', 'Gw', 'Sa'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' hag '], 'meridiem' => ['A.M.', 'G.M.'], 'y' => ':count bl.', 'd' => ':count d', 'h' => ':count e', 'min' => ':count min', 's' => ':count s', ]; PK������<1ZpG��G����Carbon/Lang/en_TV.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z y������Carbon/Lang/saq.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['Tesiran', 'Teipa'], 'weekdays' => ['Mderot ee are', 'Mderot ee kuni', 'Mderot ee ong’wan', 'Mderot ee inet', 'Mderot ee ile', 'Mderot ee sapa', 'Mderot ee kwe'], 'weekdays_short' => ['Are', 'Kun', 'Ong', 'Ine', 'Ile', 'Sap', 'Kwe'], 'weekdays_min' => ['Are', 'Kun', 'Ong', 'Ine', 'Ile', 'Sap', 'Kwe'], 'months' => ['Lapa le obo', 'Lapa le waare', 'Lapa le okuni', 'Lapa le ong’wan', 'Lapa le imet', 'Lapa le ile', 'Lapa le sapa', 'Lapa le isiet', 'Lapa le saal', 'Lapa le tomon', 'Lapa le tomon obo', 'Lapa le tomon waare'], 'months_short' => ['Obo', 'Waa', 'Oku', 'Ong', 'Ime', 'Ile', 'Sap', 'Isi', 'Saa', 'Tom', 'Tob', 'Tow'], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], ]); PK������<1Z �� ����Carbon/Lang/nb_NO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/nb.php'; PK������<1ZlN��N����Carbon/Lang/ti.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/ti_ER.php'; PK������<1Z*'. �� ����Carbon/Lang/tg.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Orif N. Jr */ return [ 'year' => '{1}як сол|:count сол', 'month' => '{1}як моҳ|:count моҳ', 'week' => '{1}як ҳафта|:count ҳафта', 'day' => '{1}як рӯз|:count рӯз', 'hour' => '{1}як соат|:count соат', 'minute' => '{1}як дақиқа|:count дақиқа', 'second' => '{1}якчанд сония|:count сония', 'ago' => ':time пеш', 'from_now' => 'баъди :time', 'diff_today' => 'Имрӯз', 'diff_yesterday' => 'Дирӯз', 'diff_yesterday_regexp' => 'Дирӯз(?:\\s+соати)?', 'diff_tomorrow' => 'Пагоҳ', 'diff_tomorrow_regexp' => 'Пагоҳ(?:\\s+соати)?', 'diff_today_regexp' => 'Имрӯз(?:\\s+соати)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[Имрӯз соати] LT', 'nextDay' => '[Пагоҳ соати] LT', 'nextWeek' => 'dddd[и] [ҳафтаи оянда соати] LT', 'lastDay' => '[Дирӯз соати] LT', 'lastWeek' => 'dddd[и] [ҳафтаи гузашта соати] LT', 'sameElse' => 'L', ], 'ordinal' => function ($number) { if ($number === 0) { // special case for zero return "$number-ıncı"; } static $suffixes = [ 0 => '-ум', 1 => '-ум', 2 => '-юм', 3 => '-юм', 4 => '-ум', 5 => '-ум', 6 => '-ум', 7 => '-ум', 8 => '-ум', 9 => '-ум', 10 => '-ум', 12 => '-ум', 13 => '-ум', 20 => '-ум', 30 => '-юм', 40 => '-ум', 50 => '-ум', 60 => '-ум', 70 => '-ум', 80 => '-ум', 90 => '-ум', 100 => '-ум', ]; return $number.($suffixes[$number] ?? $suffixes[$number % 10] ?? $suffixes[$number >= 100 ? 100 : -1] ?? ''); }, 'meridiem' => function ($hour) { if ($hour < 4) { return 'шаб'; } if ($hour < 11) { return 'субҳ'; } if ($hour < 16) { return 'рӯз'; } if ($hour < 19) { return 'бегоҳ'; } return 'шаб'; }, 'months' => ['январ', 'феврал', 'март', 'апрел', 'май', 'июн', 'июл', 'август', 'сентябр', 'октябр', 'ноябр', 'декабр'], 'months_short' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'], 'weekdays' => ['якшанбе', 'душанбе', 'сешанбе', 'чоршанбе', 'панҷшанбе', 'ҷумъа', 'шанбе'], 'weekdays_short' => ['яшб', 'дшб', 'сшб', 'чшб', 'пшб', 'ҷум', 'шнб'], 'weekdays_min' => ['яш', 'дш', 'сш', 'чш', 'пш', 'ҷм', 'шб'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' ва '], ]; PK������<1Z �� ����Carbon/Lang/my_MM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/my.php'; PK������<1Z4͠������Carbon/Lang/es_UY.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/es.php', [ 'months' => ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'], 'months_short' => ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'set', 'oct', 'nov', 'dic'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, ]); PK������<1ZpG��G����Carbon/Lang/en_PW.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZpG��G����Carbon/Lang/en_MG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Zy������Carbon/Lang/fur_IT.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Pablo Saratxaga pablo@mandrakesoft.com */ return [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD. MM. YY', 'LL' => 'DD di MMMM dal YYYY', 'LLL' => 'DD di MMM HH:mm', 'LLLL' => 'DD di MMMM dal YYYY HH:mm', ], 'months' => ['zenâr', 'fevrâr', 'març', 'avrîl', 'mai', 'jugn', 'lui', 'avost', 'setembar', 'otubar', 'novembar', 'dicembar'], 'months_short' => ['zen', 'fev', 'mar', 'avr', 'mai', 'jug', 'lui', 'avo', 'set', 'otu', 'nov', 'dic'], 'weekdays' => ['domenie', 'lunis', 'martars', 'miercus', 'joibe', 'vinars', 'sabide'], 'weekdays_short' => ['dom', 'lun', 'mar', 'mie', 'joi', 'vin', 'sab'], 'weekdays_min' => ['dom', 'lun', 'mar', 'mie', 'joi', 'vin', 'sab'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'year' => ':count an', 'month' => ':count mês', 'week' => ':count setemane', 'day' => ':count zornade', 'hour' => ':count ore', 'minute' => ':count minût', 'second' => ':count secont', ]; PK������<1ZpG��G����Carbon/Lang/en_PN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z!/] ��] ����Carbon/Lang/jv.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - tgfjt * - JD Isaacks */ return [ 'year' => '{1}setaun|]1,Inf[:count taun', 'month' => '{1}sewulan|]1,Inf[:count wulan', 'week' => '{1}sakminggu|]1,Inf[:count minggu', 'day' => '{1}sedinten|]1,Inf[:count dinten', 'hour' => '{1}setunggal jam|]1,Inf[:count jam', 'minute' => '{1}setunggal menit|]1,Inf[:count menit', 'second' => '{1}sawetawis detik|]1,Inf[:count detik', 'ago' => ':time ingkang kepengker', 'from_now' => 'wonten ing :time', 'diff_today' => 'Dinten', 'diff_yesterday' => 'Kala', 'diff_yesterday_regexp' => 'Kala(?:\\s+wingi)?(?:\\s+pukul)?', 'diff_tomorrow' => 'Mbenjang', 'diff_tomorrow_regexp' => 'Mbenjang(?:\\s+pukul)?', 'diff_today_regexp' => 'Dinten(?:\\s+puniko)?(?:\\s+pukul)?', 'formats' => [ 'LT' => 'HH.mm', 'LTS' => 'HH.mm.ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY [pukul] HH.mm', 'LLLL' => 'dddd, D MMMM YYYY [pukul] HH.mm', ], 'calendar' => [ 'sameDay' => '[Dinten puniko pukul] LT', 'nextDay' => '[Mbenjang pukul] LT', 'nextWeek' => 'dddd [pukul] LT', 'lastDay' => '[Kala wingi pukul] LT', 'lastWeek' => 'dddd [kepengker pukul] LT', 'sameElse' => 'L', ], 'meridiem' => function ($hour) { if ($hour < 11) { return 'enjing'; } if ($hour < 15) { return 'siyang'; } if ($hour < 19) { return 'sonten'; } return 'ndalu'; }, 'months' => ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'Nopember', 'Desember'], 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Ags', 'Sep', 'Okt', 'Nop', 'Des'], 'weekdays' => ['Minggu', 'Senen', 'Seloso', 'Rebu', 'Kemis', 'Jemuwah', 'Septu'], 'weekdays_short' => ['Min', 'Sen', 'Sel', 'Reb', 'Kem', 'Jem', 'Sep'], 'weekdays_min' => ['Mg', 'Sn', 'Sl', 'Rb', 'Km', 'Jm', 'Sp'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' lan '], ]; PK������<1ZoO��O����Carbon/Lang/the.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/the_NP.php'; PK������<1Zʷ������Carbon/Lang/zh_Hant_HK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/zh_Hant.php'; PK������<1ZZ ��Z ����Carbon/Lang/sh.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ // @codeCoverageIgnoreStart use Symfony\Component\Translation\PluralizationRules; if (class_exists('Symfony\\Component\\Translation\\PluralizationRules')) { PluralizationRules::set(static function ($number) { return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); }, 'sh'); } // @codeCoverageIgnoreEnd /* * Authors: * - Томица Кораћ * - Enrique Vidal * - Christopher Dell * - dmilisic * - danijel * - Miroslav Matkovic (mikki021) */ return [ 'diff_now' => 'sada', 'diff_yesterday' => 'juče', 'diff_tomorrow' => 'sutra', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'MMMM D, YYYY', 'LLL' => 'DD MMM HH:mm', 'LLLL' => 'MMMM DD, YYYY HH:mm', ], 'year' => ':count godina|:count godine|:count godina', 'y' => ':count g.', 'month' => ':count mesec|:count meseca|:count meseci', 'm' => ':count m.', 'week' => ':count nedelja|:count nedelje|:count nedelja', 'w' => ':count n.', 'day' => ':count dan|:count dana|:count dana', 'd' => ':count d.', 'hour' => ':count sat|:count sata|:count sati', 'h' => ':count č.', 'minute' => ':count minut|:count minuta|:count minuta', 'min' => ':count min.', 'second' => ':count sekund|:count sekunde|:count sekundi', 's' => ':count s.', 'ago' => 'pre :time', 'from_now' => 'za :time', 'after' => 'nakon :time', 'before' => ':time raniјe', 'weekdays' => ['Nedelja', 'Ponedeljak', 'Utorak', 'Sreda', 'Četvrtak', 'Petak', 'Subota'], 'weekdays_short' => ['Ned', 'Pon', 'Uto', 'Sre', 'Čet', 'Pet', 'Sub'], 'weekdays_min' => ['Ned', 'Pon', 'Uto', 'Sre', 'Čet', 'Pet', 'Sub'], 'months' => ['Januar', 'Februar', 'Mart', 'April', 'Maj', 'Jun', 'Jul', 'Avgust', 'Septembar', 'Oktobar', 'Novembar', 'Decembar'], 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Avg', 'Sep', 'Okt', 'Nov', 'Dec'], 'list' => [', ', ' i '], 'meridiem' => ['pre podne', 'po podne'], ]; PK������<1ZU������Carbon/Lang/gez_ET.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ge'ez Frontier Foundation locales@geez.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች', 'ኤፕረል', 'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት', 'ሴፕቴምበር', 'ኦክተውበር', 'ኖቬምበር', 'ዲሴምበር'], 'months_short' => ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕረ', 'ሜይ ', 'ጁን ', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክተ', 'ኖቬም', 'ዲሴም'], 'weekdays' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚት'], 'weekdays_short' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚ'], 'weekdays_min' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚ'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['ጽባሕ', 'ምሴት'], ]); PK������<1Z `������Carbon/Lang/es_MX.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/es.php', [ 'diff_before_yesterday' => 'antier', 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]); PK������<1Zl �� ����Carbon/Lang/cv_RU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/cv.php'; PK������<1ZpG��G����Carbon/Lang/en_KI.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZpG��G����Carbon/Lang/en_SS.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZO��O����Carbon/Lang/fur.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/fur_IT.php'; PK������<1Z}zO��O����Carbon/Lang/om_KE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/om.php', [ 'day_of_first_week_of_year' => 0, ]); PK������<1Z''x �� ����Carbon/Lang/fr_PM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Z{r  �� ����Carbon/Lang/vai.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'weekdays' => ['ꕞꕌꔵ', 'ꗳꗡꘉ', 'ꕚꕞꕚ', 'ꕉꕞꕒ', 'ꕉꔤꕆꕢ', 'ꕉꔤꕀꕮ', 'ꔻꔬꔳ'], 'weekdays_short' => ['ꕞꕌꔵ', 'ꗳꗡꘉ', 'ꕚꕞꕚ', 'ꕉꕞꕒ', 'ꕉꔤꕆꕢ', 'ꕉꔤꕀꕮ', 'ꔻꔬꔳ'], 'weekdays_min' => ['ꕞꕌꔵ', 'ꗳꗡꘉ', 'ꕚꕞꕚ', 'ꕉꕞꕒ', 'ꕉꔤꕆꕢ', 'ꕉꔤꕀꕮ', 'ꔻꔬꔳ'], 'months' => ['ꖨꖕ ꕪꕴ ꔞꔀꕮꕊ', 'ꕒꕡꖝꖕ', 'ꕾꖺ', 'ꖢꖕ', 'ꖑꕱ', 'ꖱꘋ', 'ꖱꕞꔤ', 'ꗛꔕ', 'ꕢꕌ', 'ꕭꖃ', 'ꔞꘋꕔꕿ ꕸꖃꗏ', 'ꖨꖕ ꕪꕴ ꗏꖺꕮꕊ'], 'months_short' => ['ꖨꖕꔞ', 'ꕒꕡ', 'ꕾꖺ', 'ꖢꖕ', 'ꖑꕱ', 'ꖱꘋ', 'ꖱꕞ', 'ꗛꔕ', 'ꕢꕌ', 'ꕭꖃ', 'ꔞꘋ', 'ꖨꖕꗏ'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY h:mm a', 'LLLL' => 'dddd, D MMMM YYYY h:mm a', ], 'year' => ':count ꕀ', // less reliable 'y' => ':count ꕀ', // less reliable 'a_year' => ':count ꕀ', // less reliable 'second' => ':count ꗱꕞꕯꕊ', // less reliable 's' => ':count ꗱꕞꕯꕊ', // less reliable 'a_second' => ':count ꗱꕞꕯꕊ', // less reliable ]); PK������<1ZpG��G����Carbon/Lang/en_VG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZC2X)��)����Carbon/Lang/qu.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/es_UY.php', [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM, YYYY HH:mm', ], 'first_day_of_week' => 0, ]); PK������<1ZZO �� ����Carbon/Lang/vai_Vaii.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/vai.php'; PK������<1Z*������Carbon/Lang/sk.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Philippe Vaucher * - Martin Suja * - Tsutomu Kuroda * - tjku * - Max Melentiev * - Juanito Fatas * - Ivan Stana * - Akira Matsuda * - Christopher Dell * - James McKinney * - Enrique Vidal * - Simone Carletti * - Aaron Patterson * - Jozef Fulop * - Nicolás Hock Isaza * - Tom Hughes * - Simon Hürlimann (CyT) * - jofi * - Jakub ADAMEC * - Marek Adamický * - AlterwebStudio */ use Carbon\CarbonInterface; $fromNow = function ($time) { return 'o '.strtr($time, [ 'hodina' => 'hodinu', 'minúta' => 'minútu', 'sekunda' => 'sekundu', ]); }; $ago = function ($time) { $replacements = [ '/\bhodina\b/' => 'hodinou', '/\bminúta\b/' => 'minútou', '/\bsekunda\b/' => 'sekundou', '/\bdeň\b/u' => 'dňom', '/\btýždeň\b/u' => 'týždňom', '/\bmesiac\b/' => 'mesiacom', '/\brok\b/' => 'rokom', ]; $replacementsPlural = [ '/\bhodiny\b/' => 'hodinami', '/\bminúty\b/' => 'minútami', '/\bsekundy\b/' => 'sekundami', '/\bdni\b/' => 'dňami', '/\btýždne\b/' => 'týždňami', '/\bmesiace\b/' => 'mesiacmi', '/\broky\b/' => 'rokmi', ]; foreach ($replacements + $replacementsPlural as $pattern => $replacement) { $time = preg_replace($pattern, $replacement, $time); } return "pred $time"; }; return [ 'year' => ':count rok|:count roky|:count rokov', 'a_year' => 'rok|:count roky|:count rokov', 'y' => ':count r', 'month' => ':count mesiac|:count mesiace|:count mesiacov', 'a_month' => 'mesiac|:count mesiace|:count mesiacov', 'm' => ':count m', 'week' => ':count týždeň|:count týždne|:count týždňov', 'a_week' => 'týždeň|:count týždne|:count týždňov', 'w' => ':count t', 'day' => ':count deň|:count dni|:count dní', 'a_day' => 'deň|:count dni|:count dní', 'd' => ':count d', 'hour' => ':count hodina|:count hodiny|:count hodín', 'a_hour' => 'hodina|:count hodiny|:count hodín', 'h' => ':count h', 'minute' => ':count minúta|:count minúty|:count minút', 'a_minute' => 'minúta|:count minúty|:count minút', 'min' => ':count min', 'second' => ':count sekunda|:count sekundy|:count sekúnd', 'a_second' => 'sekunda|:count sekundy|:count sekúnd', 's' => ':count s', 'millisecond' => ':count milisekunda|:count milisekundy|:count milisekúnd', 'a_millisecond' => 'milisekunda|:count milisekundy|:count milisekúnd', 'ms' => ':count ms', 'microsecond' => ':count mikrosekunda|:count mikrosekundy|:count mikrosekúnd', 'a_microsecond' => 'mikrosekunda|:count mikrosekundy|:count mikrosekúnd', 'µs' => ':count µs', 'ago' => $ago, 'from_now' => $fromNow, 'before' => ':time pred', 'after' => ':time po', 'hour_after' => ':count hodinu|:count hodiny|:count hodín', 'minute_after' => ':count minútu|:count minúty|:count minút', 'second_after' => ':count sekundu|:count sekundy|:count sekúnd', 'hour_before' => ':count hodinu|:count hodiny|:count hodín', 'minute_before' => ':count minútu|:count minúty|:count minút', 'second_before' => ':count sekundu|:count sekundy|:count sekúnd', 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' a '], 'diff_now' => 'teraz', 'diff_yesterday' => 'včera', 'diff_tomorrow' => 'zajtra', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'DD. MMMM YYYY', 'LLL' => 'D. M. HH:mm', 'LLLL' => 'dddd D. MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[dnes o] LT', 'nextDay' => '[zajtra o] LT', 'lastDay' => '[včera o] LT', 'nextWeek' => 'dddd [o] LT', 'lastWeek' => static function (CarbonInterface $date) { switch ($date->dayOfWeek) { case 1: case 2: case 4: case 5: return '[minulý] dddd [o] LT'; //pondelok/utorok/štvrtok/piatok default: return '[minulá] dddd [o] LT'; } }, 'sameElse' => 'L', ], 'weekdays' => ['nedeľa', 'pondelok', 'utorok', 'streda', 'štvrtok', 'piatok', 'sobota'], 'weekdays_short' => ['ned', 'pon', 'uto', 'str', 'štv', 'pia', 'sob'], 'weekdays_min' => ['ne', 'po', 'ut', 'st', 'št', 'pi', 'so'], 'months' => ['január', 'február', 'marec', 'apríl', 'máj', 'jún', 'júl', 'august', 'september', 'október', 'november', 'december'], 'months_short' => ['jan', 'feb', 'mar', 'apr', 'máj', 'jún', 'júl', 'aug', 'sep', 'okt', 'nov', 'dec'], 'meridiem' => ['dopoludnia', 'popoludní'], ]; PK������<1ZB` O��O����Carbon/Lang/hsb.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/hsb_DE.php'; PK������<1ZT.C��C����Carbon/Lang/vun.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['utuko', 'kyiukonyi'], 'weekdays' => ['Jumapilyi', 'Jumatatuu', 'Jumanne', 'Jumatanu', 'Alhamisi', 'Ijumaa', 'Jumamosi'], 'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'], 'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'], 'months' => ['Januari', 'Februari', 'Machi', 'Aprilyi', 'Mei', 'Junyi', 'Julyai', 'Agusti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'], 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], ]); PK������<1Z/N��N����Carbon/Lang/nr.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/nr_ZA.php'; PK������<1Z������Carbon/Lang/en_NG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, ]); PK������<1Zw �� ����Carbon/Lang/fr_MR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/fr.php', [ 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY h:mm a', 'LLLL' => 'dddd D MMMM YYYY h:mm a', ], ]); PK������<1ZpG��G����Carbon/Lang/en_NL.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZpG��G����Carbon/Lang/en_FJ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z8Qsp��p����Carbon/Lang/om.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ge'ez Frontier Foundation & Sagalee Oromoo Publishing Co. Inc. locales@geez.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'dd-MMM-YYYY', 'LLL' => 'dd MMMM YYYY HH:mm', 'LLLL' => 'dddd, MMMM D, YYYY HH:mm', ], 'months' => ['Amajjii', 'Guraandhala', 'Bitooteessa', 'Elba', 'Caamsa', 'Waxabajjii', 'Adooleessa', 'Hagayya', 'Fuulbana', 'Onkololeessa', 'Sadaasa', 'Muddee'], 'months_short' => ['Ama', 'Gur', 'Bit', 'Elb', 'Cam', 'Wax', 'Ado', 'Hag', 'Ful', 'Onk', 'Sad', 'Mud'], 'weekdays' => ['Dilbata', 'Wiixata', 'Qibxata', 'Roobii', 'Kamiisa', 'Jimaata', 'Sanbata'], 'weekdays_short' => ['Dil', 'Wix', 'Qib', 'Rob', 'Kam', 'Jim', 'San'], 'weekdays_min' => ['Dil', 'Wix', 'Qib', 'Rob', 'Kam', 'Jim', 'San'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['WD', 'WB'], 'year' => 'wggoota :count', 'y' => 'wggoota :count', 'a_year' => 'wggoota :count', 'month' => 'ji’a :count', 'm' => 'ji’a :count', 'a_month' => 'ji’a :count', 'week' => 'torban :count', 'w' => 'torban :count', 'a_week' => 'torban :count', 'day' => 'guyyaa :count', 'd' => 'guyyaa :count', 'a_day' => 'guyyaa :count', 'hour' => 'saʼaatii :count', 'h' => 'saʼaatii :count', 'a_hour' => 'saʼaatii :count', 'minute' => 'daqiiqaa :count', 'min' => 'daqiiqaa :count', 'a_minute' => 'daqiiqaa :count', 'second' => 'sekoondii :count', 's' => 'sekoondii :count', 'a_second' => 'sekoondii :count', ]); PK������<1ZpG��G����Carbon/Lang/en_RW.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z  �� ����Carbon/Lang/sk_SK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/sk.php'; PK������<1ZiV �� ����Carbon/Lang/ku_TR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ku.php'; PK������<1Z6������Carbon/Lang/fr_CA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Dieter Sting * - François B * - Maxime VALY * - JD Isaacks */ return array_replace_recursive(require __DIR__.'/fr.php', [ 'formats' => [ 'L' => 'YYYY-MM-DD', ], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]); PK������<1Z������Carbon/Lang/de_CH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - sheriffmarley * - Timo * - Michael Hohl */ return array_replace_recursive(require __DIR__.'/de.php', [ 'weekdays_short' => ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'], ]); PK������<1Z. �� ����Carbon/Lang/dv_MV.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ahmed Ali */ $months = [ 'ޖެނުއަރީ', 'ފެބްރުއަރީ', 'މާރިޗު', 'އޭޕްރީލު', 'މޭ', 'ޖޫން', 'ޖުލައި', 'އޯގަސްޓު', 'ސެޕްޓެމްބަރު', 'އޮކްޓޯބަރު', 'ނޮވެމްބަރު', 'ޑިސެމްބަރު', ]; $weekdays = [ 'އާދިއްތަ', 'ހޯމަ', 'އަންގާރަ', 'ބުދަ', 'ބުރާސްފަތި', 'ހުކުރު', 'ހޮނިހިރު', ]; return [ 'year' => '{0}އަހަރެއް|[1,Inf]:count އަހަރު', 'y' => '{0}އަހަރެއް|[1,Inf]:count އަހަރު', 'month' => '{0}މައްސަރެއް|[1,Inf]:count މަސް', 'm' => '{0}މައްސަރެއް|[1,Inf]:count މަސް', 'week' => '{0}ހަފްތާއެއް|[1,Inf]:count ހަފްތާ', 'w' => '{0}ހަފްތާއެއް|[1,Inf]:count ހަފްތާ', 'day' => '{0}ދުވަސް|[1,Inf]:count ދުވަސް', 'd' => '{0}ދުވަސް|[1,Inf]:count ދުވަސް', 'hour' => '{0}ގަޑިއިރެއް|[1,Inf]:count ގަޑި', 'h' => '{0}ގަޑިއިރެއް|[1,Inf]:count ގަޑި', 'minute' => '{0}މިނެޓެއް|[1,Inf]:count މިނެޓް', 'min' => '{0}މިނެޓެއް|[1,Inf]:count މިނެޓް', 'second' => '{0}ސިކުންތެއް|[1,Inf]:count ސިކުންތު', 's' => '{0}ސިކުންތެއް|[1,Inf]:count ސިކުންތު', 'ago' => ':time ކުރިން', 'from_now' => ':time ފަހުން', 'after' => ':time ފަހުން', 'before' => ':time ކުރި', 'diff_yesterday' => 'އިއްޔެ', 'diff_today' => 'މިއަދު', 'diff_tomorrow' => 'މާދަމާ', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[މިއަދު] LT', 'nextDay' => '[މާދަމާ] LT', 'nextWeek' => 'dddd LT', 'lastDay' => '[އިއްޔެ] LT', 'lastWeek' => '[ފާއިތުވި] dddd LT', 'sameElse' => 'L', ], 'meridiem' => ['މކ', 'މފ'], 'months' => $months, 'months_short' => $months, 'weekdays' => $weekdays, 'weekdays_short' => $weekdays, 'weekdays_min' => ['އާދި', 'ހޯމަ', 'އަން', 'ބުދަ', 'ބުރާ', 'ހުކު', 'ހޮނި'], 'list' => [', ', ' އަދި '], ]; PK������<1Z>������Carbon/Lang/yuw_PG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Information from native speakers Hannah Sarvasy nungon.localization@gmail.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'months' => ['jenuari', 'febuari', 'mas', 'epril', 'mei', 'jun', 'julai', 'ögus', 'septemba', 'öktoba', 'nöwemba', 'diksemba'], 'months_short' => ['jen', 'feb', 'mas', 'epr', 'mei', 'jun', 'jul', 'ögu', 'sep', 'ökt', 'nöw', 'dis'], 'weekdays' => ['sönda', 'mönda', 'sinda', 'mitiwö', 'sogipbono', 'nenggo', 'söndanggie'], 'weekdays_short' => ['sön', 'mön', 'sin', 'mit', 'soi', 'nen', 'sab'], 'weekdays_min' => ['sön', 'mön', 'sin', 'mit', 'soi', 'nen', 'sab'], 'day_of_first_week_of_year' => 1, ]); PK������<1Z''x �� ����Carbon/Lang/fr_NC.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Z?Ej �� ����Carbon/Lang/en_GU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1Z4N��N����Carbon/Lang/ia.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/ia_FR.php'; PK������<1Z''x �� ����Carbon/Lang/fr_KM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Z''x �� ����Carbon/Lang/fr_RE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1ZȌf��f����Carbon/Lang/nyn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'weekdays' => ['Sande', 'Orwokubanza', 'Orwakabiri', 'Orwakashatu', 'Orwakana', 'Orwakataano', 'Orwamukaaga'], 'weekdays_short' => ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'], 'weekdays_min' => ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'], 'months' => ['Okwokubanza', 'Okwakabiri', 'Okwakashatu', 'Okwakana', 'Okwakataana', 'Okwamukaaga', 'Okwamushanju', 'Okwamunaana', 'Okwamwenda', 'Okwaikumi', 'Okwaikumi na kumwe', 'Okwaikumi na ibiri'], 'months_short' => ['KBZ', 'KBR', 'KST', 'KKN', 'KTN', 'KMK', 'KMS', 'KMN', 'KMW', 'KKM', 'KNK', 'KNB'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], ]); PK������<1ZQiD �� ����Carbon/Lang/fa_AF.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/fa.php', [ 'meridiem' => ['ق', 'ب'], 'weekend' => [4, 5], 'formats' => [ 'L' => 'OY/OM/OD', 'LL' => 'OD MMM OY', 'LLL' => 'OD MMMM OY،‏ H:mm', 'LLLL' => 'dddd OD MMMM OY،‏ H:mm', ], ]); PK������<1ZdO��O����Carbon/Lang/yuw.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/yuw_PG.php'; PK������<1Z~������Carbon/Lang/fr_BE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/fr.php', [ 'months_short' => ['jan', 'fév', 'mar', 'avr', 'mai', 'jun', 'jui', 'aoû', 'sep', 'oct', 'nov', 'déc'], ]); PK������<1Z7T �� ����Carbon/Lang/de_LI.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/de.php'; PK������<1Z}:be �� ����Carbon/Lang/gu_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/gu.php'; PK������<1Zn9��9����Carbon/Lang/es_PH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 0, 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'D/M/yy', 'LL' => 'D MMM YYYY', 'LLL' => 'D [de] MMMM [de] YYYY h:mm a', 'LLLL' => 'dddd, D [de] MMMM [de] YYYY h:mm a', ], ]); PK������<1Z, H������Carbon/Lang/iu_CA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Pablo Saratxaga pablo@mandriva.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'MM/DD/YY', ], 'months' => ['ᔮᓄᐊᓕ', 'ᕕᕗᐊᓕ', 'ᒪᔅᓯ', 'ᐃᐳᓗ', 'ᒪᐃ', 'ᔪᓂ', 'ᔪᓚᐃ', 'ᐊᒋᓯ', 'ᓯᑎᕙ', 'ᐊᑦᑐᕙ', 'ᓄᕕᕙ', 'ᑎᓯᕝᕙ'], 'months_short' => ['ᔮᓄ', 'ᕕᕗ', 'ᒪᔅ', 'ᐃᐳ', 'ᒪᐃ', 'ᔪᓂ', 'ᔪᓚ', 'ᐊᒋ', 'ᓯᑎ', 'ᐊᑦ', 'ᓄᕕ', 'ᑎᓯ'], 'weekdays' => ['ᓈᑦᑎᖑᔭᕐᕕᒃ', 'ᓇᒡᒐᔾᔭᐅ', 'ᓇᒡᒐᔾᔭᐅᓕᖅᑭᑦ', 'ᐱᖓᓲᓕᖅᓯᐅᑦ', 'ᕿᑎᖅᑰᑦ', 'ᐅᓪᓗᕈᓘᑐᐃᓇᖅ', 'ᓯᕙᑖᕕᒃ'], 'weekdays_short' => ['ᓈ', 'ᓇ', 'ᓕ', 'ᐱ', 'ᕿ', 'ᐅ', 'ᓯ'], 'weekdays_min' => ['ᓈ', 'ᓇ', 'ᓕ', 'ᐱ', 'ᕿ', 'ᐅ', 'ᓯ'], 'day_of_first_week_of_year' => 1, 'year' => ':count ᐅᑭᐅᖅ', 'y' => ':count ᐅᑭᐅᖅ', 'a_year' => ':count ᐅᑭᐅᖅ', 'month' => ':count qaammat', 'm' => ':count qaammat', 'a_month' => ':count qaammat', 'week' => ':count sapaatip akunnera', 'w' => ':count sapaatip akunnera', 'a_week' => ':count sapaatip akunnera', 'day' => ':count ulloq', 'd' => ':count ulloq', 'a_day' => ':count ulloq', 'hour' => ':count ikarraq', 'h' => ':count ikarraq', 'a_hour' => ':count ikarraq', 'minute' => ':count titiqqaralaaq', // less reliable 'min' => ':count titiqqaralaaq', // less reliable 'a_minute' => ':count titiqqaralaaq', // less reliable 'second' => ':count marluk', // less reliable 's' => ':count marluk', // less reliable 'a_second' => ':count marluk', // less reliable ]); PK������<1ZpG��G����Carbon/Lang/en_SZ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z4E������Carbon/Lang/en_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YY', 'LL' => 'MMMM DD, YYYY', 'LLL' => 'DD MMM HH:mm', 'LLLL' => 'MMMM DD, YYYY HH:mm', ], 'day_of_first_week_of_year' => 1, ]); PK������<1ZBkO��O����Carbon/Lang/lij.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/lij_IT.php'; PK������<1Z �� ����Carbon/Lang/shi_Tfng.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/shi.php'; PK������<1ZX �� ����Carbon/Lang/mi_NZ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/mi.php'; PK������<1ZN��N����Carbon/Lang/or.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/or_IN.php'; PK������<1Zv������Carbon/Lang/so_DJ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ge'ez Frontier Foundation locales@geez.org */ return array_replace_recursive(require __DIR__.'/so.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], ]); PK������<1ZNn �� ����Carbon/Lang/mo.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ro.php'; PK������<1Z;n �� ����Carbon/Lang/af.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - JD Isaacks * - Pierre du Plessis */ return [ 'year' => ':count jaar', 'a_year' => '\'n jaar|:count jaar', 'y' => ':count j.', 'month' => ':count maand|:count maande', 'a_month' => '\'n maand|:count maande', 'm' => ':count maa.', 'week' => ':count week|:count weke', 'a_week' => '\'n week|:count weke', 'w' => ':count w.', 'day' => ':count dag|:count dae', 'a_day' => '\'n dag|:count dae', 'd' => ':count d.', 'hour' => ':count uur', 'a_hour' => '\'n uur|:count uur', 'h' => ':count u.', 'minute' => ':count minuut|:count minute', 'a_minute' => '\'n minuut|:count minute', 'min' => ':count min.', 'second' => ':count sekond|:count sekondes', 'a_second' => '\'n paar sekondes|:count sekondes', 's' => ':count s.', 'ago' => ':time gelede', 'from_now' => 'oor :time', 'after' => ':time na', 'before' => ':time voor', 'diff_now' => 'Nou', 'diff_today' => 'Vandag', 'diff_today_regexp' => 'Vandag(?:\\s+om)?', 'diff_yesterday' => 'Gister', 'diff_yesterday_regexp' => 'Gister(?:\\s+om)?', 'diff_tomorrow' => 'Môre', 'diff_tomorrow_regexp' => 'Môre(?:\\s+om)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[Vandag om] LT', 'nextDay' => '[Môre om] LT', 'nextWeek' => 'dddd [om] LT', 'lastDay' => '[Gister om] LT', 'lastWeek' => '[Laas] dddd [om] LT', 'sameElse' => 'L', ], 'ordinal' => function ($number) { return $number.(($number === 1 || $number === 8 || $number >= 20) ? 'ste' : 'de'); }, 'meridiem' => ['VM', 'NM'], 'months' => ['Januarie', 'Februarie', 'Maart', 'April', 'Mei', 'Junie', 'Julie', 'Augustus', 'September', 'Oktober', 'November', 'Desember'], 'months_short' => ['Jan', 'Feb', 'Mrt', 'Apr', 'Mei', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Des'], 'weekdays' => ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrydag', 'Saterdag'], 'weekdays_short' => ['Son', 'Maa', 'Din', 'Woe', 'Don', 'Vry', 'Sat'], 'weekdays_min' => ['So', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Sa'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' en '], ]; PK������<1Z������Carbon/Lang/tr.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - Alan Agius * - Erhan Gundogan * - François B * - JD Isaacks * - Murat Yüksel * - Baran Şengül * - Selami (selamialtin) * - TeomanBey */ return [ 'year' => ':count yıl', 'a_year' => '{1}bir yıl|]1,Inf[:count yıl', 'y' => ':county', 'month' => ':count ay', 'a_month' => '{1}bir ay|]1,Inf[:count ay', 'm' => ':countay', 'week' => ':count hafta', 'a_week' => '{1}bir hafta|]1,Inf[:count hafta', 'w' => ':counth', 'day' => ':count gün', 'a_day' => '{1}bir gün|]1,Inf[:count gün', 'd' => ':countg', 'hour' => ':count saat', 'a_hour' => '{1}bir saat|]1,Inf[:count saat', 'h' => ':countsa', 'minute' => ':count dakika', 'a_minute' => '{1}bir dakika|]1,Inf[:count dakika', 'min' => ':countdk', 'second' => ':count saniye', 'a_second' => '{1}birkaç saniye|]1,Inf[:count saniye', 's' => ':countsn', 'ago' => ':time önce', 'from_now' => ':time sonra', 'after' => ':time sonra', 'before' => ':time önce', 'diff_now' => 'şimdi', 'diff_today' => 'bugün', 'diff_today_regexp' => 'bugün(?:\\s+saat)?', 'diff_yesterday' => 'dün', 'diff_tomorrow' => 'yarın', 'diff_tomorrow_regexp' => 'yarın(?:\\s+saat)?', 'diff_before_yesterday' => 'evvelsi gün', 'diff_after_tomorrow' => 'öbür gün', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[bugün saat] LT', 'nextDay' => '[yarın saat] LT', 'nextWeek' => '[gelecek] dddd [saat] LT', 'lastDay' => '[dün] LT', 'lastWeek' => '[geçen] dddd [saat] LT', 'sameElse' => 'L', ], 'ordinal' => function ($number, $period) { switch ($period) { case 'd': case 'D': case 'Do': case 'DD': return $number; default: if ($number === 0) { // special case for zero return "$number'ıncı"; } static $suffixes = [ 1 => '\'inci', 5 => '\'inci', 8 => '\'inci', 70 => '\'inci', 80 => '\'inci', 2 => '\'nci', 7 => '\'nci', 20 => '\'nci', 50 => '\'nci', 3 => '\'üncü', 4 => '\'üncü', 100 => '\'üncü', 6 => '\'ncı', 9 => '\'uncu', 10 => '\'uncu', 30 => '\'uncu', 60 => '\'ıncı', 90 => '\'ıncı', ]; $lastDigit = $number % 10; return $number.($suffixes[$lastDigit] ?? $suffixes[$number % 100 - $lastDigit] ?? $suffixes[$number >= 100 ? 100 : -1] ?? ''); } }, 'meridiem' => ['ÖÖ', 'ÖS', 'öö', 'ös'], 'months' => ['Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık'], 'months_short' => ['Oca', 'Şub', 'Mar', 'Nis', 'May', 'Haz', 'Tem', 'Ağu', 'Eyl', 'Eki', 'Kas', 'Ara'], 'weekdays' => ['Pazar', 'Pazartesi', 'Salı', 'Çarşamba', 'Perşembe', 'Cuma', 'Cumartesi'], 'weekdays_short' => ['Paz', 'Pts', 'Sal', 'Çar', 'Per', 'Cum', 'Cts'], 'weekdays_min' => ['Pz', 'Pt', 'Sa', 'Ça', 'Pe', 'Cu', 'Ct'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' ve '], ]; PK������<1Zw7G��G����Carbon/Lang/es_BR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 0, ]); PK������<1Z J9��9����Carbon/Lang/pap.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return [ 'formats' => [ 'LT' => 'HH.mm', 'LTS' => 'HH.mm:ss', 'L' => 'DD-MM-YY', 'LL' => 'MMMM [di] DD, YYYY', 'LLL' => 'DD MMM HH.mm', 'LLLL' => 'MMMM DD, YYYY HH.mm', ], 'months' => ['yanüari', 'febrüari', 'mart', 'aprel', 'mei', 'yüni', 'yüli', 'ougùstùs', 'sèptèmber', 'oktober', 'novèmber', 'desèmber'], 'months_short' => ['yan', 'feb', 'mar', 'apr', 'mei', 'yün', 'yül', 'oug', 'sèp', 'okt', 'nov', 'des'], 'weekdays' => ['djadomingo', 'djaluna', 'djamars', 'djawebs', 'djarason', 'djabierne', 'djasabra'], 'weekdays_short' => ['do', 'lu', 'ma', 'we', 'ra', 'bi', 'sa'], 'weekdays_min' => ['do', 'lu', 'ma', 'we', 'ra', 'bi', 'sa'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'year' => ':count aña', 'month' => ':count luna', 'week' => ':count siman', 'day' => ':count dia', 'hour' => ':count ora', 'minute' => ':count minüt', 'second' => ':count sekònde', 'list' => [', ', ' i '], ]; PK������<1Z})��)����Carbon/Lang/ca_AD.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ca.php', [ ]); PK������<1Z̄A.������Carbon/Lang/el_CY.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Greek Debian Translation Team bug-glibc@gnu.org */ return array_replace_recursive(require __DIR__.'/el.php', [ 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, ]); PK������<1Zʷ������Carbon/Lang/zh_Hant_MO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/zh_Hant.php'; PK������<1Z} �� ����Carbon/Lang/gl_ES.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/gl.php'; PK������<1ZZб �� ����Carbon/Lang/id_ID.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/id.php'; PK������<1Zw'0y ��y ����Carbon/Lang/mai_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Maithili Computing Research Center, Pune, India rajeshkajha@yahoo.com,akhilesh.k@samusng.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['बैसाख', 'जेठ', 'अषाढ़', 'सावोन', 'भादो', 'आसिन', 'कातिक', 'अगहन', 'पूस', 'माघ', 'फागुन', 'चैति'], 'months_short' => ['बैसाख', 'जेठ', 'अषाढ़', 'सावोन', 'भादो', 'आसिन', 'कातिक', 'अगहन', 'पूस', 'माघ', 'फागुन', 'चैति'], 'weekdays' => ['रविदिन', 'सोमदिन', 'मंगलदिन', 'बुधदिन', 'बृहस्पतीदिन', 'शुक्रदिन', 'शनीदिन'], 'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पती', 'शुक्र', 'शनी'], 'weekdays_min' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पती', 'शुक्र', 'शनी'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['पूर्वाह्न', 'अपराह्न'], 'year' => ':count ऋतु', // less reliable 'y' => ':count ऋतु', // less reliable 'a_year' => ':count ऋतु', // less reliable 'month' => ':count महिना', 'm' => ':count महिना', 'a_month' => ':count महिना', 'week' => ':count श्रेणी:क्यालेन्डर', // less reliable 'w' => ':count श्रेणी:क्यालेन्डर', // less reliable 'a_week' => ':count श्रेणी:क्यालेन्डर', // less reliable 'day' => ':count दिन', 'd' => ':count दिन', 'a_day' => ':count दिन', 'hour' => ':count घण्टा', 'h' => ':count घण्टा', 'a_hour' => ':count घण्टा', 'minute' => ':count समय', // less reliable 'min' => ':count समय', // less reliable 'a_minute' => ':count समय', // less reliable ]); PK������<1Z5No������Carbon/Lang/en_NZ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - Mayank Badola * - Luke McGregor * - JD Isaacks */ return array_replace_recursive(require __DIR__.'/en.php', [ 'from_now' => 'in :time', 'formats' => [ 'LT' => 'h:mm A', 'LTS' => 'h:mm:ss A', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY h:mm A', 'LLLL' => 'dddd, D MMMM YYYY h:mm A', ], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, ]); PK������<1ZP��P����Carbon/Lang/to_TO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - International Components for Unicode akhilesh.k@samsung.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'dddd DD MMM YYYY', ], 'months' => ['Sānuali', 'Fēpueli', 'Maʻasi', 'ʻEpeleli', 'Mē', 'Sune', 'Siulai', 'ʻAokosi', 'Sepitema', 'ʻOkatopa', 'Nōvema', 'Tīsema'], 'months_short' => ['Sān', 'Fēp', 'Maʻa', 'ʻEpe', 'Mē', 'Sun', 'Siu', 'ʻAok', 'Sep', 'ʻOka', 'Nōv', 'Tīs'], 'weekdays' => ['Sāpate', 'Mōnite', 'Tūsite', 'Pulelulu', 'Tuʻapulelulu', 'Falaite', 'Tokonaki'], 'weekdays_short' => ['Sāp', 'Mōn', 'Tūs', 'Pul', 'Tuʻa', 'Fal', 'Tok'], 'weekdays_min' => ['Sāp', 'Mōn', 'Tūs', 'Pul', 'Tuʻa', 'Fal', 'Tok'], 'meridiem' => ['hengihengi', 'efiafi'], 'year' => ':count fitu', // less reliable 'y' => ':count fitu', // less reliable 'a_year' => ':count fitu', // less reliable 'month' => ':count mahina', // less reliable 'm' => ':count mahina', // less reliable 'a_month' => ':count mahina', // less reliable 'week' => ':count Sapate', // less reliable 'w' => ':count Sapate', // less reliable 'a_week' => ':count Sapate', // less reliable 'day' => ':count ʻaho', // less reliable 'd' => ':count ʻaho', // less reliable 'a_day' => ':count ʻaho', // less reliable 'hour' => ':count houa', 'h' => ':count houa', 'a_hour' => ':count houa', 'minute' => ':count miniti', 'min' => ':count miniti', 'a_minute' => ':count miniti', 'second' => ':count sekoni', 's' => ':count sekoni', 'a_second' => ':count sekoni', ]); PK������<1Z[ �� ����Carbon/Lang/nn_NO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/nn.php'; PK������<1Z2=P������Carbon/Lang/nb_SJ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/nb.php', [ 'formats' => [ 'LL' => 'D. MMM YYYY', 'LLL' => 'D. MMMM YYYY, HH:mm', 'LLLL' => 'dddd D. MMMM YYYY, HH:mm', ], ]); PK������<1Z-O��O����Carbon/Lang/mag.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/mag_IN.php'; PK������<1Z + �� ����Carbon/Lang/ast_ES.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ast.php'; PK������<1Zn������Carbon/Lang/ky.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - acutexyz * - Josh Soref * - François B * - Chyngyz Arystan uulu * - Chyngyz * - acutexyz * - Josh Soref * - François B * - Chyngyz Arystan uulu */ return [ 'year' => ':count жыл', 'a_year' => '{1}бир жыл|:count жыл', 'y' => ':count жыл', 'month' => ':count ай', 'a_month' => '{1}бир ай|:count ай', 'm' => ':count ай', 'week' => ':count апта', 'a_week' => '{1}бир апта|:count апта', 'w' => ':count апт.', 'day' => ':count күн', 'a_day' => '{1}бир күн|:count күн', 'd' => ':count күн', 'hour' => ':count саат', 'a_hour' => '{1}бир саат|:count саат', 'h' => ':count саат.', 'minute' => ':count мүнөт', 'a_minute' => '{1}бир мүнөт|:count мүнөт', 'min' => ':count мүн.', 'second' => ':count секунд', 'a_second' => '{1}бирнече секунд|:count секунд', 's' => ':count сек.', 'ago' => ':time мурун', 'from_now' => ':time ичинде', 'diff_now' => 'азыр', 'diff_today' => 'Бүгүн', 'diff_today_regexp' => 'Бүгүн(?:\\s+саат)?', 'diff_yesterday' => 'кечээ', 'diff_yesterday_regexp' => 'Кече(?:\\s+саат)?', 'diff_tomorrow' => 'эртең', 'diff_tomorrow_regexp' => 'Эртең(?:\\s+саат)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[Бүгүн саат] LT', 'nextDay' => '[Эртең саат] LT', 'nextWeek' => 'dddd [саат] LT', 'lastDay' => '[Кече саат] LT', 'lastWeek' => '[Өткен аптанын] dddd [күнү] [саат] LT', 'sameElse' => 'L', ], 'ordinal' => function ($number) { static $suffixes = [ 0 => '-чү', 1 => '-чи', 2 => '-чи', 3 => '-чү', 4 => '-чү', 5 => '-чи', 6 => '-чы', 7 => '-чи', 8 => '-чи', 9 => '-чу', 10 => '-чу', 20 => '-чы', 30 => '-чу', 40 => '-чы', 50 => '-чү', 60 => '-чы', 70 => '-чи', 80 => '-чи', 90 => '-чу', 100 => '-чү', ]; return $number.($suffixes[$number] ?? $suffixes[$number % 10] ?? $suffixes[$number >= 100 ? 100 : -1] ?? ''); }, 'months' => ['январь', 'февраль', 'март', 'апрель', 'май', 'июнь', 'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь'], 'months_short' => ['янв', 'фев', 'март', 'апр', 'май', 'июнь', 'июль', 'авг', 'сен', 'окт', 'ноя', 'дек'], 'weekdays' => ['Жекшемби', 'Дүйшөмбү', 'Шейшемби', 'Шаршемби', 'Бейшемби', 'Жума', 'Ишемби'], 'weekdays_short' => ['Жек', 'Дүй', 'Шей', 'Шар', 'Бей', 'Жум', 'Ише'], 'weekdays_min' => ['Жк', 'Дй', 'Шй', 'Шр', 'Бй', 'Жм', 'Иш'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => ' ', 'meridiem' => ['таңкы', 'түштөн кийинки'], ]; PK������<1ZoP �� ����Carbon/Lang/uz_Latn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - Rasulbek * - Ilyosjon Kamoldinov (ilyosjon09) */ return [ 'year' => ':count yil', 'a_year' => '{1}bir yil|:count yil', 'y' => ':count y', 'month' => ':count oy', 'a_month' => '{1}bir oy|:count oy', 'm' => ':count o', 'week' => ':count hafta', 'a_week' => '{1}bir hafta|:count hafta', 'w' => ':count h', 'day' => ':count kun', 'a_day' => '{1}bir kun|:count kun', 'd' => ':count k', 'hour' => ':count soat', 'a_hour' => '{1}bir soat|:count soat', 'h' => ':count soat', 'minute' => ':count daqiqa', 'a_minute' => '{1}bir daqiqa|:count daqiqa', 'min' => ':count d', 'second' => ':count soniya', 'a_second' => '{1}soniya|:count soniya', 's' => ':count son.', 'ago' => ':time avval', 'from_now' => 'Yaqin :time ichida', 'after' => ':timedan keyin', 'before' => ':time oldin', 'diff_yesterday' => 'Kecha', 'diff_yesterday_regexp' => 'Kecha(?:\\s+soat)?', 'diff_today' => 'Bugun', 'diff_today_regexp' => 'Bugun(?:\\s+soat)?', 'diff_tomorrow' => 'Ertaga', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'D MMMM YYYY, dddd HH:mm', ], 'calendar' => [ 'sameDay' => '[Bugun soat] LT [da]', 'nextDay' => '[Ertaga] LT [da]', 'nextWeek' => 'dddd [kuni soat] LT [da]', 'lastDay' => '[Kecha soat] LT [da]', 'lastWeek' => '[O\'tgan] dddd [kuni soat] LT [da]', 'sameElse' => 'L', ], 'months' => ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'Iyun', 'Iyul', 'Avgust', 'Sentabr', 'Oktabr', 'Noyabr', 'Dekabr'], 'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'Iyun', 'Iyul', 'Avg', 'Sen', 'Okt', 'Noy', 'Dek'], 'weekdays' => ['Yakshanba', 'Dushanba', 'Seshanba', 'Chorshanba', 'Payshanba', 'Juma', 'Shanba'], 'weekdays_short' => ['Yak', 'Dush', 'Sesh', 'Chor', 'Pay', 'Jum', 'Shan'], 'weekdays_min' => ['Ya', 'Du', 'Se', 'Cho', 'Pa', 'Ju', 'Sha'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' va '], 'meridiem' => ['TO', 'TK'], ]; PK������<1ZXlZ��Z����Carbon/Lang/ar_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/ar.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'], 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'], 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'day_of_first_week_of_year' => 1, ]); PK������<1Z# '������Carbon/Lang/sr_Latn_BA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Component\Translation\PluralizationRules; // @codeCoverageIgnoreStart if (class_exists(PluralizationRules::class)) { PluralizationRules::set(static function ($number) { return PluralizationRules::get($number, 'sr'); }, 'sr_Latn_BA'); } // @codeCoverageIgnoreEnd return array_replace_recursive(require __DIR__.'/sr_Latn.php', [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D.M.yy.', 'LL' => 'DD.MM.YYYY.', 'LLL' => 'DD. MMMM YYYY. HH:mm', 'LLLL' => 'dddd, DD. MMMM YYYY. HH:mm', ], 'weekdays' => ['nedjelja', 'ponedeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'], 'weekdays_short' => ['ned.', 'pon.', 'ut.', 'sr.', 'čet.', 'pet.', 'sub.'], ]); PK������<1Z>N������Carbon/Lang/ka.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Tornike Razmadze * - François B * - Lasha Dolidze * - Tim Fish * - JD Isaacks * - Tornike Razmadze * - François B * - Lasha Dolidze * - JD Isaacks * - LONGMAN * - Avtandil Kikabidze (akalongman) * - Levan Velijanashvili (Stichoza) */ use Carbon\CarbonInterface; return [ 'year' => ':count წელი', 'y' => ':count წელი', 'a_year' => '{1}წელი|]1,Inf[:count წელი', 'month' => ':count თვე', 'm' => ':count თვე', 'a_month' => '{1}თვე|]1,Inf[:count თვე', 'week' => ':count კვირა', 'w' => ':count კვირა', 'a_week' => '{1}კვირა|]1,Inf[:count კვირა', 'day' => ':count დღე', 'd' => ':count დღე', 'a_day' => '{1}დღე|]1,Inf[:count დღე', 'hour' => ':count საათი', 'h' => ':count საათი', 'a_hour' => '{1}საათი|]1,Inf[:count საათი', 'minute' => ':count წუთი', 'min' => ':count წუთი', 'a_minute' => '{1}წუთი|]1,Inf[:count წუთი', 'second' => ':count წამი', 's' => ':count წამი', 'a_second' => '{1}რამდენიმე წამი|]1,Inf[:count წამი', 'ago' => function ($time) { $replacements = [ // year 'წელი' => 'წლის', // month 'თვე' => 'თვის', // week 'კვირა' => 'კვირის', // day 'დღე' => 'დღის', // hour 'საათი' => 'საათის', // minute 'წუთი' => 'წუთის', // second 'წამი' => 'წამის', ]; $time = strtr($time, array_flip($replacements)); $time = strtr($time, $replacements); return "$time წინ"; }, 'from_now' => function ($time) { $replacements = [ // year 'წელი' => 'წელიწადში', // week 'კვირა' => 'კვირაში', // day 'დღე' => 'დღეში', // month 'თვე' => 'თვეში', // hour 'საათი' => 'საათში', // minute 'წუთი' => 'წუთში', // second 'წამი' => 'წამში', ]; $time = strtr($time, array_flip($replacements)); $time = strtr($time, $replacements); return $time; }, 'after' => function ($time) { $replacements = [ // year 'წელი' => 'წლის', // month 'თვე' => 'თვის', // week 'კვირა' => 'კვირის', // day 'დღე' => 'დღის', // hour 'საათი' => 'საათის', // minute 'წუთი' => 'წუთის', // second 'წამი' => 'წამის', ]; $time = strtr($time, array_flip($replacements)); $time = strtr($time, $replacements); return "$time შემდეგ"; }, 'before' => function ($time) { $replacements = [ // year 'წელი' => 'წლით', // month 'თვე' => 'თვით', // week 'კვირა' => 'კვირით', // day 'დღე' => 'დღით', // hour 'საათი' => 'საათით', // minute 'წუთი' => 'წუთით', // second 'წამი' => 'წამით', ]; $time = strtr($time, array_flip($replacements)); $time = strtr($time, $replacements); return "$time ადრე"; }, 'diff_now' => 'ახლა', 'diff_today' => 'დღეს', 'diff_yesterday' => 'გუშინ', 'diff_tomorrow' => 'ხვალ', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[დღეს], LT[-ზე]', 'nextDay' => '[ხვალ], LT[-ზე]', 'nextWeek' => function (CarbonInterface $current, CarbonInterface $other) { return ($current->isSameWeek($other) ? '' : '[შემდეგ] ').'dddd, LT[-ზე]'; }, 'lastDay' => '[გუშინ], LT[-ზე]', 'lastWeek' => '[წინა] dddd, LT-ზე', 'sameElse' => 'L', ], 'ordinal' => function ($number) { if ($number === 0) { return $number; } if ($number === 1) { return $number.'-ლი'; } if (($number < 20) || ($number <= 100 && ($number % 20 === 0)) || ($number % 100 === 0)) { return 'მე-'.$number; } return $number.'-ე'; }, 'months' => ['იანვარი', 'თებერვალი', 'მარტი', 'აპრილი', 'მაისი', 'ივნისი', 'ივლისი', 'აგვისტო', 'სექტემბერი', 'ოქტომბერი', 'ნოემბერი', 'დეკემბერი'], 'months_standalone' => ['იანვარს', 'თებერვალს', 'მარტს', 'აპრილს', 'მაისს', 'ივნისს', 'ივლისს', 'აგვისტოს', 'სექტემბერს', 'ოქტომბერს', 'ნოემბერს', 'დეკემბერს'], 'months_short' => ['იან', 'თებ', 'მარ', 'აპრ', 'მაი', 'ივნ', 'ივლ', 'აგვ', 'სექ', 'ოქტ', 'ნოე', 'დეკ'], 'months_regexp' => '/(D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/', 'weekdays' => ['კვირას', 'ორშაბათს', 'სამშაბათს', 'ოთხშაბათს', 'ხუთშაბათს', 'პარასკევს', 'შაბათს'], 'weekdays_standalone' => ['კვირა', 'ორშაბათი', 'სამშაბათი', 'ოთხშაბათი', 'ხუთშაბათი', 'პარასკევი', 'შაბათი'], 'weekdays_short' => ['კვი', 'ორშ', 'სამ', 'ოთხ', 'ხუთ', 'პარ', 'შაბ'], 'weekdays_min' => ['კვ', 'ორ', 'სა', 'ოთ', 'ხუ', 'პა', 'შა'], 'weekdays_regexp' => '/^([^d].*|.*[^d])$/', 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' და '], 'meridiem' => function ($hour) { if ($hour >= 4) { if ($hour < 11) { return 'დილის'; } if ($hour < 16) { return 'შუადღის'; } if ($hour < 22) { return 'საღამოს'; } } return 'ღამის'; }, ]; PK������<1ZpG��G����Carbon/Lang/en_NA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z%l������Carbon/Lang/raj_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - meghrajsuthar03@gmail.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितंबर', 'अक्टूबर', 'नवंबर', 'दिसंबर'], 'months_short' => ['जन', 'फर', 'मार्च', 'अप्रै', 'मई', 'जून', 'जुल', 'अग', 'सित', 'अक्टू', 'नव', 'दिस'], 'weekdays' => ['रविवार', 'सोमवार', 'मंगल्लवार', 'बुधवार', 'बृहस्पतिवार', 'शुक्रवार', 'शनिवार'], 'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पति', 'शुक्र', 'शनि'], 'weekdays_min' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पति', 'शुक्र', 'शनि'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['पूर्वाह्न', 'अपराह्न'], 'year' => ':count आंहू', // less reliable 'y' => ':count आंहू', // less reliable 'a_year' => ':count आंहू', // less reliable 'month' => ':count सूरज', // less reliable 'm' => ':count सूरज', // less reliable 'a_month' => ':count सूरज', // less reliable 'week' => ':count निवाज', // less reliable 'w' => ':count निवाज', // less reliable 'a_week' => ':count निवाज', // less reliable 'day' => ':count अेक', // less reliable 'd' => ':count अेक', // less reliable 'a_day' => ':count अेक', // less reliable 'hour' => ':count दुनियांण', // less reliable 'h' => ':count दुनियांण', // less reliable 'a_hour' => ':count दुनियांण', // less reliable ]); PK������<1Z2o> �� ����Carbon/Lang/ik_CA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - pablo@mandriva.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'months' => ['Siqiññaatchiaq', 'Siqiññaasrugruk', 'Paniqsiqsiivik', 'Qilġich Tatqiat', 'Suppivik', 'Iġñivik', 'Itchavik', 'Tiññivik', 'Amiġaiqsivik', 'Sikkuvik', 'Nippivik', 'Siqiñġiḷaq'], 'months_short' => ['Sñt', 'Sñs', 'Pan', 'Qil', 'Sup', 'Iġñ', 'Itc', 'Tiñ', 'Ami', 'Sik', 'Nip', 'Siq'], 'weekdays' => ['Minġuiqsioiq', 'Savałłiq', 'Ilaqtchiioiq', 'Qitchiioiq', 'Sisamiioiq', 'Tallimmiioiq', 'Maqinġuoiq'], 'weekdays_short' => ['Min', 'Sav', 'Ila', 'Qit', 'Sis', 'Tal', 'Maq'], 'weekdays_min' => ['Min', 'Sav', 'Ila', 'Qit', 'Sis', 'Tal', 'Maq'], 'day_of_first_week_of_year' => 1, 'year' => ':count ukiuq', 'y' => ':count ukiuq', 'a_year' => ':count ukiuq', 'month' => ':count Tatqiat', 'm' => ':count Tatqiat', 'a_month' => ':count Tatqiat', 'week' => ':count tatqiat', // less reliable 'w' => ':count tatqiat', // less reliable 'a_week' => ':count tatqiat', // less reliable 'day' => ':count siqiñiq', // less reliable 'd' => ':count siqiñiq', // less reliable 'a_day' => ':count siqiñiq', // less reliable 'hour' => ':count Siḷa', // less reliable 'h' => ':count Siḷa', // less reliable 'a_hour' => ':count Siḷa', // less reliable 'second' => ':count iġñiq', // less reliable 's' => ':count iġñiq', // less reliable 'a_second' => ':count iġñiq', // less reliable ]); PK������<1ZIJj������Carbon/Lang/uz_UZ@cyrillic.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Mashrab Kuvatov Mashrab Kuvatov, Pablo Saratxaga kmashrab@uni-bremen.de, pablo@mandrakesoft.com */ return array_replace_recursive(require __DIR__.'/uz.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'months' => ['Январ', 'Феврал', 'Март', 'Апрел', 'Май', 'Июн', 'Июл', 'Август', 'Сентябр', 'Октябр', 'Ноябр', 'Декабр'], 'months_short' => ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'], 'weekdays' => ['Якшанба', 'Душанба', 'Сешанба', 'Чоршанба', 'Пайшанба', 'Жума', 'Шанба'], 'weekdays_short' => ['Якш', 'Душ', 'Сеш', 'Чор', 'Пай', 'Жум', 'Шан'], 'weekdays_min' => ['Якш', 'Душ', 'Сеш', 'Чор', 'Пай', 'Жум', 'Шан'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, ]); PK������<1Z[Z��Z����Carbon/Lang/ta_LK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - J.Yogaraj 94-777-315206 yogaraj.ubuntu@gmail.com */ return array_replace_recursive(require __DIR__.'/ta.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'], 'months_short' => ['ஜன', 'பிப்', 'மார்', 'ஏப்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக', 'செப்', 'அக்', 'நவ', 'டிச'], 'weekdays' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'], 'weekdays_short' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'], 'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'meridiem' => ['காலை', 'மாலை'], ]); PK������<1Z?Ej �� ����Carbon/Lang/en_BZ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1Z&5 �� ����Carbon/Lang/nl_CW.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/nl.php'; PK������<1Z1������Carbon/Lang/nds_DE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - information from Kenneth Christiansen Kenneth Christiansen, Pablo Saratxaga kenneth@gnu.org, pablo@mandrakesoft.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], 'months' => ['Jannuaar', 'Feberwaar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'], 'months_short' => ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'], 'weekdays' => ['Sünndag', 'Maandag', 'Dingsdag', 'Middeweek', 'Dunnersdag', 'Freedag', 'Sünnavend'], 'weekdays_short' => ['Sdag', 'Maan', 'Ding', 'Midd', 'Dunn', 'Free', 'Svd.'], 'weekdays_min' => ['Sd', 'Ma', 'Di', 'Mi', 'Du', 'Fr', 'Sa'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'year' => ':count Johr', 'y' => ':countJ', 'a_year' => '{1}een Johr|:count Johr', 'month' => ':count Maand', 'm' => ':countM', 'a_month' => '{1}een Maand|:count Maand', 'week' => ':count Week|:count Weken', 'w' => ':countW', 'a_week' => '{1}een Week|:count Week|:count Weken', 'day' => ':count Dag|:count Daag', 'd' => ':countD', 'a_day' => '{1}een Dag|:count Dag|:count Daag', 'hour' => ':count Stünn|:count Stünnen', 'h' => ':countSt', 'a_hour' => '{1}een Stünn|:count Stünn|:count Stünnen', 'minute' => ':count Minuut|:count Minuten', 'min' => ':countm', 'a_minute' => '{1}een Minuut|:count Minuut|:count Minuten', 'second' => ':count Sekunn|:count Sekunnen', 's' => ':counts', 'a_second' => 'en poor Sekunnen|:count Sekunn|:count Sekunnen', 'ago' => 'vör :time', 'from_now' => 'in :time', 'before' => ':time vörher', 'after' => ':time later', ]); PK������<1Zu\ ��\ ����Carbon/Lang/dz_BT.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Sherubtse College bug-glibc@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'པསྱི་ལོYYཟལMMཚེསDD', ], 'months' => ['ཟླ་བ་དང་པ་', 'ཟླ་བ་གཉིས་པ་', 'ཟླ་བ་གསུམ་པ་', 'ཟླ་བ་བཞི་པ་', 'ཟླ་བ་ལྔ་ཕ་', 'ཟླ་བ་དྲུག་པ་', 'ཟླ་བ་བདུནཔ་', 'ཟླ་བ་བརྒྱད་པ་', 'ཟླ་བ་དགུ་པ་', 'ཟླ་བ་བཅུ་པ་', 'ཟླ་བ་བཅུ་གཅིག་པ་', 'ཟླ་བ་བཅུ་གཉིས་པ་'], 'months_short' => ['ཟླ་༡', 'ཟླ་༢', 'ཟླ་༣', 'ཟླ་༤', 'ཟླ་༥', 'ཟླ་༦', 'ཟླ་༧', 'ཟླ་༨', 'ཟླ་༩', 'ཟླ་༡༠', 'ཟླ་༡༡', 'ཟླ་༡༢'], 'weekdays' => ['གཟའ་ཟླ་བ་', 'གཟའ་མིག་དམར་', 'གཟའ་ལྷག་ཕ་', 'གཟའ་པུར་བུ་', 'གཟའ་པ་སངས་', 'གཟའ་སྤེན་ཕ་', 'གཟའ་ཉི་མ་'], 'weekdays_short' => ['ཟླ་', 'མིར་', 'ལྷག་', 'པུར་', 'སངས་', 'སྤེན་', 'ཉི་'], 'weekdays_min' => ['ཟླ་', 'མིར་', 'ལྷག་', 'པུར་', 'སངས་', 'སྤེན་', 'ཉི་'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['ངས་ཆ', 'ཕྱི་ཆ'], 'year' => ':count ཆརཔ', // less reliable 'y' => ':count ཆརཔ', // less reliable 'a_year' => ':count ཆརཔ', // less reliable 'month' => ':count ཟླ་བ', // less reliable 'm' => ':count ཟླ་བ', // less reliable 'a_month' => ':count ཟླ་བ', // less reliable 'day' => ':count ཉི', // less reliable 'd' => ':count ཉི', // less reliable 'a_day' => ':count ཉི', // less reliable 'second' => ':count ཆ', // less reliable 's' => ':count ཆ', // less reliable 'a_second' => ':count ཆ', // less reliable ]); PK������<1ZV������Carbon/Lang/lzh_TW.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'OY[年]MMMMOD[日]', ], 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], 'months_short' => [' 一 ', ' 二 ', ' 三 ', ' 四 ', ' 五 ', ' 六 ', ' 七 ', ' 八 ', ' 九 ', ' 十 ', '十一', '十二'], 'weekdays' => ['週日', '週一', '週二', '週三', '週四', '週五', '週六'], 'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'], 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'], 'day_of_first_week_of_year' => 1, 'alt_numbers' => ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '廿', '廿一', '廿二', '廿三', '廿四', '廿五', '廿六', '廿七', '廿八', '廿九', '卅', '卅一'], 'meridiem' => ['朝', '暮'], 'year' => ':count 夏', // less reliable 'y' => ':count 夏', // less reliable 'a_year' => ':count 夏', // less reliable 'month' => ':count 月', // less reliable 'm' => ':count 月', // less reliable 'a_month' => ':count 月', // less reliable 'hour' => ':count 氧', // less reliable 'h' => ':count 氧', // less reliable 'a_hour' => ':count 氧', // less reliable 'minute' => ':count 點', // less reliable 'min' => ':count 點', // less reliable 'a_minute' => ':count 點', // less reliable 'second' => ':count 楚', // less reliable 's' => ':count 楚', // less reliable 'a_second' => ':count 楚', // less reliable 'week' => ':count 星期', 'w' => ':count 星期', 'a_week' => ':count 星期', 'day' => ':count 日(曆法)', 'd' => ':count 日(曆法)', 'a_day' => ':count 日(曆法)', ]); PK������<1ZC=5 �� ����Carbon/Lang/ru_BY.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ru.php'; PK������<1Z �� ����Carbon/Lang/hy.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - mhamlet */ return [ 'year' => ':count տարի', 'a_year' => 'տարի|:count տարի', 'y' => ':countտ', 'month' => ':count ամիս', 'a_month' => 'ամիս|:count ամիս', 'm' => ':countամ', 'week' => ':count շաբաթ', 'a_week' => 'շաբաթ|:count շաբաթ', 'w' => ':countշ', 'day' => ':count օր', 'a_day' => 'օր|:count օր', 'd' => ':countօր', 'hour' => ':count ժամ', 'a_hour' => 'ժամ|:count ժամ', 'h' => ':countժ', 'minute' => ':count րոպե', 'a_minute' => 'րոպե|:count րոպե', 'min' => ':countր', 'second' => ':count վայրկյան', 'a_second' => 'մի քանի վայրկյան|:count վայրկյան', 's' => ':countվրկ', 'ago' => ':time առաջ', 'from_now' => ':timeից', 'after' => ':time հետո', 'before' => ':time առաջ', 'diff_now' => 'հիմա', 'diff_today' => 'այսօր', 'diff_yesterday' => 'երեկ', 'diff_tomorrow' => 'վաղը', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D MMMM YYYY թ.', 'LLL' => 'D MMMM YYYY թ., HH:mm', 'LLLL' => 'dddd, D MMMM YYYY թ., HH:mm', ], 'calendar' => [ 'sameDay' => '[այսօր] LT', 'nextDay' => '[վաղը] LT', 'nextWeek' => 'dddd [օրը ժամը] LT', 'lastDay' => '[երեկ] LT', 'lastWeek' => '[անցած] dddd [օրը ժամը] LT', 'sameElse' => 'L', ], 'ordinal' => function ($number, $period) { switch ($period) { case 'DDD': case 'w': case 'W': case 'DDDo': return $number.($number === 1 ? '-ին' : '-րդ'); default: return $number; } }, 'meridiem' => function ($hour) { if ($hour < 4) { return 'գիշերվա'; } if ($hour < 12) { return 'առավոտվա'; } if ($hour < 17) { return 'ցերեկվա'; } return 'երեկոյան'; }, 'months' => ['հունվարի', 'փետրվարի', 'մարտի', 'ապրիլի', 'մայիսի', 'հունիսի', 'հուլիսի', 'օգոստոսի', 'սեպտեմբերի', 'հոկտեմբերի', 'նոյեմբերի', 'դեկտեմբերի'], 'months_standalone' => ['հունվար', 'փետրվար', 'մարտ', 'ապրիլ', 'մայիս', 'հունիս', 'հուլիս', 'օգոստոս', 'սեպտեմբեր', 'հոկտեմբեր', 'նոյեմբեր', 'դեկտեմբեր'], 'months_short' => ['հնվ', 'փտր', 'մրտ', 'ապր', 'մյս', 'հնս', 'հլս', 'օգս', 'սպտ', 'հկտ', 'նմբ', 'դկտ'], 'months_regexp' => '/(D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/', 'weekdays' => ['կիրակի', 'երկուշաբթի', 'երեքշաբթի', 'չորեքշաբթի', 'հինգշաբթի', 'ուրբաթ', 'շաբաթ'], 'weekdays_short' => ['կրկ', 'երկ', 'երք', 'չրք', 'հնգ', 'ուրբ', 'շբթ'], 'weekdays_min' => ['կրկ', 'երկ', 'երք', 'չրք', 'հնգ', 'ուրբ', 'շբթ'], 'list' => [', ', ' եւ '], 'first_day_of_week' => 1, ]; PK������<1ZB������Carbon/Lang/anp_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - bhashaghar@googlegroups.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितंबर', 'अक्टूबर', 'नवंबर', 'दिसंबर"'], 'months_short' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितंबर', 'अक्टूबर', 'नवंबर', 'दिसंबर'], 'weekdays' => ['रविवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'बृहस्पतिवार', 'शुक्रवार', 'शनिवार'], 'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पति', 'शुक्र', 'शनि'], 'weekdays_min' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पति', 'शुक्र', 'शनि'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['पूर्वाह्न', 'अपराह्न'], ]); PK������<1Z$c��c����Carbon/Lang/es.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Kunal Marwaha * - kostas * - François B * - Tim Fish * - Claire Coloma * - Steven Heinrich * - JD Isaacks * - Raphael Amorim * - Jorge Y. Castillo * - Víctor Díaz * - Diego * - Sebastian Thierer * - quinterocesar * - Daniel Commesse Liévanos (danielcommesse) * - Pete Scopes (pdscopes) * - gam04 */ use Carbon\CarbonInterface; return [ 'year' => ':count año|:count años', 'a_year' => 'un año|:count años', 'y' => ':count año|:count años', 'month' => ':count mes|:count meses', 'a_month' => 'un mes|:count meses', 'm' => ':count mes|:count meses', 'week' => ':count semana|:count semanas', 'a_week' => 'una semana|:count semanas', 'w' => ':countsem', 'day' => ':count día|:count días', 'a_day' => 'un día|:count días', 'd' => ':countd', 'hour' => ':count hora|:count horas', 'a_hour' => 'una hora|:count horas', 'h' => ':counth', 'minute' => ':count minuto|:count minutos', 'a_minute' => 'un minuto|:count minutos', 'min' => ':countm', 'second' => ':count segundo|:count segundos', 'a_second' => 'unos segundos|:count segundos', 's' => ':counts', 'millisecond' => ':count milisegundo|:count milisegundos', 'a_millisecond' => 'un milisegundo|:count milisegundos', 'ms' => ':countms', 'microsecond' => ':count microsegundo|:count microsegundos', 'a_microsecond' => 'un microsegundo|:count microsegundos', 'µs' => ':countµs', 'ago' => 'hace :time', 'from_now' => 'en :time', 'after' => ':time después', 'before' => ':time antes', 'diff_now' => 'ahora mismo', 'diff_today' => 'hoy', 'diff_today_regexp' => 'hoy(?:\\s+a)?(?:\\s+las)?', 'diff_yesterday' => 'ayer', 'diff_yesterday_regexp' => 'ayer(?:\\s+a)?(?:\\s+las)?', 'diff_tomorrow' => 'mañana', 'diff_tomorrow_regexp' => 'mañana(?:\\s+a)?(?:\\s+las)?', 'diff_before_yesterday' => 'anteayer', 'diff_after_tomorrow' => 'pasado mañana', 'formats' => [ 'LT' => 'H:mm', 'LTS' => 'H:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D [de] MMMM [de] YYYY', 'LLL' => 'D [de] MMMM [de] YYYY H:mm', 'LLLL' => 'dddd, D [de] MMMM [de] YYYY H:mm', ], 'calendar' => [ 'sameDay' => function (CarbonInterface $current) { return '[hoy a la'.($current->hour !== 1 ? 's' : '').'] LT'; }, 'nextDay' => function (CarbonInterface $current) { return '[mañana a la'.($current->hour !== 1 ? 's' : '').'] LT'; }, 'nextWeek' => function (CarbonInterface $current) { return 'dddd [a la'.($current->hour !== 1 ? 's' : '').'] LT'; }, 'lastDay' => function (CarbonInterface $current) { return '[ayer a la'.($current->hour !== 1 ? 's' : '').'] LT'; }, 'lastWeek' => function (CarbonInterface $current) { return '[el] dddd [pasado a la'.($current->hour !== 1 ? 's' : '').'] LT'; }, 'sameElse' => 'L', ], 'months' => ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'], 'months_short' => ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic'], 'mmm_suffix' => '.', 'ordinal' => ':numberº', 'weekdays' => ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado'], 'weekdays_short' => ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'], 'weekdays_min' => ['do', 'lu', 'ma', 'mi', 'ju', 'vi', 'sá'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' y '], 'meridiem' => ['a. m.', 'p. m.'], 'ordinal_words' => [ 'of' => 'de', 'first' => 'primer', 'second' => 'segundo', 'third' => 'tercer', 'fourth' => 'cuarto', 'fifth' => 'quinto', 'last' => 'último', ], ]; PK������<1ZpG��G����Carbon/Lang/en_MY.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z''x �� ����Carbon/Lang/fr_FR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1ZBVC ��C ����Carbon/Lang/gl.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - Fidel Pita * - JD Isaacks * - Diego Vilariño * - Sebastian Thierer */ use Carbon\CarbonInterface; return [ 'year' => ':count ano|:count anos', 'a_year' => 'un ano|:count anos', 'y' => ':count a.', 'month' => ':count mes|:count meses', 'a_month' => 'un mes|:count meses', 'm' => ':count mes.', 'week' => ':count semana|:count semanas', 'a_week' => 'unha semana|:count semanas', 'w' => ':count sem.', 'day' => ':count día|:count días', 'a_day' => 'un día|:count días', 'd' => ':count d.', 'hour' => ':count hora|:count horas', 'a_hour' => 'unha hora|:count horas', 'h' => ':count h.', 'minute' => ':count minuto|:count minutos', 'a_minute' => 'un minuto|:count minutos', 'min' => ':count min.', 'second' => ':count segundo|:count segundos', 'a_second' => 'uns segundos|:count segundos', 's' => ':count seg.', 'ago' => 'hai :time', 'from_now' => function ($time) { if (str_starts_with($time, 'un')) { return "n$time"; } return "en $time"; }, 'diff_now' => 'agora', 'diff_today' => 'hoxe', 'diff_today_regexp' => 'hoxe(?:\\s+ás)?', 'diff_yesterday' => 'onte', 'diff_yesterday_regexp' => 'onte(?:\\s+á)?', 'diff_tomorrow' => 'mañá', 'diff_tomorrow_regexp' => 'mañá(?:\\s+ás)?', 'after' => ':time despois', 'before' => ':time antes', 'formats' => [ 'LT' => 'H:mm', 'LTS' => 'H:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D [de] MMMM [de] YYYY', 'LLL' => 'D [de] MMMM [de] YYYY H:mm', 'LLLL' => 'dddd, D [de] MMMM [de] YYYY H:mm', ], 'calendar' => [ 'sameDay' => function (CarbonInterface $current) { return '[hoxe '.($current->hour !== 1 ? 'ás' : 'á').'] LT'; }, 'nextDay' => function (CarbonInterface $current) { return '[mañá '.($current->hour !== 1 ? 'ás' : 'á').'] LT'; }, 'nextWeek' => function (CarbonInterface $current) { return 'dddd ['.($current->hour !== 1 ? 'ás' : 'á').'] LT'; }, 'lastDay' => function (CarbonInterface $current) { return '[onte '.($current->hour !== 1 ? 'á' : 'a').'] LT'; }, 'lastWeek' => function (CarbonInterface $current) { return '[o] dddd [pasado '.($current->hour !== 1 ? 'ás' : 'á').'] LT'; }, 'sameElse' => 'L', ], 'ordinal' => ':numberº', 'months' => ['xaneiro', 'febreiro', 'marzo', 'abril', 'maio', 'xuño', 'xullo', 'agosto', 'setembro', 'outubro', 'novembro', 'decembro'], 'months_short' => ['xan.', 'feb.', 'mar.', 'abr.', 'mai.', 'xuñ.', 'xul.', 'ago.', 'set.', 'out.', 'nov.', 'dec.'], 'weekdays' => ['domingo', 'luns', 'martes', 'mércores', 'xoves', 'venres', 'sábado'], 'weekdays_short' => ['dom.', 'lun.', 'mar.', 'mér.', 'xov.', 'ven.', 'sáb.'], 'weekdays_min' => ['do', 'lu', 'ma', 'mé', 'xo', 've', 'sá'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' e '], 'meridiem' => ['a.m.', 'p.m.'], ]; PK������<1Z''x �� ����Carbon/Lang/fr_MQ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Z<hI ��I ����Carbon/Lang/ur.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ $months = [ 'جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر', ]; $weekdays = [ 'اتوار', 'پیر', 'منگل', 'بدھ', 'جمعرات', 'جمعہ', 'ہفتہ', ]; /* * Authors: * - Sawood Alam * - Mehshan * - Philippe Vaucher * - Tsutomu Kuroda * - tjku * - Zaid Akram * - Max Melentiev * - hafezdivandari * - Hossein Jabbari * - nimamo */ return [ 'year' => 'ایک سال|:count سال', 'month' => 'ایک ماہ|:count ماہ', 'week' => ':count ہفتے', 'day' => 'ایک دن|:count دن', 'hour' => 'ایک گھنٹہ|:count گھنٹے', 'minute' => 'ایک منٹ|:count منٹ', 'second' => 'چند سیکنڈ|:count سیکنڈ', 'ago' => ':time قبل', 'from_now' => ':time بعد', 'after' => ':time بعد', 'before' => ':time پہلے', 'diff_now' => 'اب', 'diff_today' => 'آج', 'diff_today_regexp' => 'آج(?:\\s+بوقت)?', 'diff_yesterday' => 'گزشتہ کل', 'diff_yesterday_regexp' => 'گذشتہ(?:\\s+روز)?(?:\\s+بوقت)?', 'diff_tomorrow' => 'آئندہ کل', 'diff_tomorrow_regexp' => 'کل(?:\\s+بوقت)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd، D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[آج بوقت] LT', 'nextDay' => '[کل بوقت] LT', 'nextWeek' => 'dddd [بوقت] LT', 'lastDay' => '[گذشتہ روز بوقت] LT', 'lastWeek' => '[گذشتہ] dddd [بوقت] LT', 'sameElse' => 'L', ], 'meridiem' => ['صبح', 'شام'], 'months' => $months, 'months_short' => $months, 'weekdays' => $weekdays, 'weekdays_short' => $weekdays, 'weekdays_min' => $weekdays, 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => ['، ', ' اور '], ]; PK������<1Ze�N��N����Carbon/Lang/ve.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/ve_ZA.php'; PK������<1ZCL �� ����Carbon/Lang/lo_LA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/lo.php'; PK������<1Z,q��q����Carbon/Lang/dua.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['idiɓa', 'ebyámu'], 'weekdays' => ['éti', 'mɔ́sú', 'kwasú', 'mukɔ́sú', 'ŋgisú', 'ɗónɛsú', 'esaɓasú'], 'weekdays_short' => ['ét', 'mɔ́s', 'kwa', 'muk', 'ŋgi', 'ɗón', 'esa'], 'weekdays_min' => ['ét', 'mɔ́s', 'kwa', 'muk', 'ŋgi', 'ɗón', 'esa'], 'months' => ['dimɔ́di', 'ŋgɔndɛ', 'sɔŋɛ', 'diɓáɓá', 'emiasele', 'esɔpɛsɔpɛ', 'madiɓɛ́díɓɛ́', 'diŋgindi', 'nyɛtɛki', 'mayésɛ́', 'tiníní', 'eláŋgɛ́'], 'months_short' => ['di', 'ŋgɔn', 'sɔŋ', 'diɓ', 'emi', 'esɔ', 'mad', 'diŋ', 'nyɛt', 'may', 'tin', 'elá'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'year' => ':count ma mbu', // less reliable 'y' => ':count ma mbu', // less reliable 'a_year' => ':count ma mbu', // less reliable 'month' => ':count myo̱di', // less reliable 'm' => ':count myo̱di', // less reliable 'a_month' => ':count myo̱di', // less reliable 'week' => ':count woki', // less reliable 'w' => ':count woki', // less reliable 'a_week' => ':count woki', // less reliable 'day' => ':count buńa', // less reliable 'd' => ':count buńa', // less reliable 'a_day' => ':count buńa', // less reliable 'hour' => ':count ma awa', // less reliable 'h' => ':count ma awa', // less reliable 'a_hour' => ':count ma awa', // less reliable 'minute' => ':count minuti', // less reliable 'min' => ':count minuti', // less reliable 'a_minute' => ':count minuti', // less reliable 'second' => ':count maba', // less reliable 's' => ':count maba', // less reliable 'a_second' => ':count maba', // less reliable ]); PK������<1ZpG��G����Carbon/Lang/en_MS.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZEWc��c����Carbon/Lang/sbp.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['Lwamilawu', 'Pashamihe'], 'weekdays' => ['Mulungu', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alahamisi', 'Ijumaa', 'Jumamosi'], 'weekdays_short' => ['Mul', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'], 'weekdays_min' => ['Mul', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'], 'months' => ['Mupalangulwa', 'Mwitope', 'Mushende', 'Munyi', 'Mushende Magali', 'Mujimbi', 'Mushipepo', 'Mupuguto', 'Munyense', 'Mokhu', 'Musongandembwe', 'Muhaano'], 'months_short' => ['Mup', 'Mwi', 'Msh', 'Mun', 'Mag', 'Muj', 'Msp', 'Mpg', 'Mye', 'Mok', 'Mus', 'Muh'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], ]); PK������<1ZDh������Carbon/Lang/en_HK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'day_of_first_week_of_year' => 1, ]); PK������<1Z''x �� ����Carbon/Lang/fr_PF.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1ZpG��G����Carbon/Lang/en_BI.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z������Carbon/Lang/eu.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - François B * - JD Isaacks */ return [ 'year' => 'urte bat|:count urte', 'y' => 'Urte 1|:count urte', 'month' => 'hilabete bat|:count hilabete', 'm' => 'Hile 1|:count hile', 'week' => 'Aste 1|:count aste', 'w' => 'Aste 1|:count aste', 'day' => 'egun bat|:count egun', 'd' => 'Egun 1|:count egun', 'hour' => 'ordu bat|:count ordu', 'h' => 'Ordu 1|:count ordu', 'minute' => 'minutu bat|:count minutu', 'min' => 'Minutu 1|:count minutu', 'second' => 'segundo batzuk|:count segundo', 's' => 'Segundu 1|:count segundu', 'ago' => 'duela :time', 'from_now' => ':time barru', 'after' => ':time geroago', 'before' => ':time lehenago', 'diff_now' => 'orain', 'diff_today' => 'gaur', 'diff_yesterday' => 'atzo', 'diff_tomorrow' => 'bihar', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY-MM-DD', 'LL' => 'YYYY[ko] MMMM[ren] D[a]', 'LLL' => 'YYYY[ko] MMMM[ren] D[a] HH:mm', 'LLLL' => 'dddd, YYYY[ko] MMMM[ren] D[a] HH:mm', ], 'calendar' => [ 'sameDay' => '[gaur] LT[etan]', 'nextDay' => '[bihar] LT[etan]', 'nextWeek' => 'dddd LT[etan]', 'lastDay' => '[atzo] LT[etan]', 'lastWeek' => '[aurreko] dddd LT[etan]', 'sameElse' => 'L', ], 'ordinal' => ':number.', 'months' => ['urtarrila', 'otsaila', 'martxoa', 'apirila', 'maiatza', 'ekaina', 'uztaila', 'abuztua', 'iraila', 'urria', 'azaroa', 'abendua'], 'months_short' => ['urt.', 'ots.', 'mar.', 'api.', 'mai.', 'eka.', 'uzt.', 'abu.', 'ira.', 'urr.', 'aza.', 'abe.'], 'weekdays' => ['igandea', 'astelehena', 'asteartea', 'asteazkena', 'osteguna', 'ostirala', 'larunbata'], 'weekdays_short' => ['ig.', 'al.', 'ar.', 'az.', 'og.', 'ol.', 'lr.'], 'weekdays_min' => ['ig', 'al', 'ar', 'az', 'og', 'ol', 'lr'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' eta '], 'meridiem' => ['g', 'a'], ]; PK������<1Z �� ����Carbon/Lang/fa_IR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fa.php'; PK������<1Z<N��N����Carbon/Lang/ht.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/ht_HT.php'; PK������<1Z''x �� ����Carbon/Lang/fr_CD.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Z N��N����Carbon/Lang/tk.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/tk_TM.php'; PK������<1Z[)6��6����Carbon/Lang/kde.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['Muhi', 'Chilo'], 'weekdays' => ['Liduva lyapili', 'Liduva lyatatu', 'Liduva lyanchechi', 'Liduva lyannyano', 'Liduva lyannyano na linji', 'Liduva lyannyano na mavili', 'Liduva litandi'], 'weekdays_short' => ['Ll2', 'Ll3', 'Ll4', 'Ll5', 'Ll6', 'Ll7', 'Ll1'], 'weekdays_min' => ['Ll2', 'Ll3', 'Ll4', 'Ll5', 'Ll6', 'Ll7', 'Ll1'], 'months' => ['Mwedi Ntandi', 'Mwedi wa Pili', 'Mwedi wa Tatu', 'Mwedi wa Nchechi', 'Mwedi wa Nnyano', 'Mwedi wa Nnyano na Umo', 'Mwedi wa Nnyano na Mivili', 'Mwedi wa Nnyano na Mitatu', 'Mwedi wa Nnyano na Nchechi', 'Mwedi wa Nnyano na Nnyano', 'Mwedi wa Nnyano na Nnyano na U', 'Mwedi wa Nnyano na Nnyano na M'], 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], ]); PK������<1Z� # ��# ����Carbon/Lang/et.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Philippe Vaucher * - Andres Ivanov * - Tsutomu Kuroda * - tjku * - Max Melentiev * - Juanito Fatas * - RM87 * - Akira Matsuda * - Christopher Dell * - Enrique Vidal * - Simone Carletti * - Aaron Patterson * - Esko Lehtme * - Mart Karu * - Nicolás Hock Isaza * - Kevin Valdek * - Zahhar Kirillov * - João Magalhães * - Ingmar * - Illimar Tambek * - Mihkel */ return [ 'year' => ':count aasta|:count aastat', 'y' => ':count a', 'month' => ':count kuu|:count kuud', 'm' => ':count k', 'week' => ':count nädal|:count nädalat', 'w' => ':count näd', 'day' => ':count päev|:count päeva', 'd' => ':count p', 'hour' => ':count tund|:count tundi', 'h' => ':count t', 'minute' => ':count minut|:count minutit', 'min' => ':count min', 'second' => ':count sekund|:count sekundit', 's' => ':count s', 'ago' => ':time tagasi', 'from_now' => ':time pärast', 'after' => ':time pärast', 'before' => ':time enne', 'year_from_now' => ':count aasta', 'month_from_now' => ':count kuu', 'week_from_now' => ':count nädala', 'day_from_now' => ':count päeva', 'hour_from_now' => ':count tunni', 'minute_from_now' => ':count minuti', 'second_from_now' => ':count sekundi', 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'diff_now' => 'nüüd', 'diff_today' => 'täna', 'diff_yesterday' => 'eile', 'diff_tomorrow' => 'homme', 'diff_before_yesterday' => 'üleeile', 'diff_after_tomorrow' => 'ülehomme', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D. MMMM YYYY', 'LLL' => 'D. MMMM YYYY HH:mm', 'LLLL' => 'dddd, D. MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[täna] LT', 'nextDay' => '[homme] LT', 'lastDay' => '[eile] LT', 'nextWeek' => 'dddd LT', 'lastWeek' => '[eelmine] dddd LT', 'sameElse' => 'L', ], 'months' => ['jaanuar', 'veebruar', 'märts', 'aprill', 'mai', 'juuni', 'juuli', 'august', 'september', 'oktoober', 'november', 'detsember'], 'months_short' => ['jaan', 'veebr', 'märts', 'apr', 'mai', 'juuni', 'juuli', 'aug', 'sept', 'okt', 'nov', 'dets'], 'weekdays' => ['pühapäev', 'esmaspäev', 'teisipäev', 'kolmapäev', 'neljapäev', 'reede', 'laupäev'], 'weekdays_short' => ['P', 'E', 'T', 'K', 'N', 'R', 'L'], 'weekdays_min' => ['P', 'E', 'T', 'K', 'N', 'R', 'L'], 'list' => [', ', ' ja '], 'meridiem' => ['enne lõunat', 'pärast lõunat'], ]; PK������<1ZZ,vc������Carbon/Lang/nr_ZA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['Janabari', 'uFeberbari', 'uMatjhi', 'u-Apreli', 'Meyi', 'Juni', 'Julayi', 'Arhostosi', 'Septemba', 'Oktoba', 'Usinyikhaba', 'Disemba'], 'months_short' => ['Jan', 'Feb', 'Mat', 'Apr', 'Mey', 'Jun', 'Jul', 'Arh', 'Sep', 'Okt', 'Usi', 'Dis'], 'weekdays' => ['uSonto', 'uMvulo', 'uLesibili', 'lesithathu', 'uLesine', 'ngoLesihlanu', 'umGqibelo'], 'weekdays_short' => ['Son', 'Mvu', 'Bil', 'Tha', 'Ne', 'Hla', 'Gqi'], 'weekdays_min' => ['Son', 'Mvu', 'Bil', 'Tha', 'Ne', 'Hla', 'Gqi'], 'day_of_first_week_of_year' => 1, ]); PK������<1Zpg �� ����Carbon/Lang/kk_KZ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/kk.php'; PK������<1Zi9 �� ����Carbon/Lang/da_DK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/da.php'; PK������<1Z 8(��(����Carbon/Lang/ms_SG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ms.php', [ 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'D/MM/yy', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY, h:mm a', 'LLLL' => 'dddd, D MMMM YYYY, h:mm a', ], 'meridiem' => ['a', 'p'], ]); PK������<1Z>������Carbon/Lang/sr_Cyrl_XK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Component\Translation\PluralizationRules; // @codeCoverageIgnoreStart if (class_exists(PluralizationRules::class)) { PluralizationRules::set(static function ($number) { return PluralizationRules::get($number, 'sr'); }, 'sr_Cyrl_XK'); } // @codeCoverageIgnoreEnd return array_replace_recursive(require __DIR__.'/sr_Cyrl_BA.php', [ 'weekdays' => ['недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота'], ]); PK������<1Z==������Carbon/Lang/cs.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Philippe Vaucher * - Jakub Tesinsky * - Martin Suja * - Nikos Timiopulos * - Bohuslav Blín * - Tsutomu Kuroda * - tjku * - Lukas Svoboda * - Max Melentiev * - Juanito Fatas * - Akira Matsuda * - Christopher Dell * - Václav Pávek * - CodeSkills * - Tlapi * - newman101 * - Petr Kadlec * - tommaskraus * - Karel Sommer (calvera) */ $za = function ($time) { return 'za '.strtr($time, [ 'hodina' => 'hodinu', 'minuta' => 'minutu', 'sekunda' => 'sekundu', ]); }; $pred = function ($time) { $time = strtr($time, [ 'hodina' => 'hodinou', 'minuta' => 'minutou', 'sekunda' => 'sekundou', ]); $time = preg_replace('/hodiny?(?!\w)/', 'hodinami', $time); $time = preg_replace('/minuty?(?!\w)/', 'minutami', $time); $time = preg_replace('/sekundy?(?!\w)/', 'sekundami', $time); return "před $time"; }; return [ 'year' => ':count rok|:count roky|:count let', 'y' => ':count rok|:count roky|:count let', 'a_year' => 'rok|:count roky|:count let', 'month' => ':count měsíc|:count měsíce|:count měsíců', 'm' => ':count měs.', 'a_month' => 'měsíc|:count měsíce|:count měsíců', 'week' => ':count týden|:count týdny|:count týdnů', 'w' => ':count týd.', 'a_week' => 'týden|:count týdny|:count týdnů', 'day' => ':count den|:count dny|:count dní', 'd' => ':count den|:count dny|:count dní', 'a_day' => 'den|:count dny|:count dní', 'hour' => ':count hodina|:count hodiny|:count hodin', 'h' => ':count hod.', 'a_hour' => 'hodina|:count hodiny|:count hodin', 'minute' => ':count minuta|:count minuty|:count minut', 'min' => ':count min.', 'a_minute' => 'minuta|:count minuty|:count minut', 'second' => ':count sekunda|:count sekundy|:count sekund', 's' => ':count sek.', 'a_second' => 'pár sekund|:count sekundy|:count sekund', 'month_ago' => ':count měsícem|:count měsíci|:count měsíci', 'a_month_ago' => 'měsícem|:count měsíci|:count měsíci', 'day_ago' => ':count dnem|:count dny|:count dny', 'a_day_ago' => 'dnem|:count dny|:count dny', 'week_ago' => ':count týdnem|:count týdny|:count týdny', 'a_week_ago' => 'týdnem|:count týdny|:count týdny', 'year_ago' => ':count rokem|:count roky|:count lety', 'y_ago' => ':count rok.|:count rok.|:count let.', 'a_year_ago' => 'rokem|:count roky|:count lety', 'month_before' => ':count měsícem|:count měsíci|:count měsíci', 'a_month_before' => 'měsícem|:count měsíci|:count měsíci', 'day_before' => ':count dnem|:count dny|:count dny', 'a_day_before' => 'dnem|:count dny|:count dny', 'week_before' => ':count týdnem|:count týdny|:count týdny', 'a_week_before' => 'týdnem|:count týdny|:count týdny', 'year_before' => ':count rokem|:count roky|:count lety', 'y_before' => ':count rok.|:count rok.|:count let.', 'a_year_before' => 'rokem|:count roky|:count lety', 'ago' => $pred, 'from_now' => $za, 'before' => $pred, 'after' => $za, 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'months' => ['ledna', 'února', 'března', 'dubna', 'května', 'června', 'července', 'srpna', 'září', 'října', 'listopadu', 'prosince'], 'months_standalone' => ['leden', 'únor', 'březen', 'duben', 'květen', 'červen', 'červenec', 'srpen', 'září', 'říjen', 'listopad', 'prosinec'], 'months_short' => ['led', 'úno', 'bře', 'dub', 'kvě', 'čvn', 'čvc', 'srp', 'zář', 'říj', 'lis', 'pro'], 'weekdays' => ['neděle', 'pondělí', 'úterý', 'středa', 'čtvrtek', 'pátek', 'sobota'], 'weekdays_short' => ['ned', 'pon', 'úte', 'stř', 'čtv', 'pát', 'sob'], 'weekdays_min' => ['ne', 'po', 'út', 'st', 'čt', 'pá', 'so'], 'list' => [', ', ' a '], 'diff_now' => 'nyní', 'diff_yesterday' => 'včera', 'diff_tomorrow' => 'zítra', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD. MM. YYYY', 'LL' => 'D. MMMM YYYY', 'LLL' => 'D. MMMM YYYY HH:mm', 'LLLL' => 'dddd D. MMMM YYYY HH:mm', ], 'meridiem' => ['dopoledne', 'odpoledne'], ]; PK������<1ZpG��G����Carbon/Lang/en_IM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Zo�������Carbon/Lang/nl.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Roy * - Stephan * - François B * - Tim Fish * - Kevin Huang * - Jacob Middag * - JD Isaacks * - Roy * - Stephan * - François B * - Tim Fish * - Jacob Middag * - JD Isaacks * - Propaganistas * - MegaXLR * - adriaanzon * - MonkeyPhysics * - JeroenG * - RikSomers * - proclame * - Rik de Groot (hwdegroot) */ return [ 'year' => ':count jaar|:count jaar', 'a_year' => 'een jaar|:count jaar', 'y' => ':countj', 'month' => ':count maand|:count maanden', 'a_month' => 'een maand|:count maanden', 'm' => ':countmnd', 'week' => ':count week|:count weken', 'a_week' => 'een week|:count weken', 'w' => ':countw', 'day' => ':count dag|:count dagen', 'a_day' => 'een dag|:count dagen', 'd' => ':countd', 'hour' => ':count uur|:count uur', 'a_hour' => 'een uur|:count uur', 'h' => ':countu', 'minute' => ':count minuut|:count minuten', 'a_minute' => 'een minuut|:count minuten', 'min' => ':countmin', 'second' => ':count seconde|:count seconden', 'a_second' => 'een paar seconden|:count seconden', 's' => ':counts', 'ago' => ':time geleden', 'from_now' => 'over :time', 'after' => ':time later', 'before' => ':time eerder', 'diff_now' => 'nu', 'diff_today' => 'vandaag', 'diff_today_regexp' => 'vandaag(?:\\s+om)?', 'diff_yesterday' => 'gisteren', 'diff_yesterday_regexp' => 'gisteren(?:\\s+om)?', 'diff_tomorrow' => 'morgen', 'diff_tomorrow_regexp' => 'morgen(?:\\s+om)?', 'diff_after_tomorrow' => 'overmorgen', 'diff_before_yesterday' => 'eergisteren', 'period_recurrences' => ':count keer', 'period_interval' => function (string $interval = '') { /** @var string $output */ $output = preg_replace('/^(een|één|1)\s+/u', '', $interval); if (preg_match('/^(een|één|1)( jaar|j| uur|u)/u', $interval)) { return "elk $output"; } return "elke $output"; }, 'period_start_date' => 'van :date', 'period_end_date' => 'tot :date', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD-MM-YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[vandaag om] LT', 'nextDay' => '[morgen om] LT', 'nextWeek' => 'dddd [om] LT', 'lastDay' => '[gisteren om] LT', 'lastWeek' => '[afgelopen] dddd [om] LT', 'sameElse' => 'L', ], 'ordinal' => function ($number) { return $number.(($number === 1 || $number === 8 || $number >= 20) ? 'ste' : 'de'); }, 'months' => ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december'], 'months_short' => ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'], 'mmm_suffix' => '.', 'weekdays' => ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'], 'weekdays_short' => ['zo.', 'ma.', 'di.', 'wo.', 'do.', 'vr.', 'za.'], 'weekdays_min' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' en '], 'meridiem' => ['\'s ochtends', '\'s middags'], ]; PK������<1Zná������Carbon/Lang/sd_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Red Hat, Pune bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/sd.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['جنوري', 'فبروري', 'مارچ', 'اپريل', 'مي', 'جون', 'جولاءِ', 'آگسٽ', 'سيپٽيمبر', 'آڪٽوبر', 'نومبر', 'ڊسمبر'], 'months_short' => ['جنوري', 'فبروري', 'مارچ', 'اپريل', 'مي', 'جون', 'جولاءِ', 'آگسٽ', 'سيپٽيمبر', 'آڪٽوبر', 'نومبر', 'ڊسمبر'], 'weekdays' => ['آرتوارُ', 'سومرُ', 'منگلُ', 'ٻُڌرُ', 'وسپت', 'جُمو', 'ڇنڇر'], 'weekdays_short' => ['آرتوارُ', 'سومرُ', 'منگلُ', 'ٻُڌرُ', 'وسپت', 'جُمو', 'ڇنڇر'], 'weekdays_min' => ['آرتوارُ', 'سومرُ', 'منگلُ', 'ٻُڌرُ', 'وسپت', 'جُمو', 'ڇنڇر'], 'day_of_first_week_of_year' => 1, ]); PK������<1Z?Ej �� ����Carbon/Lang/en_PK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1ZfK,������Carbon/Lang/hr.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - François B * - Tim Fish * - shaishavgandhi05 * - Serhan Apaydın * - JD Isaacks * - tomhorvat * - Josh Soref * - François B * - shaishavgandhi05 * - Serhan Apaydın * - JD Isaacks * - tomhorvat * - Stjepan Majdak * - Vanja Retkovac (vr00) */ use Carbon\CarbonInterface; return [ 'year' => ':count godinu|:count godine|:count godina', 'y' => ':count god.|:count god.|:count god.', 'month' => ':count mjesec|:count mjeseca|:count mjeseci', 'm' => ':count mj.|:count mj.|:count mj.', 'week' => ':count tjedan|:count tjedna|:count tjedana', 'w' => ':count tj.|:count tj.|:count tj.', 'day' => ':count dan|:count dana|:count dana', 'd' => ':count d.|:count d.|:count d.', 'hour' => ':count sat|:count sata|:count sati', 'h' => ':count sat|:count sata|:count sati', 'minute' => ':count minutu|:count minute|:count minuta', 'min' => ':count min.|:count min.|:count min.', 'second' => ':count sekundu|:count sekunde|:count sekundi', 'a_second' => 'nekoliko sekundi|:count sekunde|:count sekundi', 's' => ':count sek.|:count sek.|:count sek.', 'ago' => 'prije :time', 'from_now' => 'za :time', 'after' => ':time poslije', 'before' => ':time prije', 'diff_now' => 'sad', 'diff_today' => 'danas', 'diff_today_regexp' => 'danas(?:\\s+u)?', 'diff_yesterday' => 'jučer', 'diff_yesterday_regexp' => 'jučer(?:\\s+u)?', 'diff_tomorrow' => 'sutra', 'diff_tomorrow_regexp' => 'sutra(?:\\s+u)?', 'diff_before_yesterday' => 'prekjučer', 'diff_after_tomorrow' => 'prekosutra', 'formats' => [ 'LT' => 'H:mm', 'LTS' => 'H:mm:ss', 'L' => 'D. M. YYYY.', 'LL' => 'D. MMMM YYYY.', 'LLL' => 'D. MMMM YYYY. H:mm', 'LLLL' => 'dddd, D. MMMM YYYY. H:mm', ], 'calendar' => [ 'sameDay' => '[danas u] LT', 'nextDay' => '[sutra u] LT', 'nextWeek' => function (CarbonInterface $date) { switch ($date->dayOfWeek) { case 0: return '[u] [nedjelju] [u] LT'; case 3: return '[u] [srijedu] [u] LT'; case 6: return '[u] [subotu] [u] LT'; default: return '[u] dddd [u] LT'; } }, 'lastDay' => '[jučer u] LT', 'lastWeek' => function (CarbonInterface $date) { switch ($date->dayOfWeek) { case 0: case 3: return '[prošlu] dddd [u] LT'; case 6: return '[prošle] [subote] [u] LT'; default: return '[prošli] dddd [u] LT'; } }, 'sameElse' => 'L', ], 'ordinal' => ':number.', 'months' => ['siječnja', 'veljače', 'ožujka', 'travnja', 'svibnja', 'lipnja', 'srpnja', 'kolovoza', 'rujna', 'listopada', 'studenoga', 'prosinca'], 'months_standalone' => ['siječanj', 'veljača', 'ožujak', 'travanj', 'svibanj', 'lipanj', 'srpanj', 'kolovoz', 'rujan', 'listopad', 'studeni', 'prosinac'], 'months_short' => ['sij.', 'velj.', 'ožu.', 'tra.', 'svi.', 'lip.', 'srp.', 'kol.', 'ruj.', 'lis.', 'stu.', 'pro.'], 'months_regexp' => '/(D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/', 'weekdays' => ['nedjelju', 'ponedjeljak', 'utorak', 'srijedu', 'četvrtak', 'petak', 'subotu'], 'weekdays_standalone' => ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'], 'weekdays_short' => ['ned.', 'pon.', 'uto.', 'sri.', 'čet.', 'pet.', 'sub.'], 'weekdays_min' => ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' i '], ]; PK������<1Z`) �� ����Carbon/Lang/km.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Kruy Vanna * - Sereysethy Touch * - JD Isaacks * - Sovichet Tep */ return [ 'year' => '{1}មួយឆ្នាំ|]1,Inf[:count ឆ្នាំ', 'y' => ':count ឆ្នាំ', 'month' => '{1}មួយខែ|]1,Inf[:count ខែ', 'm' => ':count ខែ', 'week' => ':count សប្ដាហ៍', 'w' => ':count សប្ដាហ៍', 'day' => '{1}មួយថ្ងៃ|]1,Inf[:count ថ្ងៃ', 'd' => ':count ថ្ងៃ', 'hour' => '{1}មួយម៉ោង|]1,Inf[:count ម៉ោង', 'h' => ':count ម៉ោង', 'minute' => '{1}មួយនាទី|]1,Inf[:count នាទី', 'min' => ':count នាទី', 'second' => '{1}ប៉ុន្មានវិនាទី|]1,Inf[:count វិនាទី', 's' => ':count វិនាទី', 'ago' => ':timeមុន', 'from_now' => ':timeទៀត', 'after' => 'នៅ​ក្រោយ :time', 'before' => 'នៅ​មុន :time', 'diff_now' => 'ឥឡូវ', 'diff_today' => 'ថ្ងៃនេះ', 'diff_today_regexp' => 'ថ្ងៃនេះ(?:\\s+ម៉ោង)?', 'diff_yesterday' => 'ម្សិលមិញ', 'diff_yesterday_regexp' => 'ម្សិលមិញ(?:\\s+ម៉ោង)?', 'diff_tomorrow' => 'ថ្ងៃ​ស្អែក', 'diff_tomorrow_regexp' => 'ស្អែក(?:\\s+ម៉ោង)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[ថ្ងៃនេះ ម៉ោង] LT', 'nextDay' => '[ស្អែក ម៉ោង] LT', 'nextWeek' => 'dddd [ម៉ោង] LT', 'lastDay' => '[ម្សិលមិញ ម៉ោង] LT', 'lastWeek' => 'dddd [សប្តាហ៍មុន] [ម៉ោង] LT', 'sameElse' => 'L', ], 'ordinal' => 'ទី:number', 'meridiem' => ['ព្រឹក', 'ល្ងាច'], 'months' => ['មករា', 'កុម្ភៈ', 'មីនា', 'មេសា', 'ឧសភា', 'មិថុនា', 'កក្កដា', 'សីហា', 'កញ្ញា', 'តុលា', 'វិច្ឆិកា', 'ធ្នូ'], 'months_short' => ['មករា', 'កុម្ភៈ', 'មីនា', 'មេសា', 'ឧសភា', 'មិថុនា', 'កក្កដា', 'សីហា', 'កញ្ញា', 'តុលា', 'វិច្ឆិកា', 'ធ្នូ'], 'weekdays' => ['អាទិត្យ', 'ច័ន្ទ', 'អង្គារ', 'ពុធ', 'ព្រហស្បតិ៍', 'សុក្រ', 'សៅរ៍'], 'weekdays_short' => ['អា', 'ច', 'អ', 'ព', 'ព្រ', 'សុ', 'ស'], 'weekdays_min' => ['អា', 'ច', 'អ', 'ព', 'ព្រ', 'សុ', 'ស'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', 'និង '], ]; PK������<1Z''x �� ����Carbon/Lang/fr_RW.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1ZKV--N��N����Carbon/Lang/kw.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/kw_GB.php'; PK������<1Z}"������Carbon/Lang/st_ZA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['Pherekgong', 'Hlakola', 'Tlhakubele', 'Mmese', 'Motsheanong', 'Phupjane', 'Phupu', 'Phato', 'Leotse', 'Mphalane', 'Pudungwana', 'Tshitwe'], 'months_short' => ['Phe', 'Hla', 'TlH', 'Mme', 'Mot', 'Jan', 'Upu', 'Pha', 'Leo', 'Mph', 'Pud', 'Tsh'], 'weekdays' => ['Sontaha', 'Mantaha', 'Labobedi', 'Laboraro', 'Labone', 'Labohlano', 'Moqebelo'], 'weekdays_short' => ['Son', 'Mma', 'Bed', 'Rar', 'Ne', 'Hla', 'Moq'], 'weekdays_min' => ['Son', 'Mma', 'Bed', 'Rar', 'Ne', 'Hla', 'Moq'], 'day_of_first_week_of_year' => 1, 'week' => ':count Sontaha', // less reliable 'w' => ':count Sontaha', // less reliable 'a_week' => ':count Sontaha', // less reliable 'day' => ':count letsatsi', // less reliable 'd' => ':count letsatsi', // less reliable 'a_day' => ':count letsatsi', // less reliable 'hour' => ':count sešupanako', // less reliable 'h' => ':count sešupanako', // less reliable 'a_hour' => ':count sešupanako', // less reliable 'minute' => ':count menyane', // less reliable 'min' => ':count menyane', // less reliable 'a_minute' => ':count menyane', // less reliable 'second' => ':count thusa', // less reliable 's' => ':count thusa', // less reliable 'a_second' => ':count thusa', // less reliable 'year' => ':count selemo', 'y' => ':count selemo', 'a_year' => ':count selemo', 'month' => ':count kgwedi', 'm' => ':count kgwedi', 'a_month' => ':count kgwedi', ]); PK������<1Zw}��������Carbon/Lang/yue_HK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/zh_HK.php', [ 'formats' => [ 'L' => 'YYYY年MM月DD日 dddd', ], 'months' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], 'months_short' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], 'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'], 'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'], 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, 'meridiem' => ['上午', '下午'], ]); PK������<1ZaؠO��O����Carbon/Lang/tig.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/tig_ER.php'; PK������<1Zh��h����Carbon/Lang/bn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - Shakib Hossain * - Raju * - Aniruddha Adhikary * - JD Isaacks * - Saiful Islam * - Faisal Islam */ return [ 'year' => ':count বছর', 'a_year' => 'এক বছর|:count বছর', 'y' => '১ বছর|:count বছর', 'month' => ':count মাস', 'a_month' => 'এক মাস|:count মাস', 'm' => '১ মাস|:count মাস', 'week' => ':count সপ্তাহ', 'a_week' => '১ সপ্তাহ|:count সপ্তাহ', 'w' => '১ সপ্তাহ|:count সপ্তাহ', 'day' => ':count দিন', 'a_day' => 'এক দিন|:count দিন', 'd' => '১ দিন|:count দিন', 'hour' => ':count ঘন্টা', 'a_hour' => 'এক ঘন্টা|:count ঘন্টা', 'h' => '১ ঘন্টা|:count ঘন্টা', 'minute' => ':count মিনিট', 'a_minute' => 'এক মিনিট|:count মিনিট', 'min' => '১ মিনিট|:count মিনিট', 'second' => ':count সেকেন্ড', 'a_second' => 'কয়েক সেকেন্ড|:count সেকেন্ড', 's' => '১ সেকেন্ড|:count সেকেন্ড', 'ago' => ':time আগে', 'from_now' => ':time পরে', 'after' => ':time পরে', 'before' => ':time আগে', 'diff_now' => 'এখন', 'diff_today' => 'আজ', 'diff_yesterday' => 'গতকাল', 'diff_tomorrow' => 'আগামীকাল', 'period_recurrences' => ':count বার|:count বার', 'period_interval' => 'প্রতি :interval', 'period_start_date' => ':date থেকে', 'period_end_date' => ':date পর্যন্ত', 'formats' => [ 'LT' => 'A Oh:Om সময়', 'LTS' => 'A Oh:Om:Os সময়', 'L' => 'OD/OM/OY', 'LL' => 'OD MMMM OY', 'LLL' => 'OD MMMM OY, A Oh:Om সময়', 'LLLL' => 'dddd, OD MMMM OY, A Oh:Om সময়', ], 'calendar' => [ 'sameDay' => '[আজ] LT', 'nextDay' => '[আগামীকাল] LT', 'nextWeek' => 'dddd, LT', 'lastDay' => '[গতকাল] LT', 'lastWeek' => '[গত] dddd, LT', 'sameElse' => 'L', ], 'meridiem' => function ($hour) { if ($hour < 4) { return 'রাত'; } if ($hour < 10) { return 'সকাল'; } if ($hour < 17) { return 'দুপুর'; } if ($hour < 20) { return 'বিকাল'; } return 'রাত'; }, 'months' => ['জানুয়ারী', 'ফেব্রুয়ারি', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'], 'months_short' => ['জানু', 'ফেব', 'মার্চ', 'এপ্র', 'মে', 'জুন', 'জুল', 'আগ', 'সেপ্ট', 'অক্টো', 'নভে', 'ডিসে'], 'weekdays' => ['রবিবার', 'সোমবার', 'মঙ্গলবার', 'বুধবার', 'বৃহস্পতিবার', 'শুক্রবার', 'শনিবার'], 'weekdays_short' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহস্পতি', 'শুক্র', 'শনি'], 'weekdays_min' => ['রবি', 'সোম', 'মঙ্গ', 'বুধ', 'বৃহঃ', 'শুক্র', 'শনি'], 'list' => [', ', ' এবং '], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, 'weekdays_standalone' => ['রবিবার', 'সোমবার', 'মঙ্গলবার', 'বুধবার', 'বৃহষ্পতিবার', 'শুক্রবার', 'শনিবার'], 'weekdays_min_standalone' => ['রঃ', 'সোঃ', 'মঃ', 'বুঃ', 'বৃঃ', 'শুঃ', 'শনি'], 'months_short_standalone' => ['জানুয়ারী', 'ফেব্রুয়ারী', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'], 'alt_numbers' => ['০', '১', '২', '৩', '৪', '৫', '৬', '৭', '৮', '৯'], ]; PK������<1Z6k��k����Carbon/Lang/pap_AW.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - information from native speaker Pablo Saratxaga pablo@mandrakesoft.com */ return require __DIR__.'/pap.php'; PK������<1ZR �� ����Carbon/Lang/bo_CN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/bo.php'; PK������<1Z������Carbon/Lang/ayc_PE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - runasimipi.org libc-alpha@sourceware.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'months' => ['inïru', 'phiwriru', 'marsu', 'awrila', 'mayu', 'junyu', 'julyu', 'awustu', 'sitimri', 'uktuwri', 'nuwimri', 'risimri'], 'months_short' => ['ini', 'phi', 'mar', 'awr', 'may', 'jun', 'jul', 'awu', 'sit', 'ukt', 'nuw', 'ris'], 'weekdays' => ['tuminku', 'lunisa', 'martisa', 'mirkulisa', 'juywisa', 'wirnisa', 'sawäru'], 'weekdays_short' => ['tum', 'lun', 'mar', 'mir', 'juy', 'wir', 'saw'], 'weekdays_min' => ['tum', 'lun', 'mar', 'mir', 'juy', 'wir', 'saw'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['VM', 'NM'], ]); PK������<1ZpG��G����Carbon/Lang/en_DE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z=8������Carbon/Lang/ar_DZ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /** * Authors: * - Josh Soref * - Noureddine LOUAHEDJ * - JD Isaacks * - Atef Ben Ali (atefBB) * - Mohamed Sabil (mohamedsabil83) */ $months = [ 'جانفي', 'فيفري', 'مارس', 'أفريل', 'ماي', 'جوان', 'جويلية', 'أوت', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر', ]; return [ 'year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']), 'a_year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']), 'month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']), 'a_month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']), 'week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']), 'a_week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']), 'day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']), 'a_day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']), 'hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']), 'a_hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']), 'minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']), 'a_minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']), 'second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']), 'a_second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']), 'ago' => 'منذ :time', 'from_now' => 'في :time', 'after' => 'بعد :time', 'before' => 'قبل :time', 'diff_now' => 'الآن', 'diff_today' => 'اليوم', 'diff_today_regexp' => 'اليوم(?:\\s+على)?(?:\\s+الساعة)?', 'diff_yesterday' => 'أمس', 'diff_yesterday_regexp' => 'أمس(?:\\s+على)?(?:\\s+الساعة)?', 'diff_tomorrow' => 'غداً', 'diff_tomorrow_regexp' => 'غدا(?:\\s+على)?(?:\\s+الساعة)?', 'diff_before_yesterday' => 'قبل الأمس', 'diff_after_tomorrow' => 'بعد غد', 'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']), 'period_interval' => 'كل :interval', 'period_start_date' => 'من :date', 'period_end_date' => 'إلى :date', 'months' => $months, 'months_short' => $months, 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'], 'weekdays_min' => ['أح', 'إث', 'ثلا', 'أر', 'خم', 'جم', 'سب'], 'list' => ['، ', ' و '], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 4, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[اليوم على الساعة] LT', 'nextDay' => '[غدا على الساعة] LT', 'nextWeek' => 'dddd [على الساعة] LT', 'lastDay' => '[أمس على الساعة] LT', 'lastWeek' => 'dddd [على الساعة] LT', 'sameElse' => 'L', ], 'meridiem' => ['ص', 'م'], ]; PK������<1Zhu������Carbon/Lang/kea.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['a', 'p'], 'weekdays' => ['dumingu', 'sigunda-fera', 'tersa-fera', 'kuarta-fera', 'kinta-fera', 'sesta-fera', 'sabadu'], 'weekdays_short' => ['dum', 'sig', 'ter', 'kua', 'kin', 'ses', 'sab'], 'weekdays_min' => ['du', 'si', 'te', 'ku', 'ki', 'se', 'sa'], 'weekdays_standalone' => ['dumingu', 'sigunda-fera', 'tersa-fera', 'kuarta-fera', 'kinta-fera', 'sesta-fera', 'sábadu'], 'months' => ['Janeru', 'Febreru', 'Marsu', 'Abril', 'Maiu', 'Junhu', 'Julhu', 'Agostu', 'Setenbru', 'Otubru', 'Nuvenbru', 'Dizenbru'], 'months_short' => ['Jan', 'Feb', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Otu', 'Nuv', 'Diz'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D [di] MMMM [di] YYYY HH:mm', 'LLLL' => 'dddd, D [di] MMMM [di] YYYY HH:mm', ], 'year' => ':count otunu', // less reliable 'y' => ':count otunu', // less reliable 'a_year' => ':count otunu', // less reliable 'week' => ':count día dumingu', // less reliable 'w' => ':count día dumingu', // less reliable 'a_week' => ':count día dumingu', // less reliable 'day' => ':count diâ', // less reliable 'd' => ':count diâ', // less reliable 'a_day' => ':count diâ', // less reliable 'minute' => ':count sugundu', // less reliable 'min' => ':count sugundu', // less reliable 'a_minute' => ':count sugundu', // less reliable 'second' => ':count dós', // less reliable 's' => ':count dós', // less reliable 'a_second' => ':count dós', // less reliable ]); PK������<1ZQo\��\����Carbon/Lang/ksh.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['v.M.', 'n.M.'], 'weekdays' => ['Sunndaach', 'Mohndaach', 'Dinnsdaach', 'Metwoch', 'Dunnersdaach', 'Friidaach', 'Samsdaach'], 'weekdays_short' => ['Su.', 'Mo.', 'Di.', 'Me.', 'Du.', 'Fr.', 'Sa.'], 'weekdays_min' => ['Su', 'Mo', 'Di', 'Me', 'Du', 'Fr', 'Sa'], 'months' => ['Jannewa', 'Fäbrowa', 'Määz', 'Aprell', 'Mai', 'Juuni', 'Juuli', 'Oujoß', 'Septämber', 'Oktohber', 'Novämber', 'Dezämber'], 'months_short' => ['Jan', 'Fäb', 'Mäz', 'Apr', 'Mai', 'Jun', 'Jul', 'Ouj', 'Säp', 'Okt', 'Nov', 'Dez'], 'months_short_standalone' => ['Jan.', 'Fäb.', 'Mäz.', 'Apr.', 'Mai', 'Jun.', 'Jul.', 'Ouj.', 'Säp.', 'Okt.', 'Nov.', 'Dez.'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D. M. YYYY', 'LL' => 'D. MMM. YYYY', 'LLL' => 'D. MMMM YYYY HH:mm', 'LLLL' => 'dddd, [dä] D. MMMM YYYY HH:mm', ], 'year' => ':count Johr', 'y' => ':count Johr', 'a_year' => ':count Johr', 'month' => ':count Moohnd', 'm' => ':count Moohnd', 'a_month' => ':count Moohnd', 'week' => ':count woch', 'w' => ':count woch', 'a_week' => ':count woch', 'day' => ':count Daach', 'd' => ':count Daach', 'a_day' => ':count Daach', 'hour' => ':count Uhr', 'h' => ':count Uhr', 'a_hour' => ':count Uhr', 'minute' => ':count Menutt', 'min' => ':count Menutt', 'a_minute' => ':count Menutt', 'second' => ':count Sekůndt', 's' => ':count Sekůndt', 'a_second' => ':count Sekůndt', ]); PK������<1ZpG��G����Carbon/Lang/en_GM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z.`������Carbon/Lang/dav.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['Luma lwa K', 'luma lwa p'], 'weekdays' => ['Ituku ja jumwa', 'Kuramuka jimweri', 'Kuramuka kawi', 'Kuramuka kadadu', 'Kuramuka kana', 'Kuramuka kasanu', 'Kifula nguwo'], 'weekdays_short' => ['Jum', 'Jim', 'Kaw', 'Kad', 'Kan', 'Kas', 'Ngu'], 'weekdays_min' => ['Jum', 'Jim', 'Kaw', 'Kad', 'Kan', 'Kas', 'Ngu'], 'months' => ['Mori ghwa imbiri', 'Mori ghwa kawi', 'Mori ghwa kadadu', 'Mori ghwa kana', 'Mori ghwa kasanu', 'Mori ghwa karandadu', 'Mori ghwa mfungade', 'Mori ghwa wunyanya', 'Mori ghwa ikenda', 'Mori ghwa ikumi', 'Mori ghwa ikumi na imweri', 'Mori ghwa ikumi na iwi'], 'months_short' => ['Imb', 'Kaw', 'Kad', 'Kan', 'Kas', 'Kar', 'Mfu', 'Wun', 'Ike', 'Iku', 'Imw', 'Iwi'], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], ]); PK������<1Z㪍q �� ����Carbon/Lang/lb.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Philippe Vaucher * - Tsutomu Kuroda * - dan-nl * - Simon Lelorrain (slelorrain) */ use Carbon\CarbonInterface; return [ 'year' => ':count Joer', 'y' => ':countJ', 'month' => ':count Mount|:count Méint', 'm' => ':countMo', 'week' => ':count Woch|:count Wochen', 'w' => ':countWo|:countWo', 'day' => ':count Dag|:count Deeg', 'd' => ':countD', 'hour' => ':count Stonn|:count Stonnen', 'h' => ':countSto', 'minute' => ':count Minutt|:count Minutten', 'min' => ':countM', 'second' => ':count Sekonn|:count Sekonnen', 's' => ':countSek', 'ago' => 'virun :time', 'from_now' => 'an :time', 'before' => ':time virdrun', 'after' => ':time duerno', 'diff_today' => 'Haut', 'diff_yesterday' => 'Gëschter', 'diff_yesterday_regexp' => 'Gëschter(?:\\s+um)?', 'diff_tomorrow' => 'Muer', 'diff_tomorrow_regexp' => 'Muer(?:\\s+um)?', 'diff_today_regexp' => 'Haut(?:\\s+um)?', 'formats' => [ 'LT' => 'H:mm [Auer]', 'LTS' => 'H:mm:ss [Auer]', 'L' => 'DD.MM.YYYY', 'LL' => 'D. MMMM YYYY', 'LLL' => 'D. MMMM YYYY H:mm [Auer]', 'LLLL' => 'dddd, D. MMMM YYYY H:mm [Auer]', ], 'calendar' => [ 'sameDay' => '[Haut um] LT', 'nextDay' => '[Muer um] LT', 'nextWeek' => 'dddd [um] LT', 'lastDay' => '[Gëschter um] LT', 'lastWeek' => function (CarbonInterface $date) { // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule switch ($date->dayOfWeek) { case 2: case 4: return '[Leschten] dddd [um] LT'; default: return '[Leschte] dddd [um] LT'; } }, 'sameElse' => 'L', ], 'months' => ['Januar', 'Februar', 'Mäerz', 'Abrëll', 'Mee', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'], 'months_short' => ['Jan.', 'Febr.', 'Mrz.', 'Abr.', 'Mee', 'Jun.', 'Jul.', 'Aug.', 'Sept.', 'Okt.', 'Nov.', 'Dez.'], 'weekdays' => ['Sonndeg', 'Méindeg', 'Dënschdeg', 'Mëttwoch', 'Donneschdeg', 'Freideg', 'Samschdeg'], 'weekdays_short' => ['So.', 'Mé.', 'Dë.', 'Më.', 'Do.', 'Fr.', 'Sa.'], 'weekdays_min' => ['So', 'Mé', 'Dë', 'Më', 'Do', 'Fr', 'Sa'], 'ordinal' => ':number.', 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' an '], 'meridiem' => ['moies', 'mëttes'], 'weekdays_short_standalone' => ['Son', 'Méi', 'Dën', 'Mët', 'Don', 'Fre', 'Sam'], 'months_short_standalone' => ['Jan', 'Feb', 'Mäe', 'Abr', 'Mee', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'], ]; PK������<1Zj��j����Carbon/Lang/en_SG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'from_now' => 'in :time', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, ]); PK������<1Zn!KA �� ����Carbon/Lang/kok_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Red Hat, Pune bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'D-M-YY', ], 'months' => ['जानेवारी', 'फेब्रुवारी', 'मार्च', 'एप्रिल', 'मे', 'जून', 'जुलै', 'ओगस्ट', 'सेप्टेंबर', 'ओक्टोबर', 'नोव्हेंबर', 'डिसेंबर'], 'months_short' => ['जानेवारी', 'फेब्रुवारी', 'मार्च', 'एप्रिल', 'मे', 'जून', 'जुलै', 'ओगस्ट', 'सेप्टेंबर', 'ओक्टोबर', 'नोव्हेंबर', 'डिसेंबर'], 'weekdays' => ['आयतार', 'सोमार', 'मंगळवार', 'बुधवार', 'बेरेसतार', 'शुकरार', 'शेनवार'], 'weekdays_short' => ['आयतार', 'सोमार', 'मंगळवार', 'बुधवार', 'बेरेसतार', 'शुकरार', 'शेनवार'], 'weekdays_min' => ['आयतार', 'सोमार', 'मंगळवार', 'बुधवार', 'बेरेसतार', 'शुकरार', 'शेनवार'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['म.पू.', 'म.नं.'], 'year' => ':count वैशाकु', // less reliable 'y' => ':count वैशाकु', // less reliable 'a_year' => ':count वैशाकु', // less reliable 'week' => ':count आदित्यवार', // less reliable 'w' => ':count आदित्यवार', // less reliable 'a_week' => ':count आदित्यवार', // less reliable 'minute' => ':count नोंद', // less reliable 'min' => ':count नोंद', // less reliable 'a_minute' => ':count नोंद', // less reliable 'second' => ':count तेंको', // less reliable 's' => ':count तेंको', // less reliable 'a_second' => ':count तेंको', // less reliable 'month' => ':count मैनो', 'm' => ':count मैनो', 'a_month' => ':count मैनो', 'day' => ':count दिवसु', 'd' => ':count दिवसु', 'a_day' => ':count दिवसु', 'hour' => ':count घंते', 'h' => ':count घंते', 'a_hour' => ':count घंते', ]); PK������<1Z?Ej �� ����Carbon/Lang/en_WS.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1Z9#��#����Carbon/Lang/fr_TN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/fr.php', [ 'weekend' => [5, 6], 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY h:mm a', 'LLLL' => 'dddd D MMMM YYYY h:mm a', ], ]); PK������<1ZX �� ����Carbon/Lang/th.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Nate Whittaker * - John MacAslan * - Chanintorn Asavavichairoj * - JD Isaacks * - ROKAISAKKON * - RO'KAISAKKON * - Andreas Möller * - nithisa */ return [ 'year' => ':count ปี', 'y' => ':count ปี', 'month' => ':count เดือน', 'm' => ':count เดือน', 'week' => ':count สัปดาห์', 'w' => ':count สัปดาห์', 'day' => ':count วัน', 'd' => ':count วัน', 'hour' => ':count ชั่วโมง', 'h' => ':count ชั่วโมง', 'minute' => ':count นาที', 'min' => ':count นาที', 'second' => ':count วินาที', 'a_second' => '{1}ไม่กี่วินาที|]1,Inf[:count วินาที', 's' => ':count วินาที', 'ago' => ':timeที่แล้ว', 'from_now' => 'อีก :time', 'after' => ':timeหลังจากนี้', 'before' => ':timeก่อน', 'diff_now' => 'ขณะนี้', 'diff_today' => 'วันนี้', 'diff_today_regexp' => 'วันนี้(?:\\s+เวลา)?', 'diff_yesterday' => 'เมื่อวาน', 'diff_yesterday_regexp' => 'เมื่อวานนี้(?:\\s+เวลา)?', 'diff_tomorrow' => 'พรุ่งนี้', 'diff_tomorrow_regexp' => 'พรุ่งนี้(?:\\s+เวลา)?', 'formats' => [ 'LT' => 'H:mm', 'LTS' => 'H:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY เวลา H:mm', 'LLLL' => 'วันddddที่ D MMMM YYYY เวลา H:mm', ], 'calendar' => [ 'sameDay' => '[วันนี้ เวลา] LT', 'nextDay' => '[พรุ่งนี้ เวลา] LT', 'nextWeek' => 'dddd[หน้า เวลา] LT', 'lastDay' => '[เมื่อวานนี้ เวลา] LT', 'lastWeek' => '[วัน]dddd[ที่แล้ว เวลา] LT', 'sameElse' => 'L', ], 'meridiem' => ['ก่อนเที่ยง', 'หลังเที่ยง'], 'months' => ['มกราคม', 'กุมภาพันธ์', 'มีนาคม', 'เมษายน', 'พฤษภาคม', 'มิถุนายน', 'กรกฎาคม', 'สิงหาคม', 'กันยายน', 'ตุลาคม', 'พฤศจิกายน', 'ธันวาคม'], 'months_short' => ['ม.ค.', 'ก.พ.', 'มี.ค.', 'เม.ย.', 'พ.ค.', 'มิ.ย.', 'ก.ค.', 'ส.ค.', 'ก.ย.', 'ต.ค.', 'พ.ย.', 'ธ.ค.'], 'weekdays' => ['อาทิตย์', 'จันทร์', 'อังคาร', 'พุธ', 'พฤหัสบดี', 'ศุกร์', 'เสาร์'], 'weekdays_short' => ['อาทิตย์', 'จันทร์', 'อังคาร', 'พุธ', 'พฤหัส', 'ศุกร์', 'เสาร์'], 'weekdays_min' => ['อา.', 'จ.', 'อ.', 'พ.', 'พฤ.', 'ศ.', 'ส.'], 'list' => [', ', ' และ '], ]; PK������<1Z10��0����Carbon/Lang/fil_PH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Rene Torres Rene Torres, Pablo Saratxaga rgtorre@rocketmail.com, pablo@mandrakesoft.com * - Jaycee Mariano (alohajaycee) */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'MM/DD/YY', ], 'months' => ['Enero', 'Pebrero', 'Marso', 'Abril', 'Mayo', 'Hunyo', 'Hulyo', 'Agosto', 'Setyembre', 'Oktubre', 'Nobyembre', 'Disyembre'], 'months_short' => ['Ene', 'Peb', 'Mar', 'Abr', 'May', 'Hun', 'Hul', 'Ago', 'Set', 'Okt', 'Nob', 'Dis'], 'weekdays' => ['Linggo', 'Lunes', 'Martes', 'Miyerkoles', 'Huwebes', 'Biyernes', 'Sabado'], 'weekdays_short' => ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'], 'weekdays_min' => ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['N.U.', 'N.H.'], 'before' => ':time bago', 'after' => ':time pagkatapos', 'year' => ':count taon', 'y' => ':count taon', 'a_year' => ':count taon', 'month' => ':count buwan', 'm' => ':count buwan', 'a_month' => ':count buwan', 'week' => ':count linggo', 'w' => ':count linggo', 'a_week' => ':count linggo', 'day' => ':count araw', 'd' => ':count araw', 'a_day' => ':count araw', 'hour' => ':count oras', 'h' => ':count oras', 'a_hour' => ':count oras', 'minute' => ':count minuto', 'min' => ':count minuto', 'a_minute' => ':count minuto', 'second' => ':count segundo', 's' => ':count segundo', 'a_second' => ':count segundo', 'ago' => ':time ang nakalipas', 'from_now' => 'sa :time', ]); PK������<1Z������Carbon/Lang/ti_ER.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ge'ez Frontier Foundation locales@geez.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['ጥሪ', 'ለካቲት', 'መጋቢት', 'ሚያዝያ', 'ግንቦት', 'ሰነ', 'ሓምለ', 'ነሓሰ', 'መስከረም', 'ጥቅምቲ', 'ሕዳር', 'ታሕሳስ'], 'months_short' => ['ጥሪ ', 'ለካቲ', 'መጋቢ', 'ሚያዝ', 'ግንቦ', 'ሰነ ', 'ሓምለ', 'ነሓሰ', 'መስከ', 'ጥቅም', 'ሕዳር', 'ታሕሳ'], 'weekdays' => ['ሰንበት', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'], 'weekdays_short' => ['ሰንበ', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'], 'weekdays_min' => ['ሰንበ', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'meridiem' => ['ንጉሆ ሰዓተ', 'ድሕር ሰዓት'], 'year' => ':count ዓመት', 'y' => ':count ዓመት', 'a_year' => ':count ዓመት', 'month' => 'ወርሒ :count', 'm' => 'ወርሒ :count', 'a_month' => 'ወርሒ :count', 'week' => ':count ሰሙን', 'w' => ':count ሰሙን', 'a_week' => ':count ሰሙን', 'day' => ':count መዓልቲ', 'd' => ':count መዓልቲ', 'a_day' => ':count መዓልቲ', 'hour' => ':count ሰዓት', 'h' => ':count ሰዓት', 'a_hour' => ':count ሰዓት', 'minute' => ':count ደቒቕ', 'min' => ':count ደቒቕ', 'a_minute' => ':count ደቒቕ', 'second' => ':count ሰከንድ', 's' => ':count ሰከንድ', 'a_second' => ':count ሰከንድ', ]); PK������<1Z#�!��!����Carbon/Lang/ckb.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Swara Mohammed */ $months = [ 'ڕێبەندان', 'ڕەشەمە', 'نەورۆز', 'گوڵان', 'جۆزەردان', 'پوشپەڕ', 'گەلاوێژ', 'خەرمانان', 'ڕەزبەر', 'گەڵاڕێزان', 'سەرماوەرز', 'بەفرانبار', ]; return [ 'year' => implode('|', ['{0}:count ساڵێک', '{1}ساڵێک', '{2}دوو ساڵ', ']2,11[:count ساڵ', ']10,Inf[:count ساڵ']), 'a_year' => implode('|', ['{0}:count ساڵێک', '{1}ساڵێک', '{2}دوو ساڵ', ']2,11[:count ساڵ', ']10,Inf[:count ساڵ']), 'month' => implode('|', ['{0}:count مانگێک', '{1}مانگێک', '{2}دوو مانگ', ']2,11[:count مانگ', ']10,Inf[:count مانگ']), 'a_month' => implode('|', ['{0}:count مانگێک', '{1}مانگێک', '{2}دوو مانگ', ']2,11[:count مانگ', ']10,Inf[:count مانگ']), 'week' => implode('|', ['{0}:count هەفتەیەک', '{1}هەفتەیەک', '{2}دوو هەفتە', ']2,11[:count هەفتە', ']10,Inf[:count هەفتە']), 'a_week' => implode('|', ['{0}:count هەفتەیەک', '{1}هەفتەیەک', '{2}دوو هەفتە', ']2,11[:count هەفتە', ']10,Inf[:count هەفتە']), 'day' => implode('|', ['{0}:count ڕۆژێک', '{1}ڕۆژێک', '{2}دوو ڕۆژ', ']2,11[:count ڕۆژ', ']10,Inf[:count ڕۆژ']), 'a_day' => implode('|', ['{0}:count ڕۆژێک', '{1}ڕۆژێک', '{2}دوو ڕۆژ', ']2,11[:count ڕۆژ', ']10,Inf[:count ڕۆژ']), 'hour' => implode('|', ['{0}:count کاتژمێرێک', '{1}کاتژمێرێک', '{2}دوو کاتژمێر', ']2,11[:count کاتژمێر', ']10,Inf[:count کاتژمێر']), 'a_hour' => implode('|', ['{0}:count کاتژمێرێک', '{1}کاتژمێرێک', '{2}دوو کاتژمێر', ']2,11[:count کاتژمێر', ']10,Inf[:count کاتژمێر']), 'minute' => implode('|', ['{0}:count خولەکێک', '{1}خولەکێک', '{2}دوو خولەک', ']2,11[:count خولەک', ']10,Inf[:count خولەک']), 'a_minute' => implode('|', ['{0}:count خولەکێک', '{1}خولەکێک', '{2}دوو خولەک', ']2,11[:count خولەک', ']10,Inf[:count خولەک']), 'second' => implode('|', ['{0}:count چرکەیەک', '{1}چرکەیەک', '{2}دوو چرکە', ']2,11[:count چرکە', ']10,Inf[:count چرکە']), 'a_second' => implode('|', ['{0}:count چرکەیەک', '{1}چرکەیەک', '{2}دوو چرکە', ']2,11[:count چرکە', ']10,Inf[:count چرکە']), 'ago' => 'پێش :time', 'from_now' => ':time لە ئێستاوە', 'after' => 'دوای :time', 'before' => 'پێش :time', 'diff_now' => 'ئێستا', 'diff_today' => 'ئەمڕۆ', 'diff_today_regexp' => 'ڕۆژ(?:\\s+لە)?(?:\\s+کاتژمێر)?', 'diff_yesterday' => 'دوێنێ', 'diff_yesterday_regexp' => 'دوێنێ(?:\\s+لە)?(?:\\s+کاتژمێر)?', 'diff_tomorrow' => 'سبەینێ', 'diff_tomorrow_regexp' => 'سبەینێ(?:\\s+لە)?(?:\\s+کاتژمێر)?', 'diff_before_yesterday' => 'پێش دوێنێ', 'diff_after_tomorrow' => 'دوای سبەینێ', 'period_recurrences' => implode('|', ['{0}جار', '{1}جار', '{2}:count دووجار', ']2,11[:count جار', ']10,Inf[:count جار']), 'period_interval' => 'هەموو :interval', 'period_start_date' => 'لە :date', 'period_end_date' => 'بۆ :date', 'months' => $months, 'months_short' => $months, 'weekdays' => ['یەکشەممە', 'دووشەممە', 'سێشەممە', 'چوارشەممە', 'پێنجشەممە', 'هەینی', 'شەممە'], 'weekdays_short' => ['یەکشەممە', 'دووشەممە', 'سێشەممە', 'چوارشەممە', 'پێنجشەممە', 'هەینی', 'شەممە'], 'weekdays_min' => ['یەکشەممە', 'دووشەممە', 'سێشەممە', 'چوارشەممە', 'پێنجشەممە', 'هەینی', 'شەممە'], 'list' => ['، ', ' و '], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[ئەمڕۆ لە کاتژمێر] LT', 'nextDay' => '[سبەینێ لە کاتژمێر] LT', 'nextWeek' => 'dddd [لە کاتژمێر] LT', 'lastDay' => '[دوێنێ لە کاتژمێر] LT', 'lastWeek' => 'dddd [لە کاتژمێر] LT', 'sameElse' => 'L', ], 'meridiem' => ['پ.ن', 'د.ن'], 'weekend' => [5, 6], ]; PK������<1Z-GYO��O����Carbon/Lang/nso.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/nso_ZA.php'; PK������<1ZN��N����Carbon/Lang/yi.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/yi_US.php'; PK������<1Z-Ј �� ����Carbon/Lang/zh_Hant.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Adam * - monkeycon * - François B * - Jason Katz-Brown * - Chris Lam * - Serhan Apaydın * - Gary Lo * - JD Isaacks * - Chris Hemp * - Eddie * - KID * - shankesgk2 * - Daniel Cheung (danvim) */ return [ 'year' => ':count:optional-space年', 'y' => ':count:optional-space年', 'month' => ':count:optional-space個月', 'm' => ':count:optional-space月', 'week' => ':count:optional-space週', 'w' => ':count:optional-space週', 'day' => ':count:optional-space天', 'd' => ':count:optional-space天', 'hour' => ':count:optional-space小時', 'h' => ':count:optional-space小時', 'minute' => ':count:optional-space分鐘', 'min' => ':count:optional-space分鐘', 'second' => ':count:optional-space秒', 'a_second' => '{1}幾秒|]1,Inf[:count:optional-space秒', 's' => ':count:optional-space秒', 'ago' => ':time前', 'from_now' => ':time後', 'after' => ':time後', 'before' => ':time前', 'diff_now' => '現在', 'diff_today' => '今天', 'diff_yesterday' => '昨天', 'diff_tomorrow' => '明天', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY/MM/DD', 'LL' => 'YYYY年M月D日', 'LLL' => 'YYYY年M月D日 HH:mm', 'LLLL' => 'YYYY年M月D日dddd HH:mm', ], 'calendar' => [ 'sameDay' => '[今天] LT', 'nextDay' => '[明天] LT', 'nextWeek' => '[下]dddd LT', 'lastDay' => '[昨天] LT', 'lastWeek' => '[上]dddd LT', 'sameElse' => 'L', ], 'ordinal' => function ($number, $period) { switch ($period) { case 'd': case 'D': case 'DDD': return $number.'日'; case 'M': return $number.'月'; case 'w': case 'W': return $number.'周'; default: return $number; } }, 'meridiem' => function ($hour, $minute) { $time = $hour * 100 + $minute; if ($time < 600) { return '凌晨'; } if ($time < 900) { return '早上'; } if ($time < 1130) { return '上午'; } if ($time < 1230) { return '中午'; } if ($time < 1800) { return '下午'; } return '晚上'; }, 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], 'months_short' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], 'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'], 'weekdays_short' => ['週日', '週一', '週二', '週三', '週四', '週五', '週六'], 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => '', ]; PK������<1ZpG��G����Carbon/Lang/en_SI.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZڗO��O����Carbon/Lang/dsb.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/dsb_DE.php'; PK������<1Z''x �� ����Carbon/Lang/fr_BI.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Zϑ �� ����Carbon/Lang/hi_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/hi.php'; PK������<1ZpG��G����Carbon/Lang/en_NR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z �� ����Carbon/Lang/sw.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - leyluj * - Josh Soref * - ryanhart2 */ return [ 'year' => 'mwaka :count|miaka :count', 'a_year' => 'mwaka mmoja|miaka :count', 'y' => 'mwaka :count|miaka :count', 'month' => 'mwezi :count|miezi :count', 'a_month' => 'mwezi mmoja|miezi :count', 'm' => 'mwezi :count|miezi :count', 'week' => 'wiki :count', 'a_week' => 'wiki mmoja|wiki :count', 'w' => 'w. :count', 'day' => 'siku :count', 'a_day' => 'siku moja|masiku :count', 'd' => 'si. :count', 'hour' => 'saa :count|masaa :count', 'a_hour' => 'saa limoja|masaa :count', 'h' => 'saa :count|masaa :count', 'minute' => 'dakika :count', 'a_minute' => 'dakika moja|dakika :count', 'min' => 'd. :count', 'second' => 'sekunde :count', 'a_second' => 'hivi punde|sekunde :count', 's' => 'se. :count', 'ago' => 'tokea :time', 'from_now' => ':time baadaye', 'after' => ':time baada', 'before' => ':time kabla', 'diff_now' => 'sasa hivi', 'diff_today' => 'leo', 'diff_today_regexp' => 'leo(?:\\s+saa)?', 'diff_yesterday' => 'jana', 'diff_tomorrow' => 'kesho', 'diff_tomorrow_regexp' => 'kesho(?:\\s+saa)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[leo saa] LT', 'nextDay' => '[kesho saa] LT', 'nextWeek' => '[wiki ijayo] dddd [saat] LT', 'lastDay' => '[jana] LT', 'lastWeek' => '[wiki iliyopita] dddd [saat] LT', 'sameElse' => 'L', ], 'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'], 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'], 'weekdays' => ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi', 'Ijumaa', 'Jumamosi'], 'weekdays_short' => ['Jpl', 'Jtat', 'Jnne', 'Jtan', 'Alh', 'Ijm', 'Jmos'], 'weekdays_min' => ['J2', 'J3', 'J4', 'J5', 'Al', 'Ij', 'J1'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' na '], ]; PK������<1Zm|������Carbon/Lang/tet.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Joshua Brooks * - François B */ return [ 'year' => 'tinan :count', 'a_year' => '{1}tinan ida|tinan :count', 'month' => 'fulan :count', 'a_month' => '{1}fulan ida|fulan :count', 'week' => 'semana :count', 'a_week' => '{1}semana ida|semana :count', 'day' => 'loron :count', 'a_day' => '{1}loron ida|loron :count', 'hour' => 'oras :count', 'a_hour' => '{1}oras ida|oras :count', 'minute' => 'minutu :count', 'a_minute' => '{1}minutu ida|minutu :count', 'second' => 'segundu :count', 'a_second' => '{1}segundu balun|segundu :count', 'ago' => ':time liuba', 'from_now' => 'iha :time', 'diff_yesterday' => 'Horiseik', 'diff_yesterday_regexp' => 'Horiseik(?:\\s+iha)?', 'diff_today' => 'Ohin', 'diff_today_regexp' => 'Ohin(?:\\s+iha)?', 'diff_tomorrow' => 'Aban', 'diff_tomorrow_regexp' => 'Aban(?:\\s+iha)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[Ohin iha] LT', 'nextDay' => '[Aban iha] LT', 'nextWeek' => 'dddd [iha] LT', 'lastDay' => '[Horiseik iha] LT', 'lastWeek' => 'dddd [semana kotuk] [iha] LT', 'sameElse' => 'L', ], 'ordinal' => ':numberº', 'months' => ['Janeiru', 'Fevereiru', 'Marsu', 'Abril', 'Maiu', 'Juñu', 'Jullu', 'Agustu', 'Setembru', 'Outubru', 'Novembru', 'Dezembru'], 'months_short' => ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'], 'weekdays' => ['Domingu', 'Segunda', 'Tersa', 'Kuarta', 'Kinta', 'Sesta', 'Sabadu'], 'weekdays_short' => ['Dom', 'Seg', 'Ters', 'Kua', 'Kint', 'Sest', 'Sab'], 'weekdays_min' => ['Do', 'Seg', 'Te', 'Ku', 'Ki', 'Ses', 'Sa'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, ]; PK������<1Zߟ$��$����Carbon/Lang/aa_ER.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ge'ez Frontier Foundation locales@geez.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['Qunxa Garablu', 'Naharsi Kudo', 'Ciggilta Kudo', 'Agda Baxisso', 'Caxah Alsa', 'Qasa Dirri', 'Qado Dirri', 'Leqeeni', 'Waysu', 'Diteli', 'Ximoli', 'Kaxxa Garablu'], 'months_short' => ['Qun', 'Nah', 'Cig', 'Agd', 'Cax', 'Qas', 'Qad', 'Leq', 'Way', 'Dit', 'Xim', 'Kax'], 'weekdays' => ['Acaada', 'Etleeni', 'Talaata', 'Arbaqa', 'Kamiisi', 'Gumqata', 'Sabti'], 'weekdays_short' => ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'], 'weekdays_min' => ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'meridiem' => ['saaku', 'carra'], ]); PK������<1ZpG��G����Carbon/Lang/en_UG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZJe������Carbon/Lang/miq_NI.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'months' => ['siakwa kati', 'kuswa kati', 'kakamuk kati', 'lî wainhka kati', 'lih mairin kati', 'lî kati', 'pastara kati', 'sikla kati', 'wîs kati', 'waupasa kati', 'yahbra kati', 'trisu kati'], 'months_short' => ['siakwa kati', 'kuswa kati', 'kakamuk kati', 'lî wainhka kati', 'lih mairin kati', 'lî kati', 'pastara kati', 'sikla kati', 'wîs kati', 'waupasa kati', 'yahbra kati', 'trisu kati'], 'weekdays' => ['sandi', 'mundi', 'tiusdi', 'wensde', 'tausde', 'praidi', 'satadi'], 'weekdays_short' => ['san', 'mun', 'tius', 'wens', 'taus', 'prai', 'sat'], 'weekdays_min' => ['san', 'mun', 'tius', 'wens', 'taus', 'prai', 'sat'], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 7, 'meridiem' => ['VM', 'NM'], 'month' => ':count kati', // less reliable 'm' => ':count kati', // less reliable 'a_month' => ':count kati', // less reliable ]); PK������<1Zc������Carbon/Lang/nl_AW.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/nl.php', [ 'formats' => [ 'L' => 'DD-MM-YY', ], 'months' => ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december'], 'months_short' => ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'], 'weekdays' => ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'], 'weekdays_short' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'], 'weekdays_min' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, ]); PK������<1ZpG��G����Carbon/Lang/en_SB.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZA`��`����Carbon/Lang/fr_MA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/fr.php', [ 'first_day_of_week' => 6, 'weekend' => [5, 6], ]); PK������<1Zu �� ����Carbon/Lang/te_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/te.php'; PK������<1ZpG��G����Carbon/Lang/en_FK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z+3������Carbon/Lang/ar_YE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org * - Abdullah-Alhariri */ return array_replace_recursive(require __DIR__.'/ar.php', [ 'formats' => [ 'L' => 'DD MMM, YYYY', ], 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'], 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'], 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'day_of_first_week_of_year' => 1, 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'], ]); PK������<1ZvÕ������Carbon/Lang/el_GR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/el.php', [ 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, ]); PK������<1Zl3A��A����Carbon/Lang/ug_CN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Kunal Marwaha * - Alim Boyaq */ return require __DIR__.'/ug.php'; PK������<1Z)t��t����Carbon/Lang/ta_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/ta.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'], 'months_short' => ['ஜன.', 'பிப்.', 'மார்.', 'ஏப்.', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக.', 'செப்.', 'அக்.', 'நவ.', 'டிச.'], 'weekdays' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'], 'weekdays_short' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'], 'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['காலை', 'மாலை'], ]); PK������<1Zңq��q����Carbon/Lang/kk.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - François B * - Talat Uspanov * - Нурлан Рахимжанов * - Toleugazy Kali */ return [ 'year' => ':count жыл', 'a_year' => '{1}бір жыл|:count жыл', 'y' => ':count ж.', 'month' => ':count ай', 'a_month' => '{1}бір ай|:count ай', 'm' => ':count ай', 'week' => ':count апта', 'a_week' => '{1}бір апта', 'w' => ':count ап.', 'day' => ':count күн', 'a_day' => '{1}бір күн|:count күн', 'd' => ':count к.', 'hour' => ':count сағат', 'a_hour' => '{1}бір сағат|:count сағат', 'h' => ':count са.', 'minute' => ':count минут', 'a_minute' => '{1}бір минут|:count минут', 'min' => ':count м.', 'second' => ':count секунд', 'a_second' => '{1}бірнеше секунд|:count секунд', 's' => ':count се.', 'ago' => ':time бұрын', 'from_now' => ':time ішінде', 'after' => ':time кейін', 'before' => ':time бұрын', 'diff_now' => 'қазір', 'diff_today' => 'Бүгін', 'diff_today_regexp' => 'Бүгін(?:\\s+сағат)?', 'diff_yesterday' => 'кеше', 'diff_yesterday_regexp' => 'Кеше(?:\\s+сағат)?', 'diff_tomorrow' => 'ертең', 'diff_tomorrow_regexp' => 'Ертең(?:\\s+сағат)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[Бүгін сағат] LT', 'nextDay' => '[Ертең сағат] LT', 'nextWeek' => 'dddd [сағат] LT', 'lastDay' => '[Кеше сағат] LT', 'lastWeek' => '[Өткен аптаның] dddd [сағат] LT', 'sameElse' => 'L', ], 'ordinal' => function ($number) { static $suffixes = [ 0 => '-ші', 1 => '-ші', 2 => '-ші', 3 => '-ші', 4 => '-ші', 5 => '-ші', 6 => '-шы', 7 => '-ші', 8 => '-ші', 9 => '-шы', 10 => '-шы', 20 => '-шы', 30 => '-шы', 40 => '-шы', 50 => '-ші', 60 => '-шы', 70 => '-ші', 80 => '-ші', 90 => '-шы', 100 => '-ші', ]; return $number.($suffixes[$number] ?? $suffixes[$number % 10] ?? $suffixes[$number >= 100 ? 100 : -1] ?? ''); }, 'months' => ['қаңтар', 'ақпан', 'наурыз', 'сәуір', 'мамыр', 'маусым', 'шілде', 'тамыз', 'қыркүйек', 'қазан', 'қараша', 'желтоқсан'], 'months_short' => ['қаң', 'ақп', 'нау', 'сәу', 'мам', 'мау', 'шіл', 'там', 'қыр', 'қаз', 'қар', 'жел'], 'weekdays' => ['жексенбі', 'дүйсенбі', 'сейсенбі', 'сәрсенбі', 'бейсенбі', 'жұма', 'сенбі'], 'weekdays_short' => ['жек', 'дүй', 'сей', 'сәр', 'бей', 'жұм', 'сен'], 'weekdays_min' => ['жк', 'дй', 'сй', 'ср', 'бй', 'жм', 'сн'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' және '], ]; PK������<1ZM *��*����Carbon/Lang/lrc_IQ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/lrc.php', [ ]); PK������<1ZӾ6������Carbon/Lang/zh_Hans_SG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/zh_Hans.php'; PK������<1Z?Ej �� ����Carbon/Lang/en_VI.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1ZM �� ����Carbon/Lang/tr_TR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/tr.php'; PK������<1Z������Carbon/Lang/nan_TW@latin.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Arne Goetje arne@canonical.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'YYYY-MM-DD', ], 'months' => ['1goe̍h', '2goe̍h', '3goe̍h', '4goe̍h', '5goe̍h', '6goe̍h', '7goe̍h', '8goe̍h', '9goe̍h', '10goe̍h', '11goe̍h', '12goe̍h'], 'months_short' => ['1g', '2g', '3g', '4g', '5g', '6g', '7g', '8g', '9g', '10g', '11g', '12g'], 'weekdays' => ['lé-pài-ji̍t', 'pài-it', 'pài-jī', 'pài-saⁿ', 'pài-sì', 'pài-gō͘', 'pài-la̍k'], 'weekdays_short' => ['lp', 'p1', 'p2', 'p3', 'p4', 'p5', 'p6'], 'weekdays_min' => ['lp', 'p1', 'p2', 'p3', 'p4', 'p5', 'p6'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['téng-po͘', 'ē-po͘'], ]); PK������<1Z?Ej �� ����Carbon/Lang/en_TT.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1ZDh������Carbon/Lang/en_PH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'day_of_first_week_of_year' => 1, ]); PK������<1Z< �� ����Carbon/Lang/vi.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - Andre Polykanine A.K.A. Menelion Elensúlë * - JD Isaacks */ return [ 'year' => ':count năm', 'a_year' => '{1}một năm|]1, Inf[:count năm', 'y' => ':count năm', 'month' => ':count tháng', 'a_month' => '{1}một tháng|]1, Inf[:count tháng', 'm' => ':count tháng', 'week' => ':count tuần', 'a_week' => '{1}một tuần|]1, Inf[:count tuần', 'w' => ':count tuần', 'day' => ':count ngày', 'a_day' => '{1}một ngày|]1, Inf[:count ngày', 'd' => ':count ngày', 'hour' => ':count giờ', 'a_hour' => '{1}một giờ|]1, Inf[:count giờ', 'h' => ':count giờ', 'minute' => ':count phút', 'a_minute' => '{1}một phút|]1, Inf[:count phút', 'min' => ':count phút', 'second' => ':count giây', 'a_second' => '{1}vài giây|]1, Inf[:count giây', 's' => ':count giây', 'ago' => ':time trước', 'from_now' => ':time tới', 'after' => ':time sau', 'before' => ':time trước', 'diff_now' => 'bây giờ', 'diff_today' => 'Hôm', 'diff_today_regexp' => 'Hôm(?:\\s+nay)?(?:\\s+lúc)?', 'diff_yesterday' => 'Hôm qua', 'diff_yesterday_regexp' => 'Hôm(?:\\s+qua)?(?:\\s+lúc)?', 'diff_tomorrow' => 'Ngày mai', 'diff_tomorrow_regexp' => 'Ngày(?:\\s+mai)?(?:\\s+lúc)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM [năm] YYYY', 'LLL' => 'D MMMM [năm] YYYY HH:mm', 'LLLL' => 'dddd, D MMMM [năm] YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[Hôm nay lúc] LT', 'nextDay' => '[Ngày mai lúc] LT', 'nextWeek' => 'dddd [tuần tới lúc] LT', 'lastDay' => '[Hôm qua lúc] LT', 'lastWeek' => 'dddd [tuần trước lúc] LT', 'sameElse' => 'L', ], 'meridiem' => ['SA', 'CH'], 'months' => ['tháng 1', 'tháng 2', 'tháng 3', 'tháng 4', 'tháng 5', 'tháng 6', 'tháng 7', 'tháng 8', 'tháng 9', 'tháng 10', 'tháng 11', 'tháng 12'], 'months_short' => ['Th01', 'Th02', 'Th03', 'Th04', 'Th05', 'Th06', 'Th07', 'Th08', 'Th09', 'Th10', 'Th11', 'Th12'], 'weekdays' => ['chủ nhật', 'thứ hai', 'thứ ba', 'thứ tư', 'thứ năm', 'thứ sáu', 'thứ bảy'], 'weekdays_short' => ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'], 'weekdays_min' => ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' và '], ]; PK������<1Z-^������Carbon/Lang/nl_NL.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/nl.php', [ 'months' => ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december'], 'months_short' => ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'], 'weekdays' => ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'], 'weekdays_short' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'], 'weekdays_min' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, ]); PK������<1Z5������Carbon/Lang/li_NL.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - information from Kenneth Christiansen Kenneth Christiansen, Pablo Saratxaga kenneth@gnu.org, pablo@mandriva.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], 'months' => ['jannewarie', 'fibberwarie', 'miert', 'eprèl', 'meij', 'junie', 'julie', 'augustus', 'september', 'oktober', 'november', 'desember'], 'months_short' => ['jan', 'fib', 'mie', 'epr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'], 'weekdays' => ['zóndig', 'maondig', 'daensdig', 'goonsdig', 'dónderdig', 'vriedig', 'zaoterdig'], 'weekdays_short' => ['zón', 'mao', 'dae', 'goo', 'dón', 'vri', 'zao'], 'weekdays_min' => ['zón', 'mao', 'dae', 'goo', 'dón', 'vri', 'zao'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'minute' => ':count momênt', // less reliable 'min' => ':count momênt', // less reliable 'a_minute' => ':count momênt', // less reliable 'year' => ':count jaor', 'y' => ':count jaor', 'a_year' => ':count jaor', 'month' => ':count maond', 'm' => ':count maond', 'a_month' => ':count maond', 'week' => ':count waek', 'w' => ':count waek', 'a_week' => ':count waek', 'day' => ':count daag', 'd' => ':count daag', 'a_day' => ':count daag', 'hour' => ':count oer', 'h' => ':count oer', 'a_hour' => ':count oer', 'second' => ':count Secónd', 's' => ':count Secónd', 'a_second' => ':count Secónd', ]); PK������<1Zй@��@����Carbon/Lang/ksb.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['makeo', 'nyiaghuo'], 'weekdays' => ['Jumaapii', 'Jumaatatu', 'Jumaane', 'Jumaatano', 'Alhamisi', 'Ijumaa', 'Jumaamosi'], 'weekdays_short' => ['Jpi', 'Jtt', 'Jmn', 'Jtn', 'Alh', 'Iju', 'Jmo'], 'weekdays_min' => ['Jpi', 'Jtt', 'Jmn', 'Jtn', 'Alh', 'Iju', 'Jmo'], 'months' => ['Januali', 'Febluali', 'Machi', 'Aplili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'], 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], ]); PK������<1Z5R ��R ����Carbon/Lang/kn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - MOHAN M U * - François B * - rajeevnaikte */ return [ 'year' => '{1}ಒಂದು ವರ್ಷ|]1,Inf[:count ವರ್ಷ', 'month' => '{1}ಒಂದು ತಿಂಗಳು|]1,Inf[:count ತಿಂಗಳು', 'week' => '{1}ಒಂದು ವಾರ|]1,Inf[:count ವಾರಗಳು', 'day' => '{1}ಒಂದು ದಿನ|]1,Inf[:count ದಿನ', 'hour' => '{1}ಒಂದು ಗಂಟೆ|]1,Inf[:count ಗಂಟೆ', 'minute' => '{1}ಒಂದು ನಿಮಿಷ|]1,Inf[:count ನಿಮಿಷ', 'second' => '{1}ಕೆಲವು ಕ್ಷಣಗಳು|]1,Inf[:count ಸೆಕೆಂಡುಗಳು', 'ago' => ':time ಹಿಂದೆ', 'from_now' => ':time ನಂತರ', 'diff_now' => 'ಈಗ', 'diff_today' => 'ಇಂದು', 'diff_yesterday' => 'ನಿನ್ನೆ', 'diff_tomorrow' => 'ನಾಳೆ', 'formats' => [ 'LT' => 'A h:mm', 'LTS' => 'A h:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY, A h:mm', 'LLLL' => 'dddd, D MMMM YYYY, A h:mm', ], 'calendar' => [ 'sameDay' => '[ಇಂದು] LT', 'nextDay' => '[ನಾಳೆ] LT', 'nextWeek' => 'dddd, LT', 'lastDay' => '[ನಿನ್ನೆ] LT', 'lastWeek' => '[ಕೊನೆಯ] dddd, LT', 'sameElse' => 'L', ], 'ordinal' => ':numberನೇ', 'meridiem' => function ($hour) { if ($hour < 4) { return 'ರಾತ್ರಿ'; } if ($hour < 10) { return 'ಬೆಳಿಗ್ಗೆ'; } if ($hour < 17) { return 'ಮಧ್ಯಾಹ್ನ'; } if ($hour < 20) { return 'ಸಂಜೆ'; } return 'ರಾತ್ರಿ'; }, 'months' => ['ಜನವರಿ', 'ಫೆಬ್ರವರಿ', 'ಮಾರ್ಚ್', 'ಏಪ್ರಿಲ್', 'ಮೇ', 'ಜೂನ್', 'ಜುಲೈ', 'ಆಗಸ್ಟ್', 'ಸೆಪ್ಟೆಂಬರ್', 'ಅಕ್ಟೋಬರ್', 'ನವೆಂಬರ್', 'ಡಿಸೆಂಬರ್'], 'months_short' => ['ಜನ', 'ಫೆಬ್ರ', 'ಮಾರ್ಚ್', 'ಏಪ್ರಿಲ್', 'ಮೇ', 'ಜೂನ್', 'ಜುಲೈ', 'ಆಗಸ್ಟ್', 'ಸೆಪ್ಟೆಂ', 'ಅಕ್ಟೋ', 'ನವೆಂ', 'ಡಿಸೆಂ'], 'weekdays' => ['ಭಾನುವಾರ', 'ಸೋಮವಾರ', 'ಮಂಗಳವಾರ', 'ಬುಧವಾರ', 'ಗುರುವಾರ', 'ಶುಕ್ರವಾರ', 'ಶನಿವಾರ'], 'weekdays_short' => ['ಭಾನು', 'ಸೋಮ', 'ಮಂಗಳ', 'ಬುಧ', 'ಗುರು', 'ಶುಕ್ರ', 'ಶನಿ'], 'weekdays_min' => ['ಭಾ', 'ಸೋ', 'ಮಂ', 'ಬು', 'ಗು', 'ಶು', 'ಶ'], 'list' => ', ', 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, 'weekend' => [0, 0], ]; PK������<1Z������Carbon/Lang/en_CY.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - NehaGautam */ return array_replace_recursive(require __DIR__.'/en.php', [ 'from_now' => 'in :time', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD-MM-YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, ]); PK������<1ZxG��G����Carbon/Lang/ko_KP.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ko.php', [ 'first_day_of_week' => 1, ]); PK������<1Z*Q������Carbon/Lang/sd.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ $months = [ 'جنوري', 'فيبروري', 'مارچ', 'اپريل', 'مئي', 'جون', 'جولاءِ', 'آگسٽ', 'سيپٽمبر', 'آڪٽوبر', 'نومبر', 'ڊسمبر', ]; $weekdays = [ 'آچر', 'سومر', 'اڱارو', 'اربع', 'خميس', 'جمع', 'ڇنڇر', ]; /* * Authors: * - Narain Sagar * - Sawood Alam * - Narain Sagar */ return [ 'year' => '{1}'.'هڪ سال'.'|:count '.'سال', 'month' => '{1}'.'هڪ مهينو'.'|:count '.'مهينا', 'week' => '{1}'.'ھڪ ھفتو'.'|:count '.'هفتا', 'day' => '{1}'.'هڪ ڏينهن'.'|:count '.'ڏينهن', 'hour' => '{1}'.'هڪ ڪلاڪ'.'|:count '.'ڪلاڪ', 'minute' => '{1}'.'هڪ منٽ'.'|:count '.'منٽ', 'second' => '{1}'.'چند سيڪنڊ'.'|:count '.'سيڪنڊ', 'ago' => ':time اڳ', 'from_now' => ':time پوء', 'diff_yesterday' => 'ڪالهه', 'diff_today' => 'اڄ', 'diff_tomorrow' => 'سڀاڻي', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd، D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[اڄ] LT', 'nextDay' => '[سڀاڻي] LT', 'nextWeek' => 'dddd [اڳين هفتي تي] LT', 'lastDay' => '[ڪالهه] LT', 'lastWeek' => '[گزريل هفتي] dddd [تي] LT', 'sameElse' => 'L', ], 'meridiem' => ['صبح', 'شام'], 'months' => $months, 'months_short' => $months, 'weekdays' => $weekdays, 'weekdays_short' => $weekdays, 'weekdays_min' => $weekdays, 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => ['، ', ' ۽ '], ]; PK������<1Z\G��G����Carbon/Lang/qu_BO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/qu.php', [ 'first_day_of_week' => 1, ]); PK������<1ZA������Carbon/Lang/mzn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/fa.php', [ 'months' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'], 'months_short' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'], 'first_day_of_week' => 6, 'weekend' => [5, 5], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY-MM-dd', 'LL' => 'YYYY MMM D', 'LLL' => 'YYYY MMMM D HH:mm', 'LLLL' => 'YYYY MMMM D, dddd HH:mm', ], ]); PK������<1Zs������Carbon/Lang/cgg.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'weekdays' => ['Sande', 'Orwokubanza', 'Orwakabiri', 'Orwakashatu', 'Orwakana', 'Orwakataano', 'Orwamukaaga'], 'weekdays_short' => ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'], 'weekdays_min' => ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'], 'months' => ['Okwokubanza', 'Okwakabiri', 'Okwakashatu', 'Okwakana', 'Okwakataana', 'Okwamukaaga', 'Okwamushanju', 'Okwamunaana', 'Okwamwenda', 'Okwaikumi', 'Okwaikumi na kumwe', 'Okwaikumi na ibiri'], 'months_short' => ['KBZ', 'KBR', 'KST', 'KKN', 'KTN', 'KMK', 'KMS', 'KMN', 'KMW', 'KKM', 'KNK', 'KNB'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'day' => ':count ruhanga', // less reliable 'd' => ':count ruhanga', // less reliable 'a_day' => ':count ruhanga', // less reliable ]); PK������<1ZN������Carbon/Lang/sn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['a', 'p'], 'weekdays' => ['Svondo', 'Muvhuro', 'Chipiri', 'Chitatu', 'China', 'Chishanu', 'Mugovera'], 'weekdays_short' => ['Svo', 'Muv', 'Chp', 'Cht', 'Chn', 'Chs', 'Mug'], 'weekdays_min' => ['Sv', 'Mu', 'Cp', 'Ct', 'Cn', 'Cs', 'Mg'], 'months' => ['Ndira', 'Kukadzi', 'Kurume', 'Kubvumbi', 'Chivabvu', 'Chikumi', 'Chikunguru', 'Nyamavhuvhu', 'Gunyana', 'Gumiguru', 'Mbudzi', 'Zvita'], 'months_short' => ['Ndi', 'Kuk', 'Kur', 'Kub', 'Chv', 'Chk', 'Chg', 'Nya', 'Gun', 'Gum', 'Mbu', 'Zvi'], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY-MM-dd', 'LL' => 'YYYY MMM D', 'LLL' => 'YYYY MMMM D HH:mm', 'LLLL' => 'YYYY MMMM D, dddd HH:mm', ], 'year' => 'makore :count', 'y' => 'makore :count', 'a_year' => 'makore :count', 'month' => 'mwedzi :count', 'm' => 'mwedzi :count', 'a_month' => 'mwedzi :count', 'week' => 'vhiki :count', 'w' => 'vhiki :count', 'a_week' => 'vhiki :count', 'day' => 'mazuva :count', 'd' => 'mazuva :count', 'a_day' => 'mazuva :count', 'hour' => 'maawa :count', 'h' => 'maawa :count', 'a_hour' => 'maawa :count', 'minute' => 'minitsi :count', 'min' => 'minitsi :count', 'a_minute' => 'minitsi :count', 'second' => 'sekonzi :count', 's' => 'sekonzi :count', 'a_second' => 'sekonzi :count', ]); PK������<1Z �������Carbon/Lang/rm.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Philippe Vaucher * - tjku * - Max Melentiev * - Juanito Fatas * - Tsutomu Kuroda * - Akira Matsuda * - Christopher Dell * - Enrique Vidal * - Simone Carletti * - Aaron Patterson * - Nicolás Hock Isaza * - sebastian de castelberg */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'Do MMMM YYYY', 'LLL' => 'Do MMMM, HH:mm [Uhr]', 'LLLL' => 'dddd, Do MMMM YYYY, HH:mm [Uhr]', ], 'year' => ':count onn|:count onns', 'month' => ':count mais', 'week' => ':count emna|:count emnas', 'day' => ':count di|:count dis', 'hour' => ':count oura|:count ouras', 'minute' => ':count minuta|:count minutas', 'second' => ':count secunda|:count secundas', 'weekdays' => ['dumengia', 'glindesdi', 'mardi', 'mesemna', 'gievgia', 'venderdi', 'sonda'], 'weekdays_short' => ['du', 'gli', 'ma', 'me', 'gie', 've', 'so'], 'weekdays_min' => ['du', 'gli', 'ma', 'me', 'gie', 've', 'so'], 'months' => ['schaner', 'favrer', 'mars', 'avrigl', 'matg', 'zercladur', 'fanadur', 'avust', 'settember', 'october', 'november', 'december'], 'months_short' => ['schan', 'favr', 'mars', 'avr', 'matg', 'zercl', 'fan', 'avust', 'sett', 'oct', 'nov', 'dec'], 'meridiem' => ['avantmezdi', 'suentermezdi'], 'list' => [', ', ' e '], 'first_day_of_week' => 1, ]); PK������<1ZR^I��I����Carbon/Lang/cmn_TW.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'YYYY年MM月DD號', ], 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], 'months_short' => [' 1月', ' 2月', ' 3月', ' 4月', ' 5月', ' 6月', ' 7月', ' 8月', ' 9月', '10月', '11月', '12月'], 'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'], 'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'], 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'], 'meridiem' => ['上午', '下午'], 'year' => ':count 年', 'y' => ':count 年', 'a_year' => ':count 年', 'month' => ':count 月', 'm' => ':count 月', 'a_month' => ':count 月', 'week' => ':count 周', 'w' => ':count 周', 'a_week' => ':count 周', 'day' => ':count 白天', 'd' => ':count 白天', 'a_day' => ':count 白天', 'hour' => ':count 小时', 'h' => ':count 小时', 'a_hour' => ':count 小时', 'minute' => ':count 分钟', 'min' => ':count 分钟', 'a_minute' => ':count 分钟', 'second' => ':count 秒', 's' => ':count 秒', 'a_second' => ':count 秒', ]); PK������<1Z| �� ����Carbon/Lang/mr.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Vikram-enyota */ return [ 'year' => ':count वर्ष', 'y' => ':count वर्ष', 'month' => ':count महिना|:count महिने', 'm' => ':count महिना|:count महिने', 'week' => ':count आठवडा|:count आठवडे', 'w' => ':count आठवडा|:count आठवडे', 'day' => ':count दिवस', 'd' => ':count दिवस', 'hour' => ':count तास', 'h' => ':count तास', 'minute' => ':count मिनिटे', 'min' => ':count मिनिटे', 'second' => ':count सेकंद', 's' => ':count सेकंद', 'ago' => ':timeपूर्वी', 'from_now' => ':timeमध्ये', 'before' => ':timeपूर्वी', 'after' => ':timeनंतर', 'diff_now' => 'आत्ता', 'diff_today' => 'आज', 'diff_yesterday' => 'काल', 'diff_tomorrow' => 'उद्या', 'formats' => [ 'LT' => 'A h:mm वाजता', 'LTS' => 'A h:mm:ss वाजता', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY, A h:mm वाजता', 'LLLL' => 'dddd, D MMMM YYYY, A h:mm वाजता', ], 'calendar' => [ 'sameDay' => '[आज] LT', 'nextDay' => '[उद्या] LT', 'nextWeek' => 'dddd, LT', 'lastDay' => '[काल] LT', 'lastWeek' => '[मागील] dddd, LT', 'sameElse' => 'L', ], 'meridiem' => function ($hour) { if ($hour < 4) { return 'रात्री'; } if ($hour < 10) { return 'सकाळी'; } if ($hour < 17) { return 'दुपारी'; } if ($hour < 20) { return 'सायंकाळी'; } return 'रात्री'; }, 'months' => ['जानेवारी', 'फेब्रुवारी', 'मार्च', 'एप्रिल', 'मे', 'जून', 'जुलै', 'ऑगस्ट', 'सप्टेंबर', 'ऑक्टोबर', 'नोव्हेंबर', 'डिसेंबर'], 'months_short' => ['जाने.', 'फेब्रु.', 'मार्च.', 'एप्रि.', 'मे.', 'जून.', 'जुलै.', 'ऑग.', 'सप्टें.', 'ऑक्टो.', 'नोव्हें.', 'डिसें.'], 'weekdays' => ['रविवार', 'सोमवार', 'मंगळवार', 'बुधवार', 'गुरूवार', 'शुक्रवार', 'शनिवार'], 'weekdays_short' => ['रवि', 'सोम', 'मंगळ', 'बुध', 'गुरू', 'शुक्र', 'शनि'], 'weekdays_min' => ['र', 'सो', 'मं', 'बु', 'गु', 'शु', 'श'], 'list' => [', ', ' आणि '], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, 'weekend' => [0, 0], ]; PK������<1ZӾ6������Carbon/Lang/yue_Hans.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/zh_Hans.php'; PK������<1Z s �� ����Carbon/Lang/gd_GB.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/gd.php'; PK������<1ZpG��G����Carbon/Lang/en_GH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZnE%��%����Carbon/Lang/en_CH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], ]); PK������<1ZM2A��A����Carbon/Lang/asa.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['icheheavo', 'ichamthi'], 'weekdays' => ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi', 'Ijumaa', 'Jumamosi'], 'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Ijm', 'Jmo'], 'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Ijm', 'Jmo'], 'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'], 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Dec'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], ]); PK������<1Z:N��N����Carbon/Lang/yo_BJ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/yo.php', [ 'meridiem' => ['Àárɔ̀', 'Ɔ̀sán'], 'weekdays' => ['Ɔjɔ́ Àìkú', 'Ɔjɔ́ Ajé', 'Ɔjɔ́ Ìsɛ́gun', 'Ɔjɔ́rú', 'Ɔjɔ́bɔ', 'Ɔjɔ́ Ɛtì', 'Ɔjɔ́ Àbámɛ́ta'], 'weekdays_short' => ['Àìkú', 'Ajé', 'Ìsɛ́gun', 'Ɔjɔ́rú', 'Ɔjɔ́bɔ', 'Ɛtì', 'Àbámɛ́ta'], 'weekdays_min' => ['Àìkú', 'Ajé', 'Ìsɛ́gun', 'Ɔjɔ́rú', 'Ɔjɔ́bɔ', 'Ɛtì', 'Àbámɛ́ta'], 'months' => ['Oshù Shɛ́rɛ́', 'Oshù Èrèlè', 'Oshù Ɛrɛ̀nà', 'Oshù Ìgbé', 'Oshù Ɛ̀bibi', 'Oshù Òkúdu', 'Oshù Agɛmɔ', 'Oshù Ògún', 'Oshù Owewe', 'Oshù Ɔ̀wàrà', 'Oshù Bélú', 'Oshù Ɔ̀pɛ̀'], 'months_short' => ['Shɛ́rɛ́', 'Èrèlè', 'Ɛrɛ̀nà', 'Ìgbé', 'Ɛ̀bibi', 'Òkúdu', 'Agɛmɔ', 'Ògún', 'Owewe', 'Ɔ̀wàrà', 'Bélú', 'Ɔ̀pɛ̀'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], ]); PK������<1ZcQ��Q����Carbon/Lang/ca_ES_Valencia.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Component\Translation\PluralizationRules; // @codeCoverageIgnoreStart if (class_exists(PluralizationRules::class)) { PluralizationRules::set(static function ($number) { return PluralizationRules::get($number, 'ca'); }, 'ca_ES_Valencia'); } // @codeCoverageIgnoreEnd return array_replace_recursive(require __DIR__.'/ca.php', [ ]); PK������<1Zc"��"����Carbon/Lang/wo_SN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - The Debian Project Christian Perrier bubulle@debian.org */ return [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'MMMM DD, YYYY', 'LLL' => 'DD MMM HH:mm', 'LLLL' => 'MMMM DD, YYYY HH:mm', ], 'months' => ['sanwiy\'e', 'feebriy\'e', 'mars', 'awril', 'me', 'suwen', 'sulet', 'uut', 'septaambar', 'oktoobar', 'nowaambar', 'desaambar'], 'months_short' => ['san', 'fee', 'mar', 'awr', 'me ', 'suw', 'sul', 'uut', 'sep', 'okt', 'now', 'des'], 'weekdays' => ['dib\'eer', 'altine', 'talaata', 'allarba', 'alxames', 'ajjuma', 'gaawu'], 'weekdays_short' => ['dib', 'alt', 'tal', 'all', 'alx', 'ajj', 'gaa'], 'weekdays_min' => ['dib', 'alt', 'tal', 'all', 'alx', 'ajj', 'gaa'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'year' => ':count at', 'month' => ':count wèr', 'week' => ':count ayubés', 'day' => ':count bés', 'hour' => ':count waxtu', 'minute' => ':count simili', 'second' => ':count saa', ]; PK������<1ZnvB]?��?����Carbon/Lang/pt.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Cassiano Montanari * - Matt Pope * - François B * - Prodis * - JD Isaacks * - Raphael Amorim * - João Magalhães * - victortobias * - Paulo Freitas * - Sebastian Thierer * - Claudson Martins (claudsonm) */ use Carbon\CarbonInterface; return [ 'year' => ':count ano|:count anos', 'a_year' => 'um ano|:count anos', 'y' => ':counta', 'month' => ':count mês|:count meses', 'a_month' => 'um mês|:count meses', 'm' => ':countm', 'week' => ':count semana|:count semanas', 'a_week' => 'uma semana|:count semanas', 'w' => ':countsem', 'day' => ':count dia|:count dias', 'a_day' => 'um dia|:count dias', 'd' => ':countd', 'hour' => ':count hora|:count horas', 'a_hour' => 'uma hora|:count horas', 'h' => ':counth', 'minute' => ':count minuto|:count minutos', 'a_minute' => 'um minuto|:count minutos', 'min' => ':countmin', 'second' => ':count segundo|:count segundos', 'a_second' => 'alguns segundos|:count segundos', 's' => ':counts', 'millisecond' => ':count milissegundo|:count milissegundos', 'a_millisecond' => 'um milissegundo|:count milissegundos', 'ms' => ':countms', 'microsecond' => ':count microssegundo|:count microssegundos', 'a_microsecond' => 'um microssegundo|:count microssegundos', 'µs' => ':countµs', 'ago' => 'há :time', 'from_now' => 'em :time', 'after' => ':time depois', 'before' => ':time antes', 'diff_now' => 'agora', 'diff_today' => 'Hoje', 'diff_today_regexp' => 'Hoje(?:\\s+às)?', 'diff_yesterday' => 'ontem', 'diff_yesterday_regexp' => 'Ontem(?:\\s+às)?', 'diff_tomorrow' => 'amanhã', 'diff_tomorrow_regexp' => 'Amanhã(?:\\s+às)?', 'diff_before_yesterday' => 'anteontem', 'diff_after_tomorrow' => 'depois de amanhã', 'period_recurrences' => 'uma vez|:count vezes', 'period_interval' => 'cada :interval', 'period_start_date' => 'de :date', 'period_end_date' => 'até :date', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D [de] MMMM [de] YYYY', 'LLL' => 'D [de] MMMM [de] YYYY HH:mm', 'LLLL' => 'dddd, D [de] MMMM [de] YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[Hoje às] LT', 'nextDay' => '[Amanhã às] LT', 'nextWeek' => 'dddd [às] LT', 'lastDay' => '[Ontem às] LT', 'lastWeek' => function (CarbonInterface $date) { switch ($date->dayOfWeek) { case 0: case 6: return '[Último] dddd [às] LT'; default: return '[Última] dddd [às] LT'; } }, 'sameElse' => 'L', ], 'ordinal' => ':numberº', 'months' => ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho', 'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'], 'months_short' => ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set', 'out', 'nov', 'dez'], 'weekdays' => ['domingo', 'segunda-feira', 'terça-feira', 'quarta-feira', 'quinta-feira', 'sexta-feira', 'sábado'], 'weekdays_short' => ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'], 'weekdays_min' => ['Do', '2ª', '3ª', '4ª', '5ª', '6ª', 'Sá'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' e '], 'ordinal_words' => [ 'of' => 'de', 'first' => 'primeira', 'second' => 'segunda', 'third' => 'terceira', 'fourth' => 'quarta', 'fifth' => 'quinta', 'last' => 'última', ], ]; PK������<1Z"������Carbon/Lang/bez.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['pamilau', 'pamunyi'], 'weekdays' => ['pa mulungu', 'pa shahuviluha', 'pa hivili', 'pa hidatu', 'pa hitayi', 'pa hihanu', 'pa shahulembela'], 'weekdays_short' => ['Mul', 'Vil', 'Hiv', 'Hid', 'Hit', 'Hih', 'Lem'], 'weekdays_min' => ['Mul', 'Vil', 'Hiv', 'Hid', 'Hit', 'Hih', 'Lem'], 'months' => ['pa mwedzi gwa hutala', 'pa mwedzi gwa wuvili', 'pa mwedzi gwa wudatu', 'pa mwedzi gwa wutai', 'pa mwedzi gwa wuhanu', 'pa mwedzi gwa sita', 'pa mwedzi gwa saba', 'pa mwedzi gwa nane', 'pa mwedzi gwa tisa', 'pa mwedzi gwa kumi', 'pa mwedzi gwa kumi na moja', 'pa mwedzi gwa kumi na mbili'], 'months_short' => ['Hut', 'Vil', 'Dat', 'Tai', 'Han', 'Sit', 'Sab', 'Nan', 'Tis', 'Kum', 'Kmj', 'Kmb'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], ]); PK������<1Z6k��k����Carbon/Lang/pap_CW.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - information from native speaker Pablo Saratxaga pablo@mandrakesoft.com */ return require __DIR__.'/pap.php'; PK������<1Z&5 �� ����Carbon/Lang/nl_BQ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/nl.php'; PK������<1ZK:������Carbon/Lang/sah_RU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Valery Timiriliyev Valery Timiriliyev timiriliyev@gmail.com */ return array_replace_recursive(require __DIR__.'/ru.php', [ 'formats' => [ 'L' => 'YYYY.MM.DD', ], 'months' => ['тохсунньу', 'олунньу', 'кулун тутар', 'муус устар', 'ыам ыйын', 'бэс ыйын', 'от ыйын', 'атырдьах ыйын', 'балаҕан ыйын', 'алтынньы', 'сэтинньи', 'ахсынньы'], 'months_short' => ['тохс', 'олун', 'кул', 'муус', 'ыам', 'бэс', 'от', 'атыр', 'бал', 'алт', 'сэт', 'ахс'], 'weekdays' => ['баскыһыанньа', 'бэнидиэнньик', 'оптуорунньук', 'сэрэдэ', 'чэппиэр', 'бээтинсэ', 'субуота'], 'weekdays_short' => ['бс', 'бн', 'оп', 'ср', 'чп', 'бт', 'сб'], 'weekdays_min' => ['бс', 'бн', 'оп', 'ср', 'чп', 'бт', 'сб'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, ]); PK������<1ZC������Carbon/Lang/ar_TN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /** * Authors: * - JD Isaacks * - Atef Ben Ali (atefBB) * - Mohamed Sabil (mohamedsabil83) */ $months = [ 'جانفي', 'فيفري', 'مارس', 'أفريل', 'ماي', 'جوان', 'جويلية', 'أوت', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر', ]; return [ 'year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']), 'a_year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']), 'month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']), 'a_month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']), 'week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']), 'a_week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']), 'day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']), 'a_day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']), 'hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']), 'a_hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']), 'minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']), 'a_minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']), 'second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']), 'a_second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']), 'ago' => 'منذ :time', 'from_now' => 'في :time', 'after' => 'بعد :time', 'before' => 'قبل :time', 'diff_now' => 'الآن', 'diff_today' => 'اليوم', 'diff_today_regexp' => 'اليوم(?:\\s+على)?(?:\\s+الساعة)?', 'diff_yesterday' => 'أمس', 'diff_yesterday_regexp' => 'أمس(?:\\s+على)?(?:\\s+الساعة)?', 'diff_tomorrow' => 'غداً', 'diff_tomorrow_regexp' => 'غدا(?:\\s+على)?(?:\\s+الساعة)?', 'diff_before_yesterday' => 'قبل الأمس', 'diff_after_tomorrow' => 'بعد غد', 'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']), 'period_interval' => 'كل :interval', 'period_start_date' => 'من :date', 'period_end_date' => 'إلى :date', 'months' => $months, 'months_short' => $months, 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'], 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'list' => ['، ', ' و '], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[اليوم على الساعة] LT', 'nextDay' => '[غدا على الساعة] LT', 'nextWeek' => 'dddd [على الساعة] LT', 'lastDay' => '[أمس على الساعة] LT', 'lastWeek' => 'dddd [على الساعة] LT', 'sameElse' => 'L', ], 'meridiem' => ['ص', 'م'], 'weekend' => [5, 6], ]; PK������<1Z''x �� ����Carbon/Lang/fr_MU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Z%������Carbon/Lang/iw.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'months' => ['ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר'], 'months_short' => ['ינו׳', 'פבר׳', 'מרץ', 'אפר׳', 'מאי', 'יוני', 'יולי', 'אוג׳', 'ספט׳', 'אוק׳', 'נוב׳', 'דצמ׳'], 'weekdays' => ['יום ראשון', 'יום שני', 'יום שלישי', 'יום רביעי', 'יום חמישי', 'יום שישי', 'יום שבת'], 'weekdays_short' => ['יום א׳', 'יום ב׳', 'יום ג׳', 'יום ד׳', 'יום ה׳', 'יום ו׳', 'שבת'], 'weekdays_min' => ['א׳', 'ב׳', 'ג׳', 'ד׳', 'ה׳', 'ו׳', 'ש׳'], 'meridiem' => ['לפנה״צ', 'אחה״צ'], 'formats' => [ 'LT' => 'H:mm', 'LTS' => 'H:mm:ss', 'L' => 'D.M.YYYY', 'LL' => 'D בMMM YYYY', 'LLL' => 'D בMMMM YYYY H:mm', 'LLLL' => 'dddd, D בMMMM YYYY H:mm', ], 'year' => ':count שנה', 'y' => ':count שנה', 'a_year' => ':count שנה', 'month' => ':count חודש', 'm' => ':count חודש', 'a_month' => ':count חודש', 'week' => ':count שבוע', 'w' => ':count שבוע', 'a_week' => ':count שבוע', 'day' => ':count יום', 'd' => ':count יום', 'a_day' => ':count יום', 'hour' => ':count שעה', 'h' => ':count שעה', 'a_hour' => ':count שעה', 'minute' => ':count דקה', 'min' => ':count דקה', 'a_minute' => ':count דקה', 'second' => ':count שניה', 's' => ':count שניה', 'a_second' => ':count שניה', 'ago' => 'לפני :time', 'from_now' => 'בעוד :time', ]); PK������<1ZDŽ������Carbon/Lang/fy_NL.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/fy.php', [ 'formats' => [ 'L' => 'DD-MM-YY', ], 'months' => ['Jannewaris', 'Febrewaris', 'Maart', 'April', 'Maaie', 'Juny', 'July', 'Augustus', 'Septimber', 'Oktober', 'Novimber', 'Desimber'], 'months_short' => ['Jan', 'Feb', 'Mrt', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Des'], 'weekdays' => ['Snein', 'Moandei', 'Tiisdei', 'Woansdei', 'Tongersdei', 'Freed', 'Sneon'], 'weekdays_short' => ['Sn', 'Mo', 'Ti', 'Wo', 'To', 'Fr', 'Sn'], 'weekdays_min' => ['Sn', 'Mo', 'Ti', 'Wo', 'To', 'Fr', 'Sn'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, ]); PK������<1Z._������Carbon/Lang/sgs_LT.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Arnas Udovičius bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'YYYY.MM.DD', ], 'months' => ['sausė', 'vasarė', 'kuova', 'balondė', 'gegožės', 'bėrželė', 'lëpas', 'rogpjūtė', 'siejės', 'spalė', 'lapkrėstė', 'grůdė'], 'months_short' => ['Sau', 'Vas', 'Kuo', 'Bal', 'Geg', 'Bėr', 'Lëp', 'Rgp', 'Sie', 'Spa', 'Lap', 'Grd'], 'weekdays' => ['nedielės dëna', 'panedielis', 'oterninks', 'sereda', 'četvergs', 'petnīčė', 'sobata'], 'weekdays_short' => ['Nd', 'Pn', 'Ot', 'Sr', 'Čt', 'Pt', 'Sb'], 'weekdays_min' => ['Nd', 'Pn', 'Ot', 'Sr', 'Čt', 'Pt', 'Sb'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'minute' => ':count mažos', // less reliable 'min' => ':count mažos', // less reliable 'a_minute' => ':count mažos', // less reliable 'year' => ':count metā', 'y' => ':count metā', 'a_year' => ':count metā', 'month' => ':count mienou', 'm' => ':count mienou', 'a_month' => ':count mienou', 'week' => ':count nedielė', 'w' => ':count nedielė', 'a_week' => ':count nedielė', 'day' => ':count dīna', 'd' => ':count dīna', 'a_day' => ':count dīna', 'hour' => ':count adīna', 'h' => ':count adīna', 'a_hour' => ':count adīna', 'second' => ':count Sekondė', 's' => ':count Sekondė', 'a_second' => ':count Sekondė', ]); PK������<1ZpG��G����Carbon/Lang/en_BM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z}TO��O����Carbon/Lang/sat.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/sat_IN.php'; PK������<1ZTʟ%@��@����Carbon/Lang/ar_LY.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Atef Ben Ali (atefBB) * - Ibrahim AshShohail * - MLTDev */ $months = [ 'يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر', ]; return [ 'year' => implode('|', [':count سنة', 'سنة', 'سنتين', ':count سنوات', ':count سنة']), 'a_year' => implode('|', [':count سنة', 'سنة', 'سنتين', ':count سنوات', ':count سنة']), 'month' => implode('|', [':count شهر', 'شهر', 'شهرين', ':count أشهر', ':count شهر']), 'a_month' => implode('|', [':count شهر', 'شهر', 'شهرين', ':count أشهر', ':count شهر']), 'week' => implode('|', [':count أسبوع', 'أسبوع', 'أسبوعين', ':count أسابيع', ':count أسبوع']), 'a_week' => implode('|', [':count أسبوع', 'أسبوع', 'أسبوعين', ':count أسابيع', ':count أسبوع']), 'day' => implode('|', [':count يوم', 'يوم', 'يومين', ':count أيام', ':count يوم']), 'a_day' => implode('|', [':count يوم', 'يوم', 'يومين', ':count أيام', ':count يوم']), 'hour' => implode('|', [':count ساعة', 'ساعة', 'ساعتين', ':count ساعات', ':count ساعة']), 'a_hour' => implode('|', [':count ساعة', 'ساعة', 'ساعتين', ':count ساعات', ':count ساعة']), 'minute' => implode('|', [':count دقيقة', 'دقيقة', 'دقيقتين', ':count دقائق', ':count دقيقة']), 'a_minute' => implode('|', [':count دقيقة', 'دقيقة', 'دقيقتين', ':count دقائق', ':count دقيقة']), 'second' => implode('|', [':count ثانية', 'ثانية', 'ثانيتين', ':count ثواني', ':count ثانية']), 'a_second' => implode('|', [':count ثانية', 'ثانية', 'ثانيتين', ':count ثواني', ':count ثانية']), 'ago' => 'منذ :time', 'from_now' => ':time من الآن', 'after' => 'بعد :time', 'before' => 'قبل :time', 'diff_now' => 'الآن', 'diff_today' => 'اليوم', 'diff_today_regexp' => 'اليوم(?:\\s+عند)?(?:\\s+الساعة)?', 'diff_yesterday' => 'أمس', 'diff_yesterday_regexp' => 'أمس(?:\\s+عند)?(?:\\s+الساعة)?', 'diff_tomorrow' => 'غداً', 'diff_tomorrow_regexp' => 'غدًا(?:\\s+عند)?(?:\\s+الساعة)?', 'diff_before_yesterday' => 'قبل الأمس', 'diff_after_tomorrow' => 'بعد غد', 'period_recurrences' => implode('|', ['مرة', 'مرة', ':count مرتين', ':count مرات', ':count مرة']), 'period_interval' => 'كل :interval', 'period_start_date' => 'من :date', 'period_end_date' => 'إلى :date', 'months' => $months, 'months_short' => $months, 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'], 'weekdays_min' => ['ح', 'اث', 'ثل', 'أر', 'خم', 'ج', 'س'], 'list' => ['، ', ' و '], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[اليوم عند الساعة] LT', 'nextDay' => '[غدًا عند الساعة] LT', 'nextWeek' => 'dddd [عند الساعة] LT', 'lastDay' => '[أمس عند الساعة] LT', 'lastWeek' => 'dddd [عند الساعة] LT', 'sameElse' => 'L', ], 'meridiem' => ['ص', 'م'], 'weekend' => [5, 6], ]; PK������<1ZE������Carbon/Lang/pt_PT.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/pt.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho', 'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'], 'months_short' => ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set', 'out', 'nov', 'dez'], 'weekdays' => ['domingo', 'segunda', 'terça', 'quarta', 'quinta', 'sexta', 'sábado'], 'weekdays_short' => ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'], 'weekdays_min' => ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, ]); PK������<1Zgrt������Carbon/Lang/lg_UG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Akademe ya Luganda Kizito Birabwa kompyuta@kizito.uklinux.net */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'months' => ['Janwaliyo', 'Febwaliyo', 'Marisi', 'Apuli', 'Maayi', 'Juuni', 'Julaayi', 'Agusito', 'Sebuttemba', 'Okitobba', 'Novemba', 'Desemba'], 'months_short' => ['Jan', 'Feb', 'Mar', 'Apu', 'Maa', 'Juu', 'Jul', 'Agu', 'Seb', 'Oki', 'Nov', 'Des'], 'weekdays' => ['Sabiiti', 'Balaza', 'Lwakubiri', 'Lwakusatu', 'Lwakuna', 'Lwakutaano', 'Lwamukaaga'], 'weekdays_short' => ['Sab', 'Bal', 'Lw2', 'Lw3', 'Lw4', 'Lw5', 'Lw6'], 'weekdays_min' => ['Sab', 'Bal', 'Lw2', 'Lw3', 'Lw4', 'Lw5', 'Lw6'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'month' => ':count njuba', // less reliable 'm' => ':count njuba', // less reliable 'a_month' => ':count njuba', // less reliable 'year' => ':count mwaaka', 'y' => ':count mwaaka', 'a_year' => ':count mwaaka', 'week' => ':count sabbiiti', 'w' => ':count sabbiiti', 'a_week' => ':count sabbiiti', 'day' => ':count lunaku', 'd' => ':count lunaku', 'a_day' => ':count lunaku', 'hour' => 'saawa :count', 'h' => 'saawa :count', 'a_hour' => 'saawa :count', 'minute' => 'ddakiika :count', 'min' => 'ddakiika :count', 'a_minute' => 'ddakiika :count', 'second' => ':count kyʼokubiri', 's' => ':count kyʼokubiri', 'a_second' => ':count kyʼokubiri', ]); PK������<1Z''x �� ����Carbon/Lang/fr_GQ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1ZpG��G����Carbon/Lang/en_KY.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZÂ~��~����Carbon/Lang/ar_SS.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/ar.php', [ 'formats' => [ 'L' => 'DD MMM, YYYY', ], 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'], 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'], 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, ]); PK������<1Zk_ؾ4 ��4 ����Carbon/Lang/mi.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - John Corrigan * - François B */ return [ 'year' => ':count tau', 'a_year' => '{1}he tau|:count tau', 'month' => ':count marama', 'a_month' => '{1}he marama|:count marama', 'week' => ':count wiki', 'a_week' => '{1}he wiki|:count wiki', 'day' => ':count ra', 'a_day' => '{1}he ra|:count ra', 'hour' => ':count haora', 'a_hour' => '{1}te haora|:count haora', 'minute' => ':count meneti', 'a_minute' => '{1}he meneti|:count meneti', 'second' => ':count hēkona', 'a_second' => '{1}te hēkona ruarua|:count hēkona', 'ago' => ':time i mua', 'from_now' => 'i roto i :time', 'diff_yesterday' => 'inanahi', 'diff_yesterday_regexp' => 'inanahi(?:\\s+i)?', 'diff_today' => 'i teie', 'diff_today_regexp' => 'i teie(?:\\s+mahana,)?(?:\\s+i)?', 'diff_tomorrow' => 'apopo', 'diff_tomorrow_regexp' => 'apopo(?:\\s+i)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY [i] HH:mm', 'LLLL' => 'dddd, D MMMM YYYY [i] HH:mm', ], 'calendar' => [ 'sameDay' => '[i teie mahana, i] LT', 'nextDay' => '[apopo i] LT', 'nextWeek' => 'dddd [i] LT', 'lastDay' => '[inanahi i] LT', 'lastWeek' => 'dddd [whakamutunga i] LT', 'sameElse' => 'L', ], 'ordinal' => ':numberº', 'months' => ['Kohi-tāte', 'Hui-tanguru', 'Poutū-te-rangi', 'Paenga-whāwhā', 'Haratua', 'Pipiri', 'Hōngoingoi', 'Here-turi-kōkā', 'Mahuru', 'Whiringa-ā-nuku', 'Whiringa-ā-rangi', 'Hakihea'], 'months_short' => ['Kohi', 'Hui', 'Pou', 'Pae', 'Hara', 'Pipi', 'Hōngoi', 'Here', 'Mahu', 'Whi-nu', 'Whi-ra', 'Haki'], 'weekdays' => ['Rātapu', 'Mane', 'Tūrei', 'Wenerei', 'Tāite', 'Paraire', 'Hātarei'], 'weekdays_short' => ['Ta', 'Ma', 'Tū', 'We', 'Tāi', 'Pa', 'Hā'], 'weekdays_min' => ['Ta', 'Ma', 'Tū', 'We', 'Tāi', 'Pa', 'Hā'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' me te '], ]; PK������<1Zʷ������Carbon/Lang/zh_Hant_TW.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/zh_Hant.php'; PK������<1Z������Carbon/Lang/uz_Arab.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/fa.php', [ 'weekdays' => ['یکشنبه', 'دوشنبه', 'سه‌شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'], 'weekdays_short' => ['ی.', 'د.', 'س.', 'چ.', 'پ.', 'ج.', 'ش.'], 'weekdays_min' => ['ی.', 'د.', 'س.', 'چ.', 'پ.', 'ج.', 'ش.'], 'months' => ['جنوری', 'فبروری', 'مارچ', 'اپریل', 'می', 'جون', 'جولای', 'اگست', 'سپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'], 'months_short' => ['جنو', 'فبر', 'مار', 'اپر', 'می', 'جون', 'جول', 'اگس', 'سپت', 'اکت', 'نوم', 'دسم'], 'first_day_of_week' => 6, 'weekend' => [4, 5], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY-MM-dd', 'LL' => 'YYYY MMM D', 'LLL' => 'YYYY MMMM D HH:mm', 'LLLL' => 'YYYY MMMM D, dddd HH:mm', ], ]); PK������<1Z)��)����Carbon/Lang/ar_EH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ar.php', [ ]); PK������<1ZhO��O����Carbon/Lang/mai.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/mai_IN.php'; PK������<1Z������Carbon/Lang/guz.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['Ma', 'Mo'], 'weekdays' => ['Chumapiri', 'Chumatato', 'Chumaine', 'Chumatano', 'Aramisi', 'Ichuma', 'Esabato'], 'weekdays_short' => ['Cpr', 'Ctt', 'Cmn', 'Cmt', 'Ars', 'Icm', 'Est'], 'weekdays_min' => ['Cpr', 'Ctt', 'Cmn', 'Cmt', 'Ars', 'Icm', 'Est'], 'months' => ['Chanuari', 'Feburari', 'Machi', 'Apiriri', 'Mei', 'Juni', 'Chulai', 'Agosti', 'Septemba', 'Okitoba', 'Nobemba', 'Disemba'], 'months_short' => ['Can', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Cul', 'Agt', 'Sep', 'Okt', 'Nob', 'Dis'], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'month' => ':count omotunyi', // less reliable 'm' => ':count omotunyi', // less reliable 'a_month' => ':count omotunyi', // less reliable 'week' => ':count isano naibere', // less reliable 'w' => ':count isano naibere', // less reliable 'a_week' => ':count isano naibere', // less reliable 'second' => ':count ibere', // less reliable 's' => ':count ibere', // less reliable 'a_second' => ':count ibere', // less reliable 'year' => ':count omwaka', 'y' => ':count omwaka', 'a_year' => ':count omwaka', 'day' => ':count rituko', 'd' => ':count rituko', 'a_day' => ':count rituko', ]); PK������<1Z}jZN��N����Carbon/Lang/tt.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/tt_RU.php'; PK������<1ZpG��G����Carbon/Lang/en_KN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z* T������Carbon/Lang/nmg.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['maná', 'kugú'], 'weekdays' => ['sɔ́ndɔ', 'mɔ́ndɔ', 'sɔ́ndɔ mafú mába', 'sɔ́ndɔ mafú málal', 'sɔ́ndɔ mafú mána', 'mabágá má sukul', 'sásadi'], 'weekdays_short' => ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'mbs', 'sas'], 'weekdays_min' => ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'mbs', 'sas'], 'months' => ['ngwɛn matáhra', 'ngwɛn ńmba', 'ngwɛn ńlal', 'ngwɛn ńna', 'ngwɛn ńtan', 'ngwɛn ńtuó', 'ngwɛn hɛmbuɛrí', 'ngwɛn lɔmbi', 'ngwɛn rɛbvuâ', 'ngwɛn wum', 'ngwɛn wum navǔr', 'krísimin'], 'months_short' => ['ng1', 'ng2', 'ng3', 'ng4', 'ng5', 'ng6', 'ng7', 'ng8', 'ng9', 'ng10', 'ng11', 'kris'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], ]); PK������<1ZC=5 �� ����Carbon/Lang/ru_KG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ru.php'; PK������<1Z\������Carbon/Lang/mas.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['Ɛnkakɛnyá', 'Ɛndámâ'], 'weekdays' => ['Jumapílí', 'Jumatátu', 'Jumane', 'Jumatánɔ', 'Alaámisi', 'Jumáa', 'Jumamósi'], 'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'], 'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'], 'months' => ['Oladalʉ́', 'Arát', 'Ɔɛnɨ́ɔɨŋɔk', 'Olodoyíóríê inkókúâ', 'Oloilépūnyīē inkókúâ', 'Kújúɔrɔk', 'Mórusásin', 'Ɔlɔ́ɨ́bɔ́rárɛ', 'Kúshîn', 'Olgísan', 'Pʉshʉ́ka', 'Ntʉ́ŋʉ́s'], 'months_short' => ['Dal', 'Ará', 'Ɔɛn', 'Doy', 'Lép', 'Rok', 'Sás', 'Bɔ́r', 'Kús', 'Gís', 'Shʉ́', 'Ntʉ́'], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'year' => ':count olameyu', // less reliable 'y' => ':count olameyu', // less reliable 'a_year' => ':count olameyu', // less reliable 'week' => ':count engolongeare orwiki', // less reliable 'w' => ':count engolongeare orwiki', // less reliable 'a_week' => ':count engolongeare orwiki', // less reliable 'hour' => ':count esahabu', // less reliable 'h' => ':count esahabu', // less reliable 'a_hour' => ':count esahabu', // less reliable 'second' => ':count are', // less reliable 's' => ':count are', // less reliable 'a_second' => ':count are', // less reliable 'month' => ':count olapa', 'm' => ':count olapa', 'a_month' => ':count olapa', 'day' => ':count enkolongʼ', 'd' => ':count enkolongʼ', 'a_day' => ':count enkolongʼ', ]); PK������<1Z''x �� ����Carbon/Lang/fr_SC.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1ZpG��G����Carbon/Lang/en_CX.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZO��O����Carbon/Lang/nhn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/nhn_MX.php'; PK������<1Zއ �� ����Carbon/Lang/ml.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - JD Isaacks */ return [ 'year' => ':count വർഷം', 'a_year' => 'ഒരു വർഷം|:count വർഷം', 'month' => ':count മാസം', 'a_month' => 'ഒരു മാസം|:count മാസം', 'week' => ':count ആഴ്ച', 'a_week' => 'ഒരാഴ്ച|:count ആഴ്ച', 'day' => ':count ദിവസം', 'a_day' => 'ഒരു ദിവസം|:count ദിവസം', 'hour' => ':count മണിക്കൂർ', 'a_hour' => 'ഒരു മണിക്കൂർ|:count മണിക്കൂർ', 'minute' => ':count മിനിറ്റ്', 'a_minute' => 'ഒരു മിനിറ്റ്|:count മിനിറ്റ്', 'second' => ':count സെക്കൻഡ്', 'a_second' => 'അൽപ നിമിഷങ്ങൾ|:count സെക്കൻഡ്', 'ago' => ':time മുൻപ്', 'from_now' => ':time കഴിഞ്ഞ്', 'diff_now' => 'ഇപ്പോൾ', 'diff_today' => 'ഇന്ന്', 'diff_yesterday' => 'ഇന്നലെ', 'diff_tomorrow' => 'നാളെ', 'formats' => [ 'LT' => 'A h:mm -നു', 'LTS' => 'A h:mm:ss -നു', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY, A h:mm -നു', 'LLLL' => 'dddd, D MMMM YYYY, A h:mm -നു', ], 'calendar' => [ 'sameDay' => '[ഇന്ന്] LT', 'nextDay' => '[നാളെ] LT', 'nextWeek' => 'dddd, LT', 'lastDay' => '[ഇന്നലെ] LT', 'lastWeek' => '[കഴിഞ്ഞ] dddd, LT', 'sameElse' => 'L', ], 'meridiem' => function ($hour) { if ($hour < 4) { return 'രാത്രി'; } if ($hour < 12) { return 'രാവിലെ'; } if ($hour < 17) { return 'ഉച്ച കഴിഞ്ഞ്'; } if ($hour < 20) { return 'വൈകുന്നേരം'; } return 'രാത്രി'; }, 'months' => ['ജനുവരി', 'ഫെബ്രുവരി', 'മാർച്ച്', 'ഏപ്രിൽ', 'മേയ്', 'ജൂൺ', 'ജൂലൈ', 'ഓഗസ്റ്റ്', 'സെപ്റ്റംബർ', 'ഒക്ടോബർ', 'നവംബർ', 'ഡിസംബർ'], 'months_short' => ['ജനു.', 'ഫെബ്രു.', 'മാർ.', 'ഏപ്രി.', 'മേയ്', 'ജൂൺ', 'ജൂലൈ.', 'ഓഗ.', 'സെപ്റ്റ.', 'ഒക്ടോ.', 'നവം.', 'ഡിസം.'], 'weekdays' => ['ഞായറാഴ്ച', 'തിങ്കളാഴ്ച', 'ചൊവ്വാഴ്ച', 'ബുധനാഴ്ച', 'വ്യാഴാഴ്ച', 'വെള്ളിയാഴ്ച', 'ശനിയാഴ്ച'], 'weekdays_short' => ['ഞായർ', 'തിങ്കൾ', 'ചൊവ്വ', 'ബുധൻ', 'വ്യാഴം', 'വെള്ളി', 'ശനി'], 'weekdays_min' => ['ഞാ', 'തി', 'ചൊ', 'ബു', 'വ്യാ', 'വെ', 'ശ'], 'list' => ', ', 'weekend' => [0, 0], ]; PK������<1ZC=5 �� ����Carbon/Lang/ru_KZ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ru.php'; PK������<1Z[ia �� ����Carbon/Lang/pt_GW.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/pt.php'; PK������<1ZpG��G����Carbon/Lang/en_MU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZI ������Carbon/Lang/lkt.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'month' => ':count haŋwí', // less reliable 'm' => ':count haŋwí', // less reliable 'a_month' => ':count haŋwí', // less reliable 'week' => ':count šakówiŋ', // less reliable 'w' => ':count šakówiŋ', // less reliable 'a_week' => ':count šakówiŋ', // less reliable 'hour' => ':count maza škaŋškaŋ', // less reliable 'h' => ':count maza škaŋškaŋ', // less reliable 'a_hour' => ':count maza škaŋškaŋ', // less reliable 'minute' => ':count číkʼala', // less reliable 'min' => ':count číkʼala', // less reliable 'a_minute' => ':count číkʼala', // less reliable 'year' => ':count waníyetu', 'y' => ':count waníyetu', 'a_year' => ':count waníyetu', 'day' => ':count aŋpétu', 'd' => ':count aŋpétu', 'a_day' => ':count aŋpétu', 'second' => ':count icinuŋpa', 's' => ':count icinuŋpa', 'a_second' => ':count icinuŋpa', ]); PK������<1Zƪ������Carbon/Lang/pa_Arab.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ur.php', [ 'weekdays' => ['اتوار', 'پیر', 'منگل', 'بُدھ', 'جمعرات', 'جمعہ', 'ہفتہ'], 'weekdays_short' => ['اتوار', 'پیر', 'منگل', 'بُدھ', 'جمعرات', 'جمعہ', 'ہفتہ'], 'weekdays_min' => ['اتوار', 'پیر', 'منگل', 'بُدھ', 'جمعرات', 'جمعہ', 'ہفتہ'], 'months' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئ', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'], 'months_short' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئ', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'], 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY h:mm a', 'LLLL' => 'dddd, DD MMMM YYYY h:mm a', ], ]); PK������<1Z_������Carbon/Lang/az_Latn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/az.php', [ 'meridiem' => ['a', 'p'], 'weekdays' => ['bazar', 'bazar ertəsi', 'çərşənbə axşamı', 'çərşənbə', 'cümə axşamı', 'cümə', 'şənbə'], 'weekdays_short' => ['B.', 'B.E.', 'Ç.A.', 'Ç.', 'C.A.', 'C.', 'Ş.'], 'weekdays_min' => ['B.', 'B.E.', 'Ç.A.', 'Ç.', 'C.A.', 'C.', 'Ş.'], 'months' => ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust', 'sentyabr', 'oktyabr', 'noyabr', 'dekabr'], 'months_short' => ['yan', 'fev', 'mar', 'apr', 'may', 'iyn', 'iyl', 'avq', 'sen', 'okt', 'noy', 'dek'], 'months_standalone' => ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'İyun', 'İyul', 'Avqust', 'Sentyabr', 'Oktyabr', 'Noyabr', 'Dekabr'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'D MMMM YYYY, dddd HH:mm', ], ]); PK������<1Zޙ������Carbon/Lang/ta_SG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ta.php', [ 'formats' => [ 'LT' => 'a h:mm', 'LTS' => 'a h:mm:ss', 'L' => 'D/M/yy', 'LL' => 'D MMM, YYYY', 'LLL' => 'D MMMM, YYYY, a h:mm', 'LLLL' => 'dddd, D MMMM, YYYY, a h:mm', ], 'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'], 'months_short' => ['ஜன.', 'பிப்.', 'மார்.', 'ஏப்.', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக.', 'செப்.', 'அக்.', 'நவ.', 'டிச.'], 'weekdays' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'], 'weekdays_short' => ['ஞாயி.', 'திங்.', 'செவ்.', 'புத.', 'வியா.', 'வெள்.', 'சனி'], 'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'], 'meridiem' => ['மு.ப', 'பி.ப'], ]); PK������<1Z泺4>��>����Carbon/Lang/ar_LB.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org * - Abdullah-Alhariri */ return array_replace_recursive(require __DIR__.'/ar.php', [ 'formats' => [ 'L' => 'DD MMM, YYYY', ], 'months' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'], 'months_short' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'], 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'], ]); PK������<1ZpG��G����Carbon/Lang/en_MP.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z''x �� ����Carbon/Lang/fr_BJ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Zd������Carbon/Lang/es_PA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]); PK������<1Z 7|��|����Carbon/Lang/mhr_RU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - PeshSajSoft Ltd. Vyacheslav Kileev slavakileev@yandex.ru */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'YYYY.MM.DD', ], 'months' => ['Шорыкйол', 'Пургыж', 'Ӱярня', 'Вӱдшор', 'Ага', 'Пеледыш', 'Сӱрем', 'Сорла', 'Идым', 'Шыжа', 'Кылме', 'Теле'], 'months_short' => ['Шрк', 'Пгж', 'Ӱрн', 'Вшр', 'Ага', 'Пдш', 'Срм', 'Срл', 'Идм', 'Шыж', 'Клм', 'Тел'], 'weekdays' => ['Рушарня', 'Шочмо', 'Кушкыжмо', 'Вӱргече', 'Изарня', 'Кугарня', 'Шуматкече'], 'weekdays_short' => ['Ршр', 'Шчм', 'Кжм', 'Вгч', 'Изр', 'Кгр', 'Шмт'], 'weekdays_min' => ['Ршр', 'Шчм', 'Кжм', 'Вгч', 'Изр', 'Кгр', 'Шмт'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'year' => ':count идалык', 'y' => ':count идалык', 'a_year' => ':count идалык', 'month' => ':count Тылзе', 'm' => ':count Тылзе', 'a_month' => ':count Тылзе', 'week' => ':count арня', 'w' => ':count арня', 'a_week' => ':count арня', 'day' => ':count кече', 'd' => ':count кече', 'a_day' => ':count кече', 'hour' => ':count час', 'h' => ':count час', 'a_hour' => ':count час', 'minute' => ':count минут', 'min' => ':count минут', 'a_minute' => ':count минут', 'second' => ':count кокымшан', 's' => ':count кокымшан', 'a_second' => ':count кокымшан', ]); PK������<1Z. �� ����Carbon/Lang/sv_SE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/sv.php'; PK������<1Z3  �� ����Carbon/Lang/tzm_Latn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - JD Isaacks */ return [ 'year' => '{1}:count asgas|:count isgasn', 'a_year' => 'asgas|:count isgasn', 'month' => '{1}:count ayowr|:count iyyirn', 'a_month' => 'ayowr|:count iyyirn', 'week' => ':count imalass', 'a_week' => ':imalass', 'day' => '{1}:count ass|:count ossan', 'a_day' => 'ass|:count ossan', 'hour' => '{1}:count saɛa|:count tassaɛin', 'a_hour' => '{1}saɛa|:count tassaɛin', 'minute' => ':count minuḍ', 'a_minute' => '{1}minuḍ|:count minuḍ', 'second' => ':count imik', 'a_second' => '{1}imik|:count imik', 'ago' => 'yan :time', 'from_now' => 'dadkh s yan :time', 'diff_yesterday' => 'assant', 'diff_yesterday_regexp' => 'assant(?:\\s+g)?', 'diff_today' => 'asdkh', 'diff_today_regexp' => 'asdkh(?:\\s+g)?', 'diff_tomorrow' => 'aska', 'diff_tomorrow_regexp' => 'aska(?:\\s+g)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[asdkh g] LT', 'nextDay' => '[aska g] LT', 'nextWeek' => 'dddd [g] LT', 'lastDay' => '[assant g] LT', 'lastWeek' => 'dddd [g] LT', 'sameElse' => 'L', ], 'months' => ['innayr', 'brˤayrˤ', 'marˤsˤ', 'ibrir', 'mayyw', 'ywnyw', 'ywlywz', 'ɣwšt', 'šwtanbir', 'ktˤwbrˤ', 'nwwanbir', 'dwjnbir'], 'months_short' => ['innayr', 'brˤayrˤ', 'marˤsˤ', 'ibrir', 'mayyw', 'ywnyw', 'ywlywz', 'ɣwšt', 'šwtanbir', 'ktˤwbrˤ', 'nwwanbir', 'dwjnbir'], 'weekdays' => ['asamas', 'aynas', 'asinas', 'akras', 'akwas', 'asimwas', 'asiḍyas'], 'weekdays_short' => ['asamas', 'aynas', 'asinas', 'akras', 'akwas', 'asimwas', 'asiḍyas'], 'weekdays_min' => ['asamas', 'aynas', 'asinas', 'akras', 'akwas', 'asimwas', 'asiḍyas'], 'meridiem' => ['Zdat azal', 'Ḍeffir aza'], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, ]; PK������<1Zv_��_����Carbon/Lang/bi_VU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Samsung Electronics Co., Ltd. akhilesh.k@samsung.com & maninder1.s@samsung.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'dddd DD MMM YYYY', ], 'months' => ['jenuware', 'febwari', 'maj', 'epril', 'mei', 'jun', 'julae', 'ogis', 'septemba', 'oktoba', 'novemba', 'disemba'], 'months_short' => ['jen', 'feb', 'maj', 'epr', 'mei', 'jun', 'jul', 'ogi', 'sep', 'okt', 'nov', 'dis'], 'weekdays' => ['sande', 'mande', 'maj', 'wota', 'fraede', 'sarede'], 'weekdays_short' => ['san', 'man', 'maj', 'wot', 'fra', 'sar'], 'weekdays_min' => ['san', 'man', 'maj', 'wot', 'fra', 'sar'], 'year' => ':count seven', // less reliable 'y' => ':count seven', // less reliable 'a_year' => ':count seven', // less reliable 'month' => ':count mi', // less reliable 'm' => ':count mi', // less reliable 'a_month' => ':count mi', // less reliable 'week' => ':count sarede', // less reliable 'w' => ':count sarede', // less reliable 'a_week' => ':count sarede', // less reliable 'day' => ':count betde', // less reliable 'd' => ':count betde', // less reliable 'a_day' => ':count betde', // less reliable 'hour' => ':count klok', // less reliable 'h' => ':count klok', // less reliable 'a_hour' => ':count klok', // less reliable 'minute' => ':count smol', // less reliable 'min' => ':count smol', // less reliable 'a_minute' => ':count smol', // less reliable 'second' => ':count tu', // less reliable 's' => ':count tu', // less reliable 'a_second' => ':count tu', // less reliable ]); PK������<1Z?Ej �� ����Carbon/Lang/en_BW.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1ZJ> O��O����Carbon/Lang/lzh.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/lzh_TW.php'; PK������<1ZQJ?��?����Carbon/Lang/tpi_PG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Samsung Electronics Co., Ltd. akhilesh.k@samsung.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['Janueri', 'Februeri', 'Mas', 'Epril', 'Me', 'Jun', 'Julai', 'Ogas', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'], 'months_short' => ['Jan', 'Feb', 'Mas', 'Epr', 'Me', 'Jun', 'Jul', 'Oga', 'Sep', 'Okt', 'Nov', 'Des'], 'weekdays' => ['Sande', 'Mande', 'Tunde', 'Trinde', 'Fonde', 'Fraide', 'Sarere'], 'weekdays_short' => ['San', 'Man', 'Tun', 'Tri', 'Fon', 'Fra', 'Sar'], 'weekdays_min' => ['San', 'Man', 'Tun', 'Tri', 'Fon', 'Fra', 'Sar'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['biknait', 'apinun'], 'year' => 'yia :count', 'y' => 'yia :count', 'a_year' => 'yia :count', 'month' => ':count mun', 'm' => ':count mun', 'a_month' => ':count mun', 'week' => ':count wik', 'w' => ':count wik', 'a_week' => ':count wik', 'day' => ':count de', 'd' => ':count de', 'a_day' => ':count de', 'hour' => ':count aua', 'h' => ':count aua', 'a_hour' => ':count aua', 'minute' => ':count minit', 'min' => ':count minit', 'a_minute' => ':count minit', 'second' => ':count namba tu', 's' => ':count namba tu', 'a_second' => ':count namba tu', ]); PK������<1Z f������Carbon/Lang/luo.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['OD', 'OT'], 'weekdays' => ['Jumapil', 'Wuok Tich', 'Tich Ariyo', 'Tich Adek', 'Tich Ang’wen', 'Tich Abich', 'Ngeso'], 'weekdays_short' => ['JMP', 'WUT', 'TAR', 'TAD', 'TAN', 'TAB', 'NGS'], 'weekdays_min' => ['JMP', 'WUT', 'TAR', 'TAD', 'TAN', 'TAB', 'NGS'], 'months' => ['Dwe mar Achiel', 'Dwe mar Ariyo', 'Dwe mar Adek', 'Dwe mar Ang’wen', 'Dwe mar Abich', 'Dwe mar Auchiel', 'Dwe mar Abiriyo', 'Dwe mar Aboro', 'Dwe mar Ochiko', 'Dwe mar Apar', 'Dwe mar gi achiel', 'Dwe mar Apar gi ariyo'], 'months_short' => ['DAC', 'DAR', 'DAD', 'DAN', 'DAH', 'DAU', 'DAO', 'DAB', 'DOC', 'DAP', 'DGI', 'DAG'], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'year' => 'higni :count', 'y' => 'higni :count', 'a_year' => ':higni :count', 'month' => 'dweche :count', 'm' => 'dweche :count', 'a_month' => 'dweche :count', 'week' => 'jumbe :count', 'w' => 'jumbe :count', 'a_week' => 'jumbe :count', 'day' => 'ndalo :count', 'd' => 'ndalo :count', 'a_day' => 'ndalo :count', 'hour' => 'seche :count', 'h' => 'seche :count', 'a_hour' => 'seche :count', 'minute' => 'dakika :count', 'min' => 'dakika :count', 'a_minute' => 'dakika :count', 'second' => 'nus dakika :count', 's' => 'nus dakika :count', 'a_second' => 'nus dakika :count', ]); PK������<1Z ������Carbon/Lang/es_BO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, ]); PK������<1Zʷ������Carbon/Lang/yue_Hant.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/zh_Hant.php'; PK������<1Z?Ej �� ����Carbon/Lang/en_US.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1ZGF/��/����Carbon/Lang/de.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Michael Hohl * - sheriffmarley * - dennisoderwald * - Timo * - Karag2006 * - Pete Scopes (pdscopes) */ return [ 'year' => ':count Jahr|:count Jahre', 'a_year' => 'ein Jahr|:count Jahre', 'y' => ':count J.', 'month' => ':count Monat|:count Monate', 'a_month' => 'ein Monat|:count Monate', 'm' => ':count Mon.', 'week' => ':count Woche|:count Wochen', 'a_week' => 'eine Woche|:count Wochen', 'w' => ':count Wo.', 'day' => ':count Tag|:count Tage', 'a_day' => 'ein Tag|:count Tage', 'd' => ':count Tg.', 'hour' => ':count Stunde|:count Stunden', 'a_hour' => 'eine Stunde|:count Stunden', 'h' => ':count Std.', 'minute' => ':count Minute|:count Minuten', 'a_minute' => 'eine Minute|:count Minuten', 'min' => ':count Min.', 'second' => ':count Sekunde|:count Sekunden', 'a_second' => 'ein paar Sekunden|:count Sekunden', 's' => ':count Sek.', 'millisecond' => ':count Millisekunde|:count Millisekunden', 'a_millisecond' => 'eine Millisekunde|:count Millisekunden', 'ms' => ':countms', 'microsecond' => ':count Mikrosekunde|:count Mikrosekunden', 'a_microsecond' => 'eine Mikrosekunde|:count Mikrosekunden', 'µs' => ':countµs', 'ago' => 'vor :time', 'from_now' => 'in :time', 'after' => ':time später', 'before' => ':time zuvor', 'year_from_now' => ':count Jahr|:count Jahren', 'month_from_now' => ':count Monat|:count Monaten', 'week_from_now' => ':count Woche|:count Wochen', 'day_from_now' => ':count Tag|:count Tagen', 'year_ago' => ':count Jahr|:count Jahren', 'month_ago' => ':count Monat|:count Monaten', 'week_ago' => ':count Woche|:count Wochen', 'day_ago' => ':count Tag|:count Tagen', 'a_year_from_now' => 'ein Jahr|:count Jahren', 'a_month_from_now' => 'ein Monat|:count Monaten', 'a_week_from_now' => 'eine Woche|:count Wochen', 'a_day_from_now' => 'ein Tag|:count Tagen', 'a_year_ago' => 'ein Jahr|:count Jahren', 'a_month_ago' => 'ein Monat|:count Monaten', 'a_week_ago' => 'eine Woche|:count Wochen', 'a_day_ago' => 'ein Tag|:count Tagen', 'diff_now' => 'Gerade eben', 'diff_today' => 'heute', 'diff_today_regexp' => 'heute(?:\\s+um)?', 'diff_yesterday' => 'Gestern', 'diff_yesterday_regexp' => 'gestern(?:\\s+um)?', 'diff_tomorrow' => 'Morgen', 'diff_tomorrow_regexp' => 'morgen(?:\\s+um)?', 'diff_before_yesterday' => 'Vorgestern', 'diff_after_tomorrow' => 'Übermorgen', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D. MMMM YYYY', 'LLL' => 'D. MMMM YYYY HH:mm', 'LLLL' => 'dddd, D. MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[heute um] LT [Uhr]', 'nextDay' => '[morgen um] LT [Uhr]', 'nextWeek' => 'dddd [um] LT [Uhr]', 'lastDay' => '[gestern um] LT [Uhr]', 'lastWeek' => '[letzten] dddd [um] LT [Uhr]', 'sameElse' => 'L', ], 'months' => ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'], 'months_short' => ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'], 'weekdays' => ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'], 'weekdays_short' => ['So.', 'Mo.', 'Di.', 'Mi.', 'Do.', 'Fr.', 'Sa.'], 'weekdays_min' => ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'], 'ordinal' => ':number.', 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' und '], 'ordinal_words' => [ 'of' => 'im', 'first' => 'erster', 'second' => 'zweiter', 'third' => 'dritter', 'fourth' => 'vierten', 'fifth' => 'fünfter', 'last' => 'letzten', ], ]; PK������<1ZK �� ����Carbon/Lang/eu_ES.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/eu.php'; PK������<1ZzO��O����Carbon/Lang/mjw.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/mjw_IN.php'; PK������<1ZQ_L#��#����Carbon/Lang/uz_UZ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Bobir Ismailov Bobir Ismailov, Pablo Saratxaga, Mashrab Kuvatov bobir_is@yahoo.com, pablo@mandrakesoft.com, kmashrab@uni-bremen.de */ return array_replace_recursive(require __DIR__.'/uz_Latn.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'months' => ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'Iyun', 'Iyul', 'Avgust', 'Sentabr', 'Oktabr', 'Noyabr', 'Dekabr'], 'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'Iyn', 'Iyl', 'Avg', 'Sen', 'Okt', 'Noy', 'Dek'], 'weekdays' => ['Yakshanba', 'Dushanba', 'Seshanba', 'Chorshanba', 'Payshanba', 'Juma', 'Shanba'], 'weekdays_short' => ['Yak', 'Du', 'Se', 'Cho', 'Pay', 'Ju', 'Sha'], 'weekdays_min' => ['Yak', 'Du', 'Se', 'Cho', 'Pay', 'Ju', 'Sha'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, ]); PK������<1Z"Ϟ �� ����Carbon/Lang/fo.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Kristian Sakarisson * - François B * - JD Isaacks * - Sverri Mohr Olsen */ return [ 'year' => 'eitt ár|:count ár', 'y' => ':count ár|:count ár', 'month' => 'ein mánaði|:count mánaðir', 'm' => ':count mánaður|:count mánaðir', 'week' => ':count vika|:count vikur', 'w' => ':count vika|:count vikur', 'day' => 'ein dagur|:count dagar', 'd' => ':count dag|:count dagar', 'hour' => 'ein tími|:count tímar', 'h' => ':count tími|:count tímar', 'minute' => 'ein minutt|:count minuttir', 'min' => ':count minutt|:count minuttir', 'second' => 'fá sekund|:count sekundir', 's' => ':count sekund|:count sekundir', 'ago' => ':time síðani', 'from_now' => 'um :time', 'after' => ':time aftaná', 'before' => ':time áðrenn', 'diff_today' => 'Í', 'diff_yesterday' => 'Í', 'diff_yesterday_regexp' => 'Í(?:\\s+gjár)?(?:\\s+kl.)?', 'diff_tomorrow' => 'Í', 'diff_tomorrow_regexp' => 'Í(?:\\s+morgin)?(?:\\s+kl.)?', 'diff_today_regexp' => 'Í(?:\\s+dag)?(?:\\s+kl.)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D. MMMM, YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[Í dag kl.] LT', 'nextDay' => '[Í morgin kl.] LT', 'nextWeek' => 'dddd [kl.] LT', 'lastDay' => '[Í gjár kl.] LT', 'lastWeek' => '[síðstu] dddd [kl] LT', 'sameElse' => 'L', ], 'ordinal' => ':number.', 'months' => ['januar', 'februar', 'mars', 'apríl', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember'], 'months_short' => ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'], 'weekdays' => ['sunnudagur', 'mánadagur', 'týsdagur', 'mikudagur', 'hósdagur', 'fríggjadagur', 'leygardagur'], 'weekdays_short' => ['sun', 'mán', 'týs', 'mik', 'hós', 'frí', 'ley'], 'weekdays_min' => ['su', 'má', 'tý', 'mi', 'hó', 'fr', 'le'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' og '], ]; PK������<1Z������Carbon/Lang/ebu.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['KI', 'UT'], 'weekdays' => ['Kiumia', 'Njumatatu', 'Njumaine', 'Njumatano', 'Aramithi', 'Njumaa', 'NJumamothii'], 'weekdays_short' => ['Kma', 'Tat', 'Ine', 'Tan', 'Arm', 'Maa', 'NMM'], 'weekdays_min' => ['Kma', 'Tat', 'Ine', 'Tan', 'Arm', 'Maa', 'NMM'], 'months' => ['Mweri wa mbere', 'Mweri wa kaĩri', 'Mweri wa kathatũ', 'Mweri wa kana', 'Mweri wa gatano', 'Mweri wa gatantatũ', 'Mweri wa mũgwanja', 'Mweri wa kanana', 'Mweri wa kenda', 'Mweri wa ikũmi', 'Mweri wa ikũmi na ũmwe', 'Mweri wa ikũmi na Kaĩrĩ'], 'months_short' => ['Mbe', 'Kai', 'Kat', 'Kan', 'Gat', 'Gan', 'Mug', 'Knn', 'Ken', 'Iku', 'Imw', 'Igi'], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], ]); PK������<1Z<0��0����Carbon/Lang/bas.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['I bikɛ̂glà', 'I ɓugajɔp'], 'weekdays' => ['ŋgwà nɔ̂y', 'ŋgwà njaŋgumba', 'ŋgwà ûm', 'ŋgwà ŋgê', 'ŋgwà mbɔk', 'ŋgwà kɔɔ', 'ŋgwà jôn'], 'weekdays_short' => ['nɔy', 'nja', 'uum', 'ŋge', 'mbɔ', 'kɔɔ', 'jon'], 'weekdays_min' => ['nɔy', 'nja', 'uum', 'ŋge', 'mbɔ', 'kɔɔ', 'jon'], 'months' => ['Kɔndɔŋ', 'Màcɛ̂l', 'Màtùmb', 'Màtop', 'M̀puyɛ', 'Hìlòndɛ̀', 'Njèbà', 'Hìkaŋ', 'Dìpɔ̀s', 'Bìòôm', 'Màyɛsèp', 'Lìbuy li ńyèe'], 'months_short' => ['kɔn', 'mac', 'mat', 'mto', 'mpu', 'hil', 'nje', 'hik', 'dip', 'bio', 'may', 'liɓ'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM, YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'second' => ':count móndî', // less reliable 's' => ':count móndî', // less reliable 'a_second' => ':count móndî', // less reliable ]); PK������<1ZpW)Q������Carbon/Lang/kab_DZ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - belkacem77@gmail.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['Yennayer', 'Fuṛar', 'Meɣres', 'Yebrir', 'Mayyu', 'Yunyu', 'Yulyu', 'ɣuct', 'Ctembeṛ', 'Tubeṛ', 'Wambeṛ', 'Dujembeṛ'], 'months_short' => ['Yen', 'Fur', 'Meɣ', 'Yeb', 'May', 'Yun', 'Yul', 'ɣuc', 'Cte', 'Tub', 'Wam', 'Duj'], 'weekdays' => ['Acer', 'Arim', 'Aram', 'Ahad', 'Amhad', 'Sem', 'Sed'], 'weekdays_short' => ['Ace', 'Ari', 'Ara', 'Aha', 'Amh', 'Sem', 'Sed'], 'weekdays_min' => ['Ace', 'Ari', 'Ara', 'Aha', 'Amh', 'Sem', 'Sed'], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'meridiem' => ['FT', 'MD'], 'year' => ':count n yiseggasen', 'y' => ':count n yiseggasen', 'a_year' => ':count n yiseggasen', 'month' => ':count n wayyuren', 'm' => ':count n wayyuren', 'a_month' => ':count n wayyuren', 'week' => ':count n ledwaṛ', // less reliable 'w' => ':count n ledwaṛ', // less reliable 'a_week' => ':count n ledwaṛ', // less reliable 'day' => ':count n wussan', 'd' => ':count n wussan', 'a_day' => ':count n wussan', 'hour' => ':count n tsaɛtin', 'h' => ':count n tsaɛtin', 'a_hour' => ':count n tsaɛtin', 'minute' => ':count n tedqiqin', 'min' => ':count n tedqiqin', 'a_minute' => ':count n tedqiqin', 'second' => ':count tasdidt', // less reliable 's' => ':count tasdidt', // less reliable 'a_second' => ':count tasdidt', // less reliable ]); PK������<1ZEk������Carbon/Lang/nl_BE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Roy * - Stephan * - François B * - Tim Fish * - Kevin Huang * - Jacob Middag * - JD Isaacks * - Propaganistas */ return array_replace_recursive(require __DIR__.'/nl.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], ]); PK������<1ZlIQO��O����Carbon/Lang/yue.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/yue_HK.php'; PK������<1ZNd �� ����Carbon/Lang/i18n.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'YYYY-MM-DD', ], 'months' => ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'], 'months_short' => ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'], 'weekdays' => ['1', '2', '3', '4', '5', '6', '7'], 'weekdays_short' => ['1', '2', '3', '4', '5', '6', '7'], 'weekdays_min' => ['1', '2', '3', '4', '5', '6', '7'], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 4, ]); PK������<1ZpG��G����Carbon/Lang/en_PG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZNU&������Carbon/Lang/ar_AE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org * - Abdullah-Alhariri */ return array_replace_recursive(require __DIR__.'/ar.php', [ 'formats' => [ 'L' => 'DD MMM, YYYY', ], 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'], 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'], 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت '], 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'], ]); PK������<1Zd Z �� ����Carbon/Lang/si_LK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/si.php'; PK������<1Z �� ����Carbon/Lang/sr_Latn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/sr.php'; PK������<1Z9I��I����Carbon/Lang/rn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['Z.MU.', 'Z.MW.'], 'weekdays' => ['Ku w’indwi', 'Ku wa mbere', 'Ku wa kabiri', 'Ku wa gatatu', 'Ku wa kane', 'Ku wa gatanu', 'Ku wa gatandatu'], 'weekdays_short' => ['cu.', 'mbe.', 'kab.', 'gtu.', 'kan.', 'gnu.', 'gnd.'], 'weekdays_min' => ['cu.', 'mbe.', 'kab.', 'gtu.', 'kan.', 'gnu.', 'gnd.'], 'months' => ['Nzero', 'Ruhuhuma', 'Ntwarante', 'Ndamukiza', 'Rusama', 'Ruheshi', 'Mukakaro', 'Nyandagaro', 'Nyakanga', 'Gitugutu', 'Munyonyo', 'Kigarama'], 'months_short' => ['Mut.', 'Gas.', 'Wer.', 'Mat.', 'Gic.', 'Kam.', 'Nya.', 'Kan.', 'Nze.', 'Ukw.', 'Ugu.', 'Uku.'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'year' => 'imyaka :count', 'y' => 'imyaka :count', 'a_year' => 'imyaka :count', 'month' => 'amezi :count', 'm' => 'amezi :count', 'a_month' => 'amezi :count', 'week' => 'indwi :count', 'w' => 'indwi :count', 'a_week' => 'indwi :count', 'day' => 'imisi :count', 'd' => 'imisi :count', 'a_day' => 'imisi :count', 'hour' => 'amasaha :count', 'h' => 'amasaha :count', 'a_hour' => 'amasaha :count', 'minute' => 'iminuta :count', 'min' => 'iminuta :count', 'a_minute' => 'iminuta :count', 'second' => 'inguvu :count', // less reliable 's' => 'inguvu :count', // less reliable 'a_second' => 'inguvu :count', // less reliable ]); PK������<1Zς������Carbon/Lang/tr_CY.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/tr.php', [ 'weekdays_short' => ['Paz', 'Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cmt'], 'weekdays_min' => ['Pa', 'Pt', 'Sa', 'Ça', 'Pe', 'Cu', 'Ct'], 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'D.MM.YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY h:mm a', 'LLLL' => 'D MMMM YYYY dddd h:mm a', ], ]); PK������<1Zv������Carbon/Lang/sw_TZ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Kamusi Project Martin Benjamin locales@kamusi.org */ return array_replace_recursive(require __DIR__.'/sw.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'], 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'], 'weekdays' => ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi', 'Ijumaa', 'Jumamosi'], 'weekdays_short' => ['J2', 'J3', 'J4', 'J5', 'Alh', 'Ij', 'J1'], 'weekdays_min' => ['J2', 'J3', 'J4', 'J5', 'Alh', 'Ij', 'J1'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'meridiem' => ['asubuhi', 'alasiri'], ]); PK������<1ZpG��G����Carbon/Lang/en_150.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZDO��O����Carbon/Lang/bem.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/bem_ZM.php'; PK������<1Z"BO��O����Carbon/Lang/anp.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/anp_IN.php'; PK������<1Z8 �� ����Carbon/Lang/tzm.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - JD Isaacks */ return [ 'year' => '{1}ⴰⵙⴳⴰⵙ|:count ⵉⵙⴳⴰⵙⵏ', 'month' => '{1}ⴰⵢoⵓⵔ|:count ⵉⵢⵢⵉⵔⵏ', 'week' => ':count ⵉⵎⴰⵍⴰⵙⵙ', 'day' => '{1}ⴰⵙⵙ|:count oⵙⵙⴰⵏ', 'hour' => '{1}ⵙⴰⵄⴰ|:count ⵜⴰⵙⵙⴰⵄⵉⵏ', 'minute' => '{1}ⵎⵉⵏⵓⴺ|:count ⵎⵉⵏⵓⴺ', 'second' => '{1}ⵉⵎⵉⴽ|:count ⵉⵎⵉⴽ', 'ago' => 'ⵢⴰⵏ :time', 'from_now' => 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ :time', 'diff_today' => 'ⴰⵙⴷⵅ', 'diff_yesterday' => 'ⴰⵚⴰⵏⵜ', 'diff_yesterday_regexp' => 'ⴰⵚⴰⵏⵜ(?:\\s+ⴴ)?', 'diff_tomorrow' => 'ⴰⵙⴽⴰ', 'diff_tomorrow_regexp' => 'ⴰⵙⴽⴰ(?:\\s+ⴴ)?', 'diff_today_regexp' => 'ⴰⵙⴷⵅ(?:\\s+ⴴ)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[ⴰⵙⴷⵅ ⴴ] LT', 'nextDay' => '[ⴰⵙⴽⴰ ⴴ] LT', 'nextWeek' => 'dddd [ⴴ] LT', 'lastDay' => '[ⴰⵚⴰⵏⵜ ⴴ] LT', 'lastWeek' => 'dddd [ⴴ] LT', 'sameElse' => 'L', ], 'months' => ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ', 'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ', 'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ', 'ⴽⵟⵓⴱⵕ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⵏⴱⵉⵔ'], 'months_short' => ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ', 'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ', 'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ', 'ⴽⵟⵓⴱⵕ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⵏⴱⵉⵔ'], 'weekdays' => ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ', 'ⴰⵙⵉⵏⴰⵙ', 'ⴰⴽⵔⴰⵙ', 'ⴰⴽⵡⴰⵙ', 'ⴰⵙⵉⵎⵡⴰⵙ', 'ⴰⵙⵉⴹⵢⴰⵙ'], 'weekdays_short' => ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ', 'ⴰⵙⵉⵏⴰⵙ', 'ⴰⴽⵔⴰⵙ', 'ⴰⴽⵡⴰⵙ', 'ⴰⵙⵉⵎⵡⴰⵙ', 'ⴰⵙⵉⴹⵢⴰⵙ'], 'weekdays_min' => ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ', 'ⴰⵙⵉⵏⴰⵙ', 'ⴰⴽⵔⴰⵙ', 'ⴰⴽⵡⴰⵙ', 'ⴰⵙⵉⵎⵡⴰⵙ', 'ⴰⵙⵉⴹⵢⴰⵙ'], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'weekend' => [5, 6], ]; PK������<1Z8O��O����Carbon/Lang/chr.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/chr_US.php'; PK������<1Zq a �� ����Carbon/Lang/it_SM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/it.php'; PK������<1ZUG �� ����Carbon/Lang/tzl.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return [ 'year' => '[0,1]:count ar|:count ars', 'y' => '[0,1]:count ar|:count ars', 'month' => '[0,1]:count mes|:count mesen', 'm' => '[0,1]:count mes|:count mesen', 'week' => '[0,1]:count seifetziua|:count seifetziuas', 'w' => '[0,1]:count seifetziua|:count seifetziuas', 'day' => '[0,1]:count ziua|:count ziuas', 'd' => '[0,1]:count ziua|:count ziuas', 'hour' => '[0,1]:count þora|:count þoras', 'h' => '[0,1]:count þora|:count þoras', 'minute' => '[0,1]:count míut|:count míuts', 'min' => '[0,1]:count míut|:count míuts', 'second' => ':count secunds', 's' => ':count secunds', 'ago' => 'ja :time', 'from_now' => 'osprei :time', 'diff_yesterday' => 'ieiri', 'diff_yesterday_regexp' => 'ieiri(?:\\s+à)?', 'diff_today' => 'oxhi', 'diff_today_regexp' => 'oxhi(?:\\s+à)?', 'diff_tomorrow' => 'demà', 'diff_tomorrow_regexp' => 'demà(?:\\s+à)?', 'formats' => [ 'LT' => 'HH.mm', 'LTS' => 'HH.mm.ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D. MMMM [dallas] YYYY', 'LLL' => 'D. MMMM [dallas] YYYY HH.mm', 'LLLL' => 'dddd, [li] D. MMMM [dallas] YYYY HH.mm', ], 'calendar' => [ 'sameDay' => '[oxhi à] LT', 'nextDay' => '[demà à] LT', 'nextWeek' => 'dddd [à] LT', 'lastDay' => '[ieiri à] LT', 'lastWeek' => '[sür el] dddd [lasteu à] LT', 'sameElse' => 'L', ], 'meridiem' => ["D'A", "D'O"], 'months' => ['Januar', 'Fevraglh', 'Març', 'Avrïu', 'Mai', 'Gün', 'Julia', 'Guscht', 'Setemvar', 'Listopäts', 'Noemvar', 'Zecemvar'], 'months_short' => ['Jan', 'Fev', 'Mar', 'Avr', 'Mai', 'Gün', 'Jul', 'Gus', 'Set', 'Lis', 'Noe', 'Zec'], 'weekdays' => ['Súladi', 'Lúneçi', 'Maitzi', 'Márcuri', 'Xhúadi', 'Viénerçi', 'Sáturi'], 'weekdays_short' => ['Súl', 'Lún', 'Mai', 'Már', 'Xhú', 'Vié', 'Sát'], 'weekdays_min' => ['Sú', 'Lú', 'Ma', 'Má', 'Xh', 'Vi', 'Sá'], 'ordinal' => ':number.', 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, ]; PK������<1Zaz������Carbon/Lang/hy_AM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - François B * - Tim Fish * - Serhan Apaydın * - JD Isaacks */ return array_replace_recursive(require __DIR__.'/hy.php', [ 'from_now' => ':time հետո', 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, ]); PK������<1ZpG��G����Carbon/Lang/en_GD.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z0RXw������Carbon/Lang/chr_US.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Cherokee Nation Joseph Erb josepherb7@gmail.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'MM/DD/YYYY', ], 'months' => ['ᎤᏃᎸᏔᏅ', 'ᎧᎦᎵ', 'ᎠᏅᏱ', 'ᎧᏬᏂ', 'ᎠᏂᏍᎬᏘ', 'ᏕᎭᎷᏱ', 'ᎫᏰᏉᏂ', 'ᎦᎶᏂ', 'ᏚᎵᏍᏗ', 'ᏚᏂᏅᏗ', 'ᏅᏓᏕᏆ', 'ᎥᏍᎩᏱ'], 'months_short' => ['ᎤᏃ', 'ᎧᎦ', 'ᎠᏅ', 'ᎧᏬ', 'ᎠᏂ', 'ᏕᎭ', 'ᎫᏰ', 'ᎦᎶ', 'ᏚᎵ', 'ᏚᏂ', 'ᏅᏓ', 'ᎥᏍ'], 'weekdays' => ['ᎤᎾᏙᏓᏆᏍᎬ', 'ᎤᎾᏙᏓᏉᏅᎯ', 'ᏔᎵᏁᎢᎦ', 'ᏦᎢᏁᎢᎦ', 'ᏅᎩᏁᎢᎦ', 'ᏧᎾᎩᎶᏍᏗ', 'ᎤᎾᏙᏓᏈᏕᎾ'], 'weekdays_short' => ['ᏆᏍᎬ', 'ᏉᏅᎯ', 'ᏔᎵᏁ', 'ᏦᎢᏁ', 'ᏅᎩᏁ', 'ᏧᎾᎩ', 'ᏈᏕᎾ'], 'weekdays_min' => ['ᏆᏍᎬ', 'ᏉᏅᎯ', 'ᏔᎵᏁ', 'ᏦᎢᏁ', 'ᏅᎩᏁ', 'ᏧᎾᎩ', 'ᏈᏕᎾ'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['ᏌᎾᎴ', 'ᏒᎯᏱᎢᏗᏢ', 'ꮜꮎꮄ', 'ꮢꭿᏹꭲꮧꮲ'], 'second' => ':count ᏐᎢ', // less reliable 's' => ':count ᏐᎢ', // less reliable 'a_second' => ':count ᏐᎢ', // less reliable 'year' => ':count ᏑᏕᏘᏴᏓ', 'y' => ':count ᏑᏕᏘᏴᏓ', 'a_year' => ':count ᏑᏕᏘᏴᏓ', 'month' => ':count ᏏᏅᏙ', 'm' => ':count ᏏᏅᏙ', 'a_month' => ':count ᏏᏅᏙ', 'week' => ':count ᏑᎾᏙᏓᏆᏍᏗ', 'w' => ':count ᏑᎾᏙᏓᏆᏍᏗ', 'a_week' => ':count ᏑᎾᏙᏓᏆᏍᏗ', 'day' => ':count ᎢᎦ', 'd' => ':count ᎢᎦ', 'a_day' => ':count ᎢᎦ', 'hour' => ':count ᏑᏟᎶᏛ', 'h' => ':count ᏑᏟᎶᏛ', 'a_hour' => ':count ᏑᏟᎶᏛ', 'minute' => ':count ᎢᏯᏔᏬᏍᏔᏅ', 'min' => ':count ᎢᏯᏔᏬᏍᏔᏅ', 'a_minute' => ':count ᎢᏯᏔᏬᏍᏔᏅ', 'ago' => ':time ᏥᎨᏒ', 'from_now' => 'ᎾᎿ :time', ]); PK������<1Z%u��u����Carbon/Lang/ia_FR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Fedora Project Nik Kalach nikka@fedoraproject.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], 'months' => ['januario', 'februario', 'martio', 'april', 'maio', 'junio', 'julio', 'augusto', 'septembre', 'octobre', 'novembre', 'decembre'], 'months_short' => ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'], 'weekdays' => ['dominica', 'lunedi', 'martedi', 'mercuridi', 'jovedi', 'venerdi', 'sabbato'], 'weekdays_short' => ['dom', 'lun', 'mar', 'mer', 'jov', 'ven', 'sab'], 'weekdays_min' => ['dom', 'lun', 'mar', 'mer', 'jov', 'ven', 'sab'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'year' => 'anno :count', 'y' => 'anno :count', 'a_year' => 'anno :count', 'month' => ':count mense', 'm' => ':count mense', 'a_month' => ':count mense', 'week' => ':count septimana', 'w' => ':count septimana', 'a_week' => ':count septimana', 'day' => ':count die', 'd' => ':count die', 'a_day' => ':count die', 'hour' => ':count hora', 'h' => ':count hora', 'a_hour' => ':count hora', 'minute' => ':count minuscule', 'min' => ':count minuscule', 'a_minute' => ':count minuscule', 'second' => ':count secunda', 's' => ':count secunda', 'a_second' => ':count secunda', ]); PK������<1Z7\��\����Carbon/Lang/sr_Cyrl.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - François B * - shaishavgandhi05 * - Serhan Apaydın * - JD Isaacks * - Glavić * - Nikola Zeravcic * - Milos Sakovic */ use Carbon\CarbonInterface; return [ 'year' => ':count година|:count године|:count година', 'y' => ':count г.', 'month' => ':count месец|:count месеца|:count месеци', 'm' => ':count м.', 'week' => ':count недеља|:count недеље|:count недеља', 'w' => ':count нед.', 'day' => ':count дан|:count дана|:count дана', 'd' => ':count д.', 'hour' => ':count сат|:count сата|:count сати', 'h' => ':count ч.', 'minute' => ':count минут|:count минута|:count минута', 'min' => ':count мин.', 'second' => ':count секунд|:count секунде|:count секунди', 's' => ':count сек.', 'ago' => 'пре :time', 'from_now' => 'за :time', 'after' => ':time након', 'before' => ':time пре', 'year_from_now' => ':count годину|:count године|:count година', 'year_ago' => ':count годину|:count године|:count година', 'week_from_now' => ':count недељу|:count недеље|:count недеља', 'week_ago' => ':count недељу|:count недеље|:count недеља', 'diff_now' => 'управо сада', 'diff_today' => 'данас', 'diff_today_regexp' => 'данас(?:\\s+у)?', 'diff_yesterday' => 'јуче', 'diff_yesterday_regexp' => 'јуче(?:\\s+у)?', 'diff_tomorrow' => 'сутра', 'diff_tomorrow_regexp' => 'сутра(?:\\s+у)?', 'diff_before_yesterday' => 'прекјуче', 'diff_after_tomorrow' => 'прекосутра', 'formats' => [ 'LT' => 'H:mm', 'LTS' => 'H:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D. MMMM YYYY', 'LLL' => 'D. MMMM YYYY H:mm', 'LLLL' => 'dddd, D. MMMM YYYY H:mm', ], 'calendar' => [ 'sameDay' => '[данас у] LT', 'nextDay' => '[сутра у] LT', 'nextWeek' => function (CarbonInterface $date) { switch ($date->dayOfWeek) { case 0: return '[у недељу у] LT'; case 3: return '[у среду у] LT'; case 6: return '[у суботу у] LT'; default: return '[у] dddd [у] LT'; } }, 'lastDay' => '[јуче у] LT', 'lastWeek' => function (CarbonInterface $date) { switch ($date->dayOfWeek) { case 0: return '[прошле недеље у] LT'; case 1: return '[прошлог понедељка у] LT'; case 2: return '[прошлог уторка у] LT'; case 3: return '[прошле среде у] LT'; case 4: return '[прошлог четвртка у] LT'; case 5: return '[прошлог петка у] LT'; default: return '[прошле суботе у] LT'; } }, 'sameElse' => 'L', ], 'ordinal' => ':number.', 'months' => ['јануар', 'фебруар', 'март', 'април', 'мај', 'јун', 'јул', 'август', 'септембар', 'октобар', 'новембар', 'децембар'], 'months_short' => ['јан.', 'феб.', 'мар.', 'апр.', 'мај', 'јун', 'јул', 'авг.', 'сеп.', 'окт.', 'нов.', 'дец.'], 'weekdays' => ['недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота'], 'weekdays_short' => ['нед.', 'пон.', 'уто.', 'сре.', 'чет.', 'пет.', 'суб.'], 'weekdays_min' => ['не', 'по', 'ут', 'ср', 'че', 'пе', 'су'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' и '], 'meridiem' => ['АМ', 'ПМ'], ]; PK������<1ZYm6]V��V����Carbon/Lang/doi_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Red Hat Pune libc-alpha@sourceware.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['जनवरी', 'फरवरी', 'मार्च', 'एप्रैल', 'मेई', 'जून', 'जूलै', 'अगस्त', 'सितंबर', 'अक्तूबर', 'नवंबर', 'दिसंबर'], 'months_short' => ['जनवरी', 'फरवरी', 'मार्च', 'एप्रैल', 'मेई', 'जून', 'जूलै', 'अगस्त', 'सितंबर', 'अक्तूबर', 'नवंबर', 'दिसंबर'], 'weekdays' => ['ऐतबार', 'सोमबार', 'मंगलबर', 'बुधबार', 'बीरबार', 'शुक्करबार', 'श्नीचरबार'], 'weekdays_short' => ['ऐत', 'सोम', 'मंगल', 'बुध', 'बीर', 'शुक्कर', 'श्नीचर'], 'weekdays_min' => ['ऐत', 'सोम', 'मंगल', 'बुध', 'बीर', 'शुक्कर', 'श्नीचर'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['सञं', 'सबेर'], 'second' => ':count सङार', // less reliable 's' => ':count सङार', // less reliable 'a_second' => ':count सङार', // less reliable ]); PK������<1ZB������Carbon/Lang/mg_MG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - The Debian Project modified by GNU//Linux Malagasy Rado Ramarotafika,Do-Risika RAFIEFERANTSIARONJY rado@linuxmg.org,dourix@free.fr */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], 'months' => ['Janoary', 'Febroary', 'Martsa', 'Aprily', 'Mey', 'Jona', 'Jolay', 'Aogositra', 'Septambra', 'Oktobra', 'Novambra', 'Desambra'], 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Mey', 'Jon', 'Jol', 'Aog', 'Sep', 'Okt', 'Nov', 'Des'], 'weekdays' => ['alahady', 'alatsinainy', 'talata', 'alarobia', 'alakamisy', 'zoma', 'sabotsy'], 'weekdays_short' => ['lhd', 'lts', 'tlt', 'lrb', 'lkm', 'zom', 'sab'], 'weekdays_min' => ['lhd', 'lts', 'tlt', 'lrb', 'lkm', 'zom', 'sab'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'minute' => ':count minitra', // less reliable 'min' => ':count minitra', // less reliable 'a_minute' => ':count minitra', // less reliable 'year' => ':count taona', 'y' => ':count taona', 'a_year' => ':count taona', 'month' => ':count volana', 'm' => ':count volana', 'a_month' => ':count volana', 'week' => ':count herinandro', 'w' => ':count herinandro', 'a_week' => ':count herinandro', 'day' => ':count andro', 'd' => ':count andro', 'a_day' => ':count andro', 'hour' => ':count ora', 'h' => ':count ora', 'a_hour' => ':count ora', 'second' => ':count segondra', 's' => ':count segondra', 'a_second' => ':count segondra', ]); PK������<1Z?Ej �� ����Carbon/Lang/en_PR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1Zeo������Carbon/Lang/en_ISO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY-MM-dd', 'LL' => 'YYYY MMM D', 'LLL' => 'YYYY MMMM D HH:mm', 'LLLL' => 'dddd, YYYY MMMM DD HH:mm', ], ]); PK������<1Z)��)����Carbon/Lang/ar_KM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ar.php', [ ]); PK������<1Z �� ����Carbon/Lang/ga_IE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ga.php'; PK������<1Z)��)����Carbon/Lang/ar_DJ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ar.php', [ ]); PK������<1ZC)��)����Carbon/Lang/bs_Latn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/bs.php', [ ]); PK������<1Zt������Carbon/Lang/tk_TM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /** * Authors: * - Ghorban M. Tavakoly Pablo Saratxaga & Ghorban M. Tavakoly pablo@walon.org & gmt314@yahoo.com * - SuperManPHP * - Maksat Meredow (isadma) */ $transformDiff = function ($input) { return strtr($input, [ 'sekunt' => 'sekunt', 'hepde' => 'hepde', ]); }; return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], 'months' => ['Ýanwar', 'Fewral', 'Mart', 'Aprel', 'Maý', 'Iýun', 'Iýul', 'Awgust', 'Sentýabr', 'Oktýabr', 'Noýabr', 'Dekabr'], 'months_short' => ['Ýan', 'Few', 'Mar', 'Apr', 'Maý', 'Iýn', 'Iýl', 'Awg', 'Sen', 'Okt', 'Noý', 'Dek'], 'weekdays' => ['Duşenbe', 'Sişenbe', 'Çarşenbe', 'Penşenbe', 'Anna', 'Şenbe', 'Ýekşenbe'], 'weekdays_short' => ['Duş', 'Siş', 'Çar', 'Pen', 'Ann', 'Şen', 'Ýek'], 'weekdays_min' => ['Du', 'Si', 'Ça', 'Pe', 'An', 'Şe', 'Ýe'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'year' => ':count ýyl', 'y' => ':count ýyl', 'a_year' => ':count ýyl', 'month' => ':count aý', 'm' => ':count aý', 'a_month' => ':count aý', 'week' => ':count hepde', 'w' => ':count hepde', 'a_week' => ':count hepde', 'day' => ':count gün', 'd' => ':count gün', 'a_day' => ':count gün', 'hour' => ':count sagat', 'h' => ':count sagat', 'a_hour' => ':count sagat', 'minute' => ':count minut', 'min' => ':count minut', 'a_minute' => ':count minut', 'second' => ':count sekunt', 's' => ':count sekunt', 'a_second' => ':count sekunt', 'ago' => function ($time) use ($transformDiff) { return $transformDiff($time).' ozal'; }, 'from_now' => function ($time) use ($transformDiff) { return $transformDiff($time).' soňra'; }, 'after' => function ($time) use ($transformDiff) { return $transformDiff($time).' soň'; }, 'before' => function ($time) use ($transformDiff) { return $transformDiff($time).' öň'; }, ]); PK������<1Z?Ej �� ����Carbon/Lang/en_DM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1Z5.������Carbon/Lang/shs_CA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Neskie Manuel bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'months' => ['Pellkwet̓min', 'Pelctsipwen̓ten', 'Pellsqépts', 'Peslléwten', 'Pell7ell7é7llqten', 'Pelltspéntsk', 'Pelltqwelq̓wél̓t', 'Pellct̓éxel̓cten', 'Pesqelqlélten', 'Pesllwélsten', 'Pellc7ell7é7llcwten̓', 'Pelltetétq̓em'], 'months_short' => ['Kwe', 'Tsi', 'Sqe', 'Éwt', 'Ell', 'Tsp', 'Tqw', 'Ct̓é', 'Qel', 'Wél', 'U7l', 'Tet'], 'weekdays' => ['Sxetspesq̓t', 'Spetkesq̓t', 'Selesq̓t', 'Skellesq̓t', 'Smesesq̓t', 'Stselkstesq̓t', 'Stqmekstesq̓t'], 'weekdays_short' => ['Sxe', 'Spe', 'Sel', 'Ske', 'Sme', 'Sts', 'Stq'], 'weekdays_min' => ['Sxe', 'Spe', 'Sel', 'Ske', 'Sme', 'Sts', 'Stq'], 'day_of_first_week_of_year' => 1, 'year' => ':count sqlélten', // less reliable 'y' => ':count sqlélten', // less reliable 'a_year' => ':count sqlélten', // less reliable 'month' => ':count swewll', // less reliable 'm' => ':count swewll', // less reliable 'a_month' => ':count swewll', // less reliable 'hour' => ':count seqwlút', // less reliable 'h' => ':count seqwlút', // less reliable 'a_hour' => ':count seqwlút', // less reliable ]); PK������<1ZoR������Carbon/Lang/hr_BA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - DarkoDevelop */ return array_replace_recursive(require __DIR__.'/hr.php', [ 'weekdays' => ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'], 'weekdays_short' => ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'], 'weekdays_min' => ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'], 'months' => ['siječnja', 'veljače', 'ožujka', 'travnja', 'svibnja', 'lipnja', 'srpnja', 'kolovoza', 'rujna', 'listopada', 'studenoga', 'prosinca'], 'months_short' => ['sij', 'velj', 'ožu', 'tra', 'svi', 'lip', 'srp', 'kol', 'ruj', 'lis', 'stu', 'pro'], 'months_standalone' => ['siječanj', 'veljača', 'ožujak', 'travanj', 'svibanj', 'lipanj', 'srpanj', 'kolovoz', 'rujan', 'listopad', 'studeni', 'prosinac'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D. M. yy.', 'LL' => 'D. MMM YYYY.', 'LLL' => 'D. MMMM YYYY. HH:mm', 'LLLL' => 'dddd, D. MMMM YYYY. HH:mm', ], ]); PK������<1Z-!b>��>����Carbon/Lang/ar_SY.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org * - Abdullah-Alhariri */ return array_replace_recursive(require __DIR__.'/ar.php', [ 'formats' => [ 'L' => 'DD MMM, YYYY', ], 'months' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'], 'months_short' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'], 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'], ]); PK������<1ZpG��G����Carbon/Lang/en_LS.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZpG��G����Carbon/Lang/en_MW.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z]C��C����Carbon/Lang/ccp_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ccp.php', [ 'weekend' => [0, 0], ]); PK������<1ZY������Carbon/Lang/mgo.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'weekdays' => ['Aneg 1', 'Aneg 2', 'Aneg 3', 'Aneg 4', 'Aneg 5', 'Aneg 6', 'Aneg 7'], 'weekdays_short' => ['Aneg 1', 'Aneg 2', 'Aneg 3', 'Aneg 4', 'Aneg 5', 'Aneg 6', 'Aneg 7'], 'weekdays_min' => ['1', '2', '3', '4', '5', '6', '7'], 'months' => ['iməg mbegtug', 'imeg àbùbì', 'imeg mbəŋchubi', 'iməg ngwə̀t', 'iməg fog', 'iməg ichiibɔd', 'iməg àdùmbə̀ŋ', 'iməg ichika', 'iməg kud', 'iməg tèsiʼe', 'iməg zò', 'iməg krizmed'], 'months_short' => ['mbegtug', 'imeg àbùbì', 'imeg mbəŋchubi', 'iməg ngwə̀t', 'iməg fog', 'iməg ichiibɔd', 'iməg àdùmbə̀ŋ', 'iməg ichika', 'iməg kud', 'iməg tèsiʼe', 'iməg zò', 'iməg krizmed'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY-MM-dd', 'LL' => 'YYYY MMM D', 'LLL' => 'YYYY MMMM D HH:mm', 'LLLL' => 'dddd, YYYY MMMM DD HH:mm', ], ]); PK������<1Z(|@zG��G����Carbon/Lang/es_EA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 1, ]); PK������<1Z >v��v����Carbon/Lang/ses.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['Adduha', 'Aluula'], 'weekdays' => ['Alhadi', 'Atinni', 'Atalaata', 'Alarba', 'Alhamiisa', 'Alzuma', 'Asibti'], 'weekdays_short' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'], 'weekdays_min' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'], 'months' => ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me', 'Žuweŋ', 'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur', 'Deesanbur'], 'months_short' => ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy', 'Ut', 'Sek', 'Okt', 'Noo', 'Dee'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'month' => ':count alaada', // less reliable 'm' => ':count alaada', // less reliable 'a_month' => ':count alaada', // less reliable 'hour' => ':count ɲaajin', // less reliable 'h' => ':count ɲaajin', // less reliable 'a_hour' => ':count ɲaajin', // less reliable 'minute' => ':count zarbu', // less reliable 'min' => ':count zarbu', // less reliable 'a_minute' => ':count zarbu', // less reliable 'year' => ':count jiiri', 'y' => ':count jiiri', 'a_year' => ':count jiiri', 'week' => ':count jirbiiyye', 'w' => ':count jirbiiyye', 'a_week' => ':count jirbiiyye', 'day' => ':count zaari', 'd' => ':count zaari', 'a_day' => ':count zaari', 'second' => ':count ihinkante', 's' => ':count ihinkante', 'a_second' => ':count ihinkante', ]); PK������<1Z{A ]G��G����Carbon/Lang/it.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ash * - François B * - Marco Perrando * - Massimiliano Caniparoli * - JD Isaacks * - Andrea Martini * - Francesco Marasco * - Tizianoz93 * - Davide Casiraghi (davide-casiraghi) * - Pete Scopes (pdscopes) */ use Carbon\CarbonInterface; return [ 'year' => ':count anno|:count anni', 'a_year' => 'un anno|:count anni', 'y' => ':count anno|:count anni', 'month' => ':count mese|:count mesi', 'a_month' => 'un mese|:count mesi', 'm' => ':count mese|:count mesi', 'week' => ':count settimana|:count settimane', 'a_week' => 'una settimana|:count settimane', 'w' => ':count set.', 'day' => ':count giorno|:count giorni', 'a_day' => 'un giorno|:count giorni', 'd' => ':count g|:count gg', 'hour' => ':count ora|:count ore', 'a_hour' => 'un\'ora|:count ore', 'h' => ':count h', 'minute' => ':count minuto|:count minuti', 'a_minute' => 'un minuto|:count minuti', 'min' => ':count min.', 'second' => ':count secondo|:count secondi', 'a_second' => 'alcuni secondi|:count secondi', 's' => ':count sec.', 'millisecond' => ':count millisecondo|:count millisecondi', 'a_millisecond' => 'un millisecondo|:count millisecondi', 'ms' => ':countms', 'microsecond' => ':count microsecondo|:count microsecondi', 'a_microsecond' => 'un microsecondo|:count microsecondi', 'µs' => ':countµs', 'ago' => ':time fa', 'from_now' => function ($time) { return (preg_match('/^\d.+$/', $time) ? 'tra' : 'in')." $time"; }, 'after' => ':time dopo', 'before' => ':time prima', 'diff_now' => 'proprio ora', 'diff_today' => 'Oggi', 'diff_today_regexp' => 'Oggi(?:\\s+alle)?', 'diff_yesterday' => 'ieri', 'diff_yesterday_regexp' => 'Ieri(?:\\s+alle)?', 'diff_tomorrow' => 'domani', 'diff_tomorrow_regexp' => 'Domani(?:\\s+alle)?', 'diff_before_yesterday' => 'l\'altro ieri', 'diff_after_tomorrow' => 'dopodomani', 'period_interval' => 'ogni :interval', 'period_start_date' => 'dal :date', 'period_end_date' => 'al :date', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[Oggi alle] LT', 'nextDay' => '[Domani alle] LT', 'nextWeek' => 'dddd [alle] LT', 'lastDay' => '[Ieri alle] LT', 'lastWeek' => function (CarbonInterface $date) { switch ($date->dayOfWeek) { case 0: return '[la scorsa] dddd [alle] LT'; default: return '[lo scorso] dddd [alle] LT'; } }, 'sameElse' => 'L', ], 'ordinal' => ':numberº', 'months' => ['gennaio', 'febbraio', 'marzo', 'aprile', 'maggio', 'giugno', 'luglio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dicembre'], 'months_short' => ['gen', 'feb', 'mar', 'apr', 'mag', 'giu', 'lug', 'ago', 'set', 'ott', 'nov', 'dic'], 'weekdays' => ['domenica', 'lunedì', 'martedì', 'mercoledì', 'giovedì', 'venerdì', 'sabato'], 'weekdays_short' => ['dom', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab'], 'weekdays_min' => ['do', 'lu', 'ma', 'me', 'gi', 've', 'sa'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' e '], 'ordinal_words' => [ 'of' => 'di', 'first' => 'primo', 'second' => 'secondo', 'third' => 'terzo', 'fourth' => 'quarto', 'fifth' => 'quinto', 'last' => 'ultimo', ], ]; PK������<1Z �� ����Carbon/Lang/sr_RS@latin.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/sr.php'; PK������<1Zd������Carbon/Lang/es_CL.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]); PK������<1Z$�rl��l����Carbon/Lang/gsw_LI.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/gsw.php', [ 'meridiem' => ['vorm.', 'nam.'], 'months' => ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'Auguscht', 'Septämber', 'Oktoober', 'Novämber', 'Dezämber'], 'first_day_of_week' => 1, 'formats' => [ 'LLL' => 'Do MMMM YYYY HH:mm', 'LLLL' => 'dddd, Do MMMM YYYY HH:mm', ], ]); PK������<1ZW;#��#����Carbon/Lang/ms_BN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ms.php', [ 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'D/MM/yy', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY, h:mm a', 'LLLL' => 'dd MMMM YYYY, h:mm a', ], 'meridiem' => ['a', 'p'], ]); PK������<1ZF������Carbon/Lang/en_DK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Danish Standards Association bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'YYYY-MM-DD', ], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, ]); PK������<1ZbMN��N����Carbon/Lang/ce.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/ce_RU.php'; PK������<1ZN��N����Carbon/Lang/bi.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/bi_VU.php'; PK������<1Zd������Carbon/Lang/es_EC.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]); PK������<1Zҗ1kN��N����Carbon/Lang/aa.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/aa_DJ.php'; PK������<1Z5 ������Carbon/Lang/fo_DK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/fo.php', [ 'formats' => [ 'L' => 'DD.MM.yy', 'LL' => 'DD.MM.YYYY', 'LLL' => 'D. MMMM YYYY, HH:mm', 'LLLL' => 'dddd, D. MMMM YYYY, HH:mm', ], ]); PK������<1Zq~��~����Carbon/Lang/pt_BR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Cassiano Montanari * - Eduardo Dalla Vecchia * - David Rodrigues * - Matt Pope * - François B * - Prodis * - Marlon Maxwel * - JD Isaacks * - Raphael Amorim * - Rafael Raupp * - felipeleite1 * - swalker * - Lucas Macedo * - Paulo Freitas * - Sebastian Thierer */ return array_replace_recursive(require __DIR__.'/pt.php', [ 'period_recurrences' => 'uma|:count vez', 'period_interval' => 'toda :interval', 'formats' => [ 'LLL' => 'D [de] MMMM [de] YYYY [às] HH:mm', 'LLLL' => 'dddd, D [de] MMMM [de] YYYY [às] HH:mm', ], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]); PK������<1Z[ia �� ����Carbon/Lang/pt_LU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/pt.php'; PK������<1Z������Carbon/Lang/wa_BE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Djan SACRE Pablo Saratxaga pablo@mandrakesoft.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['di djanvî', 'di fevrî', 'di måss', 'd’ avri', 'di may', 'di djun', 'di djulete', 'd’ awousse', 'di setimbe', 'd’ octôbe', 'di nôvimbe', 'di decimbe'], 'months_short' => ['dja', 'fev', 'mås', 'avr', 'may', 'djn', 'djl', 'awo', 'set', 'oct', 'nôv', 'dec'], 'weekdays' => ['dimegne', 'londi', 'mårdi', 'mierkidi', 'djudi', 'vénrdi', 'semdi'], 'weekdays_short' => ['dim', 'lon', 'mår', 'mie', 'dju', 'vén', 'sem'], 'weekdays_min' => ['dim', 'lon', 'mår', 'mie', 'dju', 'vén', 'sem'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'year' => ':count anêye', 'y' => ':count anêye', 'a_year' => ':count anêye', 'month' => ':count meûs', 'm' => ':count meûs', 'a_month' => ':count meûs', 'week' => ':count samwinne', 'w' => ':count samwinne', 'a_week' => ':count samwinne', 'day' => ':count djoû', 'd' => ':count djoû', 'a_day' => ':count djoû', 'hour' => ':count eure', 'h' => ':count eure', 'a_hour' => ':count eure', 'minute' => ':count munute', 'min' => ':count munute', 'a_minute' => ':count munute', 'second' => ':count Sigonde', 's' => ':count Sigonde', 'a_second' => ':count Sigonde', ]); PK������<1Zhk �� ����Carbon/Lang/is_IS.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/is.php'; PK������<1Z"M ��M ����Carbon/Lang/si.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - Serhan Apaydın * - JD Isaacks * - Malinda Weerasinghe (MalindaWMD) */ return [ 'year' => '{1}වසර 1|වසර :count', 'a_year' => '{1}වසරක්|වසර :count', 'month' => '{1}මාස 1|මාස :count', 'a_month' => '{1}මාසය|මාස :count', 'week' => '{1}සති 1|සති :count', 'a_week' => '{1}සතියක්|සති :count', 'day' => '{1}දින 1|දින :count', 'a_day' => '{1}දිනක්|දින :count', 'hour' => '{1}පැය 1|පැය :count', 'a_hour' => '{1}පැයක්|පැය :count', 'minute' => '{1}මිනිත්තු 1|මිනිත්තු :count', 'a_minute' => '{1}මිනිත්තුවක්|මිනිත්තු :count', 'second' => '{1}තත්පර 1|තත්පර :count', 'a_second' => '{1}තත්පර කිහිපයකට|තත්පර :count', 'ago' => ':time කට පෙර', 'from_now' => function ($time) { if (preg_match('/දින \d/u', $time)) { return $time.' න්'; } return $time.' කින්'; }, 'before' => ':time කට පෙර', 'after' => function ($time) { if (preg_match('/දින \d/u', $time)) { return $time.' න්'; } return $time.' කින්'; }, 'diff_now' => 'දැන්', 'diff_today' => 'අද', 'diff_yesterday' => 'ඊයේ', 'diff_tomorrow' => 'හෙට', 'formats' => [ 'LT' => 'a h:mm', 'LTS' => 'a h:mm:ss', 'L' => 'YYYY/MM/DD', 'LL' => 'YYYY MMMM D', 'LLL' => 'YYYY MMMM D, a h:mm', 'LLLL' => 'YYYY MMMM D [වැනි] dddd, a h:mm:ss', ], 'calendar' => [ 'sameDay' => '[අද] LT[ට]', 'nextDay' => '[හෙට] LT[ට]', 'nextWeek' => 'dddd LT[ට]', 'lastDay' => '[ඊයේ] LT[ට]', 'lastWeek' => '[පසුගිය] dddd LT[ට]', 'sameElse' => 'L', ], 'ordinal' => ':number වැනි', 'meridiem' => ['පෙර වරු', 'පස් වරු', 'පෙ.ව.', 'ප.ව.'], 'months' => ['ජනවාරි', 'පෙබරවාරි', 'මාර්තු', 'අප්‍රේල්', 'මැයි', 'ජූනි', 'ජූලි', 'අගෝස්තු', 'සැප්තැම්බර්', 'ඔක්තෝබර්', 'නොවැම්බර්', 'දෙසැම්බර්'], 'months_short' => ['ජන', 'පෙබ', 'මාර්', 'අප්', 'මැයි', 'ජූනි', 'ජූලි', 'අගෝ', 'සැප්', 'ඔක්', 'නොවැ', 'දෙසැ'], 'weekdays' => ['ඉරිදා', 'සඳුදා', 'අඟහරුවාදා', 'බදාදා', 'බ්‍රහස්පතින්දා', 'සිකුරාදා', 'සෙනසුරාදා'], 'weekdays_short' => ['ඉරි', 'සඳු', 'අඟ', 'බදා', 'බ්‍රහ', 'සිකු', 'සෙන'], 'weekdays_min' => ['ඉ', 'ස', 'අ', 'බ', 'බ්‍ර', 'සි', 'සෙ'], 'first_day_of_week' => 1, ]; PK������<1Z}]������Carbon/Lang/ru.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Bari Badamshin * - Jørn Ølmheim * - François B * - Tim Fish * - Коренберг Марк (imac) * - Serhan Apaydın * - RomeroMsk * - vsn4ik * - JD Isaacks * - Bari Badamshin * - Jørn Ølmheim * - François B * - Коренберг Марк (imac) * - Serhan Apaydın * - RomeroMsk * - vsn4ik * - JD Isaacks * - Fellzo * - andrey-helldar * - Pavel Skripkin (psxx) * - AlexWalkerson * - Vladislav UnsealedOne * - dima-bzz */ use Carbon\CarbonInterface; $transformDiff = function ($input) { return strtr($input, [ 'неделя' => 'неделю', 'секунда' => 'секунду', 'минута' => 'минуту', ]); }; return [ 'year' => ':count год|:count года|:count лет', 'y' => ':count г.|:count г.|:count л.', 'a_year' => '{1}год|:count год|:count года|:count лет', 'month' => ':count месяц|:count месяца|:count месяцев', 'm' => ':count мес.', 'a_month' => '{1}месяц|:count месяц|:count месяца|:count месяцев', 'week' => ':count неделя|:count недели|:count недель', 'w' => ':count нед.', 'a_week' => '{1}неделя|:count неделю|:count недели|:count недель', 'day' => ':count день|:count дня|:count дней', 'd' => ':count д.', 'a_day' => '{1}день|:count день|:count дня|:count дней', 'hour' => ':count час|:count часа|:count часов', 'h' => ':count ч.', 'a_hour' => '{1}час|:count час|:count часа|:count часов', 'minute' => ':count минута|:count минуты|:count минут', 'min' => ':count мин.', 'a_minute' => '{1}минута|:count минута|:count минуты|:count минут', 'second' => ':count секунда|:count секунды|:count секунд', 's' => ':count сек.', 'a_second' => '{1}несколько секунд|:count секунду|:count секунды|:count секунд', 'ago' => function ($time) use ($transformDiff) { return $transformDiff($time).' назад'; }, 'from_now' => function ($time) use ($transformDiff) { return 'через '.$transformDiff($time); }, 'after' => function ($time) use ($transformDiff) { return $transformDiff($time).' после'; }, 'before' => function ($time) use ($transformDiff) { return $transformDiff($time).' до'; }, 'diff_now' => 'только что', 'diff_today' => 'Сегодня,', 'diff_today_regexp' => 'Сегодня,?(?:\\s+в)?', 'diff_yesterday' => 'вчера', 'diff_yesterday_regexp' => 'Вчера,?(?:\\s+в)?', 'diff_tomorrow' => 'завтра', 'diff_tomorrow_regexp' => 'Завтра,?(?:\\s+в)?', 'diff_before_yesterday' => 'позавчера', 'diff_after_tomorrow' => 'послезавтра', 'formats' => [ 'LT' => 'H:mm', 'LTS' => 'H:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D MMMM YYYY г.', 'LLL' => 'D MMMM YYYY г., H:mm', 'LLLL' => 'dddd, D MMMM YYYY г., H:mm', ], 'calendar' => [ 'sameDay' => '[Сегодня, в] LT', 'nextDay' => '[Завтра, в] LT', 'nextWeek' => function (CarbonInterface $current, CarbonInterface $other) { if ($current->week !== $other->week) { switch ($current->dayOfWeek) { case 0: return '[В следующее] dddd, [в] LT'; case 1: case 2: case 4: return '[В следующий] dddd, [в] LT'; case 3: case 5: case 6: return '[В следующую] dddd, [в] LT'; } } if ($current->dayOfWeek === 2) { return '[Во] dddd, [в] LT'; } return '[В] dddd, [в] LT'; }, 'lastDay' => '[Вчера, в] LT', 'lastWeek' => function (CarbonInterface $current, CarbonInterface $other) { if ($current->week !== $other->week) { switch ($current->dayOfWeek) { case 0: return '[В прошлое] dddd, [в] LT'; case 1: case 2: case 4: return '[В прошлый] dddd, [в] LT'; case 3: case 5: case 6: return '[В прошлую] dddd, [в] LT'; } } if ($current->dayOfWeek === 2) { return '[Во] dddd, [в] LT'; } return '[В] dddd, [в] LT'; }, 'sameElse' => 'L', ], 'ordinal' => function ($number, $period) { switch ($period) { case 'M': case 'd': case 'DDD': return $number.'-й'; case 'D': return $number.'-го'; case 'w': case 'W': return $number.'-я'; default: return $number; } }, 'meridiem' => function ($hour) { if ($hour < 4) { return 'ночи'; } if ($hour < 12) { return 'утра'; } if ($hour < 17) { return 'дня'; } return 'вечера'; }, 'months' => ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'], 'months_standalone' => ['январь', 'февраль', 'март', 'апрель', 'май', 'июнь', 'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь'], 'months_short' => ['янв', 'фев', 'мар', 'апр', 'мая', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'], 'months_short_standalone' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'], 'months_regexp' => '/(DD?o?\.?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/', 'weekdays' => ['воскресенье', 'понедельник', 'вторник', 'среду', 'четверг', 'пятницу', 'субботу'], 'weekdays_standalone' => ['воскресенье', 'понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота'], 'weekdays_short' => ['вск', 'пнд', 'втр', 'срд', 'чтв', 'птн', 'сбт'], 'weekdays_min' => ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'], 'weekdays_regexp' => '/\[\s*(В|в)\s*((?:прошлую|следующую|эту)\s*)?\]\s*dddd/', 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' и '], ]; PK������<1Z������Carbon/Lang/en_IE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Martin McWhorter * - François B * - Chris Cartlidge * - JD Isaacks */ return array_replace_recursive(require __DIR__.'/en.php', [ 'from_now' => 'in :time', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD-MM-YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, ]); PK������<1ZBk �� ����Carbon/Lang/ps_AF.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ps.php'; PK������<1Z''x �� ����Carbon/Lang/fr_MF.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Z^5&������Carbon/Lang/fa.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - François B * - Nasser Ghiasi * - JD Isaacks * - Hossein Jabbari * - nimamo * - hafezdivandari * - Hassan Pezeshk (hpez) */ return [ 'year' => ':count سال', 'a_year' => 'یک سال'.'|:count '.'سال', 'y' => ':count سال', 'month' => ':count ماه', 'a_month' => 'یک ماه'.'|:count '.'ماه', 'm' => ':count ماه', 'week' => ':count هفته', 'a_week' => 'یک هفته'.'|:count '.'هفته', 'w' => ':count هفته', 'day' => ':count روز', 'a_day' => 'یک روز'.'|:count '.'روز', 'd' => ':count روز', 'hour' => ':count ساعت', 'a_hour' => 'یک ساعت'.'|:count '.'ساعت', 'h' => ':count ساعت', 'minute' => ':count دقیقه', 'a_minute' => 'یک دقیقه'.'|:count '.'دقیقه', 'min' => ':count دقیقه', 'second' => ':count ثانیه', 's' => ':count ثانیه', 'ago' => ':time پیش', 'from_now' => ':time دیگر', 'after' => ':time پس از', 'before' => ':time پیش از', 'diff_now' => 'اکنون', 'diff_today' => 'امروز', 'diff_today_regexp' => 'امروز(?:\\s+ساعت)?', 'diff_yesterday' => 'دیروز', 'diff_yesterday_regexp' => 'دیروز(?:\\s+ساعت)?', 'diff_tomorrow' => 'فردا', 'diff_tomorrow_regexp' => 'فردا(?:\\s+ساعت)?', 'formats' => [ 'LT' => 'OH:Om', 'LTS' => 'OH:Om:Os', 'L' => 'OD/OM/OY', 'LL' => 'OD MMMM OY', 'LLL' => 'OD MMMM OY OH:Om', 'LLLL' => 'dddd, OD MMMM OY OH:Om', ], 'calendar' => [ 'sameDay' => '[امروز ساعت] LT', 'nextDay' => '[فردا ساعت] LT', 'nextWeek' => 'dddd [ساعت] LT', 'lastDay' => '[دیروز ساعت] LT', 'lastWeek' => 'dddd [پیش] [ساعت] LT', 'sameElse' => 'L', ], 'ordinal' => ':timeم', 'meridiem' => ['قبل از ظهر', 'بعد از ظهر'], 'months' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'], 'months_short' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'], 'weekdays' => ['یکشنبه', 'دوشنبه', 'سه‌شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'], 'weekdays_short' => ['یکشنبه', 'دوشنبه', 'سه‌شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'], 'weekdays_min' => ['ی', 'د', 'س', 'چ', 'پ', 'ج', 'ش'], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'list' => ['، ', ' و '], 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰۴', '۰۵', '۰۶', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱۴', '۱۵', '۱۶', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲۴', '۲۵', '۲۶', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳۴', '۳۵', '۳۶', '۳۷', '۳۸', '۳۹', '۴۰', '۴۱', '۴۲', '۴۳', '۴۴', '۴۵', '۴۶', '۴۷', '۴۸', '۴۹', '۵۰', '۵۱', '۵۲', '۵۳', '۵۴', '۵۵', '۵۶', '۵۷', '۵۸', '۵۹', '۶۰', '۶۱', '۶۲', '۶۳', '۶۴', '۶۵', '۶۶', '۶۷', '۶۸', '۶۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷۴', '۷۵', '۷۶', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸۴', '۸۵', '۸۶', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹۴', '۹۵', '۹۶', '۹۷', '۹۸', '۹۹'], 'months_short_standalone' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'], 'weekend' => [5, 5], ]; PK������<1ZpG��G����Carbon/Lang/en_SH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZHD��D����Carbon/Lang/it_IT.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return require __DIR__.'/it.php'; PK������<1Z,͹ �� ����Carbon/Lang/ro.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - JD Isaacks * - Cătălin Georgescu * - Valentin Ivaşcu (oriceon) */ return [ 'year' => ':count an|:count ani|:count ani', 'a_year' => 'un an|:count ani|:count ani', 'y' => ':count a.', 'month' => ':count lună|:count luni|:count luni', 'a_month' => 'o lună|:count luni|:count luni', 'm' => ':count l.', 'week' => ':count săptămână|:count săptămâni|:count săptămâni', 'a_week' => 'o săptămână|:count săptămâni|:count săptămâni', 'w' => ':count săp.', 'day' => ':count zi|:count zile|:count zile', 'a_day' => 'o zi|:count zile|:count zile', 'd' => ':count z.', 'hour' => ':count oră|:count ore|:count ore', 'a_hour' => 'o oră|:count ore|:count ore', 'h' => ':count o.', 'minute' => ':count minut|:count minute|:count minute', 'a_minute' => 'un minut|:count minute|:count minute', 'min' => ':count m.', 'second' => ':count secundă|:count secunde|:count secunde', 'a_second' => 'câteva secunde|:count secunde|:count secunde', 's' => ':count sec.', 'ago' => ':time în urmă', 'from_now' => 'peste :time', 'after' => 'peste :time', 'before' => 'acum :time', 'diff_now' => 'acum', 'diff_today' => 'azi', 'diff_today_regexp' => 'azi(?:\\s+la)?', 'diff_yesterday' => 'ieri', 'diff_yesterday_regexp' => 'ieri(?:\\s+la)?', 'diff_tomorrow' => 'mâine', 'diff_tomorrow_regexp' => 'mâine(?:\\s+la)?', 'formats' => [ 'LT' => 'H:mm', 'LTS' => 'H:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY H:mm', 'LLLL' => 'dddd, D MMMM YYYY H:mm', ], 'calendar' => [ 'sameDay' => '[azi la] LT', 'nextDay' => '[mâine la] LT', 'nextWeek' => 'dddd [la] LT', 'lastDay' => '[ieri la] LT', 'lastWeek' => '[fosta] dddd [la] LT', 'sameElse' => 'L', ], 'months' => ['ianuarie', 'februarie', 'martie', 'aprilie', 'mai', 'iunie', 'iulie', 'august', 'septembrie', 'octombrie', 'noiembrie', 'decembrie'], 'months_short' => ['ian.', 'feb.', 'mar.', 'apr.', 'mai', 'iun.', 'iul.', 'aug.', 'sept.', 'oct.', 'nov.', 'dec.'], 'weekdays' => ['duminică', 'luni', 'marți', 'miercuri', 'joi', 'vineri', 'sâmbătă'], 'weekdays_short' => ['dum', 'lun', 'mar', 'mie', 'joi', 'vin', 'sâm'], 'weekdays_min' => ['du', 'lu', 'ma', 'mi', 'jo', 'vi', 'sâ'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' și '], 'meridiem' => ['a.m.', 'p.m.'], ]; PK������<1ZYb1������Carbon/Lang/es_DO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - kostas * - François B * - Tim Fish * - Chiel Robben * - Claire Coloma * - Steven Heinrich * - JD Isaacks * - Raphael Amorim */ return array_replace_recursive(require __DIR__.'/es.php', [ 'diff_before_yesterday' => 'anteayer', 'formats' => [ 'LT' => 'h:mm A', 'LTS' => 'h:mm:ss A', 'LLL' => 'D [de] MMMM [de] YYYY h:mm A', 'LLLL' => 'dddd, D [de] MMMM [de] YYYY h:mm A', ], ]); PK������<1Z ������Carbon/Lang/mgh.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['wichishu', 'mchochil’l'], 'weekdays' => ['Sabato', 'Jumatatu', 'Jumanne', 'Jumatano', 'Arahamisi', 'Ijumaa', 'Jumamosi'], 'weekdays_short' => ['Sab', 'Jtt', 'Jnn', 'Jtn', 'Ara', 'Iju', 'Jmo'], 'weekdays_min' => ['Sab', 'Jtt', 'Jnn', 'Jtn', 'Ara', 'Iju', 'Jmo'], 'months' => ['Mweri wo kwanza', 'Mweri wo unayeli', 'Mweri wo uneraru', 'Mweri wo unecheshe', 'Mweri wo unethanu', 'Mweri wo thanu na mocha', 'Mweri wo saba', 'Mweri wo nane', 'Mweri wo tisa', 'Mweri wo kumi', 'Mweri wo kumi na moja', 'Mweri wo kumi na yel’li'], 'months_short' => ['Kwa', 'Una', 'Rar', 'Che', 'Tha', 'Moc', 'Sab', 'Nan', 'Tis', 'Kum', 'Moj', 'Yel'], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], ]); PK������<1Zd������Carbon/Lang/es_HN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]); PK������<1Z{$������Carbon/Lang/zh_TW.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/zh_Hant_TW.php'; PK������<1Z QV������Carbon/Lang/nhn_MX.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP libc-alpha@sourceware.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'months' => ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'], 'months_short' => ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic'], 'weekdays' => ['teoilhuitl', 'ceilhuitl', 'omeilhuitl', 'yeilhuitl', 'nahuilhuitl', 'macuililhuitl', 'chicuaceilhuitl'], 'weekdays_short' => ['teo', 'cei', 'ome', 'yei', 'nau', 'mac', 'chi'], 'weekdays_min' => ['teo', 'cei', 'ome', 'yei', 'nau', 'mac', 'chi'], 'day_of_first_week_of_year' => 1, 'month' => ':count metztli', // less reliable 'm' => ':count metztli', // less reliable 'a_month' => ':count metztli', // less reliable 'week' => ':count tonalli', // less reliable 'w' => ':count tonalli', // less reliable 'a_week' => ':count tonalli', // less reliable 'day' => ':count tonatih', // less reliable 'd' => ':count tonatih', // less reliable 'a_day' => ':count tonatih', // less reliable 'minute' => ':count toltecayotl', // less reliable 'min' => ':count toltecayotl', // less reliable 'a_minute' => ':count toltecayotl', // less reliable 'second' => ':count ome', // less reliable 's' => ':count ome', // less reliable 'a_second' => ':count ome', // less reliable 'year' => ':count xihuitl', 'y' => ':count xihuitl', 'a_year' => ':count xihuitl', ]); PK������<1Z^4 �� ����Carbon/Lang/sat_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Red Hat Pune libc-alpha@sourceware.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रेल', 'मई', 'जुन', 'जुलाई', 'अगस्त', 'सितम्बर', 'अखथबर', 'नवम्बर', 'दिसम्बर'], 'months_short' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रेल', 'मई', 'जुन', 'जुलाई', 'अगस्त', 'सितम्बर', 'अखथबर', 'नवम्बर', 'दिसम्बर'], 'weekdays' => ['सिंगेमाँहाँ', 'ओतेमाँहाँ', 'बालेमाँहाँ', 'सागुनमाँहाँ', 'सारदीमाँहाँ', 'जारुममाँहाँ', 'ञुहुममाँहाँ'], 'weekdays_short' => ['सिंगे', 'ओते', 'बाले', 'सागुन', 'सारदी', 'जारुम', 'ञुहुम'], 'weekdays_min' => ['सिंगे', 'ओते', 'बाले', 'सागुन', 'सारदी', 'जारुम', 'ञुहुम'], 'day_of_first_week_of_year' => 1, 'month' => ':count ńindạ cando', // less reliable 'm' => ':count ńindạ cando', // less reliable 'a_month' => ':count ńindạ cando', // less reliable 'week' => ':count mãhã', // less reliable 'w' => ':count mãhã', // less reliable 'a_week' => ':count mãhã', // less reliable 'hour' => ':count ᱥᱳᱱᱚ', // less reliable 'h' => ':count ᱥᱳᱱᱚ', // less reliable 'a_hour' => ':count ᱥᱳᱱᱚ', // less reliable 'minute' => ':count ᱯᱤᱞᱪᱩ', // less reliable 'min' => ':count ᱯᱤᱞᱪᱩ', // less reliable 'a_minute' => ':count ᱯᱤᱞᱪᱩ', // less reliable 'second' => ':count ar', // less reliable 's' => ':count ar', // less reliable 'a_second' => ':count ar', // less reliable 'year' => ':count ne̲s', 'y' => ':count ne̲s', 'a_year' => ':count ne̲s', 'day' => ':count ᱫᱤᱱ', 'd' => ':count ᱫᱤᱱ', 'a_day' => ':count ᱫᱤᱱ', ]); PK������<1ZgY ��Y ����Carbon/Lang/id.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - du * - JD Isaacks * - Nafies Luthfi * - Raymundus Jati Primanda (mundusjp) * - diankur313 * - a-wip0 */ return [ 'year' => ':count tahun', 'a_year' => '{1}setahun|]1,Inf[:count tahun', 'y' => ':countthn', 'month' => ':count bulan', 'a_month' => '{1}sebulan|]1,Inf[:count bulan', 'm' => ':countbln', 'week' => ':count minggu', 'a_week' => '{1}seminggu|]1,Inf[:count minggu', 'w' => ':countmgg', 'day' => ':count hari', 'a_day' => '{1}sehari|]1,Inf[:count hari', 'd' => ':counthr', 'hour' => ':count jam', 'a_hour' => '{1}sejam|]1,Inf[:count jam', 'h' => ':countj', 'minute' => ':count menit', 'a_minute' => '{1}semenit|]1,Inf[:count menit', 'min' => ':countmnt', 'second' => ':count detik', 'a_second' => '{1}beberapa detik|]1,Inf[:count detik', 's' => ':countdt', 'ago' => ':time yang lalu', 'from_now' => ':time dari sekarang', 'after' => ':time setelahnya', 'before' => ':time sebelumnya', 'diff_now' => 'sekarang', 'diff_today' => 'Hari', 'diff_today_regexp' => 'Hari(?:\\s+ini)?(?:\\s+pukul)?', 'diff_yesterday' => 'kemarin', 'diff_yesterday_regexp' => 'Kemarin(?:\\s+pukul)?', 'diff_tomorrow' => 'besok', 'diff_tomorrow_regexp' => 'Besok(?:\\s+pukul)?', 'formats' => [ 'LT' => 'HH.mm', 'LTS' => 'HH.mm.ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY [pukul] HH.mm', 'LLLL' => 'dddd, D MMMM YYYY [pukul] HH.mm', ], 'calendar' => [ 'sameDay' => '[Hari ini pukul] LT', 'nextDay' => '[Besok pukul] LT', 'nextWeek' => 'dddd [pukul] LT', 'lastDay' => '[Kemarin pukul] LT', 'lastWeek' => 'dddd [lalu pukul] LT', 'sameElse' => 'L', ], 'meridiem' => function ($hour) { if ($hour < 11) { return 'pagi'; } if ($hour < 15) { return 'siang'; } if ($hour < 19) { return 'sore'; } return 'malam'; }, 'months' => ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember'], 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agt', 'Sep', 'Okt', 'Nov', 'Des'], 'weekdays' => ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'], 'weekdays_short' => ['Min', 'Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab'], 'weekdays_min' => ['Mg', 'Sn', 'Sl', 'Rb', 'Km', 'Jm', 'Sb'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' dan '], ]; PK������<1ZpG��G����Carbon/Lang/en_AI.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z ذQ ��Q ����Carbon/Lang/nn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - Alexander Tømmerås * - Øystein * - JD Isaacks * - Gaute Hvoslef Kvalnes (gaute) */ return [ 'year' => ':count år', 'a_year' => 'eit år|:count år', 'y' => ':count år', 'month' => ':count månad|:count månader', 'a_month' => 'ein månad|:count månader', 'm' => ':count md', 'week' => ':count veke|:count veker', 'a_week' => 'ei veke|:count veker', 'w' => ':countv', 'day' => ':count dag|:count dagar', 'a_day' => 'ein dag|:count dagar', 'd' => ':countd', 'hour' => ':count time|:count timar', 'a_hour' => 'ein time|:count timar', 'h' => ':countt', 'minute' => ':count minutt', 'a_minute' => 'eit minutt|:count minutt', 'min' => ':countm', 'second' => ':count sekund', 'a_second' => 'nokre sekund|:count sekund', 's' => ':counts', 'ago' => ':time sidan', 'from_now' => 'om :time', 'after' => ':time etter', 'before' => ':time før', 'diff_today' => 'I dag', 'diff_yesterday' => 'I går', 'diff_yesterday_regexp' => 'I går(?:\\s+klokka)?', 'diff_tomorrow' => 'I morgon', 'diff_tomorrow_regexp' => 'I morgon(?:\\s+klokka)?', 'diff_today_regexp' => 'I dag(?:\\s+klokka)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D. MMMM YYYY', 'LLL' => 'D. MMMM YYYY [kl.] H:mm', 'LLLL' => 'dddd D. MMMM YYYY [kl.] HH:mm', ], 'calendar' => [ 'sameDay' => '[I dag klokka] LT', 'nextDay' => '[I morgon klokka] LT', 'nextWeek' => 'dddd [klokka] LT', 'lastDay' => '[I går klokka] LT', 'lastWeek' => '[Føregåande] dddd [klokka] LT', 'sameElse' => 'L', ], 'ordinal' => ':number.', 'months' => ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember'], 'months_short' => ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'], 'weekdays' => ['sundag', 'måndag', 'tysdag', 'onsdag', 'torsdag', 'fredag', 'laurdag'], 'weekdays_short' => ['sun', 'mån', 'tys', 'ons', 'tor', 'fre', 'lau'], 'weekdays_min' => ['su', 'må', 'ty', 'on', 'to', 'fr', 'la'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' og '], 'meridiem' => ['f.m.', 'e.m.'], ]; PK������<1Z''x �� ����Carbon/Lang/fr_ML.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Z /eb������Carbon/Lang/lrc.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'minute' => ':count هنر', // less reliable 'min' => ':count هنر', // less reliable 'a_minute' => ':count هنر', // less reliable ]); PK������<1Z\ �� ����Carbon/Lang/ff_MR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ff.php', [ 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'D/M/YYYY', 'LL' => 'D MMM, YYYY', 'LLL' => 'D MMMM YYYY h:mm a', 'LLLL' => 'dddd D MMMM YYYY h:mm a', ], ]); PK������<1Zb �� ����Carbon/Lang/bs.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - bokideckonja * - Josh Soref * - François B * - shaishavgandhi05 * - Serhan Apaydın * - JD Isaacks */ use Carbon\CarbonInterface; return [ 'year' => ':count godina|:count godine|:count godina', 'y' => ':count godina|:count godine|:count godina', 'month' => ':count mjesec|:count mjeseca|:count mjeseci', 'm' => ':count mjesec|:count mjeseca|:count mjeseci', 'week' => ':count sedmice|:count sedmicu|:count sedmica', 'w' => ':count sedmice|:count sedmicu|:count sedmica', 'day' => ':count dan|:count dana|:count dana', 'd' => ':count dan|:count dana|:count dana', 'hour' => ':count sat|:count sata|:count sati', 'h' => ':count sat|:count sata|:count sati', 'minute' => ':count minut|:count minuta|:count minuta', 'min' => ':count minut|:count minuta|:count minuta', 'second' => ':count sekund|:count sekunda|:count sekundi', 's' => ':count sekund|:count sekunda|:count sekundi', 'ago' => 'prije :time', 'from_now' => 'za :time', 'after' => 'nakon :time', 'before' => ':time ranije', 'diff_now' => 'sada', 'diff_today' => 'danas', 'diff_today_regexp' => 'danas(?:\\s+u)?', 'diff_yesterday' => 'jučer', 'diff_yesterday_regexp' => 'jučer(?:\\s+u)?', 'diff_tomorrow' => 'sutra', 'diff_tomorrow_regexp' => 'sutra(?:\\s+u)?', 'formats' => [ 'LT' => 'H:mm', 'LTS' => 'H:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D. MMMM YYYY', 'LLL' => 'D. MMMM YYYY H:mm', 'LLLL' => 'dddd, D. MMMM YYYY H:mm', ], 'calendar' => [ 'sameDay' => '[danas u] LT', 'nextDay' => '[sutra u] LT', 'nextWeek' => function (CarbonInterface $current) { switch ($current->dayOfWeek) { case 0: return '[u] [nedjelju] [u] LT'; case 3: return '[u] [srijedu] [u] LT'; case 6: return '[u] [subotu] [u] LT'; default: return '[u] dddd [u] LT'; } }, 'lastDay' => '[jučer u] LT', 'lastWeek' => function (CarbonInterface $current) { switch ($current->dayOfWeek) { case 0: case 3: return '[prošlu] dddd [u] LT'; case 6: return '[prošle] [subote] [u] LT'; default: return '[prošli] dddd [u] LT'; } }, 'sameElse' => 'L', ], 'ordinal' => ':number.', 'months' => ['januar', 'februar', 'mart', 'april', 'maj', 'juni', 'juli', 'august', 'septembar', 'oktobar', 'novembar', 'decembar'], 'months_short' => ['jan.', 'feb.', 'mar.', 'apr.', 'maj.', 'jun.', 'jul.', 'aug.', 'sep.', 'okt.', 'nov.', 'dec.'], 'weekdays' => ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'], 'weekdays_short' => ['ned.', 'pon.', 'uto.', 'sri.', 'čet.', 'pet.', 'sub.'], 'weekdays_min' => ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' i '], 'meridiem' => ['prijepodne', 'popodne'], ]; PK������<1ZKnO��O����Carbon/Lang/kok.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/kok_IN.php'; PK������<1ZV ������Carbon/Lang/tt_RU@iqtelif.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Reshat Sabiq tatar.iqtelif.i18n@gmail.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], 'months' => ['Ğınwar', 'Fiwral\'', 'Mart', 'April', 'May', 'Yün', 'Yül', 'Awgust', 'Sintebír', 'Üktebír', 'Noyebír', 'Dikebír'], 'months_short' => ['Ğın', 'Fiw', 'Mar', 'Apr', 'May', 'Yün', 'Yül', 'Awg', 'Sin', 'Ükt', 'Noy', 'Dik'], 'weekdays' => ['Yekşembí', 'Düşembí', 'Sişembí', 'Çerşembí', 'Pencíşembí', 'Comğa', 'Şimbe'], 'weekdays_short' => ['Yek', 'Düş', 'Siş', 'Çer', 'Pen', 'Com', 'Şim'], 'weekdays_min' => ['Yek', 'Düş', 'Siş', 'Çer', 'Pen', 'Com', 'Şim'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'meridiem' => ['ÖA', 'ÖS'], ]); PK������<1ZE������Carbon/Lang/mfe_MU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Samsung Electronics Co., Ltd. akhilesh.k@samsung.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'months' => ['zanvie', 'fevriye', 'mars', 'avril', 'me', 'zin', 'zilye', 'out', 'septam', 'oktob', 'novam', 'desam'], 'months_short' => ['zan', 'fev', 'mar', 'avr', 'me', 'zin', 'zil', 'out', 'sep', 'okt', 'nov', 'des'], 'weekdays' => ['dimans', 'lindi', 'mardi', 'merkredi', 'zedi', 'vandredi', 'samdi'], 'weekdays_short' => ['dim', 'lin', 'mar', 'mer', 'ze', 'van', 'sam'], 'weekdays_min' => ['dim', 'lin', 'mar', 'mer', 'ze', 'van', 'sam'], 'year' => ':count banané', 'y' => ':count banané', 'a_year' => ':count banané', 'month' => ':count mwa', 'm' => ':count mwa', 'a_month' => ':count mwa', 'week' => ':count sémenn', 'w' => ':count sémenn', 'a_week' => ':count sémenn', 'day' => ':count zour', 'd' => ':count zour', 'a_day' => ':count zour', 'hour' => ':count -er-tan', 'h' => ':count -er-tan', 'a_hour' => ':count -er-tan', 'minute' => ':count minitt', 'min' => ':count minitt', 'a_minute' => ':count minitt', 'second' => ':count déziém', 's' => ':count déziém', 'a_second' => ':count déziém', ]); PK������<1Z.������Carbon/Lang/gv_GB.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Alastair McKinstry bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'months' => ['Jerrey-geuree', 'Toshiaght-arree', 'Mayrnt', 'Averil', 'Boaldyn', 'Mean-souree', 'Jerrey-souree', 'Luanistyn', 'Mean-fouyir', 'Jerrey-fouyir', 'Mee Houney', 'Mee ny Nollick'], 'months_short' => ['J-guer', 'T-arree', 'Mayrnt', 'Avrril', 'Boaldyn', 'M-souree', 'J-souree', 'Luanistyn', 'M-fouyir', 'J-fouyir', 'M.Houney', 'M.Nollick'], 'weekdays' => ['Jedoonee', 'Jelhein', 'Jemayrt', 'Jercean', 'Jerdein', 'Jeheiney', 'Jesarn'], 'weekdays_short' => ['Jed', 'Jel', 'Jem', 'Jerc', 'Jerd', 'Jeh', 'Jes'], 'weekdays_min' => ['Jed', 'Jel', 'Jem', 'Jerc', 'Jerd', 'Jeh', 'Jes'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'year' => ':count blein', 'y' => ':count blein', 'a_year' => ':count blein', 'month' => ':count mee', 'm' => ':count mee', 'a_month' => ':count mee', 'week' => ':count shiaghtin', 'w' => ':count shiaghtin', 'a_week' => ':count shiaghtin', 'day' => ':count laa', 'd' => ':count laa', 'a_day' => ':count laa', 'hour' => ':count oor', 'h' => ':count oor', 'a_hour' => ':count oor', 'minute' => ':count feer veg', 'min' => ':count feer veg', 'a_minute' => ':count feer veg', 'second' => ':count derrey', 's' => ':count derrey', 'a_second' => ':count derrey', ]); PK������<1Z������Carbon/Lang/en_CA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - Zhan Tong Zhang * - Mayank Badola * - JD Isaacks */ return array_replace_recursive(require __DIR__.'/en.php', [ 'from_now' => 'in :time', 'formats' => [ 'LT' => 'h:mm A', 'LTS' => 'h:mm:ss A', 'L' => 'YYYY-MM-DD', 'LL' => 'MMMM D, YYYY', 'LLL' => 'MMMM D, YYYY h:mm A', 'LLLL' => 'dddd, MMMM D, YYYY h:mm A', ], ]); PK������<1Z}4O��O����Carbon/Lang/quz.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/quz_PE.php'; PK������<1ZFƸ������Carbon/Lang/lag.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['TOO', 'MUU'], 'weekdays' => ['Jumapíiri', 'Jumatátu', 'Jumaíne', 'Jumatáano', 'Alamíisi', 'Ijumáa', 'Jumamóosi'], 'weekdays_short' => ['Píili', 'Táatu', 'Íne', 'Táano', 'Alh', 'Ijm', 'Móosi'], 'weekdays_min' => ['Píili', 'Táatu', 'Íne', 'Táano', 'Alh', 'Ijm', 'Móosi'], 'months' => ['Kʉfúngatɨ', 'Kʉnaanɨ', 'Kʉkeenda', 'Kwiikumi', 'Kwiinyambála', 'Kwiidwaata', 'Kʉmʉʉnchɨ', 'Kʉvɨɨrɨ', 'Kʉsaatʉ', 'Kwiinyi', 'Kʉsaano', 'Kʉsasatʉ'], 'months_short' => ['Fúngatɨ', 'Naanɨ', 'Keenda', 'Ikúmi', 'Inyambala', 'Idwaata', 'Mʉʉnchɨ', 'Vɨɨrɨ', 'Saatʉ', 'Inyi', 'Saano', 'Sasatʉ'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], ]); PK������<1Zv������Carbon/Lang/wae_CH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Walser Translation Team ml@translate-wae.ch */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'YYYY-MM-DD', ], 'months' => ['Jenner', 'Hornig', 'Märze', 'Abrille', 'Meije', 'Bráčet', 'Heiwet', 'Öigšte', 'Herbštmánet', 'Wímánet', 'Wintermánet', 'Chrištmánet'], 'months_short' => ['Jen', 'Hor', 'Mär', 'Abr', 'Mei', 'Brá', 'Hei', 'Öig', 'Her', 'Wím', 'Win', 'Chr'], 'weekdays' => ['Suntag', 'Mäntag', 'Zischtag', 'Mittwuch', 'Frontag', 'Fritag', 'Samschtag'], 'weekdays_short' => ['Sun', 'Män', 'Zis', 'Mit', 'Fro', 'Fri', 'Sam'], 'weekdays_min' => ['Sun', 'Män', 'Zis', 'Mit', 'Fro', 'Fri', 'Sam'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'month' => ':count Maano', // less reliable 'm' => ':count Maano', // less reliable 'a_month' => ':count Maano', // less reliable ]); PK������<1ZDɳ������Carbon/Lang/zh_CN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - monkeycon * - François B * - Jason Katz-Brown * - Serhan Apaydın * - Matt Johnson * - JD Isaacks * - Zeno Zeng * - Chris Hemp * - shankesgk2 */ return array_merge(require __DIR__.'/zh.php', [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY/MM/DD', 'LL' => 'YYYY年M月D日', 'LLL' => 'YYYY年M月D日Ah点mm分', 'LLLL' => 'YYYY年M月D日ddddAh点mm分', ], ]); PK������<1Z2������Carbon/Lang/sid_ET.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ge'ez Frontier Foundation locales@geez.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], 'weekdays' => ['Sambata', 'Sanyo', 'Maakisanyo', 'Roowe', 'Hamuse', 'Arbe', 'Qidaame'], 'weekdays_short' => ['Sam', 'San', 'Mak', 'Row', 'Ham', 'Arb', 'Qid'], 'weekdays_min' => ['Sam', 'San', 'Mak', 'Row', 'Ham', 'Arb', 'Qid'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['soodo', 'hawwaro'], ]); PK������<1Z?J& �� ����Carbon/Lang/sr_Latn_ME.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Glavić * - Milos Sakovic */ use Carbon\CarbonInterface; use Symfony\Component\Translation\PluralizationRules; // @codeCoverageIgnoreStart if (class_exists(PluralizationRules::class)) { PluralizationRules::set(static function ($number) { return PluralizationRules::get($number, 'sr'); }, 'sr_Latn_ME'); } // @codeCoverageIgnoreEnd return array_replace_recursive(require __DIR__.'/sr.php', [ 'month' => ':count mjesec|:count mjeseca|:count mjeseci', 'week' => ':count nedjelja|:count nedjelje|:count nedjelja', 'second' => ':count sekund|:count sekunde|:count sekundi', 'ago' => 'prije :time', 'from_now' => 'za :time', 'after' => ':time nakon', 'before' => ':time prije', 'week_from_now' => ':count nedjelju|:count nedjelje|:count nedjelja', 'week_ago' => ':count nedjelju|:count nedjelje|:count nedjelja', 'second_ago' => ':count sekund|:count sekunde|:count sekundi', 'diff_tomorrow' => 'sjutra', 'calendar' => [ 'nextDay' => '[sjutra u] LT', 'nextWeek' => function (CarbonInterface $date) { switch ($date->dayOfWeek) { case 0: return '[u nedjelju u] LT'; case 3: return '[u srijedu u] LT'; case 6: return '[u subotu u] LT'; default: return '[u] dddd [u] LT'; } }, 'lastWeek' => function (CarbonInterface $date) { switch ($date->dayOfWeek) { case 0: return '[prošle nedjelje u] LT'; case 1: return '[prošle nedjelje u] LT'; case 2: return '[prošlog utorka u] LT'; case 3: return '[prošle srijede u] LT'; case 4: return '[prošlog četvrtka u] LT'; case 5: return '[prošlog petka u] LT'; default: return '[prošle subote u] LT'; } }, ], 'weekdays' => ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'], 'weekdays_short' => ['ned.', 'pon.', 'uto.', 'sri.', 'čet.', 'pet.', 'sub.'], ]); PK������<1Z ĩN��N����Carbon/Lang/gv.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/gv_GB.php'; PK������<1Zq �� ����Carbon/Lang/om_ET.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/om.php'; PK������<1Zqh}��}����Carbon/Lang/ur_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Red Hat, Pune bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/ur.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'], 'months_short' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'], 'weekdays' => ['اتوار', 'پیر', 'منگل', 'بدھ', 'جمعرات', 'جمعہ', 'سنیچر'], 'weekdays_short' => ['اتوار', 'پیر', 'منگل', 'بدھ', 'جمعرات', 'جمعہ', 'سنیچر'], 'weekdays_min' => ['اتوار', 'پیر', 'منگل', 'بدھ', 'جمعرات', 'جمعہ', 'سنیچر'], 'day_of_first_week_of_year' => 1, ]); PK������<1Z?Ej �� ����Carbon/Lang/en_MO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1ZpG��G����Carbon/Lang/en_NU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZL' ��' ����Carbon/Lang/gu.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - Kaushik Thanki * - Josh Soref */ return [ 'year' => 'એક વર્ષ|:count વર્ષ', 'y' => ':countવર્ષ|:countવર્ષો', 'month' => 'એક મહિનો|:count મહિના', 'm' => ':countમહિનો|:countમહિના', 'week' => ':count અઠવાડિયું|:count અઠવાડિયા', 'w' => ':countઅઠ.|:countઅઠ.', 'day' => 'એક દિવસ|:count દિવસ', 'd' => ':countદિ.|:countદિ.', 'hour' => 'એક કલાક|:count કલાક', 'h' => ':countક.|:countક.', 'minute' => 'એક મિનિટ|:count મિનિટ', 'min' => ':countમિ.|:countમિ.', 'second' => 'અમુક પળો|:count સેકંડ', 's' => ':countસે.|:countસે.', 'ago' => ':time પેહલા', 'from_now' => ':time મા', 'after' => ':time પછી', 'before' => ':time પહેલા', 'diff_now' => 'હમણાં', 'diff_today' => 'આજ', 'diff_yesterday' => 'ગઇકાલે', 'diff_tomorrow' => 'કાલે', 'formats' => [ 'LT' => 'A h:mm વાગ્યે', 'LTS' => 'A h:mm:ss વાગ્યે', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY, A h:mm વાગ્યે', 'LLLL' => 'dddd, D MMMM YYYY, A h:mm વાગ્યે', ], 'calendar' => [ 'sameDay' => '[આજ] LT', 'nextDay' => '[કાલે] LT', 'nextWeek' => 'dddd, LT', 'lastDay' => '[ગઇકાલે] LT', 'lastWeek' => '[પાછલા] dddd, LT', 'sameElse' => 'L', ], 'meridiem' => function ($hour) { if ($hour < 4) { return 'રાત'; } if ($hour < 10) { return 'સવાર'; } if ($hour < 17) { return 'બપોર'; } if ($hour < 20) { return 'સાંજ'; } return 'રાત'; }, 'months' => ['જાન્યુઆરી', 'ફેબ્રુઆરી', 'માર્ચ', 'એપ્રિલ', 'મે', 'જૂન', 'જુલાઈ', 'ઑગસ્ટ', 'સપ્ટેમ્બર', 'ઑક્ટ્બર', 'નવેમ્બર', 'ડિસેમ્બર'], 'months_short' => ['જાન્યુ.', 'ફેબ્રુ.', 'માર્ચ', 'એપ્રિ.', 'મે', 'જૂન', 'જુલા.', 'ઑગ.', 'સપ્ટે.', 'ઑક્ટ્.', 'નવે.', 'ડિસે.'], 'weekdays' => ['રવિવાર', 'સોમવાર', 'મંગળવાર', 'બુધ્વાર', 'ગુરુવાર', 'શુક્રવાર', 'શનિવાર'], 'weekdays_short' => ['રવિ', 'સોમ', 'મંગળ', 'બુધ્', 'ગુરુ', 'શુક્ર', 'શનિ'], 'weekdays_min' => ['ર', 'સો', 'મં', 'બુ', 'ગુ', 'શુ', 'શ'], 'list' => [', ', ' અને '], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, 'weekend' => [0, 0], ]; PK������<1Z7h#��#����Carbon/Lang/tn_ZA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['Ferikgong', 'Tlhakole', 'Mopitlwe', 'Moranang', 'Motsheganong', 'Seetebosigo', 'Phukwi', 'Phatwe', 'Lwetse', 'Diphalane', 'Ngwanatsele', 'Sedimonthole'], 'months_short' => ['Fer', 'Tlh', 'Mop', 'Mor', 'Mot', 'See', 'Phu', 'Pha', 'Lwe', 'Dip', 'Ngw', 'Sed'], 'weekdays' => ['laTshipi', 'Mosupologo', 'Labobedi', 'Laboraro', 'Labone', 'Labotlhano', 'Lamatlhatso'], 'weekdays_short' => ['Tsh', 'Mos', 'Bed', 'Rar', 'Ne', 'Tlh', 'Mat'], 'weekdays_min' => ['Tsh', 'Mos', 'Bed', 'Rar', 'Ne', 'Tlh', 'Mat'], 'day_of_first_week_of_year' => 1, 'year' => 'dingwaga di le :count', 'y' => 'dingwaga di le :count', 'a_year' => 'dingwaga di le :count', 'month' => 'dikgwedi di le :count', 'm' => 'dikgwedi di le :count', 'a_month' => 'dikgwedi di le :count', 'week' => 'dibeke di le :count', 'w' => 'dibeke di le :count', 'a_week' => 'dibeke di le :count', 'day' => 'malatsi :count', 'd' => 'malatsi :count', 'a_day' => 'malatsi :count', 'hour' => 'diura di le :count', 'h' => 'diura di le :count', 'a_hour' => 'diura di le :count', 'minute' => 'metsotso e le :count', 'min' => 'metsotso e le :count', 'a_minute' => 'metsotso e le :count', 'second' => 'metsotswana e le :count', 's' => 'metsotswana e le :count', 'a_second' => 'metsotswana e le :count', ]); PK������<1ZN��N����Carbon/Lang/ks.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/ks_IN.php'; PK������<1Z{ �� ����Carbon/Lang/yo.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - Atolagbe Abisoye */ return [ 'year' => 'ọdún :count', 'a_year' => '{1}ọdún kan|ọdún :count', 'month' => 'osù :count', 'a_month' => '{1}osù kan|osù :count', 'week' => 'ọsẹ :count', 'a_week' => '{1}ọsẹ kan|ọsẹ :count', 'day' => 'ọjọ́ :count', 'a_day' => '{1}ọjọ́ kan|ọjọ́ :count', 'hour' => 'wákati :count', 'a_hour' => '{1}wákati kan|wákati :count', 'minute' => 'ìsẹjú :count', 'a_minute' => '{1}ìsẹjú kan|ìsẹjú :count', 'second' => 'iaayá :count', 'a_second' => '{1}ìsẹjú aayá die|aayá :count', 'ago' => ':time kọjá', 'from_now' => 'ní :time', 'diff_yesterday' => 'Àna', 'diff_yesterday_regexp' => 'Àna(?:\\s+ni)?', 'diff_today' => 'Ònì', 'diff_today_regexp' => 'Ònì(?:\\s+ni)?', 'diff_tomorrow' => 'Ọ̀la', 'diff_tomorrow_regexp' => 'Ọ̀la(?:\\s+ni)?', 'formats' => [ 'LT' => 'h:mm A', 'LTS' => 'h:mm:ss A', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY h:mm A', 'LLLL' => 'dddd, D MMMM YYYY h:mm A', ], 'calendar' => [ 'sameDay' => '[Ònì ni] LT', 'nextDay' => '[Ọ̀la ni] LT', 'nextWeek' => 'dddd [Ọsẹ̀ tón\'bọ] [ni] LT', 'lastDay' => '[Àna ni] LT', 'lastWeek' => 'dddd [Ọsẹ̀ tólọ́] [ni] LT', 'sameElse' => 'L', ], 'ordinal' => 'ọjọ́ :number', 'months' => ['Sẹ́rẹ́', 'Èrèlè', 'Ẹrẹ̀nà', 'Ìgbé', 'Èbibi', 'Òkùdu', 'Agẹmo', 'Ògún', 'Owewe', 'Ọ̀wàrà', 'Bélú', 'Ọ̀pẹ̀̀'], 'months_short' => ['Sẹ́r', 'Èrl', 'Ẹrn', 'Ìgb', 'Èbi', 'Òkù', 'Agẹ', 'Ògú', 'Owe', 'Ọ̀wà', 'Bél', 'Ọ̀pẹ̀̀'], 'weekdays' => ['Àìkú', 'Ajé', 'Ìsẹ́gun', 'Ọjọ́rú', 'Ọjọ́bọ', 'Ẹtì', 'Àbámẹ́ta'], 'weekdays_short' => ['Àìk', 'Ajé', 'Ìsẹ́', 'Ọjr', 'Ọjb', 'Ẹtì', 'Àbá'], 'weekdays_min' => ['Àì', 'Aj', 'Ìs', 'Ọr', 'Ọb', 'Ẹt', 'Àb'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'meridiem' => ['Àárọ̀', 'Ọ̀sán'], ]; PK������<1Z[ia �� ����Carbon/Lang/pt_CH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/pt.php'; PK������<1Z �� ����Carbon/Lang/lo.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - ryanhart2 */ return [ 'year' => ':count ປີ', 'y' => ':count ປີ', 'month' => ':count ເດືອນ', 'm' => ':count ດ. ', 'week' => ':count ອາທິດ', 'w' => ':count ອທ. ', 'day' => ':count ມື້', 'd' => ':count ມື້', 'hour' => ':count ຊົ່ວໂມງ', 'h' => ':count ຊມ. ', 'minute' => ':count ນາທີ', 'min' => ':count ນທ. ', 'second' => '{1}ບໍ່ເທົ່າໃດວິນາທີ|]1,Inf[:count ວິນາທີ', 's' => ':count ວິ. ', 'ago' => ':timeຜ່ານມາ', 'from_now' => 'ອີກ :time', 'diff_now' => 'ຕອນນີ້', 'diff_today' => 'ມື້ນີ້ເວລາ', 'diff_yesterday' => 'ມື້ວານນີ້ເວລາ', 'diff_tomorrow' => 'ມື້ອື່ນເວລາ', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'ວັນdddd D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[ມື້ນີ້ເວລາ] LT', 'nextDay' => '[ມື້ອື່ນເວລາ] LT', 'nextWeek' => '[ວັນ]dddd[ໜ້າເວລາ] LT', 'lastDay' => '[ມື້ວານນີ້ເວລາ] LT', 'lastWeek' => '[ວັນ]dddd[ແລ້ວນີ້ເວລາ] LT', 'sameElse' => 'L', ], 'ordinal' => 'ທີ່:number', 'meridiem' => ['ຕອນເຊົ້າ', 'ຕອນແລງ'], 'months' => ['ມັງກອນ', 'ກຸມພາ', 'ມີນາ', 'ເມສາ', 'ພຶດສະພາ', 'ມິຖຸນາ', 'ກໍລະກົດ', 'ສິງຫາ', 'ກັນຍາ', 'ຕຸລາ', 'ພະຈິກ', 'ທັນວາ'], 'months_short' => ['ມັງກອນ', 'ກຸມພາ', 'ມີນາ', 'ເມສາ', 'ພຶດສະພາ', 'ມິຖຸນາ', 'ກໍລະກົດ', 'ສິງຫາ', 'ກັນຍາ', 'ຕຸລາ', 'ພະຈິກ', 'ທັນວາ'], 'weekdays' => ['ອາທິດ', 'ຈັນ', 'ອັງຄານ', 'ພຸດ', 'ພະຫັດ', 'ສຸກ', 'ເສົາ'], 'weekdays_short' => ['ທິດ', 'ຈັນ', 'ອັງຄານ', 'ພຸດ', 'ພະຫັດ', 'ສຸກ', 'ເສົາ'], 'weekdays_min' => ['ທ', 'ຈ', 'ອຄ', 'ພ', 'ພຫ', 'ສກ', 'ສ'], 'list' => [', ', 'ແລະ '], ]; PK������<1Z;O��O����Carbon/Lang/bhb.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/bhb_IN.php'; PK������<1Zd������Carbon/Lang/es_PE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]); PK������<1Zfff��f����Carbon/Lang/ta.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - François B * - JD Isaacks * - Satheez */ return [ 'year' => ':count வருடம்|:count ஆண்டுகள்', 'a_year' => 'ஒரு வருடம்|:count ஆண்டுகள்', 'y' => ':count வருட.|:count ஆண்.', 'month' => ':count மாதம்|:count மாதங்கள்', 'a_month' => 'ஒரு மாதம்|:count மாதங்கள்', 'm' => ':count மாத.', 'week' => ':count வாரம்|:count வாரங்கள்', 'a_week' => 'ஒரு வாரம்|:count வாரங்கள்', 'w' => ':count வார.', 'day' => ':count நாள்|:count நாட்கள்', 'a_day' => 'ஒரு நாள்|:count நாட்கள்', 'd' => ':count நாள்|:count நாட்.', 'hour' => ':count மணி நேரம்|:count மணி நேரம்', 'a_hour' => 'ஒரு மணி நேரம்|:count மணி நேரம்', 'h' => ':count மணி.', 'minute' => ':count நிமிடம்|:count நிமிடங்கள்', 'a_minute' => 'ஒரு நிமிடம்|:count நிமிடங்கள்', 'min' => ':count நிமி.', 'second' => ':count சில விநாடிகள்|:count விநாடிகள்', 'a_second' => 'ஒரு சில விநாடிகள்|:count விநாடிகள்', 's' => ':count விநா.', 'ago' => ':time முன்', 'from_now' => ':time இல்', 'before' => ':time முன்', 'after' => ':time பின்', 'diff_now' => 'இப்போது', 'diff_today' => 'இன்று', 'diff_yesterday' => 'நேற்று', 'diff_tomorrow' => 'நாளை', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY, HH:mm', 'LLLL' => 'dddd, D MMMM YYYY, HH:mm', ], 'calendar' => [ 'sameDay' => '[இன்று] LT', 'nextDay' => '[நாளை] LT', 'nextWeek' => 'dddd, LT', 'lastDay' => '[நேற்று] LT', 'lastWeek' => '[கடந்த வாரம்] dddd, LT', 'sameElse' => 'L', ], 'ordinal' => ':numberவது', 'meridiem' => function ($hour) { if ($hour < 2) { return ' யாமம்'; } if ($hour < 6) { return ' வைகறை'; } if ($hour < 10) { return ' காலை'; } if ($hour < 14) { return ' நண்பகல்'; } if ($hour < 18) { return ' எற்பாடு'; } if ($hour < 22) { return ' மாலை'; } return ' யாமம்'; }, 'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டெம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'], 'months_short' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டெம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'], 'weekdays' => ['ஞாயிற்றுக்கிழமை', 'திங்கட்கிழமை', 'செவ்வாய்கிழமை', 'புதன்கிழமை', 'வியாழக்கிழமை', 'வெள்ளிக்கிழமை', 'சனிக்கிழமை'], 'weekdays_short' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'], 'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' மற்றும் '], 'weekend' => [0, 0], ]; PK������<1Z}O��O����Carbon/Lang/mfe.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/mfe_MU.php'; PK������<1Z-!b>��>����Carbon/Lang/ar_JO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org * - Abdullah-Alhariri */ return array_replace_recursive(require __DIR__.'/ar.php', [ 'formats' => [ 'L' => 'DD MMM, YYYY', ], 'months' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'], 'months_short' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'], 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'], ]); PK������<1Z �� ����Carbon/Lang/hr_HR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/hr.php'; PK������<1Zxs��s����Carbon/Lang/ii.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['ꎸꄑ', 'ꁯꋒ'], 'weekdays' => ['ꑭꆏꑍ', 'ꆏꊂꋍ', 'ꆏꊂꑍ', 'ꆏꊂꌕ', 'ꆏꊂꇖ', 'ꆏꊂꉬ', 'ꆏꊂꃘ'], 'weekdays_short' => ['ꑭꆏ', 'ꆏꋍ', 'ꆏꑍ', 'ꆏꌕ', 'ꆏꇖ', 'ꆏꉬ', 'ꆏꃘ'], 'weekdays_min' => ['ꑭꆏ', 'ꆏꋍ', 'ꆏꑍ', 'ꆏꌕ', 'ꆏꇖ', 'ꆏꉬ', 'ꆏꃘ'], 'months' => null, 'months_short' => ['ꋍꆪ', 'ꑍꆪ', 'ꌕꆪ', 'ꇖꆪ', 'ꉬꆪ', 'ꃘꆪ', 'ꏃꆪ', 'ꉆꆪ', 'ꈬꆪ', 'ꊰꆪ', 'ꊰꊪꆪ', 'ꊰꑋꆪ'], 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'YYYY-MM-dd', 'LL' => 'YYYY MMM D', 'LLL' => 'YYYY MMMM D h:mm a', 'LLLL' => 'YYYY MMMM D, dddd h:mm a', ], 'year' => ':count ꒉ', // less reliable 'y' => ':count ꒉ', // less reliable 'a_year' => ':count ꒉ', // less reliable 'month' => ':count ꆪ', 'm' => ':count ꆪ', 'a_month' => ':count ꆪ', 'week' => ':count ꏃ', // less reliable 'w' => ':count ꏃ', // less reliable 'a_week' => ':count ꏃ', // less reliable 'day' => ':count ꏜ', // less reliable 'd' => ':count ꏜ', // less reliable 'a_day' => ':count ꏜ', // less reliable 'hour' => ':count ꄮꈉ', 'h' => ':count ꄮꈉ', 'a_hour' => ':count ꄮꈉ', 'minute' => ':count ꀄꊭ', // less reliable 'min' => ':count ꀄꊭ', // less reliable 'a_minute' => ':count ꀄꊭ', // less reliable 'second' => ':count ꇅ', // less reliable 's' => ':count ꇅ', // less reliable 'a_second' => ':count ꇅ', // less reliable ]); PK������<1Z''x �� ����Carbon/Lang/fr_SN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1ZpG��G����Carbon/Lang/en_GG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Zv������Carbon/Lang/fr_CH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Dieter Sting * - François B * - Gaspard Bucher * - Maxime VALY * - JD Isaacks */ return array_replace_recursive(require __DIR__.'/fr.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], ]); PK������<1ZvR`O��O����Carbon/Lang/mhr.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/mhr_RU.php'; PK������<1Z}*B �� ����Carbon/Lang/ha_GH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ha.php'; PK������<1ZpG��G����Carbon/Lang/en_FI.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z䇢 �� ����Carbon/Lang/kn_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/kn.php'; PK������<1Zڼ������Carbon/Lang/ksf.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['sárúwá', 'cɛɛ́nko'], 'weekdays' => ['sɔ́ndǝ', 'lǝndí', 'maadí', 'mɛkrɛdí', 'jǝǝdí', 'júmbá', 'samdí'], 'weekdays_short' => ['sɔ́n', 'lǝn', 'maa', 'mɛk', 'jǝǝ', 'júm', 'sam'], 'weekdays_min' => ['sɔ́n', 'lǝn', 'maa', 'mɛk', 'jǝǝ', 'júm', 'sam'], 'months' => ['ŋwíí a ntɔ́ntɔ', 'ŋwíí akǝ bɛ́ɛ', 'ŋwíí akǝ ráá', 'ŋwíí akǝ nin', 'ŋwíí akǝ táan', 'ŋwíí akǝ táafɔk', 'ŋwíí akǝ táabɛɛ', 'ŋwíí akǝ táaraa', 'ŋwíí akǝ táanin', 'ŋwíí akǝ ntɛk', 'ŋwíí akǝ ntɛk di bɔ́k', 'ŋwíí akǝ ntɛk di bɛ́ɛ'], 'months_short' => ['ŋ1', 'ŋ2', 'ŋ3', 'ŋ4', 'ŋ5', 'ŋ6', 'ŋ7', 'ŋ8', 'ŋ9', 'ŋ10', 'ŋ11', 'ŋ12'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], ]); PK������<1ZNJ������Carbon/Lang/sc_IT.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Sardinian Translators Team Massimeddu Cireddu massimeddu@gmail.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD. MM. YY', ], 'months' => ['Ghennàrgiu', 'Freàrgiu', 'Martzu', 'Abrile', 'Maju', 'Làmpadas', 'Argiolas//Trìulas', 'Austu', 'Cabudanni', 'Santugaine//Ladàmine', 'Onniasantu//Santandria', 'Nadale//Idas'], 'months_short' => ['Ghe', 'Fre', 'Mar', 'Abr', 'Maj', 'Làm', 'Arg', 'Aus', 'Cab', 'Lad', 'Onn', 'Nad'], 'weekdays' => ['Domìnigu', 'Lunis', 'Martis', 'Mèrcuris', 'Giòbia', 'Chenàbura', 'Sàbadu'], 'weekdays_short' => ['Dom', 'Lun', 'Mar', 'Mèr', 'Giò', 'Che', 'Sàb'], 'weekdays_min' => ['Dom', 'Lun', 'Mar', 'Mèr', 'Giò', 'Che', 'Sàb'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'minute' => ':count mementu', // less reliable 'min' => ':count mementu', // less reliable 'a_minute' => ':count mementu', // less reliable 'year' => ':count annu', 'y' => ':count annu', 'a_year' => ':count annu', 'month' => ':count mese', 'm' => ':count mese', 'a_month' => ':count mese', 'week' => ':count chida', 'w' => ':count chida', 'a_week' => ':count chida', 'day' => ':count dí', 'd' => ':count dí', 'a_day' => ':count dí', 'hour' => ':count ora', 'h' => ':count ora', 'a_hour' => ':count ora', 'second' => ':count secundu', 's' => ':count secundu', 'a_second' => ':count secundu', ]); PK������<1Zj\ ������Carbon/Lang/ks_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Red Hat, Pune bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'M/D/YY', ], 'months' => ['جنؤری', 'فرؤری', 'مارٕچ', 'اپریل', 'میٔ', 'جوٗن', 'جوٗلایی', 'اگست', 'ستمبر', 'اکتوٗبر', 'نومبر', 'دسمبر'], 'months_short' => ['جنؤری', 'فرؤری', 'مارٕچ', 'اپریل', 'میٔ', 'جوٗن', 'جوٗلایی', 'اگست', 'ستمبر', 'اکتوٗبر', 'نومبر', 'دسمبر'], 'weekdays' => ['آتهوار', 'ژءندروار', 'بوءںوار', 'بودهوار', 'برىسوار', 'جمع', 'بٹوار'], 'weekdays_short' => ['آتهوار', 'ژءنتروار', 'بوءںوار', 'بودهوار', 'برىسوار', 'جمع', 'بٹوار'], 'weekdays_min' => ['آتهوار', 'ژءنتروار', 'بوءںوار', 'بودهوار', 'برىسوار', 'جمع', 'بٹوار'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['دوپھربرونھ', 'دوپھرپتھ'], 'year' => ':count آب', // less reliable 'y' => ':count آب', // less reliable 'a_year' => ':count آب', // less reliable 'month' => ':count रान्', // less reliable 'm' => ':count रान्', // less reliable 'a_month' => ':count रान्', // less reliable 'week' => ':count آتھٕوار', // less reliable 'w' => ':count آتھٕوار', // less reliable 'a_week' => ':count آتھٕوار', // less reliable 'hour' => ':count سۄن', // less reliable 'h' => ':count سۄن', // less reliable 'a_hour' => ':count سۄن', // less reliable 'minute' => ':count فَن', // less reliable 'min' => ':count فَن', // less reliable 'a_minute' => ':count فَن', // less reliable 'second' => ':count दोʼयुम', // less reliable 's' => ':count दोʼयुम', // less reliable 'a_second' => ':count दोʼयुम', // less reliable ]); PK������<1Z>~!o �� ����Carbon/Lang/cy_GB.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/cy.php'; PK������<1Z`Y �� ����Carbon/Lang/zh_Hans.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - monkeycon * - François B * - Jason Katz-Brown * - Konstantin Konev * - Chris Lam * - Serhan Apaydın * - Gary Lo * - JD Isaacks * - Chris Hemp * - shankesgk2 * - Daniel Cheung (danvim) */ return [ 'year' => ':count:optional-space年', 'y' => ':count:optional-space年', 'month' => ':count:optional-space个月', 'm' => ':count:optional-space个月', 'week' => ':count:optional-space周', 'w' => ':count:optional-space周', 'day' => ':count:optional-space天', 'd' => ':count:optional-space天', 'hour' => ':count:optional-space小时', 'h' => ':count:optional-space小时', 'minute' => ':count:optional-space分钟', 'min' => ':count:optional-space分钟', 'second' => ':count:optional-space秒', 'a_second' => '{1}几秒|]1,Inf[:count:optional-space秒', 's' => ':count:optional-space秒', 'ago' => ':time前', 'from_now' => ':time后', 'after' => ':time后', 'before' => ':time前', 'diff_now' => '现在', 'diff_today' => '今天', 'diff_yesterday' => '昨天', 'diff_tomorrow' => '明天', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY/MM/DD', 'LL' => 'YYYY年M月D日', 'LLL' => 'YYYY年M月D日 HH:mm', 'LLLL' => 'YYYY年M月D日dddd HH:mm', ], 'calendar' => [ 'sameDay' => '[今天]LT', 'nextDay' => '[明天]LT', 'nextWeek' => '[下]ddddLT', 'lastDay' => '[昨天]LT', 'lastWeek' => '[上]ddddLT', 'sameElse' => 'L', ], 'ordinal' => function ($number, $period) { switch ($period) { case 'd': case 'D': case 'DDD': return $number.'日'; case 'M': return $number.'月'; case 'w': case 'W': return $number.'周'; default: return $number; } }, 'meridiem' => function ($hour, $minute) { $time = $hour * 100 + $minute; if ($time < 600) { return '凌晨'; } if ($time < 900) { return '早上'; } if ($time < 1130) { return '上午'; } if ($time < 1230) { return '中午'; } if ($time < 1800) { return '下午'; } return '晚上'; }, 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], 'months_short' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], 'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'], 'weekdays_short' => ['周日', '周一', '周二', '周三', '周四', '周五', '周六'], 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => '', ]; PK������<1Z1H(��(����Carbon/Lang/aa_ER@saaho.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ge'ez Frontier Foundation locales@geez.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['Qunxa Garablu', 'Naharsi Kudo', 'Ciggilta Kudo', 'Agda Baxisso', 'Caxah Alsa', 'Qasa Dirri', 'Qado Dirri', 'Leqeeni', 'Waysu', 'Diteli', 'Ximoli', 'Kaxxa Garablu'], 'months_short' => ['Qun', 'Nah', 'Cig', 'Agd', 'Cax', 'Qas', 'Qad', 'Leq', 'Way', 'Dit', 'Xim', 'Kax'], 'weekdays' => ['Naba Sambat', 'Sani', 'Salus', 'Rabuq', 'Camus', 'Jumqata', 'Qunxa Sambat'], 'weekdays_short' => ['Nab', 'San', 'Sal', 'Rab', 'Cam', 'Jum', 'Qun'], 'weekdays_min' => ['Nab', 'San', 'Sal', 'Rab', 'Cam', 'Jum', 'Qun'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'meridiem' => ['saaku', 'carra'], ]); PK������<1Z.a������Carbon/Lang/sv_AX.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/sv.php', [ 'formats' => [ 'L' => 'YYYY-MM-dd', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], ]); PK������<1ZkzN��N����Carbon/Lang/ms_MY.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - Azri Jamil * - JD Isaacks */ return require __DIR__.'/ms.php'; PK������<1ZF1k �� ����Carbon/Lang/ko.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Kunal Marwaha * - FourwingsY * - François B * - Jason Katz-Brown * - Seokjun Kim * - Junho Kim * - JD Isaacks * - Juwon Kim */ return [ 'year' => ':count년', 'a_year' => '{1}일년|]1,Inf[:count년', 'y' => ':count년', 'month' => ':count개월', 'a_month' => '{1}한달|]1,Inf[:count개월', 'm' => ':count개월', 'week' => ':count주', 'a_week' => '{1}일주일|]1,Inf[:count 주', 'w' => ':count주일', 'day' => ':count일', 'a_day' => '{1}하루|]1,Inf[:count일', 'd' => ':count일', 'hour' => ':count시간', 'a_hour' => '{1}한시간|]1,Inf[:count시간', 'h' => ':count시간', 'minute' => ':count분', 'a_minute' => '{1}일분|]1,Inf[:count분', 'min' => ':count분', 'second' => ':count초', 'a_second' => '{1}몇초|]1,Inf[:count초', 's' => ':count초', 'ago' => ':time 전', 'from_now' => ':time 후', 'after' => ':time 후', 'before' => ':time 전', 'diff_now' => '지금', 'diff_today' => '오늘', 'diff_yesterday' => '어제', 'diff_tomorrow' => '내일', 'formats' => [ 'LT' => 'A h:mm', 'LTS' => 'A h:mm:ss', 'L' => 'YYYY.MM.DD.', 'LL' => 'YYYY년 MMMM D일', 'LLL' => 'YYYY년 MMMM D일 A h:mm', 'LLLL' => 'YYYY년 MMMM D일 dddd A h:mm', ], 'calendar' => [ 'sameDay' => '오늘 LT', 'nextDay' => '내일 LT', 'nextWeek' => 'dddd LT', 'lastDay' => '어제 LT', 'lastWeek' => '지난주 dddd LT', 'sameElse' => 'L', ], 'ordinal' => function ($number, $period) { switch ($period) { case 'd': case 'D': case 'DDD': return $number.'일'; case 'M': return $number.'월'; case 'w': case 'W': return $number.'주'; default: return $number; } }, 'meridiem' => ['오전', '오후'], 'months' => ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'], 'months_short' => ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'], 'weekdays' => ['일요일', '월요일', '화요일', '수요일', '목요일', '금요일', '토요일'], 'weekdays_short' => ['일', '월', '화', '수', '목', '금', '토'], 'weekdays_min' => ['일', '월', '화', '수', '목', '금', '토'], 'list' => ' ', ]; PK������<1Z2Uw��w����Carbon/Lang/oc.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Quentí */ // @codeCoverageIgnoreStart use Symfony\Component\Translation\PluralizationRules; if (class_exists('Symfony\\Component\\Translation\\PluralizationRules')) { PluralizationRules::set(static function ($number) { return $number == 1 ? 0 : 1; }, 'oc'); } // @codeCoverageIgnoreEnd return [ 'year' => ':count an|:count ans', 'a_year' => 'un an|:count ans', 'y' => ':count an|:count ans', 'month' => ':count mes|:count meses', 'a_month' => 'un mes|:count meses', 'm' => ':count mes|:count meses', 'week' => ':count setmana|:count setmanas', 'a_week' => 'una setmana|:count setmanas', 'w' => ':count setmana|:count setmanas', 'day' => ':count jorn|:count jorns', 'a_day' => 'un jorn|:count jorns', 'd' => ':count jorn|:count jorns', 'hour' => ':count ora|:count oras', 'a_hour' => 'una ora|:count oras', 'h' => ':count ora|:count oras', 'minute' => ':count minuta|:count minutas', 'a_minute' => 'una minuta|:count minutas', 'min' => ':count minuta|:count minutas', 'second' => ':count segonda|:count segondas', 'a_second' => 'una segonda|:count segondas', 's' => ':count segonda|:count segondas', 'ago' => 'fa :time', 'from_now' => 'd\'aquí :time', 'after' => ':time aprèp', 'before' => ':time abans', 'diff_now' => 'ara meteis', 'diff_today' => 'Uèi', 'diff_today_regexp' => 'Uèi(?:\\s+a)?', 'diff_yesterday' => 'ièr', 'diff_yesterday_regexp' => 'Ièr(?:\\s+a)?', 'diff_tomorrow' => 'deman', 'diff_tomorrow_regexp' => 'Deman(?:\\s+a)?', 'diff_before_yesterday' => 'ièr delà', 'diff_after_tomorrow' => 'deman passat', 'period_recurrences' => ':count còp|:count còps', 'period_interval' => 'cada :interval', 'period_start_date' => 'de :date', 'period_end_date' => 'fins a :date', 'formats' => [ 'LT' => 'H:mm', 'LTS' => 'H:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM [de] YYYY', 'LLL' => 'D MMMM [de] YYYY [a] H:mm', 'LLLL' => 'dddd D MMMM [de] YYYY [a] H:mm', ], 'calendar' => [ 'sameDay' => '[Uèi a] LT', 'nextDay' => '[Deman a] LT', 'nextWeek' => 'dddd [a] LT', 'lastDay' => '[Ièr a] LT', 'lastWeek' => 'dddd [passat a] LT', 'sameElse' => 'L', ], 'months' => ['de genièr', 'de febrièr', 'de març', 'd\'abrial', 'de mai', 'de junh', 'de julhet', 'd\'agost', 'de setembre', 'd’octòbre', 'de novembre', 'de decembre'], 'months_standalone' => ['genièr', 'febrièr', 'març', 'abrial', 'mai', 'junh', 'julh', 'agost', 'setembre', 'octòbre', 'novembre', 'decembre'], 'months_short' => ['gen.', 'feb.', 'març', 'abr.', 'mai', 'junh', 'julh', 'ago.', 'sep.', 'oct.', 'nov.', 'dec.'], 'weekdays' => ['dimenge', 'diluns', 'dimars', 'dimècres', 'dijòus', 'divendres', 'dissabte'], 'weekdays_short' => ['dg', 'dl', 'dm', 'dc', 'dj', 'dv', 'ds'], 'weekdays_min' => ['dg', 'dl', 'dm', 'dc', 'dj', 'dv', 'ds'], 'ordinal' => function ($number, string $period = '') { $ordinal = [1 => 'èr', 2 => 'nd'][(int) $number] ?? 'en'; // feminine for year, week, hour, minute, second if (preg_match('/^[yYwWhHgGis]$/', $period)) { $ordinal .= 'a'; } return $number.$ordinal; }, 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' e '], ]; PK������<1Zۺ �� ����Carbon/Lang/hu_HU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/hu.php'; PK������<1Z~O��O����Carbon/Lang/kab.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/kab_DZ.php'; PK������<1ZpG��G����Carbon/Lang/en_CC.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZXk��k����Carbon/Lang/mer.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['RŨ', 'ŨG'], 'weekdays' => ['Kiumia', 'Muramuko', 'Wairi', 'Wethatu', 'Wena', 'Wetano', 'Jumamosi'], 'weekdays_short' => ['KIU', 'MRA', 'WAI', 'WET', 'WEN', 'WTN', 'JUM'], 'weekdays_min' => ['KIU', 'MRA', 'WAI', 'WET', 'WEN', 'WTN', 'JUM'], 'months' => ['Januarĩ', 'Feburuarĩ', 'Machi', 'Ĩpurũ', 'Mĩĩ', 'Njuni', 'Njuraĩ', 'Agasti', 'Septemba', 'Oktũba', 'Novemba', 'Dicemba'], 'months_short' => ['JAN', 'FEB', 'MAC', 'ĨPU', 'MĨĨ', 'NJU', 'NJR', 'AGA', 'SPT', 'OKT', 'NOV', 'DEC'], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'year' => ':count murume', // less reliable 'y' => ':count murume', // less reliable 'a_year' => ':count murume', // less reliable 'month' => ':count muchaara', // less reliable 'm' => ':count muchaara', // less reliable 'a_month' => ':count muchaara', // less reliable 'minute' => ':count monto', // less reliable 'min' => ':count monto', // less reliable 'a_minute' => ':count monto', // less reliable 'second' => ':count gikeno', // less reliable 's' => ':count gikeno', // less reliable 'a_second' => ':count gikeno', // less reliable ]); PK������<1Zܒ������Carbon/Lang/prg.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'months' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'], 'months_short' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY-MM-dd', 'LL' => 'YYYY MMM D', 'LLL' => 'YYYY MMMM D HH:mm', 'LLLL' => 'YYYY MMMM D, dddd HH:mm', ], 'year' => ':count meta', 'y' => ':count meta', 'a_year' => ':count meta', 'month' => ':count mēniks', // less reliable 'm' => ':count mēniks', // less reliable 'a_month' => ':count mēniks', // less reliable 'week' => ':count sawaītin', // less reliable 'w' => ':count sawaītin', // less reliable 'a_week' => ':count sawaītin', // less reliable 'day' => ':count di', 'd' => ':count di', 'a_day' => ':count di', 'hour' => ':count bruktēt', // less reliable 'h' => ':count bruktēt', // less reliable 'a_hour' => ':count bruktēt', // less reliable 'minute' => ':count līkuts', // less reliable 'min' => ':count līkuts', // less reliable 'a_minute' => ':count līkuts', // less reliable 'second' => ':count kitan', // less reliable 's' => ':count kitan', // less reliable 'a_second' => ':count kitan', // less reliable ]); PK������<1Z' �� ����Carbon/Lang/sq_AL.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/sq.php'; PK������<1Zx �� ����Carbon/Lang/ss.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - Nicolai Davies */ return [ 'year' => '{1}umnyaka|:count iminyaka', 'month' => '{1}inyanga|:count tinyanga', 'week' => '{1}:count liviki|:count emaviki', 'day' => '{1}lilanga|:count emalanga', 'hour' => '{1}lihora|:count emahora', 'minute' => '{1}umzuzu|:count emizuzu', 'second' => '{1}emizuzwana lomcane|:count mzuzwana', 'ago' => 'wenteka nga :time', 'from_now' => 'nga :time', 'diff_yesterday' => 'Itolo', 'diff_yesterday_regexp' => 'Itolo(?:\\s+nga)?', 'diff_today' => 'Namuhla', 'diff_today_regexp' => 'Namuhla(?:\\s+nga)?', 'diff_tomorrow' => 'Kusasa', 'diff_tomorrow_regexp' => 'Kusasa(?:\\s+nga)?', 'formats' => [ 'LT' => 'h:mm A', 'LTS' => 'h:mm:ss A', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY h:mm A', 'LLLL' => 'dddd, D MMMM YYYY h:mm A', ], 'calendar' => [ 'sameDay' => '[Namuhla nga] LT', 'nextDay' => '[Kusasa nga] LT', 'nextWeek' => 'dddd [nga] LT', 'lastDay' => '[Itolo nga] LT', 'lastWeek' => 'dddd [leliphelile] [nga] LT', 'sameElse' => 'L', ], 'ordinal' => function ($number) { $lastDigit = $number % 10; return $number.( ((int) ($number % 100 / 10) === 1) ? 'e' : ( ($lastDigit === 1 || $lastDigit === 2) ? 'a' : 'e' ) ); }, 'meridiem' => function ($hour) { if ($hour < 11) { return 'ekuseni'; } if ($hour < 15) { return 'emini'; } if ($hour < 19) { return 'entsambama'; } return 'ebusuku'; }, 'months' => ['Bhimbidvwane', 'Indlovana', 'Indlov\'lenkhulu', 'Mabasa', 'Inkhwekhweti', 'Inhlaba', 'Kholwane', 'Ingci', 'Inyoni', 'Imphala', 'Lweti', 'Ingongoni'], 'months_short' => ['Bhi', 'Ina', 'Inu', 'Mab', 'Ink', 'Inh', 'Kho', 'Igc', 'Iny', 'Imp', 'Lwe', 'Igo'], 'weekdays' => ['Lisontfo', 'Umsombuluko', 'Lesibili', 'Lesitsatfu', 'Lesine', 'Lesihlanu', 'Umgcibelo'], 'weekdays_short' => ['Lis', 'Umb', 'Lsb', 'Les', 'Lsi', 'Lsh', 'Umg'], 'weekdays_min' => ['Li', 'Us', 'Lb', 'Lt', 'Ls', 'Lh', 'Ug'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, ]; PK������<1Z7șN��N����Carbon/Lang/ik.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/ik_CA.php'; PK������<1Zs Q��Q����Carbon/Lang/gom.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/gom_Latn.php'; PK������<1ZpG��G����Carbon/Lang/en_VC.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZD[��[����Carbon/Lang/ewo.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['kíkíríg', 'ngəgógəle'], 'weekdays' => ['sɔ́ndɔ', 'mɔ́ndi', 'sɔ́ndɔ məlú mə́bɛ̌', 'sɔ́ndɔ məlú mə́lɛ́', 'sɔ́ndɔ məlú mə́nyi', 'fúladé', 'séradé'], 'weekdays_short' => ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'fúl', 'sér'], 'weekdays_min' => ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'fúl', 'sér'], 'months' => ['ngɔn osú', 'ngɔn bɛ̌', 'ngɔn lála', 'ngɔn nyina', 'ngɔn tána', 'ngɔn saməna', 'ngɔn zamgbála', 'ngɔn mwom', 'ngɔn ebulú', 'ngɔn awóm', 'ngɔn awóm ai dziá', 'ngɔn awóm ai bɛ̌'], 'months_short' => ['ngo', 'ngb', 'ngl', 'ngn', 'ngt', 'ngs', 'ngz', 'ngm', 'nge', 'nga', 'ngad', 'ngab'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], // Too unreliable /* 'year' => ':count mbu', // less reliable 'y' => ':count mbu', // less reliable 'a_year' => ':count mbu', // less reliable 'month' => ':count ngòn', // less reliable 'm' => ':count ngòn', // less reliable 'a_month' => ':count ngòn', // less reliable 'week' => ':count mësë', // less reliable 'w' => ':count mësë', // less reliable 'a_week' => ':count mësë', // less reliable 'day' => ':count mësë', // less reliable 'd' => ':count mësë', // less reliable 'a_day' => ':count mësë', // less reliable 'hour' => ':count awola', // less reliable 'h' => ':count awola', // less reliable 'a_hour' => ':count awola', // less reliable 'minute' => ':count awola', // less reliable 'min' => ':count awola', // less reliable 'a_minute' => ':count awola', // less reliable */ ]); PK������<1Z1N��N����Carbon/Lang/zu.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/zu_ZA.php'; PK������<1Z+h������Carbon/Lang/am_ET.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ge'ez Frontier Foundation locales@geez.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች', 'ኤፕሪል', 'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት', 'ሴፕቴምበር', 'ኦክቶበር', 'ኖቬምበር', 'ዲሴምበር'], 'months_short' => ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕረ', 'ሜይ ', 'ጁን ', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክተ', 'ኖቬም', 'ዲሴም'], 'weekdays' => ['እሑድ', 'ሰኞ', 'ማክሰኞ', 'ረቡዕ', 'ሐሙስ', 'ዓርብ', 'ቅዳሜ'], 'weekdays_short' => ['እሑድ', 'ሰኞ ', 'ማክሰ', 'ረቡዕ', 'ሐሙስ', 'ዓርብ', 'ቅዳሜ'], 'weekdays_min' => ['እሑድ', 'ሰኞ ', 'ማክሰ', 'ረቡዕ', 'ሐሙስ', 'ዓርብ', 'ቅዳሜ'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['ጡዋት', 'ከሰዓት'], 'year' => ':count አመት', 'y' => ':count አመት', 'a_year' => ':count አመት', 'month' => ':count ወር', 'm' => ':count ወር', 'a_month' => ':count ወር', 'week' => ':count ሳምንት', 'w' => ':count ሳምንት', 'a_week' => ':count ሳምንት', 'day' => ':count ቀን', 'd' => ':count ቀን', 'a_day' => ':count ቀን', 'hour' => ':count ሰዓት', 'h' => ':count ሰዓት', 'a_hour' => ':count ሰዓት', 'minute' => ':count ደቂቃ', 'min' => ':count ደቂቃ', 'a_minute' => ':count ደቂቃ', 'second' => ':count ሴኮንድ', 's' => ':count ሴኮንድ', 'a_second' => ':count ሴኮንድ', 'ago' => 'ከ:time በፊት', 'from_now' => 'በ:time ውስጥ', ]); PK������<1Z+ �� ����Carbon/Lang/se_SE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/se.php'; PK������<1Z:ɷ������Carbon/Lang/de_AT.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - sheriffmarley * - Timo * - Michael Hohl * - Namoshek * - Bernhard Baumrock (BernhardBaumrock) */ return array_replace_recursive(require __DIR__.'/de.php', [ 'months' => [ 0 => 'Jänner', ], 'months_short' => [ 0 => 'Jän', ], ]); PK������<1Zk`��`����Carbon/Lang/en_SD.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 6, 'weekend' => [5, 6], ]); PK������<1ZTr �� ����Carbon/Lang/nds_NL.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - information from Kenneth Christiansen Kenneth Christiansen, Pablo Saratxaga kenneth@gnu.org, pablo@mandrakesoft.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], 'months' => ['Jaunuwoa', 'Februwoa', 'Moaz', 'Aprell', 'Mai', 'Juni', 'Juli', 'August', 'Septamba', 'Oktoba', 'Nowamba', 'Dezamba'], 'months_short' => ['Jan', 'Feb', 'Moz', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Now', 'Dez'], 'weekdays' => ['Sinndag', 'Mondag', 'Dingsdag', 'Meddwäakj', 'Donnadag', 'Friedag', 'Sinnowend'], 'weekdays_short' => ['Sdg', 'Mdg', 'Dsg', 'Mwk', 'Ddg', 'Fdg', 'Swd'], 'weekdays_min' => ['Sdg', 'Mdg', 'Dsg', 'Mwk', 'Ddg', 'Fdg', 'Swd'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, ]); PK������<1Z1/������Carbon/Lang/pt_MO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/pt.php', [ 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'LLL' => 'D [de] MMMM [de] YYYY, h:mm a', 'LLLL' => 'dddd, D [de] MMMM [de] YYYY, h:mm a', ], 'first_day_of_week' => 0, ]); PK������<1Z- �� ����Carbon/Lang/ff_CM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ff.php'; PK������<1Z �� ����Carbon/Lang/bm.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Estelle Comment */ return [ 'year' => 'san :count', 'a_year' => '{1}san kelen|san :count', 'y' => 'san :count', 'month' => 'kalo :count', 'a_month' => '{1}kalo kelen|kalo :count', 'm' => 'k. :count', 'week' => 'dɔgɔkun :count', 'a_week' => 'dɔgɔkun kelen', 'w' => 'd. :count', 'day' => 'tile :count', 'd' => 't. :count', 'a_day' => '{1}tile kelen|tile :count', 'hour' => 'lɛrɛ :count', 'a_hour' => '{1}lɛrɛ kelen|lɛrɛ :count', 'h' => 'l. :count', 'minute' => 'miniti :count', 'a_minute' => '{1}miniti kelen|miniti :count', 'min' => 'm. :count', 'second' => 'sekondi :count', 'a_second' => '{1}sanga dama dama|sekondi :count', 's' => 'sek. :count', 'ago' => 'a bɛ :time bɔ', 'from_now' => ':time kɔnɔ', 'diff_today' => 'Bi', 'diff_yesterday' => 'Kunu', 'diff_yesterday_regexp' => 'Kunu(?:\\s+lɛrɛ)?', 'diff_tomorrow' => 'Sini', 'diff_tomorrow_regexp' => 'Sini(?:\\s+lɛrɛ)?', 'diff_today_regexp' => 'Bi(?:\\s+lɛrɛ)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'MMMM [tile] D [san] YYYY', 'LLL' => 'MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm', 'LLLL' => 'dddd MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm', ], 'calendar' => [ 'sameDay' => '[Bi lɛrɛ] LT', 'nextDay' => '[Sini lɛrɛ] LT', 'nextWeek' => 'dddd [don lɛrɛ] LT', 'lastDay' => '[Kunu lɛrɛ] LT', 'lastWeek' => 'dddd [tɛmɛnen lɛrɛ] LT', 'sameElse' => 'L', ], 'months' => ['Zanwuyekalo', 'Fewuruyekalo', 'Marisikalo', 'Awirilikalo', 'Mɛkalo', 'Zuwɛnkalo', 'Zuluyekalo', 'Utikalo', 'Sɛtanburukalo', 'ɔkutɔburukalo', 'Nowanburukalo', 'Desanburukalo'], 'months_short' => ['Zan', 'Few', 'Mar', 'Awi', 'Mɛ', 'Zuw', 'Zul', 'Uti', 'Sɛt', 'ɔku', 'Now', 'Des'], 'weekdays' => ['Kari', 'Ntɛnɛn', 'Tarata', 'Araba', 'Alamisa', 'Juma', 'Sibiri'], 'weekdays_short' => ['Kar', 'Ntɛ', 'Tar', 'Ara', 'Ala', 'Jum', 'Sib'], 'weekdays_min' => ['Ka', 'Nt', 'Ta', 'Ar', 'Al', 'Ju', 'Si'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' ni '], ]; PK������<1Zb �� ����Carbon/Lang/fo_FO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fo.php'; PK������<1Z,�������Carbon/Lang/ar_SD.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org * - Abdullah-Alhariri */ return array_replace_recursive(require __DIR__.'/ar.php', [ 'formats' => [ 'L' => 'DD MMM, YYYY', ], 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'], 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'], 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'], ]); PK������<1Z''x �� ����Carbon/Lang/fr_TG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Z �� ����Carbon/Lang/bo_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/bo.php', [ 'meridiem' => ['སྔ་དྲོ་', 'ཕྱི་དྲོ་'], 'weekdays' => ['གཟའ་ཉི་མ་', 'གཟའ་ཟླ་བ་', 'གཟའ་མིག་དམར་', 'གཟའ་ལྷག་པ་', 'གཟའ་ཕུར་བུ་', 'གཟའ་པ་སངས་', 'གཟའ་སྤེན་པ་'], 'weekdays_short' => ['ཉི་མ་', 'ཟླ་བ་', 'མིག་དམར་', 'ལྷག་པ་', 'ཕུར་བུ་', 'པ་སངས་', 'སྤེན་པ་'], 'weekdays_min' => ['ཉི་མ་', 'ཟླ་བ་', 'མིག་དམར་', 'ལྷག་པ་', 'ཕུར་བུ་', 'པ་སངས་', 'སྤེན་པ་'], 'months' => ['ཟླ་བ་དང་པོ', 'ཟླ་བ་གཉིས་པ', 'ཟླ་བ་གསུམ་པ', 'ཟླ་བ་བཞི་པ', 'ཟླ་བ་ལྔ་པ', 'ཟླ་བ་དྲུག་པ', 'ཟླ་བ་བདུན་པ', 'ཟླ་བ་བརྒྱད་པ', 'ཟླ་བ་དགུ་པ', 'ཟླ་བ་བཅུ་པ', 'ཟླ་བ་བཅུ་གཅིག་པ', 'ཟླ་བ་བཅུ་གཉིས་པ'], 'months_short' => ['ཟླ་༡', 'ཟླ་༢', 'ཟླ་༣', 'ཟླ་༤', 'ཟླ་༥', 'ཟླ་༦', 'ཟླ་༧', 'ཟླ་༨', 'ཟླ་༩', 'ཟླ་༡༠', 'ཟླ་༡༡', 'ཟླ་༡༢'], 'months_standalone' => ['ཟླ་བ་དང་པོ་', 'ཟླ་བ་གཉིས་པ་', 'ཟླ་བ་གསུམ་པ་', 'ཟླ་བ་བཞི་པ་', 'ཟླ་བ་ལྔ་པ་', 'ཟླ་བ་དྲུག་པ་', 'ཟླ་བ་བདུན་པ་', 'ཟླ་བ་བརྒྱད་པ་', 'ཟླ་བ་དགུ་པ་', 'ཟླ་བ་བཅུ་པ་', 'ཟླ་བ་བཅུ་གཅིག་པ་', 'ཟླ་བ་བཅུ་གཉིས་པ་'], 'weekend' => [0, 0], 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'YYYY-MM-DD', 'LL' => 'YYYY ལོའི་MMMཚེས་D', 'LLL' => 'སྤྱི་ལོ་YYYY MMMMའི་ཚེས་D h:mm a', 'LLLL' => 'YYYY MMMMའི་ཚེས་D, dddd h:mm a', ], ]); PK������<1ZrO��O����Carbon/Lang/byn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/byn_ER.php'; PK������<1ZߜH��H����Carbon/Lang/mas_TZ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/mas.php', [ 'first_day_of_week' => 1, ]); PK������<1Z)��)����Carbon/Lang/ar_SO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ar.php', [ ]); PK������<1Z}< �� ����Carbon/Lang/mt_MT.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/mt.php'; PK������<1Z_������Carbon/Lang/en_ZM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - ANLoc Martin Benjamin locales@africanlocalization.net */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, ]); PK������<1Z5ƭ �� ����Carbon/Lang/gsw.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Christopher Dell * - Akira Matsuda * - Enrique Vidal * - Simone Carletti * - Henning Kiel * - Aaron Patterson * - Florian Hanke */ return [ 'year' => ':count Johr', 'month' => ':count Monet', 'week' => ':count Woche', 'day' => ':count Tag', 'hour' => ':count Schtund', 'minute' => ':count Minute', 'second' => ':count Sekunde', 'weekdays' => ['Sunntig', 'Mäntig', 'Ziischtig', 'Mittwuch', 'Dunschtig', 'Friitig', 'Samschtig'], 'weekdays_short' => ['Su', 'Mä', 'Zi', 'Mi', 'Du', 'Fr', 'Sa'], 'weekdays_min' => ['Su', 'Mä', 'Zi', 'Mi', 'Du', 'Fr', 'Sa'], 'months' => ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'Auguscht', 'September', 'Oktober', 'November', 'Dezember'], 'months_short' => ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'], 'meridiem' => ['am Vormittag', 'am Namittag'], 'ordinal' => ':number.', 'list' => [', ', ' und '], 'diff_now' => 'now', 'diff_yesterday' => 'geschter', 'diff_tomorrow' => 'moorn', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'Do MMMM YYYY', 'LLL' => 'Do MMMM, HH:mm [Uhr]', 'LLLL' => 'dddd, Do MMMM YYYY, HH:mm [Uhr]', ], ]; PK������<1Z������Carbon/Lang/nnh.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['mbaʼámbaʼ', 'ncwònzém'], 'weekdays' => null, 'weekdays_short' => ['lyɛʼɛ́ sẅíŋtè', 'mvfò lyɛ̌ʼ', 'mbɔ́ɔntè mvfò lyɛ̌ʼ', 'tsètsɛ̀ɛ lyɛ̌ʼ', 'mbɔ́ɔntè tsetsɛ̀ɛ lyɛ̌ʼ', 'mvfò màga lyɛ̌ʼ', 'màga lyɛ̌ʼ'], 'weekdays_min' => null, 'months' => null, 'months_short' => ['saŋ tsetsɛ̀ɛ lùm', 'saŋ kàg ngwóŋ', 'saŋ lepyè shúm', 'saŋ cÿó', 'saŋ tsɛ̀ɛ cÿó', 'saŋ njÿoláʼ', 'saŋ tyɛ̀b tyɛ̀b mbʉ̀ŋ', 'saŋ mbʉ̀ŋ', 'saŋ ngwɔ̀ʼ mbÿɛ', 'saŋ tàŋa tsetsáʼ', 'saŋ mejwoŋó', 'saŋ lùm'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/yy', 'LL' => 'D MMM, YYYY', 'LLL' => '[lyɛ]̌ʼ d [na] MMMM, YYYY HH:mm', 'LLLL' => 'dddd , [lyɛ]̌ʼ d [na] MMMM, YYYY HH:mm', ], ]); PK������<1ZpG��G����Carbon/Lang/en_TZ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1ZI)��)����Carbon/Lang/agq.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['a.g', 'a.k'], 'weekdays' => ['tsuʔntsɨ', 'tsuʔukpà', 'tsuʔughɔe', 'tsuʔutɔ̀mlò', 'tsuʔumè', 'tsuʔughɨ̂m', 'tsuʔndzɨkɔʔɔ'], 'weekdays_short' => ['nts', 'kpa', 'ghɔ', 'tɔm', 'ume', 'ghɨ', 'dzk'], 'weekdays_min' => ['nts', 'kpa', 'ghɔ', 'tɔm', 'ume', 'ghɨ', 'dzk'], 'months' => ['ndzɔ̀ŋɔ̀nùm', 'ndzɔ̀ŋɔ̀kƗ̀zùʔ', 'ndzɔ̀ŋɔ̀tƗ̀dʉ̀ghà', 'ndzɔ̀ŋɔ̀tǎafʉ̄ghā', 'ndzɔ̀ŋèsèe', 'ndzɔ̀ŋɔ̀nzùghò', 'ndzɔ̀ŋɔ̀dùmlo', 'ndzɔ̀ŋɔ̀kwîfɔ̀e', 'ndzɔ̀ŋɔ̀tƗ̀fʉ̀ghàdzughù', 'ndzɔ̀ŋɔ̀ghǔuwelɔ̀m', 'ndzɔ̀ŋɔ̀chwaʔàkaa wo', 'ndzɔ̀ŋèfwòo'], 'months_short' => ['nùm', 'kɨz', 'tɨd', 'taa', 'see', 'nzu', 'dum', 'fɔe', 'dzu', 'lɔm', 'kaa', 'fwo'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM, YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], ]); PK������<1Z[ia �� ����Carbon/Lang/pt_TL.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/pt.php'; PK������<1Zd������Carbon/Lang/tcy_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IndLinux.org, Samsung Electronics Co., Ltd. alexey.merzlyakov@samsung.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['ಜನವರಿ', 'ಫೆಬ್ರುವರಿ', 'ಮಾರ್ಚ್', 'ಏಪ್ರಿಲ್‌‌', 'ಮೇ', 'ಜೂನ್', 'ಜುಲೈ', 'ಆಗಸ್ಟ್', 'ಸೆಪ್ಟೆಂಬರ್‌', 'ಅಕ್ಟೋಬರ್', 'ನವೆಂಬರ್', 'ಡಿಸೆಂಬರ್'], 'months_short' => ['ಜ', 'ಫೆ', 'ಮಾ', 'ಏ', 'ಮೇ', 'ಜೂ', 'ಜು', 'ಆ', 'ಸೆ', 'ಅ', 'ನ', 'ಡಿ'], 'weekdays' => ['ಐಥಾರ', 'ಸೋಮಾರ', 'ಅಂಗರೆ', 'ಬುಧಾರ', 'ಗುರುವಾರ', 'ಶುಕ್ರರ', 'ಶನಿವಾರ'], 'weekdays_short' => ['ಐ', 'ಸೋ', 'ಅಂ', 'ಬು', 'ಗು', 'ಶು', 'ಶ'], 'weekdays_min' => ['ಐ', 'ಸೋ', 'ಅಂ', 'ಬು', 'ಗು', 'ಶು', 'ಶ'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['ಕಾಂಡೆ', 'ಬಯ್ಯ'], 'year' => ':count ನೀರ್', // less reliable 'y' => ':count ನೀರ್', // less reliable 'a_year' => ':count ನೀರ್', // less reliable 'month' => ':count ಮೀನ್', // less reliable 'm' => ':count ಮೀನ್', // less reliable 'a_month' => ':count ಮೀನ್', // less reliable 'day' => ':count ಸುಗ್ಗಿ', // less reliable 'd' => ':count ಸುಗ್ಗಿ', // less reliable 'a_day' => ':count ಸುಗ್ಗಿ', // less reliable ]); PK������<1Z-|K������Carbon/Lang/es_NI.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]); PK������<1ZP������Carbon/Lang/pa_PK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['جنوري', 'فروري', 'مارچ', 'اپريل', 'مٓی', 'جون', 'جولاي', 'اگست', 'ستمبر', 'اكتوبر', 'نومبر', 'دسمبر'], 'months_short' => ['جنوري', 'فروري', 'مارچ', 'اپريل', 'مٓی', 'جون', 'جولاي', 'اگست', 'ستمبر', 'اكتوبر', 'نومبر', 'دسمبر'], 'weekdays' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'], 'weekdays_short' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'], 'weekdays_min' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['ص', 'ش'], ]); PK������<1Zǖ������Carbon/Lang/an_ES.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Softaragones Jordi Mallach Pérez, Juan Pablo Martínez bug-glibc-locales@gnu.org, softaragones@softaragones.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['chinero', 'febrero', 'marzo', 'abril', 'mayo', 'chunyo', 'chuliol', 'agosto', 'setiembre', 'octubre', 'noviembre', 'aviento'], 'months_short' => ['chi', 'feb', 'mar', 'abr', 'may', 'chn', 'chl', 'ago', 'set', 'oct', 'nov', 'avi'], 'weekdays' => ['domingo', 'luns', 'martes', 'mierques', 'chueves', 'viernes', 'sabado'], 'weekdays_short' => ['dom', 'lun', 'mar', 'mie', 'chu', 'vie', 'sab'], 'weekdays_min' => ['dom', 'lun', 'mar', 'mie', 'chu', 'vie', 'sab'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'year' => ':count año', 'y' => ':count año', 'a_year' => ':count año', 'month' => ':count mes', 'm' => ':count mes', 'a_month' => ':count mes', 'week' => ':count semana', 'w' => ':count semana', 'a_week' => ':count semana', 'day' => ':count día', 'd' => ':count día', 'a_day' => ':count día', 'hour' => ':count reloch', // less reliable 'h' => ':count reloch', // less reliable 'a_hour' => ':count reloch', // less reliable 'minute' => ':count minuto', 'min' => ':count minuto', 'a_minute' => ':count minuto', 'second' => ':count segundo', 's' => ':count segundo', 'a_second' => ':count segundo', ]); PK������<1Zco������Carbon/Lang/rw_RW.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Rwanda Steve Murphy murf@e-tools.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], 'months' => ['Mutarama', 'Gashyantare', 'Werurwe', 'Mata', 'Gicuransi', 'Kamena', 'Nyakanga', 'Kanama', 'Nzeli', 'Ukwakira', 'Ugushyingo', 'Ukuboza'], 'months_short' => ['Mut', 'Gas', 'Wer', 'Mat', 'Gic', 'Kam', 'Nya', 'Kan', 'Nze', 'Ukw', 'Ugu', 'Uku'], 'weekdays' => ['Ku cyumweru', 'Kuwa mbere', 'Kuwa kabiri', 'Kuwa gatatu', 'Kuwa kane', 'Kuwa gatanu', 'Kuwa gatandatu'], 'weekdays_short' => ['Mwe', 'Mbe', 'Kab', 'Gtu', 'Kan', 'Gnu', 'Gnd'], 'weekdays_min' => ['Mwe', 'Mbe', 'Kab', 'Gtu', 'Kan', 'Gnu', 'Gnd'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'second' => ':count vuna', // less reliable 's' => ':count vuna', // less reliable 'a_second' => ':count vuna', // less reliable 'year' => 'aka :count', 'y' => 'aka :count', 'a_year' => 'aka :count', 'month' => 'ezi :count', 'm' => 'ezi :count', 'a_month' => 'ezi :count', 'week' => ':count icyumweru', 'w' => ':count icyumweru', 'a_week' => ':count icyumweru', 'day' => ':count nsi', 'd' => ':count nsi', 'a_day' => ':count nsi', 'hour' => 'saha :count', 'h' => 'saha :count', 'a_hour' => 'saha :count', 'minute' => ':count -nzinya', 'min' => ':count -nzinya', 'a_minute' => ':count -nzinya', ]); PK������<1ZHl������Carbon/Lang/mjw_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Jor Teron bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['Arkoi', 'Thangthang', 'There', 'Jangmi', 'Aru', 'Vosik', 'Jakhong', 'Paipai', 'Chiti', 'Phere', 'Phaikuni', 'Matijong'], 'months_short' => ['Ark', 'Thang', 'The', 'Jang', 'Aru', 'Vos', 'Jak', 'Pai', 'Chi', 'Phe', 'Phai', 'Mati'], 'weekdays' => ['Bhomkuru', 'Urmi', 'Durmi', 'Thelang', 'Theman', 'Bhomta', 'Bhomti'], 'weekdays_short' => ['Bhom', 'Ur', 'Dur', 'Tkel', 'Tkem', 'Bhta', 'Bhti'], 'weekdays_min' => ['Bhom', 'Ur', 'Dur', 'Tkel', 'Tkem', 'Bhta', 'Bhti'], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]); PK������<1Z�kO��O����Carbon/Lang/unm.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/unm_US.php'; PK������<1Z. �� ����Carbon/Lang/sv_FI.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/sv.php'; PK������<1Z8������Carbon/Lang/my.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - JD Isaacks * - Nay Lin Aung */ return [ 'year' => '{1}တစ်နှစ်|]1,Inf[:count နှစ်', 'y' => ':count နှစ်', 'month' => '{1}တစ်လ|]1,Inf[:count လ', 'm' => ':count လ', 'week' => ':count ပတ်', 'w' => ':count ပတ်', 'day' => '{1}တစ်ရက်|]1,Inf[:count ရက်', 'd' => ':count ရက်', 'hour' => '{1}တစ်နာရီ|]1,Inf[:count နာရီ', 'h' => ':count နာရီ', 'minute' => '{1}တစ်မိနစ်|]1,Inf[:count မိနစ်', 'min' => ':count မိနစ်', 'second' => '{1}စက္ကန်.အနည်းငယ်|]1,Inf[:count စက္ကန့်', 's' => ':count စက္ကန့်', 'ago' => 'လွန်ခဲ့သော :time က', 'from_now' => 'လာမည့် :time မှာ', 'after' => ':time ကြာပြီးနောက်', 'before' => ':time မတိုင်ခင်', 'diff_now' => 'အခုလေးတင်', 'diff_today' => 'ယနေ.', 'diff_yesterday' => 'မနေ့က', 'diff_yesterday_regexp' => 'မနေ.က', 'diff_tomorrow' => 'မနက်ဖြန်', 'diff_before_yesterday' => 'တမြန်နေ့က', 'diff_after_tomorrow' => 'တဘက်ခါ', 'period_recurrences' => ':count ကြိမ်', 'formats' => [ 'LT' => 'Oh:Om A', 'LTS' => 'Oh:Om:Os A', 'L' => 'OD/OM/OY', 'LL' => 'OD MMMM OY', 'LLL' => 'OD MMMM OY Oh:Om A', 'LLLL' => 'dddd OD MMMM OY Oh:Om A', ], 'calendar' => [ 'sameDay' => '[ယနေ.] LT [မှာ]', 'nextDay' => '[မနက်ဖြန်] LT [မှာ]', 'nextWeek' => 'dddd LT [မှာ]', 'lastDay' => '[မနေ.က] LT [မှာ]', 'lastWeek' => '[ပြီးခဲ့သော] dddd LT [မှာ]', 'sameElse' => 'L', ], 'months' => ['ဇန်နဝါရီ', 'ဖေဖော်ဝါရီ', 'မတ်', 'ဧပြီ', 'မေ', 'ဇွန်', 'ဇူလိုင်', 'သြဂုတ်', 'စက်တင်ဘာ', 'အောက်တိုဘာ', 'နိုဝင်ဘာ', 'ဒီဇင်ဘာ'], 'months_short' => ['ဇန်', 'ဖေ', 'မတ်', 'ပြီ', 'မေ', 'ဇွန်', 'လိုင်', 'သြ', 'စက်', 'အောက်', 'နို', 'ဒီ'], 'weekdays' => ['တနင်္ဂနွေ', 'တနင်္လာ', 'အင်္ဂါ', 'ဗုဒ္ဓဟူး', 'ကြာသပတေး', 'သောကြာ', 'စနေ'], 'weekdays_short' => ['နွေ', 'လာ', 'ဂါ', 'ဟူး', 'ကြာ', 'သော', 'နေ'], 'weekdays_min' => ['နွေ', 'လာ', 'ဂါ', 'ဟူး', 'ကြာ', 'သော', 'နေ'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'alt_numbers' => ['၀၀', '၀၁', '၀၂', '၀၃', '၀၄', '၀၅', '၀၆', '၀၇', '၀၈', '၀၉', '၁၀', '၁၁', '၁၂', '၁၃', '၁၄', '၁၅', '၁၆', '၁၇', '၁၈', '၁၉', '၂၀', '၂၁', '၂၂', '၂၃', '၂၄', '၂၅', '၂၆', '၂၇', '၂၈', '၂၉', '၃၀', '၃၁', '၃၂', '၃၃', '၃၄', '၃၅', '၃၆', '၃၇', '၃၈', '၃၉', '၄၀', '၄၁', '၄၂', '၄၃', '၄၄', '၄၅', '၄၆', '၄၇', '၄၈', '၄၉', '၅၀', '၅၁', '၅၂', '၅၃', '၅၄', '၅၅', '၅၆', '၅၇', '၅၈', '၅၉', '၆၀', '၆၁', '၆၂', '၆၃', '၆၄', '၆၅', '၆၆', '၆၇', '၆၈', '၆၉', '၇၀', '၇၁', '၇၂', '၇၃', '၇၄', '၇၅', '၇၆', '၇၇', '၇၈', '၇၉', '၈၀', '၈၁', '၈၂', '၈၃', '၈၄', '၈၅', '၈၆', '၈၇', '၈၈', '၈၉', '၉၀', '၉၁', '၉၂', '၉၃', '၉၄', '၉၅', '၉၆', '၉၇', '၉၈', '၉၉'], 'meridiem' => ['နံနက်', 'ညနေ'], ]; PK������<1Z[ia �� ����Carbon/Lang/pt_ST.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/pt.php'; PK������<1ZpG��G����Carbon/Lang/en_VU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z6N��N����Carbon/Lang/ak.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/ak_GH.php'; PK������<1Z-jIN��N����Carbon/Lang/to.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/to_TO.php'; PK������<1ZT.C��C����Carbon/Lang/jmc.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['utuko', 'kyiukonyi'], 'weekdays' => ['Jumapilyi', 'Jumatatuu', 'Jumanne', 'Jumatanu', 'Alhamisi', 'Ijumaa', 'Jumamosi'], 'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'], 'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'], 'months' => ['Januari', 'Februari', 'Machi', 'Aprilyi', 'Mei', 'Junyi', 'Julyai', 'Agusti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'], 'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], ]); PK������<1Z猪N �� ����Carbon/Lang/shi.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['ⵜⵉⴼⴰⵡⵜ', 'ⵜⴰⴷⴳⴳⵯⴰⵜ'], 'weekdays' => ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ', 'ⴰⵙⵉⵏⴰⵙ', 'ⴰⴽⵕⴰⵙ', 'ⴰⴽⵡⴰⵙ', 'ⵙⵉⵎⵡⴰⵙ', 'ⴰⵙⵉⴹⵢⴰⵙ'], 'weekdays_short' => ['ⴰⵙⴰ', 'ⴰⵢⵏ', 'ⴰⵙⵉ', 'ⴰⴽⵕ', 'ⴰⴽⵡ', 'ⴰⵙⵉⵎ', 'ⴰⵙⵉⴹ'], 'weekdays_min' => ['ⴰⵙⴰ', 'ⴰⵢⵏ', 'ⴰⵙⵉ', 'ⴰⴽⵕ', 'ⴰⴽⵡ', 'ⴰⵙⵉⵎ', 'ⴰⵙⵉⴹ'], 'months' => ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ', 'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ', 'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ', 'ⴽⵜⵓⴱⵔ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⴰⵏⴱⵉⵔ'], 'months_short' => ['ⵉⵏⵏ', 'ⴱⵕⴰ', 'ⵎⴰⵕ', 'ⵉⴱⵔ', 'ⵎⴰⵢ', 'ⵢⵓⵏ', 'ⵢⵓⵍ', 'ⵖⵓⵛ', 'ⵛⵓⵜ', 'ⴽⵜⵓ', 'ⵏⵓⵡ', 'ⴷⵓⵊ'], 'first_day_of_week' => 6, 'weekend' => [5, 6], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM, YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'year' => ':count aseggwas', 'y' => ':count aseggwas', 'a_year' => ':count aseggwas', 'month' => ':count ayyur', 'm' => ':count ayyur', 'a_month' => ':count ayyur', 'week' => ':count imalass', 'w' => ':count imalass', 'a_week' => ':count imalass', 'day' => ':count ass', 'd' => ':count ass', 'a_day' => ':count ass', 'hour' => ':count urɣ', // less reliable 'h' => ':count urɣ', // less reliable 'a_hour' => ':count urɣ', // less reliable 'minute' => ':count ⴰⵎⵥⵉ', // less reliable 'min' => ':count ⴰⵎⵥⵉ', // less reliable 'a_minute' => ':count ⴰⵎⵥⵉ', // less reliable 'second' => ':count sin', // less reliable 's' => ':count sin', // less reliable 'a_second' => ':count sin', // less reliable ]); PK������<1Zn������Carbon/Lang/lij_IT.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Gastaldi alessio.gastaldi@libero.it */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['zenâ', 'fevrâ', 'marzo', 'avrî', 'mazzo', 'zûgno', 'lûggio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dixembre'], 'months_short' => ['zen', 'fev', 'mar', 'arv', 'maz', 'zûg', 'lûg', 'ago', 'set', 'ött', 'nov', 'dix'], 'weekdays' => ['domenega', 'lûnedì', 'martedì', 'mercUrdì', 'zêggia', 'venardì', 'sabbo'], 'weekdays_short' => ['dom', 'lûn', 'mar', 'mer', 'zêu', 'ven', 'sab'], 'weekdays_min' => ['dom', 'lûn', 'mar', 'mer', 'zêu', 'ven', 'sab'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'year' => ':count etæ', // less reliable 'y' => ':count etæ', // less reliable 'a_year' => ':count etæ', // less reliable 'month' => ':count meize', 'm' => ':count meize', 'a_month' => ':count meize', 'week' => ':count settemannha', 'w' => ':count settemannha', 'a_week' => ':count settemannha', 'day' => ':count giorno', 'd' => ':count giorno', 'a_day' => ':count giorno', 'hour' => ':count reléuio', // less reliable 'h' => ':count reléuio', // less reliable 'a_hour' => ':count reléuio', // less reliable 'minute' => ':count menûo', 'min' => ':count menûo', 'a_minute' => ':count menûo', 'second' => ':count segondo', 's' => ':count segondo', 'a_second' => ':count segondo', ]); PK������<1Zm'1������Carbon/Lang/mni_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Red Hat Pune libc-alpha@sourceware.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['জানুৱারি', 'ফেব্রুৱারি', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগষ্ট', 'সেপ্তেম্বর', 'ওক্তোবর', 'নবেম্বর', 'ডিসেম্বর'], 'months_short' => ['জান', 'ফেব', 'মার', 'এপ্রি', 'মে', 'জুন', 'জুল', 'আগ', 'সেপ', 'ওক্ত', 'নবে', 'ডিস'], 'weekdays' => ['নোংমাইজিং', 'নিংথৌকাবা', 'লৈবাকপোকপা', 'য়ুমশকৈশা', 'শগোলশেন', 'ইরাই', 'থাংজ'], 'weekdays_short' => ['নোং', 'নিং', 'লৈবাক', 'য়ুম', 'শগোল', 'ইরা', 'থাং'], 'weekdays_min' => ['নোং', 'নিং', 'লৈবাক', 'য়ুম', 'শগোল', 'ইরা', 'থাং'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['এ.ম.', 'প.ম.'], 'year' => ':count ইসিং', // less reliable 'y' => ':count ইসিং', // less reliable 'a_year' => ':count ইসিং', // less reliable 'second' => ':count ꯅꯤꯡꯊꯧꯀꯥꯕ', // less reliable 's' => ':count ꯅꯤꯡꯊꯧꯀꯥꯕ', // less reliable 'a_second' => ':count ꯅꯤꯡꯊꯧꯀꯥꯕ', // less reliable ]); PK������<1Z9>������Carbon/Lang/ar_SA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /** * Authors: * - Josh Soref * - JD Isaacks * - Atef Ben Ali (atefBB) * - Mohamed Sabil (mohamedsabil83) * - Abdullah-Alhariri */ $months = [ 'يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر', ]; return [ 'year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']), 'a_year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']), 'month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']), 'a_month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']), 'week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']), 'a_week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']), 'day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']), 'a_day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']), 'hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']), 'a_hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']), 'minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']), 'a_minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']), 'second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']), 'a_second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']), 'ago' => 'منذ :time', 'from_now' => 'في :time', 'after' => 'بعد :time', 'before' => 'قبل :time', 'diff_now' => 'الآن', 'diff_today' => 'اليوم', 'diff_today_regexp' => 'اليوم(?:\\s+على)?(?:\\s+الساعة)?', 'diff_yesterday' => 'أمس', 'diff_yesterday_regexp' => 'أمس(?:\\s+على)?(?:\\s+الساعة)?', 'diff_tomorrow' => 'غداً', 'diff_tomorrow_regexp' => 'غدا(?:\\s+على)?(?:\\s+الساعة)?', 'diff_before_yesterday' => 'قبل الأمس', 'diff_after_tomorrow' => 'بعد غد', 'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']), 'period_interval' => 'كل :interval', 'period_start_date' => 'من :date', 'period_end_date' => 'إلى :date', 'months' => $months, 'months_short' => $months, 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'], 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'list' => ['، ', ' و '], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[اليوم على الساعة] LT', 'nextDay' => '[غدا على الساعة] LT', 'nextWeek' => 'dddd [على الساعة] LT', 'lastDay' => '[أمس على الساعة] LT', 'lastWeek' => 'dddd [على الساعة] LT', 'sameElse' => 'L', ], 'meridiem' => ['ص', 'م'], 'weekend' => [5, 6], 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'], ]; PK������<1ZT �� ����Carbon/Lang/ca_ES.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ca.php'; PK������<1Z� �� ����Carbon/Lang/sl_SI.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/sl.php'; PK������<1Z?Ej �� ����Carbon/Lang/en_MH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/en.php'; PK������<1Z!Hj��j����Carbon/Lang/ee.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['ŋ', 'ɣ'], 'weekdays' => ['kɔsiɖa', 'dzoɖa', 'blaɖa', 'kuɖa', 'yawoɖa', 'fiɖa', 'memleɖa'], 'weekdays_short' => ['kɔs', 'dzo', 'bla', 'kuɖ', 'yaw', 'fiɖ', 'mem'], 'weekdays_min' => ['kɔs', 'dzo', 'bla', 'kuɖ', 'yaw', 'fiɖ', 'mem'], 'months' => ['dzove', 'dzodze', 'tedoxe', 'afɔfĩe', 'dama', 'masa', 'siamlɔm', 'deasiamime', 'anyɔnyɔ', 'kele', 'adeɛmekpɔxe', 'dzome'], 'months_short' => ['dzv', 'dzd', 'ted', 'afɔ', 'dam', 'mas', 'sia', 'dea', 'any', 'kel', 'ade', 'dzm'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'a [ga] h:mm', 'LTS' => 'a [ga] h:mm:ss', 'L' => 'M/D/YYYY', 'LL' => 'MMM D [lia], YYYY', 'LLL' => 'a [ga] h:mm MMMM D [lia] YYYY', 'LLLL' => 'a [ga] h:mm dddd, MMMM D [lia] YYYY', ], 'year' => 'ƒe :count', 'y' => 'ƒe :count', 'a_year' => 'ƒe :count', 'month' => 'ɣleti :count', 'm' => 'ɣleti :count', 'a_month' => 'ɣleti :count', 'week' => 'kwasiɖa :count', 'w' => 'kwasiɖa :count', 'a_week' => 'kwasiɖa :count', 'day' => 'ŋkeke :count', 'd' => 'ŋkeke :count', 'a_day' => 'ŋkeke :count', 'hour' => 'gaƒoƒo :count', 'h' => 'gaƒoƒo :count', 'a_hour' => 'gaƒoƒo :count', 'minute' => 'miniti :count', // less reliable 'min' => 'miniti :count', // less reliable 'a_minute' => 'miniti :count', // less reliable 'second' => 'sɛkɛnd :count', // less reliable 's' => 'sɛkɛnd :count', // less reliable 'a_second' => 'sɛkɛnd :count', // less reliable ]); PK������<1ZpG��G����Carbon/Lang/en_BB.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z"wN��N����Carbon/Lang/sm.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/sm_WS.php'; PK������<1ZFcK������Carbon/Lang/be_BY@latin.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], 'months' => ['studzienia', 'lutaha', 'sakavika', 'krasavika', 'maja', 'červienia', 'lipienia', 'žniŭnia', 'vieraśnia', 'kastryčnika', 'listapada', 'śniežnia'], 'months_short' => ['Stu', 'Lut', 'Sak', 'Kra', 'Maj', 'Čer', 'Lip', 'Žni', 'Vie', 'Kas', 'Lis', 'Śni'], 'weekdays' => ['Niadziela', 'Paniadziełak', 'Aŭtorak', 'Sierada', 'Čaćvier', 'Piatnica', 'Subota'], 'weekdays_short' => ['Nia', 'Pan', 'Aŭt', 'Sie', 'Čać', 'Pia', 'Sub'], 'weekdays_min' => ['Nia', 'Pan', 'Aŭt', 'Sie', 'Čać', 'Pia', 'Sub'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, ]); PK������<1ZGoV'��'����Carbon/Lang/sr_Cyrl_BA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Component\Translation\PluralizationRules; // @codeCoverageIgnoreStart if (class_exists(PluralizationRules::class)) { PluralizationRules::set(static function ($number) { return PluralizationRules::get($number, 'sr'); }, 'sr_Cyrl_BA'); } // @codeCoverageIgnoreEnd return array_replace_recursive(require __DIR__.'/sr_Cyrl.php', [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D.M.yy.', 'LL' => 'DD.MM.YYYY.', 'LLL' => 'DD. MMMM YYYY. HH:mm', 'LLLL' => 'dddd, DD. MMMM YYYY. HH:mm', ], 'weekdays' => ['недјеља', 'понедељак', 'уторак', 'сриједа', 'четвртак', 'петак', 'субота'], 'weekdays_short' => ['нед.', 'пон.', 'ут.', 'ср.', 'чет.', 'пет.', 'суб.'], ]); PK������<1Z@O��O����Carbon/Lang/hif.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/hif_FJ.php'; PK������<1Z<��������Carbon/Lang/ln.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ubuntu René Manassé GALEKWA renemanasse@gmail.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'months' => ['sánzá ya yambo', 'sánzá ya míbalé', 'sánzá ya mísáto', 'sánzá ya mínei', 'sánzá ya mítáno', 'sánzá ya motóbá', 'sánzá ya nsambo', 'sánzá ya mwambe', 'sánzá ya libwa', 'sánzá ya zómi', 'sánzá ya zómi na mɔ̌kɔ́', 'sánzá ya zómi na míbalé'], 'months_short' => ['yan', 'fbl', 'msi', 'apl', 'mai', 'yun', 'yul', 'agt', 'stb', 'ɔtb', 'nvb', 'dsb'], 'weekdays' => ['Lomíngo', 'Mosálá mɔ̌kɔ́', 'Misálá míbalé', 'Misálá mísáto', 'Misálá mínei', 'Misálá mítáno', 'Mpɔ́sɔ'], 'weekdays_short' => ['m1.', 'm2.', 'm3.', 'm4.', 'm5.', 'm6.', 'm7.'], 'weekdays_min' => ['m1.', 'm2.', 'm3.', 'm4.', 'm5.', 'm6.', 'm7.'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'year' => 'mbula :count', 'y' => 'mbula :count', 'a_year' => 'mbula :count', 'month' => 'sánzá :count', 'm' => 'sánzá :count', 'a_month' => 'sánzá :count', 'week' => 'mpɔ́sɔ :count', 'w' => 'mpɔ́sɔ :count', 'a_week' => 'mpɔ́sɔ :count', 'day' => 'mokɔlɔ :count', 'd' => 'mokɔlɔ :count', 'a_day' => 'mokɔlɔ :count', 'hour' => 'ngonga :count', 'h' => 'ngonga :count', 'a_hour' => 'ngonga :count', 'minute' => 'miniti :count', 'min' => 'miniti :count', 'a_minute' => 'miniti :count', 'second' => 'segɔnde :count', 's' => 'segɔnde :count', 'a_second' => 'segɔnde :count', ]); PK������<1ZO DM��M����Carbon/Lang/agr_PE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - somosazucar.org libc-alpha@sourceware.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'months' => ['Petsatin', 'Kupitin', 'Uyaitin', 'Tayutin', 'Kegketin', 'Tegmatin', 'Kuntutin', 'Yagkujutin', 'Daiktatin', 'Ipamtatin', 'Shinutin', 'Sakamtin'], 'months_short' => ['Pet', 'Kup', 'Uya', 'Tay', 'Keg', 'Teg', 'Kun', 'Yag', 'Dait', 'Ipam', 'Shin', 'Sak'], 'weekdays' => ['Tuntuamtin', 'Achutin', 'Kugkuktin', 'Saketin', 'Shimpitin', 'Imaptin', 'Bataetin'], 'weekdays_short' => ['Tun', 'Ach', 'Kug', 'Sak', 'Shim', 'Im', 'Bat'], 'weekdays_min' => ['Tun', 'Ach', 'Kug', 'Sak', 'Shim', 'Im', 'Bat'], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 7, 'meridiem' => ['VM', 'NM'], 'year' => ':count yaya', // less reliable 'y' => ':count yaya', // less reliable 'a_year' => ':count yaya', // less reliable 'month' => ':count nantu', // less reliable 'm' => ':count nantu', // less reliable 'a_month' => ':count nantu', // less reliable 'day' => ':count nayaim', // less reliable 'd' => ':count nayaim', // less reliable 'a_day' => ':count nayaim', // less reliable 'hour' => ':count kuwiš', // less reliable 'h' => ':count kuwiš', // less reliable 'a_hour' => ':count kuwiš', // less reliable ]); PK������<1Z''x �� ����Carbon/Lang/fr_HT.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Z z �� ����Carbon/Lang/ne_NP.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ne.php'; PK������<1ZpG��G����Carbon/Lang/en_AT.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'first_day_of_week' => 1, ]); PK������<1Z& �� ����Carbon/Lang/ky_KG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ky.php'; PK������<1Z ������Carbon/Lang/smn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['ip.', 'ep.'], 'weekdays' => ['pasepeeivi', 'vuossaargâ', 'majebaargâ', 'koskoho', 'tuorâstuv', 'vástuppeeivi', 'lávurduv'], 'weekdays_short' => ['pas', 'vuo', 'maj', 'kos', 'tuo', 'vás', 'láv'], 'weekdays_min' => ['pa', 'vu', 'ma', 'ko', 'tu', 'vá', 'lá'], 'weekdays_standalone' => ['pasepeivi', 'vuossargâ', 'majebargâ', 'koskokko', 'tuorâstâh', 'vástuppeivi', 'lávurdâh'], 'months' => ['uđđâivemáánu', 'kuovâmáánu', 'njuhčâmáánu', 'cuáŋuimáánu', 'vyesimáánu', 'kesimáánu', 'syeinimáánu', 'porgemáánu', 'čohčâmáánu', 'roovvâdmáánu', 'skammâmáánu', 'juovlâmáánu'], 'months_short' => ['uđiv', 'kuovâ', 'njuhčâ', 'cuáŋui', 'vyesi', 'kesi', 'syeini', 'porge', 'čohčâ', 'roovvâd', 'skammâ', 'juovlâ'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'H.mm', 'LTS' => 'H.mm.ss', 'L' => 'D.M.YYYY', 'LL' => 'MMM D. YYYY', 'LLL' => 'MMMM D. YYYY H.mm', 'LLLL' => 'dddd, MMMM D. YYYY H.mm', ], 'hour' => ':count äigi', // less reliable 'h' => ':count äigi', // less reliable 'a_hour' => ':count äigi', // less reliable 'year' => ':count ihe', 'y' => ':count ihe', 'a_year' => ':count ihe', 'month' => ':count mánuppaje', 'm' => ':count mánuppaje', 'a_month' => ':count mánuppaje', 'week' => ':count okko', 'w' => ':count okko', 'a_week' => ':count okko', 'day' => ':count peivi', 'd' => ':count peivi', 'a_day' => ':count peivi', 'minute' => ':count miinut', 'min' => ':count miinut', 'a_minute' => ':count miinut', 'second' => ':count nubbe', 's' => ':count nubbe', 'a_second' => ':count nubbe', ]); PK������<1Z4D o��o����Carbon/Lang/bg.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - François B * - Serhan Apaydın * - JD Isaacks * - Glavić */ use Carbon\CarbonInterface; return [ 'year' => ':count година|:count години', 'a_year' => 'година|:count години', 'y' => ':count година|:count години', 'month' => ':count месец|:count месеца', 'a_month' => 'месец|:count месеца', 'm' => ':count месец|:count месеца', 'week' => ':count седмица|:count седмици', 'a_week' => 'седмица|:count седмици', 'w' => ':count седмица|:count седмици', 'day' => ':count ден|:count дни', 'a_day' => 'ден|:count дни', 'd' => ':count ден|:count дни', 'hour' => ':count час|:count часа', 'a_hour' => 'час|:count часа', 'h' => ':count час|:count часа', 'minute' => ':count минута|:count минути', 'a_minute' => 'минута|:count минути', 'min' => ':count минута|:count минути', 'second' => ':count секунда|:count секунди', 'a_second' => 'няколко секунди|:count секунди', 's' => ':count секунда|:count секунди', 'ago' => 'преди :time', 'from_now' => 'след :time', 'after' => 'след :time', 'before' => 'преди :time', 'diff_now' => 'сега', 'diff_today' => 'Днес', 'diff_today_regexp' => 'Днес(?:\\s+в)?', 'diff_yesterday' => 'вчера', 'diff_yesterday_regexp' => 'Вчера(?:\\s+в)?', 'diff_tomorrow' => 'утре', 'diff_tomorrow_regexp' => 'Утре(?:\\s+в)?', 'formats' => [ 'LT' => 'H:mm', 'LTS' => 'H:mm:ss', 'L' => 'D.MM.YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY H:mm', 'LLLL' => 'dddd, D MMMM YYYY H:mm', ], 'calendar' => [ 'sameDay' => '[Днес в] LT', 'nextDay' => '[Утре в] LT', 'nextWeek' => 'dddd [в] LT', 'lastDay' => '[Вчера в] LT', 'lastWeek' => function (CarbonInterface $current) { switch ($current->dayOfWeek) { case 0: case 3: case 6: return '[В изминалата] dddd [в] LT'; default: return '[В изминалия] dddd [в] LT'; } }, 'sameElse' => 'L', ], 'ordinal' => function ($number) { $lastDigit = $number % 10; $last2Digits = $number % 100; if ($number === 0) { return "$number-ев"; } if ($last2Digits === 0) { return "$number-ен"; } if ($last2Digits > 10 && $last2Digits < 20) { return "$number-ти"; } if ($lastDigit === 1) { return "$number-ви"; } if ($lastDigit === 2) { return "$number-ри"; } if ($lastDigit === 7 || $lastDigit === 8) { return "$number-ми"; } return "$number-ти"; }, 'months' => ['януари', 'февруари', 'март', 'април', 'май', 'юни', 'юли', 'август', 'септември', 'октомври', 'ноември', 'декември'], 'months_short' => ['яну', 'фев', 'мар', 'апр', 'май', 'юни', 'юли', 'авг', 'сеп', 'окт', 'ное', 'дек'], 'weekdays' => ['неделя', 'понеделник', 'вторник', 'сряда', 'четвъртък', 'петък', 'събота'], 'weekdays_short' => ['нед', 'пон', 'вто', 'сря', 'чет', 'пет', 'съб'], 'weekdays_min' => ['нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' и '], 'meridiem' => ['преди обяд', 'следобед'], ]; PK������<1ZXNe��e����Carbon/Lang/crh_UA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Reşat SABIQ tilde.birlik@gmail.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], 'months' => ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'Mayıs', 'İyun', 'İyul', 'Avgust', 'Sentâbr', 'Oktâbr', 'Noyabr', 'Dekabr'], 'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'İyn', 'İyl', 'Avg', 'Sen', 'Okt', 'Noy', 'Dek'], 'weekdays' => ['Bazar', 'Bazarertesi', 'Salı', 'Çarşembe', 'Cumaaqşamı', 'Cuma', 'Cumaertesi'], 'weekdays_short' => ['Baz', 'Ber', 'Sal', 'Çar', 'Caq', 'Cum', 'Cer'], 'weekdays_min' => ['Baz', 'Ber', 'Sal', 'Çar', 'Caq', 'Cum', 'Cer'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'meridiem' => ['ÜE', 'ÜS'], 'year' => ':count yıl', 'y' => ':count yıl', 'a_year' => ':count yıl', 'month' => ':count ay', 'm' => ':count ay', 'a_month' => ':count ay', 'week' => ':count afta', 'w' => ':count afta', 'a_week' => ':count afta', 'day' => ':count kün', 'd' => ':count kün', 'a_day' => ':count kün', 'hour' => ':count saat', 'h' => ':count saat', 'a_hour' => ':count saat', 'minute' => ':count daqqa', 'min' => ':count daqqa', 'a_minute' => ':count daqqa', 'second' => ':count ekinci', 's' => ':count ekinci', 'a_second' => ':count ekinci', ]); PK������<1Z''x �� ����Carbon/Lang/fr_MG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Z,�������Carbon/Lang/ar_EG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - IBM Globalization Center of Competency, Yamato Software Laboratory bug-glibc-locales@gnu.org * - Abdullah-Alhariri */ return array_replace_recursive(require __DIR__.'/ar.php', [ 'formats' => [ 'L' => 'DD MMM, YYYY', ], 'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'], 'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'], 'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], 'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], 'first_day_of_week' => 6, 'day_of_first_week_of_year' => 1, 'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'], ]); PK������<1Za$M��M����Carbon/Lang/fr_CM.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/fr.php', [ 'meridiem' => ['mat.', 'soir'], ]); PK������<1ZZ������Carbon/Lang/nan_TW.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'YYYY年MM月DD日', ], 'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], 'months_short' => [' 1月', ' 2月', ' 3月', ' 4月', ' 5月', ' 6月', ' 7月', ' 8月', ' 9月', '10月', '11月', '12月'], 'weekdays' => ['禮拜日', '禮拜一', '禮拜二', '禮拜三', '禮拜四', '禮拜五', '禮拜六'], 'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'], 'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['頂晡', '下晡'], 'year' => ':count 年', 'y' => ':count 年', 'a_year' => ':count 年', 'month' => ':count goe̍h', 'm' => ':count goe̍h', 'a_month' => ':count goe̍h', 'week' => ':count lé-pài', 'w' => ':count lé-pài', 'a_week' => ':count lé-pài', 'day' => ':count 日', 'd' => ':count 日', 'a_day' => ':count 日', 'hour' => ':count tiám-cheng', 'h' => ':count tiám-cheng', 'a_hour' => ':count tiám-cheng', 'minute' => ':count Hun-cheng', 'min' => ':count Hun-cheng', 'a_minute' => ':count Hun-cheng', 'second' => ':count Bió', 's' => ':count Bió', 'a_second' => ':count Bió', ]); PK������<1ZWnN��N����Carbon/Lang/rw.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/rw_RW.php'; PK������<1Z[ia �� ����Carbon/Lang/pt_GQ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/pt.php'; PK������<1ZuN��N����Carbon/Lang/as.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/as_IN.php'; PK������<1Zm0ב������Carbon/Lang/kw_GB.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Alastair McKinstry bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'months' => ['mis Genver', 'mis Hwevrer', 'mis Meurth', 'mis Ebrel', 'mis Me', 'mis Metheven', 'mis Gortheren', 'mis Est', 'mis Gwynngala', 'mis Hedra', 'mis Du', 'mis Kevardhu'], 'months_short' => ['Gen', 'Hwe', 'Meu', 'Ebr', 'Me', 'Met', 'Gor', 'Est', 'Gwn', 'Hed', 'Du', 'Kev'], 'weekdays' => ['De Sul', 'De Lun', 'De Merth', 'De Merher', 'De Yow', 'De Gwener', 'De Sadorn'], 'weekdays_short' => ['Sul', 'Lun', 'Mth', 'Mhr', 'Yow', 'Gwe', 'Sad'], 'weekdays_min' => ['Sul', 'Lun', 'Mth', 'Mhr', 'Yow', 'Gwe', 'Sad'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'year' => ':count bledhen', 'y' => ':count bledhen', 'a_year' => ':count bledhen', 'month' => ':count mis', 'm' => ':count mis', 'a_month' => ':count mis', 'week' => ':count seythen', 'w' => ':count seythen', 'a_week' => ':count seythen', 'day' => ':count dydh', 'd' => ':count dydh', 'a_day' => ':count dydh', 'hour' => ':count eur', 'h' => ':count eur', 'a_hour' => ':count eur', 'minute' => ':count mynysen', 'min' => ':count mynysen', 'a_minute' => ':count mynysen', 'second' => ':count pryjwyth', 's' => ':count pryjwyth', 'a_second' => ':count pryjwyth', ]); PK������<1Z&*Bc��c����Carbon/Lang/sr_RS.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - sr_YU, sr_CS locale Danilo Segan bug-glibc-locales@gnu.org */ return require __DIR__.'/sr_Cyrl.php'; PK������<1ZzCO��O����Carbon/Lang/sah.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/sah_RU.php'; PK������<1ZS%O��O����Carbon/Lang/niu.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/niu_NU.php'; PK������<1Zl������Carbon/Lang/te.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Kunal Marwaha * - Josh Soref * - François B * - kc */ return [ 'year' => ':count సంవత్సరం|:count సంవత్సరాలు', 'a_year' => 'ఒక సంవత్సరం|:count సంవత్సరాలు', 'y' => ':count సం.', 'month' => ':count నెల|:count నెలలు', 'a_month' => 'ఒక నెల|:count నెలలు', 'm' => ':count నెల|:count నెల.', 'week' => ':count వారం|:count వారాలు', 'a_week' => 'ఒక వారం|:count వారాలు', 'w' => ':count వార.|:count వారా.', 'day' => ':count రోజు|:count రోజులు', 'a_day' => 'ఒక రోజు|:count రోజులు', 'd' => ':count రోజు|:count రోజు.', 'hour' => ':count గంట|:count గంటలు', 'a_hour' => 'ఒక గంట|:count గంటలు', 'h' => ':count గం.', 'minute' => ':count నిమిషం|:count నిమిషాలు', 'a_minute' => 'ఒక నిమిషం|:count నిమిషాలు', 'min' => ':count నిమి.', 'second' => ':count సెకను|:count సెకన్లు', 'a_second' => 'కొన్ని క్షణాలు|:count సెకన్లు', 's' => ':count సెక.', 'ago' => ':time క్రితం', 'from_now' => ':time లో', 'diff_now' => 'ప్రస్తుతం', 'diff_today' => 'నేడు', 'diff_yesterday' => 'నిన్న', 'diff_tomorrow' => 'రేపు', 'formats' => [ 'LT' => 'A h:mm', 'LTS' => 'A h:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY, A h:mm', 'LLLL' => 'dddd, D MMMM YYYY, A h:mm', ], 'calendar' => [ 'sameDay' => '[నేడు] LT', 'nextDay' => '[రేపు] LT', 'nextWeek' => 'dddd, LT', 'lastDay' => '[నిన్న] LT', 'lastWeek' => '[గత] dddd, LT', 'sameElse' => 'L', ], 'ordinal' => ':numberవ', 'meridiem' => function ($hour) { if ($hour < 4) { return 'రాత్రి'; } if ($hour < 10) { return 'ఉదయం'; } if ($hour < 17) { return 'మధ్యాహ్నం'; } if ($hour < 20) { return 'సాయంత్రం'; } return ' రాత్రి'; }, 'months' => ['జనవరి', 'ఫిబ్రవరి', 'మార్చి', 'ఏప్రిల్', 'మే', 'జూన్', 'జూలై', 'ఆగస్టు', 'సెప్టెంబర్', 'అక్టోబర్', 'నవంబర్', 'డిసెంబర్'], 'months_short' => ['జన.', 'ఫిబ్ర.', 'మార్చి', 'ఏప్రి.', 'మే', 'జూన్', 'జూలై', 'ఆగ.', 'సెప్.', 'అక్టో.', 'నవ.', 'డిసె.'], 'weekdays' => ['ఆదివారం', 'సోమవారం', 'మంగళవారం', 'బుధవారం', 'గురువారం', 'శుక్రవారం', 'శనివారం'], 'weekdays_short' => ['ఆది', 'సోమ', 'మంగళ', 'బుధ', 'గురు', 'శుక్ర', 'శని'], 'weekdays_min' => ['ఆ', 'సో', 'మం', 'బు', 'గు', 'శు', 'శ'], 'list' => ', ', 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, 'weekend' => [0, 0], ]; PK������<1ZԴ������Carbon/Lang/ast.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Jordi Mallach jordi@gnu.org * - Adolfo Jayme-Barrientos (fitojb) */ return array_replace_recursive(require __DIR__.'/es.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'months' => ['de xineru', 'de febreru', 'de marzu', 'd’abril', 'de mayu', 'de xunu', 'de xunetu', 'd’agostu', 'de setiembre', 'd’ochobre', 'de payares', 'd’avientu'], 'months_short' => ['xin', 'feb', 'mar', 'abr', 'may', 'xun', 'xnt', 'ago', 'set', 'och', 'pay', 'avi'], 'weekdays' => ['domingu', 'llunes', 'martes', 'miércoles', 'xueves', 'vienres', 'sábadu'], 'weekdays_short' => ['dom', 'llu', 'mar', 'mié', 'xue', 'vie', 'sáb'], 'weekdays_min' => ['dom', 'llu', 'mar', 'mié', 'xue', 'vie', 'sáb'], 'year' => ':count añu|:count años', 'y' => ':count añu|:count años', 'a_year' => 'un añu|:count años', 'month' => ':count mes', 'm' => ':count mes', 'a_month' => 'un mes|:count mes', 'week' => ':count selmana|:count selmanes', 'w' => ':count selmana|:count selmanes', 'a_week' => 'una selmana|:count selmanes', 'day' => ':count día|:count díes', 'd' => ':count día|:count díes', 'a_day' => 'un día|:count díes', 'hour' => ':count hora|:count hores', 'h' => ':count hora|:count hores', 'a_hour' => 'una hora|:count hores', 'minute' => ':count minutu|:count minutos', 'min' => ':count minutu|:count minutos', 'a_minute' => 'un minutu|:count minutos', 'second' => ':count segundu|:count segundos', 's' => ':count segundu|:count segundos', 'a_second' => 'un segundu|:count segundos', 'ago' => 'hai :time', 'from_now' => 'en :time', 'after' => ':time dempués', 'before' => ':time enantes', ]); PK������<1ZibE��E����Carbon/Lang/hne_IN.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Red Hat, Pune bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अपरेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितमबर', 'अकटूबर', 'नवमबर', 'दिसमबर'], 'months_short' => ['जन', 'फर', 'मार्च', 'अप', 'मई', 'जून', 'जुला', 'अग', 'सित', 'अकटू', 'नव', 'दिस'], 'weekdays' => ['इतवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'बिरसपत', 'सुकरवार', 'सनिवार'], 'weekdays_short' => ['इत', 'सोम', 'मंग', 'बुध', 'बिर', 'सुक', 'सनि'], 'weekdays_min' => ['इत', 'सोम', 'मंग', 'बुध', 'बिर', 'सुक', 'सनि'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['बिहिनियाँ', 'मंझनियाँ'], ]); PK������<1Z^ӧv ��v ����Carbon/Lang/mt.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Alessandro Maruccia */ return [ 'year' => 'sena|:count sni|:count sni|:count sni', 'y' => 'sa sena|:count snin|:count snin|:count snin', 'month' => 'xahar|:count xhur|:count xhur|:count xhur', 'm' => ':count xahar|:count xhur|:count xhur|:count xhur', 'week' => 'gimgħa|:count ġimgħat|:count ġimgħat|:count ġimgħat', 'w' => 'ġimgħa|:count ġimgħat|:count ġimgħat|:count ġimgħat', 'day' => 'ġurnata|:count ġranet|:count ġranet|:count ġranet', 'd' => 'ġurnata|:count ġranet|:count ġranet|:count ġranet', 'hour' => 'siegħa|:count siegħat|:count siegħat|:count siegħat', 'h' => 'siegħa|:count sigħat|:count sigħat|:count sigħat', 'minute' => 'minuta|:count minuti|:count minuti|:count minuti', 'min' => 'min.|:count min.|:count min.|:count min.', 'second' => 'ftit sekondi|:count sekondi|:count sekondi|:count sekondi', 's' => 'sek.|:count sek.|:count sek.|:count sek.', 'ago' => ':time ilu', 'from_now' => 'f’ :time', 'diff_now' => 'issa', 'diff_today' => 'Illum', 'diff_today_regexp' => 'Illum(?:\\s+fil-)?', 'diff_yesterday' => 'lbieraħ', 'diff_yesterday_regexp' => 'Il-bieraħ(?:\\s+fil-)?', 'diff_tomorrow' => 'għada', 'diff_tomorrow_regexp' => 'Għada(?:\\s+fil-)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[Illum fil-]LT', 'nextDay' => '[Għada fil-]LT', 'nextWeek' => 'dddd [fil-]LT', 'lastDay' => '[Il-bieraħ fil-]LT', 'lastWeek' => 'dddd [li għadda] [fil-]LT', 'sameElse' => 'L', ], 'ordinal' => ':numberº', 'months' => ['Jannar', 'Frar', 'Marzu', 'April', 'Mejju', 'Ġunju', 'Lulju', 'Awwissu', 'Settembru', 'Ottubru', 'Novembru', 'Diċembru'], 'months_short' => ['Jan', 'Fra', 'Mar', 'Apr', 'Mej', 'Ġun', 'Lul', 'Aww', 'Set', 'Ott', 'Nov', 'Diċ'], 'weekdays' => ['Il-Ħadd', 'It-Tnejn', 'It-Tlieta', 'L-Erbgħa', 'Il-Ħamis', 'Il-Ġimgħa', 'Is-Sibt'], 'weekdays_short' => ['Ħad', 'Tne', 'Tli', 'Erb', 'Ħam', 'Ġim', 'Sib'], 'weekdays_min' => ['Ħa', 'Tn', 'Tl', 'Er', 'Ħa', 'Ġi', 'Si'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' u '], ]; PK������<1Z4r(n��n����Carbon/Lang/xh_ZA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['eyoMqungu', 'eyoMdumba', 'eyoKwindla', 'uTshazimpuzi', 'uCanzibe', 'eyeSilimela', 'eyeKhala', 'eyeThupa', 'eyoMsintsi', 'eyeDwarha', 'eyeNkanga', 'eyoMnga'], 'months_short' => ['Mqu', 'Mdu', 'Kwi', 'Tsh', 'Can', 'Sil', 'Kha', 'Thu', 'Msi', 'Dwa', 'Nka', 'Mng'], 'weekdays' => ['iCawa', 'uMvulo', 'lwesiBini', 'lwesiThathu', 'ulweSine', 'lwesiHlanu', 'uMgqibelo'], 'weekdays_short' => ['Caw', 'Mvu', 'Bin', 'Tha', 'Sin', 'Hla', 'Mgq'], 'weekdays_min' => ['Caw', 'Mvu', 'Bin', 'Tha', 'Sin', 'Hla', 'Mgq'], 'day_of_first_week_of_year' => 1, 'year' => ':count ihlobo', // less reliable 'y' => ':count ihlobo', // less reliable 'a_year' => ':count ihlobo', // less reliable 'hour' => ':count iwotshi', // less reliable 'h' => ':count iwotshi', // less reliable 'a_hour' => ':count iwotshi', // less reliable 'minute' => ':count ingqalelo', // less reliable 'min' => ':count ingqalelo', // less reliable 'a_minute' => ':count ingqalelo', // less reliable 'second' => ':count nceda', // less reliable 's' => ':count nceda', // less reliable 'a_second' => ':count nceda', // less reliable 'month' => ':count inyanga', 'm' => ':count inyanga', 'a_month' => ':count inyanga', 'week' => ':count veki', 'w' => ':count veki', 'a_week' => ':count veki', 'day' => ':count imini', 'd' => ':count imini', 'a_day' => ':count imini', ]); PK������<1ZX`������Carbon/Lang/ur_PK.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/ur.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'], 'months_short' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'], 'weekdays' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'], 'weekdays_short' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'], 'weekdays_min' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['ص', 'ش'], ]); PK������<1ZZб �� ����Carbon/Lang/in.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/id.php'; PK������<1Z]F��F����Carbon/Lang/af_NA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/af.php', [ 'meridiem' => ['v', 'n'], 'weekdays' => ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrydag', 'Saterdag'], 'weekdays_short' => ['So.', 'Ma.', 'Di.', 'Wo.', 'Do.', 'Vr.', 'Sa.'], 'weekdays_min' => ['So.', 'Ma.', 'Di.', 'Wo.', 'Do.', 'Vr.', 'Sa.'], 'months' => ['Januarie', 'Februarie', 'Maart', 'April', 'Mei', 'Junie', 'Julie', 'Augustus', 'September', 'Oktober', 'November', 'Desember'], 'months_short' => ['Jan.', 'Feb.', 'Mrt.', 'Apr.', 'Mei', 'Jun.', 'Jul.', 'Aug.', 'Sep.', 'Okt.', 'Nov.', 'Des.'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'YYYY-MM-DD', 'LL' => 'DD MMM YYYY', 'LLL' => 'DD MMMM YYYY HH:mm', 'LLLL' => 'dddd, DD MMMM YYYY HH:mm', ], ]); PK������<1Z''x �� ����Carbon/Lang/fr_GP.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Z})��)����Carbon/Lang/ca_FR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ca.php', [ ]); PK������<1Z(��(����Carbon/Lang/fr_DJ.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/fr.php', [ 'first_day_of_week' => 6, 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY h:mm a', 'LLLL' => 'dddd D MMMM YYYY h:mm a', ], ]); PK������<1Za������Carbon/Lang/es_CR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, ]); PK������<1Zac������Carbon/Lang/shi_Latn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/shi.php', [ 'meridiem' => ['tifawt', 'tadggʷat'], 'weekdays' => ['asamas', 'aynas', 'asinas', 'akṛas', 'akwas', 'asimwas', 'asiḍyas'], 'weekdays_short' => ['asa', 'ayn', 'asi', 'akṛ', 'akw', 'asim', 'asiḍ'], 'weekdays_min' => ['asa', 'ayn', 'asi', 'akṛ', 'akw', 'asim', 'asiḍ'], 'months' => ['innayr', 'bṛayṛ', 'maṛṣ', 'ibrir', 'mayyu', 'yunyu', 'yulyuz', 'ɣuct', 'cutanbir', 'ktubr', 'nuwanbir', 'dujanbir'], 'months_short' => ['inn', 'bṛa', 'maṛ', 'ibr', 'may', 'yun', 'yul', 'ɣuc', 'cut', 'ktu', 'nuw', 'duj'], 'first_day_of_week' => 6, 'weekend' => [5, 6], 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM, YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'minute' => ':count agur', // less reliable 'min' => ':count agur', // less reliable 'a_minute' => ':count agur', // less reliable ]); PK������<1ZC=5 �� ����Carbon/Lang/ru_MD.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ru.php'; PK������<1Z?`W������Carbon/Lang/ak_GH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Sugar Labs // OLPC sugarlabs.org libc-alpha@sourceware.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'YYYY/MM/DD', ], 'months' => ['Sanda-Ɔpɛpɔn', 'Kwakwar-Ɔgyefuo', 'Ebɔw-Ɔbenem', 'Ebɔbira-Oforisuo', 'Esusow Aketseaba-Kɔtɔnimba', 'Obirade-Ayɛwohomumu', 'Ayɛwoho-Kitawonsa', 'Difuu-Ɔsandaa', 'Fankwa-Ɛbɔ', 'Ɔbɛsɛ-Ahinime', 'Ɔberɛfɛw-Obubuo', 'Mumu-Ɔpɛnimba'], 'months_short' => ['S-Ɔ', 'K-Ɔ', 'E-Ɔ', 'E-O', 'E-K', 'O-A', 'A-K', 'D-Ɔ', 'F-Ɛ', 'Ɔ-A', 'Ɔ-O', 'M-Ɔ'], 'weekdays' => ['Kwesida', 'Dwowda', 'Benada', 'Wukuda', 'Yawda', 'Fida', 'Memeneda'], 'weekdays_short' => ['Kwe', 'Dwo', 'Ben', 'Wuk', 'Yaw', 'Fia', 'Mem'], 'weekdays_min' => ['Kwe', 'Dwo', 'Ben', 'Wuk', 'Yaw', 'Fia', 'Mem'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'meridiem' => ['AN', 'EW'], 'year' => ':count afe', 'y' => ':count afe', 'a_year' => ':count afe', 'month' => ':count bosume', 'm' => ':count bosume', 'a_month' => ':count bosume', 'day' => ':count ɛda', 'd' => ':count ɛda', 'a_day' => ':count ɛda', ]); PK������<1Z''x �� ����Carbon/Lang/fr_GA.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1Z*v������Carbon/Lang/ta_MY.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/ta.php', [ 'formats' => [ 'LT' => 'a h:mm', 'LTS' => 'a h:mm:ss', 'L' => 'D/M/yy', 'LL' => 'D MMM, YYYY', 'LLL' => 'D MMMM, YYYY, a h:mm', 'LLLL' => 'dddd, D MMMM, YYYY, a h:mm', ], 'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'], 'months_short' => ['ஜன.', 'பிப்.', 'மார்.', 'ஏப்.', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக.', 'செப்.', 'அக்.', 'நவ.', 'டிச.'], 'weekdays' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'], 'weekdays_short' => ['ஞாயி.', 'திங்.', 'செவ்.', 'புத.', 'வியா.', 'வெள்.', 'சனி'], 'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'], 'first_day_of_week' => 1, 'meridiem' => ['மு.ப', 'பி.ப'], ]); PK������<1ZU]=��=����Carbon/Lang/byn_ER.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ge'ez Frontier Foundation locales@geez.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YYYY', ], 'months' => ['ልደትሪ', 'ካብኽብቲ', 'ክብላ', 'ፋጅኺሪ', 'ክቢቅሪ', 'ምኪኤል ትጓ̅ኒሪ', 'ኰርኩ', 'ማርያም ትሪ', 'ያኸኒ መሳቅለሪ', 'መተሉ', 'ምኪኤል መሽወሪ', 'ተሕሳስሪ'], 'months_short' => ['ልደት', 'ካብኽ', 'ክብላ', 'ፋጅኺ', 'ክቢቅ', 'ም/ት', 'ኰር', 'ማርያ', 'ያኸኒ', 'መተሉ', 'ም/ም', 'ተሕሳ'], 'weekdays' => ['ሰንበር ቅዳዅ', 'ሰኑ', 'ሰሊጝ', 'ለጓ ወሪ ለብዋ', 'ኣምድ', 'ኣርብ', 'ሰንበር ሽጓዅ'], 'weekdays_short' => ['ሰ/ቅ', 'ሰኑ', 'ሰሊጝ', 'ለጓ', 'ኣምድ', 'ኣርብ', 'ሰ/ሽ'], 'weekdays_min' => ['ሰ/ቅ', 'ሰኑ', 'ሰሊጝ', 'ለጓ', 'ኣምድ', 'ኣርብ', 'ሰ/ሽ'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'meridiem' => ['ፋዱስ ጃብ', 'ፋዱስ ደምቢ'], ]); PK������<1Z\1l �� ����Carbon/Lang/gsw_CH.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/gsw.php'; PK������<1Zf/x��x����Carbon/Lang/zgh.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - BAKTETE Miloud */ return [ 'year' => ':count ⵓⵙⴳⴳⵯⴰⵙ|:count ⵉⵙⴳⴳⵓⵙⴰ', 'a_year' => 'ⵓⵙⴳⴳⵯⴰⵙ|:count ⵉⵙⴳⴳⵓⵙⴰ', 'y' => ':count ⵓⵙⴳⴳⵯⴰⵙ|:count ⵉⵙⴳⴳⵓⵙⴰ', 'month' => ':count ⵡⴰⵢⵢⵓⵔ|:count ⴰⵢⵢⵓⵔⵏ', 'a_month' => 'ⵉⴷⵊ ⵡⴰⵢⵢⵓⵔ|:count ⴰⵢⵢⵓⵔⵏ', 'm' => ':count ⴰⵢⵢⵓⵔⵏ', 'week' => ':count ⵉⵎⴰⵍⴰⵙⵙ|:count ⵉⵎⴰⵍⴰⵙⵙⵏ', 'a_week' => 'ⵉⵛⵜ ⵉⵎⴰⵍⴰⵙⵙ|:count ⵉⵎⴰⵍⴰⵙⵙⵏ', 'w' => ':count ⵉⵎⴰⵍⴰⵙⵙ.', 'day' => ':count ⵡⴰⵙⵙ|:count ⵓⵙⵙⴰⵏ', 'a_day' => 'ⵉⴷⵊ ⵡⴰⵙⵙ|:count ⵓⵙⵙⴰⵏ', 'd' => ':count ⵓ', 'hour' => ':count ⵜⵙⵔⴰⴳⵜ|:count ⵜⵉⵙⵔⴰⴳⵉⵏ', 'a_hour' => 'ⵉⵛⵜ ⵜⵙⵔⴰⴳⵜ|:count ⵜⵉⵙⵔⴰⴳⵉⵏ', 'h' => ':count ⵜ', 'minute' => ':count ⵜⵓⵙⴷⵉⴷⵜ|:count ⵜⵓⵙⴷⵉⴷⵉⵏ', 'a_minute' => 'ⵉⵛⵜ ⵜⵓⵙⴷⵉⴷⵜ|:count ⵜⵓⵙⴷⵉⴷⵉⵏ', 'min' => ':count ⵜⵓⵙ', 'second' => ':count ⵜⵙⵉⵏⵜ|:count ⵜⵉⵙⵉⵏⴰ', 'a_second' => 'ⴽⵔⴰ ⵜⵉⵙⵉⵏⴰ|:count ⵜⵉⵙⵉⵏⴰ', 's' => ':count ⵜ', 'ago' => 'ⵣⴳ :time', 'from_now' => 'ⴷⴳ :time', 'after' => ':time ⴰⵡⴰⵔ', 'before' => ':time ⴷⴰⵜ', 'diff_now' => 'ⴰⴷⵡⴰⵍⵉ', 'diff_today' => 'ⴰⵙⵙ', 'diff_today_regexp' => 'ⴰⵙⵙ(?:\\s+ⴰ/ⴰⴷ)?(?:\\s+ⴳ)?', 'diff_yesterday' => 'ⴰⵙⵙⵏⵏⴰⵟ', 'diff_yesterday_regexp' => 'ⴰⵙⵙⵏⵏⴰⵟ(?:\\s+ⴳ)?', 'diff_tomorrow' => 'ⴰⵙⴽⴽⴰ', 'diff_tomorrow_regexp' => 'ⴰⵙⴽⴽⴰ(?:\\s+ⴳ)?', 'diff_before_yesterday' => 'ⴼⵔ ⵉⴹⵏⵏⴰⵟ', 'diff_after_tomorrow' => 'ⵏⴰⴼ ⵓⵙⴽⴽⴰ', 'period_recurrences' => ':count ⵜⵉⴽⴽⴰⵍ', 'period_interval' => 'ⴽⵓ :interval', 'period_start_date' => 'ⴳ :date', 'period_end_date' => 'ⵉ :date', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[ⴰⵙⵙ ⴰ/ⴰⴷ ⴳ] LT', 'nextDay' => '[ⴰⵙⴽⴽⴰ ⴳ] LT', 'nextWeek' => 'dddd [ⴳ] LT', 'lastDay' => '[ⴰⵙⵙⵏⵏⴰⵟ ⴳ] LT', 'lastWeek' => 'dddd [ⴰⵎⴳⴳⴰⵔⵓ ⴳ] LT', 'sameElse' => 'L', ], 'meridiem' => ['ⵜⵉⴼⴰⵡⵜ', 'ⵜⴰⴷⴳⴳⵯⴰⵜ'], 'months' => ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ', 'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ', 'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ', 'ⴽⵟⵓⴱⵕ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⴰⵏⴱⵉⵔ'], 'months_short' => ['ⵉⵏⵏ', 'ⴱⵕⴰ', 'ⵎⴰⵕ', 'ⵉⴱⵔ', 'ⵎⴰⵢ', 'ⵢⵓⵏ', 'ⵢⵓⵍ', 'ⵖⵓⵛ', 'ⵛⵓⵜ', 'ⴽⵟⵓ', 'ⵏⵓⵡ', 'ⴷⵓⵊ'], 'weekdays' => ['ⵓⵙⴰⵎⴰⵙ', 'ⵡⴰⵢⵏⴰⵙ', 'ⵓⵙⵉⵏⴰⵙ', 'ⵡⴰⴽⵕⴰⵙ', 'ⵓⴽⵡⴰⵙ', 'ⵓⵙⵉⵎⵡⴰⵙ', 'ⵓⵙⵉⴹⵢⴰⵙ'], 'weekdays_short' => ['ⵓⵙⴰ', 'ⵡⴰⵢ', 'ⵓⵙⵉ', 'ⵡⴰⴽ', 'ⵓⴽⵡ', 'ⵓⵙⵉⵎ', 'ⵓⵙⵉⴹ'], 'weekdays_min' => ['ⵓⵙⴰ', 'ⵡⴰⵢ', 'ⵓⵙⵉ', 'ⵡⴰⴽ', 'ⵓⴽⵡ', 'ⵓⵙⵉⵎ', 'ⵓⵙⵉⴹ'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' ⴷ '], ]; PK������<1Zd������Carbon/Lang/es_VE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]); PK������<1Z8������Carbon/Lang/hu.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Adam Brunner * - Brett Johnson * - balping */ use Carbon\CarbonInterface; $huWeekEndings = ['vasárnap', 'hétfőn', 'kedden', 'szerdán', 'csütörtökön', 'pénteken', 'szombaton']; return [ 'year' => ':count év', 'y' => ':count év', 'month' => ':count hónap', 'm' => ':count hónap', 'week' => ':count hét', 'w' => ':count hét', 'day' => ':count nap', 'd' => ':count nap', 'hour' => ':count óra', 'h' => ':count óra', 'minute' => ':count perc', 'min' => ':count perc', 'second' => ':count másodperc', 's' => ':count másodperc', 'ago' => ':time', 'from_now' => ':time múlva', 'after' => ':time később', 'before' => ':time korábban', 'year_ago' => ':count éve', 'y_ago' => ':count éve', 'month_ago' => ':count hónapja', 'm_ago' => ':count hónapja', 'week_ago' => ':count hete', 'w_ago' => ':count hete', 'day_ago' => ':count napja', 'd_ago' => ':count napja', 'hour_ago' => ':count órája', 'h_ago' => ':count órája', 'minute_ago' => ':count perce', 'min_ago' => ':count perce', 'second_ago' => ':count másodperce', 's_ago' => ':count másodperce', 'year_after' => ':count évvel', 'y_after' => ':count évvel', 'month_after' => ':count hónappal', 'm_after' => ':count hónappal', 'week_after' => ':count héttel', 'w_after' => ':count héttel', 'day_after' => ':count nappal', 'd_after' => ':count nappal', 'hour_after' => ':count órával', 'h_after' => ':count órával', 'minute_after' => ':count perccel', 'min_after' => ':count perccel', 'second_after' => ':count másodperccel', 's_after' => ':count másodperccel', 'year_before' => ':count évvel', 'y_before' => ':count évvel', 'month_before' => ':count hónappal', 'm_before' => ':count hónappal', 'week_before' => ':count héttel', 'w_before' => ':count héttel', 'day_before' => ':count nappal', 'd_before' => ':count nappal', 'hour_before' => ':count órával', 'h_before' => ':count órával', 'minute_before' => ':count perccel', 'min_before' => ':count perccel', 'second_before' => ':count másodperccel', 's_before' => ':count másodperccel', 'months' => ['január', 'február', 'március', 'április', 'május', 'június', 'július', 'augusztus', 'szeptember', 'október', 'november', 'december'], 'months_short' => ['jan.', 'febr.', 'márc.', 'ápr.', 'máj.', 'jún.', 'júl.', 'aug.', 'szept.', 'okt.', 'nov.', 'dec.'], 'weekdays' => ['vasárnap', 'hétfő', 'kedd', 'szerda', 'csütörtök', 'péntek', 'szombat'], 'weekdays_short' => ['vas', 'hét', 'kedd', 'sze', 'csüt', 'pén', 'szo'], 'weekdays_min' => ['v', 'h', 'k', 'sze', 'cs', 'p', 'sz'], 'ordinal' => ':number.', 'diff_now' => 'most', 'diff_today' => 'ma', 'diff_yesterday' => 'tegnap', 'diff_tomorrow' => 'holnap', 'formats' => [ 'LT' => 'H:mm', 'LTS' => 'H:mm:ss', 'L' => 'YYYY.MM.DD.', 'LL' => 'YYYY. MMMM D.', 'LLL' => 'YYYY. MMMM D. H:mm', 'LLLL' => 'YYYY. MMMM D., dddd H:mm', ], 'calendar' => [ 'sameDay' => '[ma] LT[-kor]', 'nextDay' => '[holnap] LT[-kor]', 'nextWeek' => function (CarbonInterface $date) use ($huWeekEndings) { return '['.$huWeekEndings[$date->dayOfWeek].'] LT[-kor]'; }, 'lastDay' => '[tegnap] LT[-kor]', 'lastWeek' => function (CarbonInterface $date) use ($huWeekEndings) { return '[múlt '.$huWeekEndings[$date->dayOfWeek].'] LT[-kor]'; }, 'sameElse' => 'L', ], 'meridiem' => ['DE', 'DU'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' és '], ]; PK������<1ZY�#N������Carbon/Lang/unm_US.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'DD/MM/YY', ], 'months' => ['enikwsi', 'chkwali', 'xamokhwite', 'kwetayoxe', 'tainipen', 'kichinipen', 'lainipen', 'winaminke', 'kichitahkok', 'puksit', 'wini', 'muxkotae'], 'months_short' => ['eni', 'chk', 'xam', 'kwe', 'tai', 'nip', 'lai', 'win', 'tah', 'puk', 'kun', 'mux'], 'weekdays' => ['kentuwei', 'manteke', 'tusteke', 'lelai', 'tasteke', 'pelaiteke', 'sateteke'], 'weekdays_short' => ['ken', 'man', 'tus', 'lel', 'tas', 'pel', 'sat'], 'weekdays_min' => ['ken', 'man', 'tus', 'lel', 'tas', 'pel', 'sat'], 'day_of_first_week_of_year' => 1, // Too unreliable /* 'year' => ':count kaxtëne', 'y' => ':count kaxtëne', 'a_year' => ':count kaxtëne', 'month' => ':count piskewëni kishux', // less reliable 'm' => ':count piskewëni kishux', // less reliable 'a_month' => ':count piskewëni kishux', // less reliable 'week' => ':count kishku', // less reliable 'w' => ':count kishku', // less reliable 'a_week' => ':count kishku', // less reliable 'day' => ':count kishku', 'd' => ':count kishku', 'a_day' => ':count kishku', 'hour' => ':count xkuk', // less reliable 'h' => ':count xkuk', // less reliable 'a_hour' => ':count xkuk', // less reliable 'minute' => ':count txituwàk', // less reliable 'min' => ':count txituwàk', // less reliable 'a_minute' => ':count txituwàk', // less reliable 'second' => ':count nisha', // less reliable 's' => ':count nisha', // less reliable 'a_second' => ':count nisha', // less reliable */ ]); PK������<1ZwjO��O����Carbon/Lang/az.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - Kunal Marwaha * - François B * - JD Isaacks * - Orxan * - Şəhriyar İmanov * - Baran Şengül */ return [ 'year' => ':count il', 'a_year' => '{1}bir il|]1,Inf[:count il', 'y' => ':count il', 'month' => ':count ay', 'a_month' => '{1}bir ay|]1,Inf[:count ay', 'm' => ':count ay', 'week' => ':count həftə', 'a_week' => '{1}bir həftə|]1,Inf[:count həftə', 'w' => ':count h.', 'day' => ':count gün', 'a_day' => '{1}bir gün|]1,Inf[:count gün', 'd' => ':count g.', 'hour' => ':count saat', 'a_hour' => '{1}bir saat|]1,Inf[:count saat', 'h' => ':count saat', 'minute' => ':count d.', 'a_minute' => '{1}bir dəqiqə|]1,Inf[:count dəqiqə', 'min' => ':count dəqiqə', 'second' => ':count san.', 'a_second' => '{1}birneçə saniyə|]1,Inf[:count saniyə', 's' => ':count saniyə', 'ago' => ':time əvvəl', 'from_now' => ':time sonra', 'after' => ':time sonra', 'before' => ':time əvvəl', 'diff_now' => 'indi', 'diff_today' => 'bugün', 'diff_today_regexp' => 'bugün(?:\\s+saat)?', 'diff_yesterday' => 'dünən', 'diff_tomorrow' => 'sabah', 'diff_tomorrow_regexp' => 'sabah(?:\\s+saat)?', 'diff_before_yesterday' => 'srağagün', 'diff_after_tomorrow' => 'birisi gün', 'period_recurrences' => ':count dəfədən bir', 'period_interval' => 'hər :interval', 'period_start_date' => ':date tarixindən başlayaraq', 'period_end_date' => ':date tarixinədək', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[bugün saat] LT', 'nextDay' => '[sabah saat] LT', 'nextWeek' => '[gələn həftə] dddd [saat] LT', 'lastDay' => '[dünən] LT', 'lastWeek' => '[keçən həftə] dddd [saat] LT', 'sameElse' => 'L', ], 'ordinal' => function ($number) { if ($number === 0) { // special case for zero return "$number-ıncı"; } static $suffixes = [ 1 => '-inci', 5 => '-inci', 8 => '-inci', 70 => '-inci', 80 => '-inci', 2 => '-nci', 7 => '-nci', 20 => '-nci', 50 => '-nci', 3 => '-üncü', 4 => '-üncü', 100 => '-üncü', 6 => '-ncı', 9 => '-uncu', 10 => '-uncu', 30 => '-uncu', 60 => '-ıncı', 90 => '-ıncı', ]; $lastDigit = $number % 10; return $number.($suffixes[$lastDigit] ?? $suffixes[$number % 100 - $lastDigit] ?? $suffixes[$number >= 100 ? 100 : -1] ?? ''); }, 'meridiem' => function ($hour) { if ($hour < 4) { return 'gecə'; } if ($hour < 12) { return 'səhər'; } if ($hour < 17) { return 'gündüz'; } return 'axşam'; }, 'months' => ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust', 'sentyabr', 'oktyabr', 'noyabr', 'dekabr'], 'months_short' => ['yan', 'fev', 'mar', 'apr', 'may', 'iyn', 'iyl', 'avq', 'sen', 'okt', 'noy', 'dek'], 'months_standalone' => ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'İyun', 'İyul', 'Avqust', 'Sentyabr', 'Oktyabr', 'Noyabr', 'Dekabr'], 'weekdays' => ['bazar', 'bazar ertəsi', 'çərşənbə axşamı', 'çərşənbə', 'cümə axşamı', 'cümə', 'şənbə'], 'weekdays_short' => ['baz', 'bze', 'çax', 'çər', 'cax', 'cüm', 'şən'], 'weekdays_min' => ['bz', 'be', 'ça', 'çə', 'ca', 'cü', 'şə'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' və '], ]; PK������<1ZdIk �� ����Carbon/Lang/bg_BG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/bg.php'; PK������<1ZڑQ��Q����Carbon/Lang/so_ET.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ge'ez Frontier Foundation locales@geez.org */ return require __DIR__.'/so.php'; PK������<1Z[ia �� ����Carbon/Lang/pt_AO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/pt.php'; PK������<1Zɠnd �� ����Carbon/Lang/oc_FR.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/oc.php'; PK������<1Z''x �� ����Carbon/Lang/fr_CG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/fr.php'; PK������<1ZI �� ����Carbon/Lang/lb_LU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/lb.php'; PK������<1ZI��I����Carbon/Lang/bo.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Josh Soref * - JD Isaacks */ return [ 'year' => '{1}ལོ་གཅིག|]1,Inf[:count ལོ', 'month' => '{1}ཟླ་བ་གཅིག|]1,Inf[:count ཟླ་བ', 'week' => ':count བདུན་ཕྲག', 'day' => '{1}ཉིན་གཅིག|]1,Inf[:count ཉིན་', 'hour' => '{1}ཆུ་ཚོད་གཅིག|]1,Inf[:count ཆུ་ཚོད', 'minute' => '{1}སྐར་མ་གཅིག|]1,Inf[:count སྐར་མ', 'second' => '{1}ལམ་སང|]1,Inf[:count སྐར་ཆ།', 'ago' => ':time སྔན་ལ', 'from_now' => ':time ལ་', 'diff_yesterday' => 'ཁ་སང', 'diff_today' => 'དི་རིང', 'diff_tomorrow' => 'སང་ཉིན', 'formats' => [ 'LT' => 'A h:mm', 'LTS' => 'A h:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY, A h:mm', 'LLLL' => 'dddd, D MMMM YYYY, A h:mm', ], 'calendar' => [ 'sameDay' => '[དི་རིང] LT', 'nextDay' => '[སང་ཉིན] LT', 'nextWeek' => '[བདུན་ཕྲག་རྗེས་མ], LT', 'lastDay' => '[ཁ་སང] LT', 'lastWeek' => '[བདུན་ཕྲག་མཐའ་མ] dddd, LT', 'sameElse' => 'L', ], 'meridiem' => function ($hour) { if ($hour < 4) { return 'མཚན་མོ'; } if ($hour < 10) { return 'ཞོགས་ཀས'; } if ($hour < 17) { return 'ཉིན་གུང'; } if ($hour < 20) { return 'དགོང་དག'; } return 'མཚན་མོ'; }, 'months' => ['ཟླ་བ་དང་པོ', 'ཟླ་བ་གཉིས་པ', 'ཟླ་བ་གསུམ་པ', 'ཟླ་བ་བཞི་པ', 'ཟླ་བ་ལྔ་པ', 'ཟླ་བ་དྲུག་པ', 'ཟླ་བ་བདུན་པ', 'ཟླ་བ་བརྒྱད་པ', 'ཟླ་བ་དགུ་པ', 'ཟླ་བ་བཅུ་པ', 'ཟླ་བ་བཅུ་གཅིག་པ', 'ཟླ་བ་བཅུ་གཉིས་པ'], 'months_short' => ['ཟླ་བ་དང་པོ', 'ཟླ་བ་གཉིས་པ', 'ཟླ་བ་གསུམ་པ', 'ཟླ་བ་བཞི་པ', 'ཟླ་བ་ལྔ་པ', 'ཟླ་བ་དྲུག་པ', 'ཟླ་བ་བདུན་པ', 'ཟླ་བ་བརྒྱད་པ', 'ཟླ་བ་དགུ་པ', 'ཟླ་བ་བཅུ་པ', 'ཟླ་བ་བཅུ་གཅིག་པ', 'ཟླ་བ་བཅུ་གཉིས་པ'], 'weekdays' => ['གཟའ་ཉི་མ་', 'གཟའ་ཟླ་བ་', 'གཟའ་མིག་དམར་', 'གཟའ་ལྷག་པ་', 'གཟའ་ཕུར་བུ', 'གཟའ་པ་སངས་', 'གཟའ་སྤེན་པ་'], 'weekdays_short' => ['ཉི་མ་', 'ཟླ་བ་', 'མིག་དམར་', 'ལྷག་པ་', 'ཕུར་བུ', 'པ་སངས་', 'སྤེན་པ་'], 'weekdays_min' => ['ཉི་མ་', 'ཟླ་བ་', 'མིག་དམར་', 'ལྷག་པ་', 'ཕུར་བུ', 'པ་སངས་', 'སྤེན་པ་'], 'list' => [', ', ' ཨནད་ '], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, 'months_standalone' => ['ཟླ་བ་དང་པོ་', 'ཟླ་བ་གཉིས་པ་', 'ཟླ་བ་གསུམ་པ་', 'ཟླ་བ་བཞི་པ་', 'ཟླ་བ་ལྔ་པ་', 'ཟླ་བ་དྲུག་པ་', 'ཟླ་བ་བདུན་པ་', 'ཟླ་བ་བརྒྱད་པ་', 'ཟླ་བ་དགུ་པ་', 'ཟླ་བ་བཅུ་པ་', 'ཟླ་བ་བཅུ་གཅིག་པ་', 'ཟླ་བ་བཅུ་གཉིས་པ་'], ]; PK������<1Z)ˊ �� ����Carbon/Lang/gd.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - François B * - Jon Ashdown */ return [ 'year' => ':count bliadhna', 'a_year' => '{1}bliadhna|:count bliadhna', 'y' => ':count b.', 'month' => ':count mìosan', 'a_month' => '{1}mìos|:count mìosan', 'm' => ':count ms.', 'week' => ':count seachdainean', 'a_week' => '{1}seachdain|:count seachdainean', 'w' => ':count s.', 'day' => ':count latha', 'a_day' => '{1}latha|:count latha', 'd' => ':count l.', 'hour' => ':count uairean', 'a_hour' => '{1}uair|:count uairean', 'h' => ':count u.', 'minute' => ':count mionaidean', 'a_minute' => '{1}mionaid|:count mionaidean', 'min' => ':count md.', 'second' => ':count diogan', 'a_second' => '{1}beagan diogan|:count diogan', 's' => ':count d.', 'ago' => 'bho chionn :time', 'from_now' => 'ann an :time', 'diff_yesterday' => 'An-dè', 'diff_yesterday_regexp' => 'An-dè(?:\\s+aig)?', 'diff_today' => 'An-diugh', 'diff_today_regexp' => 'An-diugh(?:\\s+aig)?', 'diff_tomorrow' => 'A-màireach', 'diff_tomorrow_regexp' => 'A-màireach(?:\\s+aig)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[An-diugh aig] LT', 'nextDay' => '[A-màireach aig] LT', 'nextWeek' => 'dddd [aig] LT', 'lastDay' => '[An-dè aig] LT', 'lastWeek' => 'dddd [seo chaidh] [aig] LT', 'sameElse' => 'L', ], 'ordinal' => function ($number) { return $number.($number === 1 ? 'd' : ($number % 10 === 2 ? 'na' : 'mh')); }, 'months' => ['Am Faoilleach', 'An Gearran', 'Am Màrt', 'An Giblean', 'An Cèitean', 'An t-Ògmhios', 'An t-Iuchar', 'An Lùnastal', 'An t-Sultain', 'An Dàmhair', 'An t-Samhain', 'An Dùbhlachd'], 'months_short' => ['Faoi', 'Gear', 'Màrt', 'Gibl', 'Cèit', 'Ògmh', 'Iuch', 'Lùn', 'Sult', 'Dàmh', 'Samh', 'Dùbh'], 'weekdays' => ['Didòmhnaich', 'Diluain', 'Dimàirt', 'Diciadain', 'Diardaoin', 'Dihaoine', 'Disathairne'], 'weekdays_short' => ['Did', 'Dil', 'Dim', 'Dic', 'Dia', 'Dih', 'Dis'], 'weekdays_min' => ['Dò', 'Lu', 'Mà', 'Ci', 'Ar', 'Ha', 'Sa'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' agus '], 'meridiem' => ['m', 'f'], ]; PK������<1Zy������Carbon/Lang/tl.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return [ 'year' => ':count taon', 'a_year' => '{1}isang taon|:count taon', 'month' => ':count buwan', 'a_month' => '{1}isang buwan|:count buwan', 'week' => ':count linggo', 'a_week' => '{1}isang linggo|:count linggo', 'day' => ':count araw', 'a_day' => '{1}isang araw|:count araw', 'hour' => ':count oras', 'a_hour' => '{1}isang oras|:count oras', 'minute' => ':count minuto', 'a_minute' => '{1}isang minuto|:count minuto', 'min' => ':count min.', 'second' => ':count segundo', 'a_second' => '{1}ilang segundo|:count segundo', 's' => ':count seg.', 'ago' => ':time ang nakalipas', 'from_now' => 'sa loob ng :time', 'diff_now' => 'ngayon', 'diff_today' => 'ngayong', 'diff_today_regexp' => 'ngayong(?:\\s+araw)?', 'diff_yesterday' => 'kahapon', 'diff_tomorrow' => 'bukas', 'diff_tomorrow_regexp' => 'Bukas(?:\\s+ng)?', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'MM/D/YYYY', 'LL' => 'MMMM D, YYYY', 'LLL' => 'MMMM D, YYYY HH:mm', 'LLLL' => 'dddd, MMMM DD, YYYY HH:mm', ], 'calendar' => [ 'sameDay' => 'LT [ngayong araw]', 'nextDay' => '[Bukas ng] LT', 'nextWeek' => 'LT [sa susunod na] dddd', 'lastDay' => 'LT [kahapon]', 'lastWeek' => 'LT [noong nakaraang] dddd', 'sameElse' => 'L', ], 'months' => ['Enero', 'Pebrero', 'Marso', 'Abril', 'Mayo', 'Hunyo', 'Hulyo', 'Agosto', 'Setyembre', 'Oktubre', 'Nobyembre', 'Disyembre'], 'months_short' => ['Ene', 'Peb', 'Mar', 'Abr', 'May', 'Hun', 'Hul', 'Ago', 'Set', 'Okt', 'Nob', 'Dis'], 'weekdays' => ['Linggo', 'Lunes', 'Martes', 'Miyerkules', 'Huwebes', 'Biyernes', 'Sabado'], 'weekdays_short' => ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'], 'weekdays_min' => ['Li', 'Lu', 'Ma', 'Mi', 'Hu', 'Bi', 'Sab'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' at '], ]; PK������<1ZQ> �� ����Carbon/Lang/kl_GL.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Danish Standards Association bug-glibc-locales@gnu.org * - John Eyðstein Johannesen (mashema) */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D. MMMM YYYY', 'LLL' => 'D. MMMM YYYY HH:mm', 'LLLL' => 'dddd [d.] D. MMMM YYYY [kl.] HH:mm', ], 'months' => ['januaarip', 'februaarip', 'marsip', 'apriilip', 'maajip', 'juunip', 'juulip', 'aggustip', 'septembarip', 'oktobarip', 'novembarip', 'decembarip'], 'months_short' => ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'], 'weekdays' => ['sapaat', 'ataasinngorneq', 'marlunngorneq', 'pingasunngorneq', 'sisamanngorneq', 'tallimanngorneq', 'arfininngorneq'], 'weekdays_short' => ['sap', 'ata', 'mar', 'pin', 'sis', 'tal', 'arf'], 'weekdays_min' => ['sap', 'ata', 'mar', 'pin', 'sis', 'tal', 'arf'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'year' => '{1}ukioq :count|{0}:count ukiut|]1,Inf[ukiut :count', 'a_year' => '{1}ukioq|{0}:count ukiut|]1,Inf[ukiut :count', 'y' => '{1}:countyr|{0}:countyrs|]1,Inf[:countyrs', 'month' => '{1}qaammat :count|{0}:count qaammatit|]1,Inf[qaammatit :count', 'a_month' => '{1}qaammat|{0}:count qaammatit|]1,Inf[qaammatit :count', 'm' => '{1}:countmo|{0}:countmos|]1,Inf[:countmos', 'week' => '{1}:count sap. ak.|{0}:count sap. ak.|]1,Inf[:count sap. ak.', 'a_week' => '{1}a sap. ak.|{0}:count sap. ak.|]1,Inf[:count sap. ak.', 'w' => ':countw', 'day' => '{1}:count ulloq|{0}:count ullut|]1,Inf[:count ullut', 'a_day' => '{1}a ulloq|{0}:count ullut|]1,Inf[:count ullut', 'd' => ':countd', 'hour' => '{1}:count tiimi|{0}:count tiimit|]1,Inf[:count tiimit', 'a_hour' => '{1}tiimi|{0}:count tiimit|]1,Inf[:count tiimit', 'h' => ':counth', 'minute' => '{1}:count minutsi|{0}:count minutsit|]1,Inf[:count minutsit', 'a_minute' => '{1}a minutsi|{0}:count minutsit|]1,Inf[:count minutsit', 'min' => ':countm', 'second' => '{1}:count sikunti|{0}:count sikuntit|]1,Inf[:count sikuntit', 'a_second' => '{1}sikunti|{0}:count sikuntit|]1,Inf[:count sikuntit', 's' => ':counts', 'ago' => ':time matuma siorna', ]); PK������<1Z\������Carbon/Lang/en.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Milos Sakovic * - Paul * - Pete Scopes (pdscopes) */ return [ /* * {1}, {0} and ]1,Inf[ are not needed as it's the default for English pluralization. * But as some languages are using en.php as a fallback, it's better to specify it * explicitly so those languages also fallback to English pluralization when a unit * is missing. */ 'year' => '{1}:count year|{0}:count years|]1,Inf[:count years', 'a_year' => '{1}a year|{0}:count years|]1,Inf[:count years', 'y' => '{1}:countyr|{0}:countyrs|]1,Inf[:countyrs', 'month' => '{1}:count month|{0}:count months|]1,Inf[:count months', 'a_month' => '{1}a month|{0}:count months|]1,Inf[:count months', 'm' => '{1}:countmo|{0}:countmos|]1,Inf[:countmos', 'week' => '{1}:count week|{0}:count weeks|]1,Inf[:count weeks', 'a_week' => '{1}a week|{0}:count weeks|]1,Inf[:count weeks', 'w' => ':countw', 'day' => '{1}:count day|{0}:count days|]1,Inf[:count days', 'a_day' => '{1}a day|{0}:count days|]1,Inf[:count days', 'd' => ':countd', 'hour' => '{1}:count hour|{0}:count hours|]1,Inf[:count hours', 'a_hour' => '{1}an hour|{0}:count hours|]1,Inf[:count hours', 'h' => ':counth', 'minute' => '{1}:count minute|{0}:count minutes|]1,Inf[:count minutes', 'a_minute' => '{1}a minute|{0}:count minutes|]1,Inf[:count minutes', 'min' => ':countm', 'second' => '{1}:count second|{0}:count seconds|]1,Inf[:count seconds', 'a_second' => '{1}a few seconds|{0}:count seconds|]1,Inf[:count seconds', 's' => ':counts', 'millisecond' => '{1}:count millisecond|{0}:count milliseconds|]1,Inf[:count milliseconds', 'a_millisecond' => '{1}a millisecond|{0}:count milliseconds|]1,Inf[:count milliseconds', 'ms' => ':countms', 'microsecond' => '{1}:count microsecond|{0}:count microseconds|]1,Inf[:count microseconds', 'a_microsecond' => '{1}a microsecond|{0}:count microseconds|]1,Inf[:count microseconds', 'µs' => ':countµs', 'ago' => ':time ago', 'from_now' => ':time from now', 'after' => ':time after', 'before' => ':time before', 'diff_now' => 'just now', 'diff_today' => 'today', 'diff_yesterday' => 'yesterday', 'diff_tomorrow' => 'tomorrow', 'diff_before_yesterday' => 'before yesterday', 'diff_after_tomorrow' => 'after tomorrow', 'period_recurrences' => '{1}once|{0}:count times|]1,Inf[:count times', 'period_interval' => 'every :interval', 'period_start_date' => 'from :date', 'period_end_date' => 'to :date', 'months' => ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], 'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], 'weekdays' => ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], 'weekdays_short' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], 'weekdays_min' => ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], 'ordinal' => function ($number) { $lastDigit = $number % 10; return $number.( ((int) ($number % 100 / 10) === 1) ? 'th' : ( ($lastDigit === 1) ? 'st' : ( ($lastDigit === 2) ? 'nd' : ( ($lastDigit === 3) ? 'rd' : 'th' ) ) ) ); }, 'list' => [', ', ' and '], 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]; PK������<1Z}*B �� ����Carbon/Lang/ha_NG.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ha.php'; PK������<1Z{ �� ����Carbon/Lang/ka_GE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/ka.php'; PK������<1ZE������Carbon/Lang/the_NP.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Chitwanix OS Development info@chitwanix.com */ return array_replace_recursive(require __DIR__.'/en.php', [ 'formats' => [ 'L' => 'dddd DD MMM YYYY', ], 'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'], 'months_short' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'], 'weekdays' => ['आइतबार', 'सोमबार', 'मंगलबार', 'बुधबार', 'बिहिबार', 'शुक्रबार', 'शनिबार'], 'weekdays_short' => ['आइत', 'सोम', 'मंगल', 'बुध', 'बिहि', 'शुक्र', 'शनि'], 'weekdays_min' => ['आइत', 'सोम', 'मंगल', 'बुध', 'बिहि', 'शुक्र', 'शनि'], 'day_of_first_week_of_year' => 1, 'meridiem' => ['पूर्वाह्न', 'अपराह्न'], ]); PK������<1ZZ)_��_����Carbon/Lang/de_DE.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Free Software Foundation, Inc. bug-glibc-locales@gnu.org */ return require __DIR__.'/de.php'; PK������<1Z[ia �� ����Carbon/Lang/pt_CV.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return require __DIR__.'/pt.php'; PK������<1ZV��V����Carbon/Lang/lu.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'meridiem' => ['Dinda', 'Dilolo'], 'weekdays' => ['Lumingu', 'Nkodya', 'Ndàayà', 'Ndangù', 'Njòwa', 'Ngòvya', 'Lubingu'], 'weekdays_short' => ['Lum', 'Nko', 'Ndy', 'Ndg', 'Njw', 'Ngv', 'Lub'], 'weekdays_min' => ['Lum', 'Nko', 'Ndy', 'Ndg', 'Njw', 'Ngv', 'Lub'], 'months' => ['Ciongo', 'Lùishi', 'Lusòlo', 'Mùuyà', 'Lumùngùlù', 'Lufuimi', 'Kabàlàshìpù', 'Lùshìkà', 'Lutongolo', 'Lungùdi', 'Kaswèkèsè', 'Ciswà'], 'months_short' => ['Cio', 'Lui', 'Lus', 'Muu', 'Lum', 'Luf', 'Kab', 'Lush', 'Lut', 'Lun', 'Kas', 'Cis'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'D/M/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd D MMMM YYYY HH:mm', ], ]); PK������<1Z������Carbon/Lang/bn_BD.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Ankur Group, Taneem Ahmed, Jamil Ahmed */ return array_replace_recursive(require __DIR__.'/bn.php', [ 'formats' => [ 'L' => 'D/M/YY', ], 'months' => ['জানুয়ারী', 'ফেব্রুয়ারী', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'], 'months_short' => ['জানু', 'ফেব', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'], 'weekdays' => ['রবিবার', 'সোমবার', 'মঙ্গলবার', 'বুধবার', 'বৃহস্পতিবার', 'শুক্রবার', 'শনিবার'], 'weekdays_short' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহঃ', 'শুক্র', 'শনি'], 'weekdays_min' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহঃ', 'শুক্র', 'শনি'], 'first_day_of_week' => 5, 'day_of_first_week_of_year' => 1, ]); PK������<1Zd������Carbon/Lang/es_CO.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/es.php', [ 'first_day_of_week' => 0, 'day_of_first_week_of_year' => 1, ]); PK������<1Z1s��s����Carbon/Lang/vai_Latn.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return array_replace_recursive(require __DIR__.'/en.php', [ 'weekdays' => ['lahadi', 'tɛɛnɛɛ', 'talata', 'alaba', 'aimisa', 'aijima', 'siɓiti'], 'weekdays_short' => ['lahadi', 'tɛɛnɛɛ', 'talata', 'alaba', 'aimisa', 'aijima', 'siɓiti'], 'weekdays_min' => ['lahadi', 'tɛɛnɛɛ', 'talata', 'alaba', 'aimisa', 'aijima', 'siɓiti'], 'months' => ['luukao kemã', 'ɓandaɓu', 'vɔɔ', 'fulu', 'goo', '6', '7', 'kɔnde', 'saah', 'galo', 'kenpkato ɓololɔ', 'luukao lɔma'], 'months_short' => ['luukao kemã', 'ɓandaɓu', 'vɔɔ', 'fulu', 'goo', '6', '7', 'kɔnde', 'saah', 'galo', 'kenpkato ɓololɔ', 'luukao lɔma'], 'first_day_of_week' => 1, 'formats' => [ 'LT' => 'h:mm a', 'LTS' => 'h:mm:ss a', 'L' => 'DD/MM/YYYY', 'LL' => 'D MMM YYYY', 'LLL' => 'D MMMM YYYY h:mm a', 'LLLL' => 'dddd, D MMMM YYYY h:mm a', ], ]); PK������<1Z]jwO��O����Carbon/Lang/shs.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Unknown default region, use the first alphabetically. */ return require __DIR__.'/shs_CA.php'; PK������<1Zv5��5����Carbon/Lang/sr_Cyrl_ME.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Glavić * - Milos Sakovic */ use Carbon\CarbonInterface; use Symfony\Component\Translation\PluralizationRules; // @codeCoverageIgnoreStart if (class_exists(PluralizationRules::class)) { PluralizationRules::set(static function ($number) { return PluralizationRules::get($number, 'sr'); }, 'sr_Cyrl_ME'); } // @codeCoverageIgnoreEnd return [ 'year' => ':count година|:count године|:count година', 'y' => ':count г.', 'month' => ':count мјесец|:count мјесеца|:count мјесеци', 'm' => ':count мј.', 'week' => ':count недјеља|:count недјеље|:count недјеља', 'w' => ':count нед.', 'day' => ':count дан|:count дана|:count дана', 'd' => ':count д.', 'hour' => ':count сат|:count сата|:count сати', 'h' => ':count ч.', 'minute' => ':count минут|:count минута|:count минута', 'min' => ':count мин.', 'second' => ':count секунд|:count секунде|:count секунди', 's' => ':count сек.', 'ago' => 'прије :time', 'from_now' => 'за :time', 'after' => ':time након', 'before' => ':time прије', 'year_from_now' => ':count годину|:count године|:count година', 'year_ago' => ':count годину|:count године|:count година', 'week_from_now' => ':count недјељу|:count недјеље|:count недјеља', 'week_ago' => ':count недјељу|:count недјеље|:count недјеља', 'diff_now' => 'управо сада', 'diff_today' => 'данас', 'diff_today_regexp' => 'данас(?:\\s+у)?', 'diff_yesterday' => 'јуче', 'diff_yesterday_regexp' => 'јуче(?:\\s+у)?', 'diff_tomorrow' => 'сутра', 'diff_tomorrow_regexp' => 'сутра(?:\\s+у)?', 'diff_before_yesterday' => 'прекјуче', 'diff_after_tomorrow' => 'прекосјутра', 'formats' => [ 'LT' => 'H:mm', 'LTS' => 'H:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D. MMMM YYYY', 'LLL' => 'D. MMMM YYYY H:mm', 'LLLL' => 'dddd, D. MMMM YYYY H:mm', ], 'calendar' => [ 'sameDay' => '[данас у] LT', 'nextDay' => '[сутра у] LT', 'nextWeek' => function (CarbonInterface $date) { switch ($date->dayOfWeek) { case 0: return '[у недељу у] LT'; case 3: return '[у среду у] LT'; case 6: return '[у суботу у] LT'; default: return '[у] dddd [у] LT'; } }, 'lastDay' => '[јуче у] LT', 'lastWeek' => function (CarbonInterface $date) { switch ($date->dayOfWeek) { case 0: return '[прошле недеље у] LT'; case 1: return '[прошлог понедељка у] LT'; case 2: return '[прошлог уторка у] LT'; case 3: return '[прошле среде у] LT'; case 4: return '[прошлог четвртка у] LT'; case 5: return '[прошлог петка у] LT'; default: return '[прошле суботе у] LT'; } }, 'sameElse' => 'L', ], 'ordinal' => ':number.', 'months' => ['јануар', 'фебруар', 'март', 'април', 'мај', 'јун', 'јул', 'август', 'септембар', 'октобар', 'новембар', 'децембар'], 'months_short' => ['јан.', 'феб.', 'мар.', 'апр.', 'мај', 'јун', 'јул', 'авг.', 'сеп.', 'окт.', 'нов.', 'дец.'], 'weekdays' => ['недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота'], 'weekdays_short' => ['нед.', 'пон.', 'уто.', 'сре.', 'чет.', 'пет.', 'суб.'], 'weekdays_min' => ['не', 'по', 'ут', 'ср', 'че', 'пе', 'су'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 1, 'list' => [', ', ' и '], 'meridiem' => ['АМ', 'ПМ'], ]; PK������<1Z4y��y����Carbon/Lang/pl.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - Wacław Jacek * - François B * - Tim Fish * - Serhan Apaydın * - Massimiliano Caniparoli * - JD Isaacks * - Jakub Szwacz * - Jan * - Paul * - damlys * - Marek (marast78) * - Peter (UnrulyNatives) * - Qrzysio * - Jan (aso824) * - diverpl */ use Carbon\CarbonInterface; return [ 'year' => ':count rok|:count lata|:count lat', 'a_year' => 'rok|:count lata|:count lat', 'y' => ':count r|:count l|:count l', 'month' => ':count miesiąc|:count miesiące|:count miesięcy', 'a_month' => 'miesiąc|:count miesiące|:count miesięcy', 'm' => ':count mies.', 'week' => ':count tydzień|:count tygodnie|:count tygodni', 'a_week' => 'tydzień|:count tygodnie|:count tygodni', 'w' => ':count tyg.', 'day' => ':count dzień|:count dni|:count dni', 'a_day' => 'dzień|:count dni|:count dni', 'd' => ':count d', 'hour' => ':count godzina|:count godziny|:count godzin', 'a_hour' => 'godzina|:count godziny|:count godzin', 'h' => ':count godz.', 'minute' => ':count minuta|:count minuty|:count minut', 'a_minute' => 'minuta|:count minuty|:count minut', 'min' => ':count min', 'second' => ':count sekunda|:count sekundy|:count sekund', 'a_second' => '{1}kilka sekund|:count sekunda|:count sekundy|:count sekund', 's' => ':count sek.', 'ago' => ':time temu', 'from_now' => static function ($time) { return 'za '.strtr($time, [ 'godzina' => 'godzinę', 'minuta' => 'minutę', 'sekunda' => 'sekundę', ]); }, 'after' => ':time po', 'before' => ':time przed', 'diff_now' => 'teraz', 'diff_today' => 'Dziś', 'diff_today_regexp' => 'Dziś(?:\\s+o)?', 'diff_yesterday' => 'wczoraj', 'diff_yesterday_regexp' => 'Wczoraj(?:\\s+o)?', 'diff_tomorrow' => 'jutro', 'diff_tomorrow_regexp' => 'Jutro(?:\\s+o)?', 'diff_before_yesterday' => 'przedwczoraj', 'diff_after_tomorrow' => 'pojutrze', 'formats' => [ 'LT' => 'HH:mm', 'LTS' => 'HH:mm:ss', 'L' => 'DD.MM.YYYY', 'LL' => 'D MMMM YYYY', 'LLL' => 'D MMMM YYYY HH:mm', 'LLLL' => 'dddd, D MMMM YYYY HH:mm', ], 'calendar' => [ 'sameDay' => '[Dziś o] LT', 'nextDay' => '[Jutro o] LT', 'nextWeek' => function (CarbonInterface $date) { switch ($date->dayOfWeek) { case 0: return '[W niedzielę o] LT'; case 2: return '[We wtorek o] LT'; case 3: return '[W środę o] LT'; case 6: return '[W sobotę o] LT'; default: return '[W] dddd [o] LT'; } }, 'lastDay' => '[Wczoraj o] LT', 'lastWeek' => function (CarbonInterface $date) { switch ($date->dayOfWeek) { case 0: return '[W zeszłą niedzielę o] LT'; case 3: return '[W zeszłą środę o] LT'; case 6: return '[W zeszłą sobotę o] LT'; default: return '[W zeszły] dddd [o] LT'; } }, 'sameElse' => 'L', ], 'ordinal' => ':number.', 'months' => ['stycznia', 'lutego', 'marca', 'kwietnia', 'maja', 'czerwca', 'lipca', 'sierpnia', 'września', 'października', 'listopada', 'grudnia'], 'months_standalone' => ['styczeń', 'luty', 'marzec', 'kwiecień', 'maj', 'czerwiec', 'lipiec', 'sierpień', 'wrzesień', 'październik', 'listopad', 'grudzień'], 'months_short' => ['sty', 'lut', 'mar', 'kwi', 'maj', 'cze', 'lip', 'sie', 'wrz', 'paź', 'lis', 'gru'], 'months_regexp' => '/(DD?o?\.?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/', 'weekdays' => ['niedziela', 'poniedziałek', 'wtorek', 'środa', 'czwartek', 'piątek', 'sobota'], 'weekdays_short' => ['ndz', 'pon', 'wt', 'śr', 'czw', 'pt', 'sob'], 'weekdays_min' => ['Nd', 'Pn', 'Wt', 'Śr', 'Cz', 'Pt', 'So'], 'first_day_of_week' => 1, 'day_of_first_week_of_year' => 4, 'list' => [', ', ' i '], 'meridiem' => ['przed południem', 'po południu'], ]; PK������<1Z]������Carbon/Lang/fr_LU.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * Authors: * - RAP bug-glibc-locales@gnu.org */ return array_replace_recursive(require __DIR__.'/fr.php', [ 'formats' => [ 'L' => 'DD.MM.YYYY', ], 'months_short' => ['jan', 'fév', 'mar', 'avr', 'mai', 'jun', 'jui', 'aoû', 'sep', 'oct', 'nov', 'déc'], ]); PK������<1Z,W����2��Carbon/MessageFormatter/MessageFormatterMapper.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\MessageFormatter; use ReflectionMethod; use Symfony\Component\Translation\Formatter\MessageFormatter; use Symfony\Component\Translation\Formatter\MessageFormatterInterface; // @codeCoverageIgnoreStart $transMethod = new ReflectionMethod(MessageFormatterInterface::class, 'format'); require $transMethod->getParameters()[0]->hasType() ? __DIR__.'/../../../lazy/Carbon/MessageFormatter/MessageFormatterMapperStrongType.php' : __DIR__.'/../../../lazy/Carbon/MessageFormatter/MessageFormatterMapperWeakType.php'; // @codeCoverageIgnoreEnd final class MessageFormatterMapper extends LazyMessageFormatter { /** * Wrapped formatter. * * @var MessageFormatterInterface */ protected $formatter; public function __construct(?MessageFormatterInterface $formatter = null) { $this->formatter = $formatter ?? new MessageFormatter(); } protected function transformLocale(?string $locale): ?string { return $locale ? preg_replace('/[_@][A-Za-z][a-z]{2,}/', '', $locale) : $locale; } } PK������<1Z=Tض����Carbon/Carbon.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon; use Carbon\Traits\Date; use Carbon\Traits\DeprecatedProperties; use DateTime; use DateTimeInterface; use DateTimeZone; /** * A simple API extension for DateTime. * * @mixin DeprecatedProperties * * <autodoc generated by `composer phpdoc`> * * @property int $year * @property int $yearIso * @property int $month * @property int $day * @property int $hour * @property int $minute * @property int $second * @property int $micro * @property int $microsecond * @property int|float|string $timestamp seconds since the Unix Epoch * @property string $englishDayOfWeek the day of week in English * @property string $shortEnglishDayOfWeek the abbreviated day of week in English * @property string $englishMonth the month in English * @property string $shortEnglishMonth the abbreviated month in English * @property int $milliseconds * @property int $millisecond * @property int $milli * @property int $week 1 through 53 * @property int $isoWeek 1 through 53 * @property int $weekYear year according to week format * @property int $isoWeekYear year according to ISO week format * @property int $dayOfYear 1 through 366 * @property int $age does a diffInYears() with default parameters * @property int $offset the timezone offset in seconds from UTC * @property int $offsetMinutes the timezone offset in minutes from UTC * @property int $offsetHours the timezone offset in hours from UTC * @property CarbonTimeZone $timezone the current timezone * @property CarbonTimeZone $tz alias of $timezone * @property-read int $dayOfWeek 0 (for Sunday) through 6 (for Saturday) * @property-read int $dayOfWeekIso 1 (for Monday) through 7 (for Sunday) * @property-read int $weekOfYear ISO-8601 week number of year, weeks starting on Monday * @property-read int $daysInMonth number of days in the given month * @property-read string $latinMeridiem "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark) * @property-read string $latinUpperMeridiem "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark) * @property-read string $timezoneAbbreviatedName the current timezone abbreviated name * @property-read string $tzAbbrName alias of $timezoneAbbreviatedName * @property-read string $dayName long name of weekday translated according to Carbon locale, in english if no translation available for current language * @property-read string $shortDayName short name of weekday translated according to Carbon locale, in english if no translation available for current language * @property-read string $minDayName very short name of weekday translated according to Carbon locale, in english if no translation available for current language * @property-read string $monthName long name of month translated according to Carbon locale, in english if no translation available for current language * @property-read string $shortMonthName short name of month translated according to Carbon locale, in english if no translation available for current language * @property-read string $meridiem lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language * @property-read string $upperMeridiem uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language * @property-read int $noZeroHour current hour from 1 to 24 * @property-read int $weeksInYear 51 through 53 * @property-read int $isoWeeksInYear 51 through 53 * @property-read int $weekOfMonth 1 through 5 * @property-read int $weekNumberInMonth 1 through 5 * @property-read int $firstWeekDay 0 through 6 * @property-read int $lastWeekDay 0 through 6 * @property-read int $daysInYear 365 or 366 * @property-read int $quarter the quarter of this instance, 1 - 4 * @property-read int $decade the decade of this instance * @property-read int $century the century of this instance * @property-read int $millennium the millennium of this instance * @property-read bool $dst daylight savings time indicator, true if DST, false otherwise * @property-read bool $local checks if the timezone is local, true if local, false otherwise * @property-read bool $utc checks if the timezone is UTC, true if UTC, false otherwise * @property-read string $timezoneName the current timezone name * @property-read string $tzName alias of $timezoneName * @property-read string $locale locale of the current instance * * @method bool isUtc() Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.) * @method bool isLocal() Check if the current instance has non-UTC timezone. * @method bool isValid() Check if the current instance is a valid date. * @method bool isDST() Check if the current instance is in a daylight saving time. * @method bool isSunday() Checks if the instance day is sunday. * @method bool isMonday() Checks if the instance day is monday. * @method bool isTuesday() Checks if the instance day is tuesday. * @method bool isWednesday() Checks if the instance day is wednesday. * @method bool isThursday() Checks if the instance day is thursday. * @method bool isFriday() Checks if the instance day is friday. * @method bool isSaturday() Checks if the instance day is saturday. * @method bool isSameYear(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same year as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentYear() Checks if the instance is in the same year as the current moment. * @method bool isNextYear() Checks if the instance is in the same year as the current moment next year. * @method bool isLastYear() Checks if the instance is in the same year as the current moment last year. * @method bool isSameWeek(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same week as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentWeek() Checks if the instance is in the same week as the current moment. * @method bool isNextWeek() Checks if the instance is in the same week as the current moment next week. * @method bool isLastWeek() Checks if the instance is in the same week as the current moment last week. * @method bool isSameDay(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same day as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentDay() Checks if the instance is in the same day as the current moment. * @method bool isNextDay() Checks if the instance is in the same day as the current moment next day. * @method bool isLastDay() Checks if the instance is in the same day as the current moment last day. * @method bool isSameHour(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same hour as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentHour() Checks if the instance is in the same hour as the current moment. * @method bool isNextHour() Checks if the instance is in the same hour as the current moment next hour. * @method bool isLastHour() Checks if the instance is in the same hour as the current moment last hour. * @method bool isSameMinute(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same minute as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentMinute() Checks if the instance is in the same minute as the current moment. * @method bool isNextMinute() Checks if the instance is in the same minute as the current moment next minute. * @method bool isLastMinute() Checks if the instance is in the same minute as the current moment last minute. * @method bool isSameSecond(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same second as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentSecond() Checks if the instance is in the same second as the current moment. * @method bool isNextSecond() Checks if the instance is in the same second as the current moment next second. * @method bool isLastSecond() Checks if the instance is in the same second as the current moment last second. * @method bool isSameMicro(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentMicro() Checks if the instance is in the same microsecond as the current moment. * @method bool isNextMicro() Checks if the instance is in the same microsecond as the current moment next microsecond. * @method bool isLastMicro() Checks if the instance is in the same microsecond as the current moment last microsecond. * @method bool isSameMicrosecond(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentMicrosecond() Checks if the instance is in the same microsecond as the current moment. * @method bool isNextMicrosecond() Checks if the instance is in the same microsecond as the current moment next microsecond. * @method bool isLastMicrosecond() Checks if the instance is in the same microsecond as the current moment last microsecond. * @method bool isCurrentMonth() Checks if the instance is in the same month as the current moment. * @method bool isNextMonth() Checks if the instance is in the same month as the current moment next month. * @method bool isLastMonth() Checks if the instance is in the same month as the current moment last month. * @method bool isCurrentQuarter() Checks if the instance is in the same quarter as the current moment. * @method bool isNextQuarter() Checks if the instance is in the same quarter as the current moment next quarter. * @method bool isLastQuarter() Checks if the instance is in the same quarter as the current moment last quarter. * @method bool isSameDecade(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same decade as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentDecade() Checks if the instance is in the same decade as the current moment. * @method bool isNextDecade() Checks if the instance is in the same decade as the current moment next decade. * @method bool isLastDecade() Checks if the instance is in the same decade as the current moment last decade. * @method bool isSameCentury(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same century as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentCentury() Checks if the instance is in the same century as the current moment. * @method bool isNextCentury() Checks if the instance is in the same century as the current moment next century. * @method bool isLastCentury() Checks if the instance is in the same century as the current moment last century. * @method bool isSameMillennium(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same millennium as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentMillennium() Checks if the instance is in the same millennium as the current moment. * @method bool isNextMillennium() Checks if the instance is in the same millennium as the current moment next millennium. * @method bool isLastMillennium() Checks if the instance is in the same millennium as the current moment last millennium. * @method $this years(int $value) Set current instance year to the given value. * @method $this year(int $value) Set current instance year to the given value. * @method $this setYears(int $value) Set current instance year to the given value. * @method $this setYear(int $value) Set current instance year to the given value. * @method $this months(int $value) Set current instance month to the given value. * @method $this month(int $value) Set current instance month to the given value. * @method $this setMonths(int $value) Set current instance month to the given value. * @method $this setMonth(int $value) Set current instance month to the given value. * @method $this days(int $value) Set current instance day to the given value. * @method $this day(int $value) Set current instance day to the given value. * @method $this setDays(int $value) Set current instance day to the given value. * @method $this setDay(int $value) Set current instance day to the given value. * @method $this hours(int $value) Set current instance hour to the given value. * @method $this hour(int $value) Set current instance hour to the given value. * @method $this setHours(int $value) Set current instance hour to the given value. * @method $this setHour(int $value) Set current instance hour to the given value. * @method $this minutes(int $value) Set current instance minute to the given value. * @method $this minute(int $value) Set current instance minute to the given value. * @method $this setMinutes(int $value) Set current instance minute to the given value. * @method $this setMinute(int $value) Set current instance minute to the given value. * @method $this seconds(int $value) Set current instance second to the given value. * @method $this second(int $value) Set current instance second to the given value. * @method $this setSeconds(int $value) Set current instance second to the given value. * @method $this setSecond(int $value) Set current instance second to the given value. * @method $this millis(int $value) Set current instance millisecond to the given value. * @method $this milli(int $value) Set current instance millisecond to the given value. * @method $this setMillis(int $value) Set current instance millisecond to the given value. * @method $this setMilli(int $value) Set current instance millisecond to the given value. * @method $this milliseconds(int $value) Set current instance millisecond to the given value. * @method $this millisecond(int $value) Set current instance millisecond to the given value. * @method $this setMilliseconds(int $value) Set current instance millisecond to the given value. * @method $this setMillisecond(int $value) Set current instance millisecond to the given value. * @method $this micros(int $value) Set current instance microsecond to the given value. * @method $this micro(int $value) Set current instance microsecond to the given value. * @method $this setMicros(int $value) Set current instance microsecond to the given value. * @method $this setMicro(int $value) Set current instance microsecond to the given value. * @method $this microseconds(int $value) Set current instance microsecond to the given value. * @method $this microsecond(int $value) Set current instance microsecond to the given value. * @method $this setMicroseconds(int $value) Set current instance microsecond to the given value. * @method $this setMicrosecond(int $value) Set current instance microsecond to the given value. * @method $this addYears(int $value = 1) Add years (the $value count passed in) to the instance (using date interval). * @method $this addYear() Add one year to the instance (using date interval). * @method $this subYears(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval). * @method $this subYear() Sub one year to the instance (using date interval). * @method $this addYearsWithOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method $this addYearWithOverflow() Add one year to the instance (using date interval) with overflow explicitly allowed. * @method $this subYearsWithOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method $this subYearWithOverflow() Sub one year to the instance (using date interval) with overflow explicitly allowed. * @method $this addYearsWithoutOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this addYearWithoutOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden. * @method $this subYearsWithoutOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this subYearWithoutOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden. * @method $this addYearsWithNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this addYearWithNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden. * @method $this subYearsWithNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this subYearWithNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden. * @method $this addYearsNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this addYearNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden. * @method $this subYearsNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this subYearNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden. * @method $this addMonths(int $value = 1) Add months (the $value count passed in) to the instance (using date interval). * @method $this addMonth() Add one month to the instance (using date interval). * @method $this subMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval). * @method $this subMonth() Sub one month to the instance (using date interval). * @method $this addMonthsWithOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method $this addMonthWithOverflow() Add one month to the instance (using date interval) with overflow explicitly allowed. * @method $this subMonthsWithOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method $this subMonthWithOverflow() Sub one month to the instance (using date interval) with overflow explicitly allowed. * @method $this addMonthsWithoutOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this addMonthWithoutOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden. * @method $this subMonthsWithoutOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this subMonthWithoutOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden. * @method $this addMonthsWithNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this addMonthWithNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden. * @method $this subMonthsWithNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this subMonthWithNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden. * @method $this addMonthsNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this addMonthNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden. * @method $this subMonthsNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this subMonthNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden. * @method $this addDays(int $value = 1) Add days (the $value count passed in) to the instance (using date interval). * @method $this addDay() Add one day to the instance (using date interval). * @method $this subDays(int $value = 1) Sub days (the $value count passed in) to the instance (using date interval). * @method $this subDay() Sub one day to the instance (using date interval). * @method $this addHours(int $value = 1) Add hours (the $value count passed in) to the instance (using date interval). * @method $this addHour() Add one hour to the instance (using date interval). * @method $this subHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using date interval). * @method $this subHour() Sub one hour to the instance (using date interval). * @method $this addMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using date interval). * @method $this addMinute() Add one minute to the instance (using date interval). * @method $this subMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using date interval). * @method $this subMinute() Sub one minute to the instance (using date interval). * @method $this addSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using date interval). * @method $this addSecond() Add one second to the instance (using date interval). * @method $this subSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using date interval). * @method $this subSecond() Sub one second to the instance (using date interval). * @method $this addMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval). * @method $this addMilli() Add one millisecond to the instance (using date interval). * @method $this subMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval). * @method $this subMilli() Sub one millisecond to the instance (using date interval). * @method $this addMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval). * @method $this addMillisecond() Add one millisecond to the instance (using date interval). * @method $this subMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval). * @method $this subMillisecond() Sub one millisecond to the instance (using date interval). * @method $this addMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval). * @method $this addMicro() Add one microsecond to the instance (using date interval). * @method $this subMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval). * @method $this subMicro() Sub one microsecond to the instance (using date interval). * @method $this addMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval). * @method $this addMicrosecond() Add one microsecond to the instance (using date interval). * @method $this subMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval). * @method $this subMicrosecond() Sub one microsecond to the instance (using date interval). * @method $this addMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval). * @method $this addMillennium() Add one millennium to the instance (using date interval). * @method $this subMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval). * @method $this subMillennium() Sub one millennium to the instance (using date interval). * @method $this addMillenniaWithOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method $this addMillenniumWithOverflow() Add one millennium to the instance (using date interval) with overflow explicitly allowed. * @method $this subMillenniaWithOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method $this subMillenniumWithOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly allowed. * @method $this addMillenniaWithoutOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this addMillenniumWithoutOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method $this subMillenniaWithoutOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this subMillenniumWithoutOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method $this addMillenniaWithNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this addMillenniumWithNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method $this subMillenniaWithNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this subMillenniumWithNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method $this addMillenniaNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this addMillenniumNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method $this subMillenniaNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this subMillenniumNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method $this addCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval). * @method $this addCentury() Add one century to the instance (using date interval). * @method $this subCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval). * @method $this subCentury() Sub one century to the instance (using date interval). * @method $this addCenturiesWithOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method $this addCenturyWithOverflow() Add one century to the instance (using date interval) with overflow explicitly allowed. * @method $this subCenturiesWithOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method $this subCenturyWithOverflow() Sub one century to the instance (using date interval) with overflow explicitly allowed. * @method $this addCenturiesWithoutOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this addCenturyWithoutOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden. * @method $this subCenturiesWithoutOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this subCenturyWithoutOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden. * @method $this addCenturiesWithNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this addCenturyWithNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden. * @method $this subCenturiesWithNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this subCenturyWithNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden. * @method $this addCenturiesNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this addCenturyNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden. * @method $this subCenturiesNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this subCenturyNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden. * @method $this addDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval). * @method $this addDecade() Add one decade to the instance (using date interval). * @method $this subDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval). * @method $this subDecade() Sub one decade to the instance (using date interval). * @method $this addDecadesWithOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method $this addDecadeWithOverflow() Add one decade to the instance (using date interval) with overflow explicitly allowed. * @method $this subDecadesWithOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method $this subDecadeWithOverflow() Sub one decade to the instance (using date interval) with overflow explicitly allowed. * @method $this addDecadesWithoutOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this addDecadeWithoutOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden. * @method $this subDecadesWithoutOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this subDecadeWithoutOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden. * @method $this addDecadesWithNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this addDecadeWithNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden. * @method $this subDecadesWithNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this subDecadeWithNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden. * @method $this addDecadesNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this addDecadeNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden. * @method $this subDecadesNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this subDecadeNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden. * @method $this addQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval). * @method $this addQuarter() Add one quarter to the instance (using date interval). * @method $this subQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval). * @method $this subQuarter() Sub one quarter to the instance (using date interval). * @method $this addQuartersWithOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method $this addQuarterWithOverflow() Add one quarter to the instance (using date interval) with overflow explicitly allowed. * @method $this subQuartersWithOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method $this subQuarterWithOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly allowed. * @method $this addQuartersWithoutOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this addQuarterWithoutOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method $this subQuartersWithoutOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this subQuarterWithoutOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method $this addQuartersWithNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this addQuarterWithNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method $this subQuartersWithNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this subQuarterWithNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method $this addQuartersNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this addQuarterNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method $this subQuartersNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method $this subQuarterNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method $this addWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using date interval). * @method $this addWeek() Add one week to the instance (using date interval). * @method $this subWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using date interval). * @method $this subWeek() Sub one week to the instance (using date interval). * @method $this addWeekdays(int $value = 1) Add weekdays (the $value count passed in) to the instance (using date interval). * @method $this addWeekday() Add one weekday to the instance (using date interval). * @method $this subWeekdays(int $value = 1) Sub weekdays (the $value count passed in) to the instance (using date interval). * @method $this subWeekday() Sub one weekday to the instance (using date interval). * @method $this addRealMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp). * @method $this addRealMicro() Add one microsecond to the instance (using timestamp). * @method $this subRealMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp). * @method $this subRealMicro() Sub one microsecond to the instance (using timestamp). * @method CarbonPeriod microsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given. * @method $this addRealMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp). * @method $this addRealMicrosecond() Add one microsecond to the instance (using timestamp). * @method $this subRealMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp). * @method $this subRealMicrosecond() Sub one microsecond to the instance (using timestamp). * @method CarbonPeriod microsecondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given. * @method $this addRealMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp). * @method $this addRealMilli() Add one millisecond to the instance (using timestamp). * @method $this subRealMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp). * @method $this subRealMilli() Sub one millisecond to the instance (using timestamp). * @method CarbonPeriod millisUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given. * @method $this addRealMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp). * @method $this addRealMillisecond() Add one millisecond to the instance (using timestamp). * @method $this subRealMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp). * @method $this subRealMillisecond() Sub one millisecond to the instance (using timestamp). * @method CarbonPeriod millisecondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given. * @method $this addRealSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using timestamp). * @method $this addRealSecond() Add one second to the instance (using timestamp). * @method $this subRealSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using timestamp). * @method $this subRealSecond() Sub one second to the instance (using timestamp). * @method CarbonPeriod secondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each second or every X seconds if a factor is given. * @method $this addRealMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using timestamp). * @method $this addRealMinute() Add one minute to the instance (using timestamp). * @method $this subRealMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using timestamp). * @method $this subRealMinute() Sub one minute to the instance (using timestamp). * @method CarbonPeriod minutesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each minute or every X minutes if a factor is given. * @method $this addRealHours(int $value = 1) Add hours (the $value count passed in) to the instance (using timestamp). * @method $this addRealHour() Add one hour to the instance (using timestamp). * @method $this subRealHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using timestamp). * @method $this subRealHour() Sub one hour to the instance (using timestamp). * @method CarbonPeriod hoursUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each hour or every X hours if a factor is given. * @method $this addRealDays(int $value = 1) Add days (the $value count passed in) to the instance (using timestamp). * @method $this addRealDay() Add one day to the instance (using timestamp). * @method $this subRealDays(int $value = 1) Sub days (the $value count passed in) to the instance (using timestamp). * @method $this subRealDay() Sub one day to the instance (using timestamp). * @method CarbonPeriod daysUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each day or every X days if a factor is given. * @method $this addRealWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using timestamp). * @method $this addRealWeek() Add one week to the instance (using timestamp). * @method $this subRealWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using timestamp). * @method $this subRealWeek() Sub one week to the instance (using timestamp). * @method CarbonPeriod weeksUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each week or every X weeks if a factor is given. * @method $this addRealMonths(int $value = 1) Add months (the $value count passed in) to the instance (using timestamp). * @method $this addRealMonth() Add one month to the instance (using timestamp). * @method $this subRealMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using timestamp). * @method $this subRealMonth() Sub one month to the instance (using timestamp). * @method CarbonPeriod monthsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each month or every X months if a factor is given. * @method $this addRealQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using timestamp). * @method $this addRealQuarter() Add one quarter to the instance (using timestamp). * @method $this subRealQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using timestamp). * @method $this subRealQuarter() Sub one quarter to the instance (using timestamp). * @method CarbonPeriod quartersUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each quarter or every X quarters if a factor is given. * @method $this addRealYears(int $value = 1) Add years (the $value count passed in) to the instance (using timestamp). * @method $this addRealYear() Add one year to the instance (using timestamp). * @method $this subRealYears(int $value = 1) Sub years (the $value count passed in) to the instance (using timestamp). * @method $this subRealYear() Sub one year to the instance (using timestamp). * @method CarbonPeriod yearsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each year or every X years if a factor is given. * @method $this addRealDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using timestamp). * @method $this addRealDecade() Add one decade to the instance (using timestamp). * @method $this subRealDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using timestamp). * @method $this subRealDecade() Sub one decade to the instance (using timestamp). * @method CarbonPeriod decadesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each decade or every X decades if a factor is given. * @method $this addRealCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using timestamp). * @method $this addRealCentury() Add one century to the instance (using timestamp). * @method $this subRealCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using timestamp). * @method $this subRealCentury() Sub one century to the instance (using timestamp). * @method CarbonPeriod centuriesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each century or every X centuries if a factor is given. * @method $this addRealMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using timestamp). * @method $this addRealMillennium() Add one millennium to the instance (using timestamp). * @method $this subRealMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using timestamp). * @method $this subRealMillennium() Sub one millennium to the instance (using timestamp). * @method CarbonPeriod millenniaUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millennium or every X millennia if a factor is given. * @method $this roundYear(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function. * @method $this roundYears(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function. * @method $this floorYear(float $precision = 1) Truncate the current instance year with given precision. * @method $this floorYears(float $precision = 1) Truncate the current instance year with given precision. * @method $this ceilYear(float $precision = 1) Ceil the current instance year with given precision. * @method $this ceilYears(float $precision = 1) Ceil the current instance year with given precision. * @method $this roundMonth(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function. * @method $this roundMonths(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function. * @method $this floorMonth(float $precision = 1) Truncate the current instance month with given precision. * @method $this floorMonths(float $precision = 1) Truncate the current instance month with given precision. * @method $this ceilMonth(float $precision = 1) Ceil the current instance month with given precision. * @method $this ceilMonths(float $precision = 1) Ceil the current instance month with given precision. * @method $this roundDay(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function. * @method $this roundDays(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function. * @method $this floorDay(float $precision = 1) Truncate the current instance day with given precision. * @method $this floorDays(float $precision = 1) Truncate the current instance day with given precision. * @method $this ceilDay(float $precision = 1) Ceil the current instance day with given precision. * @method $this ceilDays(float $precision = 1) Ceil the current instance day with given precision. * @method $this roundHour(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function. * @method $this roundHours(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function. * @method $this floorHour(float $precision = 1) Truncate the current instance hour with given precision. * @method $this floorHours(float $precision = 1) Truncate the current instance hour with given precision. * @method $this ceilHour(float $precision = 1) Ceil the current instance hour with given precision. * @method $this ceilHours(float $precision = 1) Ceil the current instance hour with given precision. * @method $this roundMinute(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function. * @method $this roundMinutes(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function. * @method $this floorMinute(float $precision = 1) Truncate the current instance minute with given precision. * @method $this floorMinutes(float $precision = 1) Truncate the current instance minute with given precision. * @method $this ceilMinute(float $precision = 1) Ceil the current instance minute with given precision. * @method $this ceilMinutes(float $precision = 1) Ceil the current instance minute with given precision. * @method $this roundSecond(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function. * @method $this roundSeconds(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function. * @method $this floorSecond(float $precision = 1) Truncate the current instance second with given precision. * @method $this floorSeconds(float $precision = 1) Truncate the current instance second with given precision. * @method $this ceilSecond(float $precision = 1) Ceil the current instance second with given precision. * @method $this ceilSeconds(float $precision = 1) Ceil the current instance second with given precision. * @method $this roundMillennium(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function. * @method $this roundMillennia(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function. * @method $this floorMillennium(float $precision = 1) Truncate the current instance millennium with given precision. * @method $this floorMillennia(float $precision = 1) Truncate the current instance millennium with given precision. * @method $this ceilMillennium(float $precision = 1) Ceil the current instance millennium with given precision. * @method $this ceilMillennia(float $precision = 1) Ceil the current instance millennium with given precision. * @method $this roundCentury(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function. * @method $this roundCenturies(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function. * @method $this floorCentury(float $precision = 1) Truncate the current instance century with given precision. * @method $this floorCenturies(float $precision = 1) Truncate the current instance century with given precision. * @method $this ceilCentury(float $precision = 1) Ceil the current instance century with given precision. * @method $this ceilCenturies(float $precision = 1) Ceil the current instance century with given precision. * @method $this roundDecade(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function. * @method $this roundDecades(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function. * @method $this floorDecade(float $precision = 1) Truncate the current instance decade with given precision. * @method $this floorDecades(float $precision = 1) Truncate the current instance decade with given precision. * @method $this ceilDecade(float $precision = 1) Ceil the current instance decade with given precision. * @method $this ceilDecades(float $precision = 1) Ceil the current instance decade with given precision. * @method $this roundQuarter(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function. * @method $this roundQuarters(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function. * @method $this floorQuarter(float $precision = 1) Truncate the current instance quarter with given precision. * @method $this floorQuarters(float $precision = 1) Truncate the current instance quarter with given precision. * @method $this ceilQuarter(float $precision = 1) Ceil the current instance quarter with given precision. * @method $this ceilQuarters(float $precision = 1) Ceil the current instance quarter with given precision. * @method $this roundMillisecond(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function. * @method $this roundMilliseconds(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function. * @method $this floorMillisecond(float $precision = 1) Truncate the current instance millisecond with given precision. * @method $this floorMilliseconds(float $precision = 1) Truncate the current instance millisecond with given precision. * @method $this ceilMillisecond(float $precision = 1) Ceil the current instance millisecond with given precision. * @method $this ceilMilliseconds(float $precision = 1) Ceil the current instance millisecond with given precision. * @method $this roundMicrosecond(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function. * @method $this roundMicroseconds(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function. * @method $this floorMicrosecond(float $precision = 1) Truncate the current instance microsecond with given precision. * @method $this floorMicroseconds(float $precision = 1) Truncate the current instance microsecond with given precision. * @method $this ceilMicrosecond(float $precision = 1) Ceil the current instance microsecond with given precision. * @method $this ceilMicroseconds(float $precision = 1) Ceil the current instance microsecond with given precision. * @method string shortAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string longAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string shortRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string longRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string shortRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string longRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string shortRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string longRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method static static|false createFromFormat(string $format, string $time, DateTimeZone|string|false|null $timezone = null) Parse a string into a new Carbon object according to the specified format. * @method static static __set_state(array $array) https://php.net/manual/en/datetime.set-state.php * * </autodoc> */ class Carbon extends DateTime implements CarbonInterface { use Date; /** * Returns true if the current class/instance is mutable. * * @return bool */ public static function isMutable() { return true; } } PK������<1Z_V����*��Carbon/Exceptions/InvalidTypeException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use InvalidArgumentException as BaseInvalidArgumentException; class InvalidTypeException extends BaseInvalidArgumentException implements InvalidArgumentException { // } PK������<1ZDQ����.��Carbon/Exceptions/InvalidTimeZoneException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use InvalidArgumentException as BaseInvalidArgumentException; class InvalidTimeZoneException extends BaseInvalidArgumentException implements InvalidArgumentException { // } PK������<1Z�����.��Carbon/Exceptions/InvalidIntervalException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use InvalidArgumentException as BaseInvalidArgumentException; class InvalidIntervalException extends BaseInvalidArgumentException implements InvalidArgumentException { // } PK������<1Ze6-M����.��Carbon/Exceptions/BadFluentSetterException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use BadMethodCallException as BaseBadMethodCallException; use Throwable; class BadFluentSetterException extends BaseBadMethodCallException implements BadMethodCallException { /** * The setter. * * @var string */ protected $setter; /** * Constructor. * * @param string $setter * @param int $code * @param Throwable|null $previous */ public function __construct($setter, $code = 0, ?Throwable $previous = null) { $this->setter = $setter; parent::__construct(\sprintf("Unknown fluent setter '%s'", $setter), $code, $previous); } /** * Get the setter. * * @return string */ public function getSetter(): string { return $this->setter; } } PK������<1Za()��)��3��Carbon/Exceptions/BadFluentConstructorException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use BadMethodCallException as BaseBadMethodCallException; use Throwable; class BadFluentConstructorException extends BaseBadMethodCallException implements BadMethodCallException { /** * The method. * * @var string */ protected $method; /** * Constructor. * * @param string $method * @param int $code * @param Throwable|null $previous */ public function __construct($method, $code = 0, ?Throwable $previous = null) { $this->method = $method; parent::__construct(\sprintf("Unknown fluent constructor '%s'.", $method), $code, $previous); } /** * Get the method. * * @return string */ public function getMethod(): string { return $this->method; } } PK������<1ZMDg@����)��Carbon/Exceptions/ParseErrorException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use InvalidArgumentException as BaseInvalidArgumentException; use Throwable; class ParseErrorException extends BaseInvalidArgumentException implements InvalidArgumentException { /** * The expected. * * @var string */ protected $expected; /** * The actual. * * @var string */ protected $actual; /** * The help message. * * @var string */ protected $help; /** * Constructor. * * @param string $expected * @param string $actual * @param int $code * @param Throwable|null $previous */ public function __construct($expected, $actual, $help = '', $code = 0, ?Throwable $previous = null) { $this->expected = $expected; $this->actual = $actual; $this->help = $help; $actual = $actual === '' ? 'data is missing' : "get '$actual'"; parent::__construct(trim("Format expected $expected but $actual\n$help"), $code, $previous); } /** * Get the expected. * * @return string */ public function getExpected(): string { return $this->expected; } /** * Get the actual. * * @return string */ public function getActual(): string { return $this->actual; } /** * Get the help message. * * @return string */ public function getHelp(): string { return $this->help; } } PK������<1ZP󋺷����0��Carbon/Exceptions/UnitNotConfiguredException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use Throwable; class UnitNotConfiguredException extends UnitException { /** * The unit. * * @var string */ protected $unit; /** * Constructor. * * @param string $unit * @param int $code * @param Throwable|null $previous */ public function __construct($unit, $code = 0, ?Throwable $previous = null) { $this->unit = $unit; parent::__construct("Unit $unit have no configuration to get total from other units.", $code, $previous); } /** * Get the unit. * * @return string */ public function getUnit(): string { return $this->unit; } } PK������<1Z)&��&����Carbon/Exceptions/Exception.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; interface Exception { // } PK������<1ZQ{����,��Carbon/Exceptions/EndLessPeriodException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use RuntimeException as BaseRuntimeException; final class EndLessPeriodException extends BaseRuntimeException implements RuntimeException { // } PK������<1Z����,��Carbon/Exceptions/UnknownSetterException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use InvalidArgumentException as BaseInvalidArgumentException; use Throwable; class UnknownSetterException extends BaseInvalidArgumentException implements BadMethodCallException { /** * The setter. * * @var string */ protected $setter; /** * Constructor. * * @param string $setter setter name * @param int $code * @param Throwable|null $previous */ public function __construct($setter, $code = 0, ?Throwable $previous = null) { $this->setter = $setter; parent::__construct("Unknown setter '$setter'", $code, $previous); } /** * Get the setter. * * @return string */ public function getSetter(): string { return $this->setter; } } PK������<1Z&AhEQ��Q��*��Carbon/Exceptions/InvalidDateException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use InvalidArgumentException as BaseInvalidArgumentException; use Throwable; class InvalidDateException extends BaseInvalidArgumentException implements InvalidArgumentException { /** * The invalid field. * * @var string */ private $field; /** * The invalid value. * * @var mixed */ private $value; /** * Constructor. * * @param string $field * @param mixed $value * @param int $code * @param Throwable|null $previous */ public function __construct($field, $value, $code = 0, ?Throwable $previous = null) { $this->field = $field; $this->value = $value; parent::__construct($field.' : '.$value.' is not a valid value.', $code, $previous); } /** * Get the invalid field. * * @return string */ public function getField() { return $this->field; } /** * Get the invalid value. * * @return mixed */ public function getValue() { return $this->value; } } PK������<1ZLb����#��Carbon/Exceptions/UnitException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use InvalidArgumentException as BaseInvalidArgumentException; class UnitException extends BaseInvalidArgumentException implements InvalidArgumentException { // } PK������<1ZY9����)��Carbon/Exceptions/OutOfRangeException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use InvalidArgumentException as BaseInvalidArgumentException; use Throwable; // This will extends OutOfRangeException instead of InvalidArgumentException since 3.0.0 // use OutOfRangeException as BaseOutOfRangeException; class OutOfRangeException extends BaseInvalidArgumentException implements InvalidArgumentException { /** * The unit or name of the value. * * @var string */ private $unit; /** * The range minimum. * * @var mixed */ private $min; /** * The range maximum. * * @var mixed */ private $max; /** * The invalid value. * * @var mixed */ private $value; /** * Constructor. * * @param string $unit * @param mixed $min * @param mixed $max * @param mixed $value * @param int $code * @param Throwable|null $previous */ public function __construct($unit, $min, $max, $value, $code = 0, ?Throwable $previous = null) { $this->unit = $unit; $this->min = $min; $this->max = $max; $this->value = $value; parent::__construct("$unit must be between $min and $max, $value given", $code, $previous); } /** * @return mixed */ public function getMax() { return $this->max; } /** * @return mixed */ public function getMin() { return $this->min; } /** * @return mixed */ public function getUnit() { return $this->unit; } /** * @return mixed */ public function getValue() { return $this->value; } } PK������<1ZoF����,��Carbon/Exceptions/UnknownGetterException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use InvalidArgumentException as BaseInvalidArgumentException; use Throwable; class UnknownGetterException extends BaseInvalidArgumentException implements InvalidArgumentException { /** * The getter. * * @var string */ protected $getter; /** * Constructor. * * @param string $getter getter name * @param int $code * @param Throwable|null $previous */ public function __construct($getter, $code = 0, ?Throwable $previous = null) { $this->getter = $getter; parent::__construct("Unknown getter '$getter'", $code, $previous); } /** * Get the getter. * * @return string */ public function getGetter(): string { return $this->getter; } } PK������<1ZF ����*��Carbon/Exceptions/UnreachableException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use RuntimeException as BaseRuntimeException; class UnreachableException extends BaseRuntimeException implements RuntimeException { // } PK������<1ZJ0o����.��Carbon/Exceptions/NotACarbonClassException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use Carbon\CarbonInterface; use InvalidArgumentException as BaseInvalidArgumentException; use Throwable; class NotACarbonClassException extends BaseInvalidArgumentException implements InvalidArgumentException { /** * The className. * * @var string */ protected $className; /** * Constructor. * * @param string $className * @param int $code * @param Throwable|null $previous */ public function __construct($className, $code = 0, ?Throwable $previous = null) { $this->className = $className; parent::__construct(\sprintf('Given class does not implement %s: %s', CarbonInterface::class, $className), $code, $previous); } /** * Get the className. * * @return string */ public function getClassName(): string { return $this->className; } } PK������<1Z'?����5��Carbon/Exceptions/InvalidPeriodParameterException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use InvalidArgumentException as BaseInvalidArgumentException; class InvalidPeriodParameterException extends BaseInvalidArgumentException implements InvalidArgumentException { // } PK������<1Zd8O?��?��&��Carbon/Exceptions/RuntimeException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; interface RuntimeException extends Exception { // } PK������<1Z1����0��Carbon/Exceptions/InvalidPeriodDateException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use InvalidArgumentException as BaseInvalidArgumentException; class InvalidPeriodDateException extends BaseInvalidArgumentException implements InvalidArgumentException { // } PK������<1ZFE��E��,��Carbon/Exceptions/BadMethodCallException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; interface BadMethodCallException extends Exception { // } PK������<1Z,G����*��Carbon/Exceptions/UnknownUnitException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use Throwable; class UnknownUnitException extends UnitException { /** * The unit. * * @var string */ protected $unit; /** * Constructor. * * @param string $unit * @param int $code * @param Throwable|null $previous */ public function __construct($unit, $code = 0, ?Throwable $previous = null) { $this->unit = $unit; parent::__construct("Unknown unit '$unit'.", $code, $previous); } /** * Get the unit. * * @return string */ public function getUnit(): string { return $this->unit; } } PK������<1ZUI 1G��G��.��Carbon/Exceptions/InvalidArgumentException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; interface InvalidArgumentException extends Exception { // } PK������<1Z(����*��Carbon/Exceptions/InvalidCastException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use InvalidArgumentException as BaseInvalidArgumentException; class InvalidCastException extends BaseInvalidArgumentException implements InvalidArgumentException { // } PK������<1Z����,��Carbon/Exceptions/InvalidFormatException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use InvalidArgumentException as BaseInvalidArgumentException; class InvalidFormatException extends BaseInvalidArgumentException implements InvalidArgumentException { // } PK������<1Z"����0��Carbon/Exceptions/BadComparisonUnitException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use Throwable; class BadComparisonUnitException extends UnitException { /** * The unit. * * @var string */ protected $unit; /** * Constructor. * * @param string $unit * @param int $code * @param Throwable|null $previous */ public function __construct($unit, $code = 0, ?Throwable $previous = null) { $this->unit = $unit; parent::__construct("Bad comparison unit: '$unit'", $code, $previous); } /** * Get the unit. * * @return string */ public function getUnit(): string { return $this->unit; } } PK������<1ZF �� ��,��Carbon/Exceptions/UnknownMethodException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use BadMethodCallException as BaseBadMethodCallException; use Throwable; class UnknownMethodException extends BaseBadMethodCallException implements BadMethodCallException { /** * The method. * * @var string */ protected $method; /** * Constructor. * * @param string $method * @param int $code * @param Throwable|null $previous */ public function __construct($method, $code = 0, ?Throwable $previous = null) { $this->method = $method; parent::__construct("Method $method does not exist.", $code, $previous); } /** * Get the method. * * @return string */ public function getMethod(): string { return $this->method; } } PK������<1ZK����-��Carbon/Exceptions/NotLocaleAwareException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use InvalidArgumentException as BaseInvalidArgumentException; use Throwable; class NotLocaleAwareException extends BaseInvalidArgumentException implements InvalidArgumentException { /** * Constructor. * * @param mixed $object * @param int $code * @param Throwable|null $previous */ public function __construct($object, $code = 0, ?Throwable $previous = null) { $dump = \is_object($object) ? \get_class($object) : \gettype($object); parent::__construct("$dump does neither implements Symfony\Contracts\Translation\LocaleAwareInterface nor getLocale() method.", $code, $previous); } } PK������<1ZA*����)��Carbon/Exceptions/NotAPeriodException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use InvalidArgumentException as BaseInvalidArgumentException; class NotAPeriodException extends BaseInvalidArgumentException implements InvalidArgumentException { // } PK������<1Zq����(��Carbon/Exceptions/ImmutableException.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Exceptions; use RuntimeException as BaseRuntimeException; use Throwable; class ImmutableException extends BaseRuntimeException implements RuntimeException { /** * The value. * * @var string */ protected $value; /** * Constructor. * * @param string $value the immutable type/value * @param int $code * @param Throwable|null $previous */ public function __construct($value, $code = 0, ?Throwable $previous = null) { $this->value = $value; parent::__construct("$value is immutable.", $code, $previous); } /** * Get the value. * * @return string */ public function getValue(): string { return $this->value; } } PK������<1Zakm������Carbon/Factory.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon; use Closure; use DateTimeInterface; use ReflectionMethod; /** * A factory to generate Carbon instances with common settings. * * <autodoc generated by `composer phpdoc`> * * @method bool canBeCreatedFromFormat($date, $format) Checks if the (date)time string is in a given format and valid to create a * new instance. * @method Carbon|false create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $tz = null) Create a new Carbon instance from a specific date and time. * If any of $year, $month or $day are set to null their now() values will * be used. * If $hour is null it will be set to its now() value and the default * values for $minute and $second will be their now() values. * If $hour is not null then the default values for $minute and $second * will be 0. * @method Carbon createFromDate($year = null, $month = null, $day = null, $tz = null) Create a Carbon instance from just a date. The time portion is set to now. * @method Carbon|false createFromFormat($format, $time, $tz = null) Create a Carbon instance from a specific format. * @method Carbon|false createFromIsoFormat($format, $time, $tz = null, $locale = 'en', $translator = null) Create a Carbon instance from a specific ISO format (same replacements as ->isoFormat()). * @method Carbon|false createFromLocaleFormat($format, $locale, $time, $tz = null) Create a Carbon instance from a specific format and a string in a given language. * @method Carbon|false createFromLocaleIsoFormat($format, $locale, $time, $tz = null) Create a Carbon instance from a specific ISO format and a string in a given language. * @method Carbon createFromTime($hour = 0, $minute = 0, $second = 0, $tz = null) Create a Carbon instance from just a time. The date portion is set to today. * @method Carbon createFromTimeString($time, $tz = null) Create a Carbon instance from a time string. The date portion is set to today. * @method Carbon createFromTimestamp($timestamp, $tz = null) Create a Carbon instance from a timestamp and set the timezone (use default one if not specified). * Timestamp input can be given as int, float or a string containing one or more numbers. * @method Carbon createFromTimestampMs($timestamp, $tz = null) Create a Carbon instance from a timestamp in milliseconds. * Timestamp input can be given as int, float or a string containing one or more numbers. * @method Carbon createFromTimestampMsUTC($timestamp) Create a Carbon instance from a timestamp in milliseconds. * Timestamp input can be given as int, float or a string containing one or more numbers. * @method Carbon createFromTimestampUTC($timestamp) Create a Carbon instance from an timestamp keeping the timezone to UTC. * Timestamp input can be given as int, float or a string containing one or more numbers. * @method Carbon createMidnightDate($year = null, $month = null, $day = null, $tz = null) Create a Carbon instance from just a date. The time portion is set to midnight. * @method Carbon|false createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null) Create a new safe Carbon instance from a specific date and time. * If any of $year, $month or $day are set to null their now() values will * be used. * If $hour is null it will be set to its now() value and the default * values for $minute and $second will be their now() values. * If $hour is not null then the default values for $minute and $second * will be 0. * If one of the set values is not valid, an InvalidDateException * will be thrown. * @method CarbonInterface createStrict(?int $year = 0, ?int $month = 1, ?int $day = 1, ?int $hour = 0, ?int $minute = 0, ?int $second = 0, $tz = null) Create a new Carbon instance from a specific date and time using strict validation. * @method Carbon disableHumanDiffOption($humanDiffOption) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * @method Carbon enableHumanDiffOption($humanDiffOption) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * @method mixed executeWithLocale($locale, $func) Set the current locale to the given, execute the passed function, reset the locale to previous one, * then return the result of the closure (or null if the closure was void). * @method Carbon fromSerialized($value) Create an instance from a serialized string. * @method void genericMacro($macro, $priority = 0) Register a custom macro. * @method array getAvailableLocales() Returns the list of internally available locales and already loaded custom locales. * (It will ignore custom translator dynamic loading.) * @method Language[] getAvailableLocalesInfo() Returns list of Language object for each available locale. This object allow you to get the ISO name, native * name, region and variant of the locale. * @method array getDays() Get the days of the week * @method string|null getFallbackLocale() Get the fallback locale. * @method array getFormatsToIsoReplacements() List of replacements from date() format to isoFormat(). * @method int getHumanDiffOptions() Return default humanDiff() options (merged flags as integer). * @method array getIsoUnits() Returns list of locale units for ISO formatting. * @method array getLastErrors() {@inheritdoc} * @method string getLocale() Get the current translator locale. * @method callable|null getMacro($name) Get the raw callable macro registered globally for a given name. * @method int getMidDayAt() get midday/noon hour * @method Closure|Carbon getTestNow() Get the Carbon instance (real or mock) to be returned when a "now" * instance is created. * @method string getTimeFormatByPrecision($unitPrecision) Return a format from H:i to H:i:s.u according to given unit precision. * @method string getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null) Returns raw translation message for a given key. * @method \Symfony\Component\Translation\TranslatorInterface getTranslator() Get the default translator instance in use. * @method int getWeekEndsAt() Get the last day of week * @method int getWeekStartsAt() Get the first day of week * @method array getWeekendDays() Get weekend days * @method bool hasFormat($date, $format) Checks if the (date)time string is in a given format. * @method bool hasFormatWithModifiers($date, $format) Checks if the (date)time string is in a given format. * @method bool hasMacro($name) Checks if macro is registered globally. * @method bool hasRelativeKeywords($time) Determine if a time string will produce a relative date. * @method bool hasTestNow() Determine if there is a valid test instance set. A valid test instance * is anything that is not null. * @method Carbon instance($date) Create a Carbon instance from a DateTime one. * @method bool isImmutable() Returns true if the current class/instance is immutable. * @method bool isModifiableUnit($unit) Returns true if a property can be changed via setter. * @method bool isMutable() Returns true if the current class/instance is mutable. * @method bool isStrictModeEnabled() Returns true if the strict mode is globally in use, false else. * (It can be overridden in specific instances.) * @method bool localeHasDiffOneDayWords($locale) Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow). * Support is considered enabled if the 3 words are translated in the given locale. * @method bool localeHasDiffSyntax($locale) Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after). * Support is considered enabled if the 4 sentences are translated in the given locale. * @method bool localeHasDiffTwoDayWords($locale) Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow). * Support is considered enabled if the 2 words are translated in the given locale. * @method bool localeHasPeriodSyntax($locale) Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X). * Support is considered enabled if the 4 sentences are translated in the given locale. * @method bool localeHasShortUnits($locale) Returns true if the given locale is internally supported and has short-units support. * Support is considered enabled if either year, day or hour has a short variant translated. * @method void macro($name, $macro) Register a custom macro. * @method Carbon|null make($var) Make a Carbon instance from given variable if possible. * Always return a new instance. Parse only strings and only these likely to be dates (skip intervals * and recurrences). Throw an exception for invalid format, but otherwise return null. * @method Carbon maxValue() Create a Carbon instance for the greatest supported date. * @method Carbon minValue() Create a Carbon instance for the lowest supported date. * @method void mixin($mixin) Mix another object into the class. * @method Carbon now($tz = null) Get a Carbon instance for the current date and time. * @method Carbon parse($time = null, $tz = null) Create a carbon instance from a string. * This is an alias for the constructor that allows better fluent syntax * as it allows you to do Carbon::parse('Monday next week')->fn() rather * than (new Carbon('Monday next week'))->fn(). * @method Carbon parseFromLocale($time, $locale = null, $tz = null) Create a carbon instance from a localized string (in French, Japanese, Arabic, etc.). * @method string pluralUnit(string $unit) Returns standardized plural of a given singular/plural unit name (in English). * @method Carbon|false rawCreateFromFormat($format, $time, $tz = null) Create a Carbon instance from a specific format. * @method Carbon rawParse($time = null, $tz = null) Create a carbon instance from a string. * This is an alias for the constructor that allows better fluent syntax * as it allows you to do Carbon::parse('Monday next week')->fn() rather * than (new Carbon('Monday next week'))->fn(). * @method Carbon resetMacros() Remove all macros and generic macros. * @method void resetMonthsOverflow() @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants * are available for quarters, years, decade, centuries, millennia (singular and plural forms). * @method void resetToStringFormat() Reset the format used to the default when type juggling a Carbon instance to a string * @method void resetYearsOverflow() @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants * are available for quarters, years, decade, centuries, millennia (singular and plural forms). * @method void serializeUsing($callback) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather transform Carbon object before the serialization. * JSON serialize all Carbon instances using the given callback. * @method Carbon setFallbackLocale($locale) Set the fallback locale. * @method Carbon setHumanDiffOptions($humanDiffOptions) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * @method bool setLocale($locale) Set the current translator locale and indicate if the source locale file exists. * Pass 'auto' as locale to use closest language from the current LC_TIME locale. * @method void setMidDayAt($hour) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather consider mid-day is always 12pm, then if you need to test if it's an other * hour, test it explicitly: * $date->format('G') == 13 * or to set explicitly to a given hour: * $date->setTime(13, 0, 0, 0) * Set midday/noon hour * @method Carbon setTestNow($testNow = null) Set a Carbon instance (real or mock) to be returned when a "now" * instance is created. The provided instance will be returned * specifically under the following conditions: * - A call to the static now() method, ex. Carbon::now() * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null) * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now') * - When a string containing the desired time is passed to Carbon::parse(). * Note the timezone parameter was left out of the examples above and * has no affect as the mock value will be returned regardless of its value. * Only the moment is mocked with setTestNow(), the timezone will still be the one passed * as parameter of date_default_timezone_get() as a fallback (see setTestNowAndTimezone()). * To clear the test instance call this method using the default * parameter of null. * /!\ Use this method for unit tests only. * @method Carbon setTestNowAndTimezone($testNow = null, $tz = null) Set a Carbon instance (real or mock) to be returned when a "now" * instance is created. The provided instance will be returned * specifically under the following conditions: * - A call to the static now() method, ex. Carbon::now() * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null) * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now') * - When a string containing the desired time is passed to Carbon::parse(). * It will also align default timezone (e.g. call date_default_timezone_set()) with * the second argument or if null, with the timezone of the given date object. * To clear the test instance call this method using the default * parameter of null. * /!\ Use this method for unit tests only. * @method void setToStringFormat($format) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather let Carbon object being cast to string with DEFAULT_TO_STRING_FORMAT, and * use other method or custom format passed to format() method if you need to dump another string * format. * Set the default format used when type juggling a Carbon instance to a string. * @method void setTranslator(TranslatorInterface $translator) Set the default translator instance to use. * @method Carbon setUtf8($utf8) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use UTF-8 language packages on every machine. * Set if UTF8 will be used for localized date/time. * @method void setWeekEndsAt($day) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * Use $weekStartsAt optional parameter instead when using startOfWeek, floorWeek, ceilWeek * or roundWeek method. You can also use the 'first_day_of_week' locale setting to change the * start of week according to current locale selected and implicitly the end of week. * Set the last day of week * @method void setWeekStartsAt($day) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * Use $weekEndsAt optional parameter instead when using endOfWeek method. You can also use the * 'first_day_of_week' locale setting to change the start of week according to current locale * selected and implicitly the end of week. * Set the first day of week * @method void setWeekendDays($days) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather consider week-end is always saturday and sunday, and if you have some custom * week-end days to handle, give to those days an other name and create a macro for them: * ``` * Carbon::macro('isDayOff', function ($date) { * return $date->isSunday() || $date->isMonday(); * }); * Carbon::macro('isNotDayOff', function ($date) { * return !$date->isDayOff(); * }); * if ($someDate->isDayOff()) ... * if ($someDate->isNotDayOff()) ... * // Add 5 not-off days * $count = 5; * while ($someDate->isDayOff() || ($count-- > 0)) { * $someDate->addDay(); * } * ``` * Set weekend days * @method bool shouldOverflowMonths() Get the month overflow global behavior (can be overridden in specific instances). * @method bool shouldOverflowYears() Get the month overflow global behavior (can be overridden in specific instances). * @method string singularUnit(string $unit) Returns standardized singular of a given singular/plural unit name (in English). * @method Carbon today($tz = null) Create a Carbon instance for today. * @method Carbon tomorrow($tz = null) Create a Carbon instance for tomorrow. * @method string translateTimeString($timeString, $from = null, $to = null, $mode = CarbonInterface::TRANSLATE_ALL) Translate a time string from a locale to an other. * @method string translateWith(TranslatorInterface $translator, string $key, array $parameters = [], $number = null) Translate using translation string or callback available. * @method void useMonthsOverflow($monthsOverflow = true) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants * are available for quarters, years, decade, centuries, millennia (singular and plural forms). * @method Carbon useStrictMode($strictModeEnabled = true) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * @method void useYearsOverflow($yearsOverflow = true) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants * are available for quarters, years, decade, centuries, millennia (singular and plural forms). * @method mixed withTestNow($testNow, $callback) Temporarily sets a static date to be used within the callback. * Using setTestNow to set the date, executing the callback, then * clearing the test instance. * /!\ Use this method for unit tests only. * @method Carbon yesterday($tz = null) Create a Carbon instance for yesterday. * * </autodoc> */ class Factory { protected $className = Carbon::class; protected $settings = []; public function __construct(array $settings = [], ?string $className = null) { if ($className) { $this->className = $className; } $this->settings = $settings; } public function getClassName() { return $this->className; } public function setClassName(string $className) { $this->className = $className; return $this; } public function className(?string $className = null) { return $className === null ? $this->getClassName() : $this->setClassName($className); } public function getSettings() { return $this->settings; } public function setSettings(array $settings) { $this->settings = $settings; return $this; } public function settings(?array $settings = null) { return $settings === null ? $this->getSettings() : $this->setSettings($settings); } public function mergeSettings(array $settings) { $this->settings = array_merge($this->settings, $settings); return $this; } public function __call($name, $arguments) { $method = new ReflectionMethod($this->className, $name); $settings = $this->settings; if ($settings && isset($settings['timezone'])) { $tzParameters = array_filter($method->getParameters(), function ($parameter) { return \in_array($parameter->getName(), ['tz', 'timezone'], true); }); if (isset($arguments[0]) && \in_array($name, ['instance', 'make', 'create', 'parse'], true)) { if ($arguments[0] instanceof DateTimeInterface) { $settings['innerTimezone'] = $settings['timezone']; } elseif (\is_string($arguments[0]) && date_parse($arguments[0])['is_localtime']) { unset($settings['timezone'], $settings['innerTimezone']); } } elseif (\count($tzParameters)) { array_splice($arguments, key($tzParameters), 0, [$settings['timezone']]); unset($settings['timezone']); } } $result = $this->className::$name(...$arguments); return $result instanceof CarbonInterface && !empty($settings) ? $result->settings($settings) : $result; } } PK������<1Z"|'��'��(��Carbon/TranslatorStrongTypeInterface.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon; use Symfony\Component\Translation\MessageCatalogueInterface; /** * Mark translator using strong type from symfony/translation >= 6. */ interface TranslatorStrongTypeInterface { public function getFromCatalogue(MessageCatalogueInterface $catalogue, string $id, string $domain = 'messages'); } PK������<1Z ""��""����Carbon/CarbonTimeZone.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon; use Carbon\Exceptions\InvalidCastException; use Carbon\Exceptions\InvalidTimeZoneException; use DateTimeInterface; use DateTimeZone; use Throwable; class CarbonTimeZone extends DateTimeZone { public function __construct($timezone = null) { parent::__construct(static::getDateTimeZoneNameFromMixed($timezone)); } protected static function parseNumericTimezone($timezone) { if ($timezone <= -100 || $timezone >= 100) { throw new InvalidTimeZoneException('Absolute timezone offset cannot be greater than 100.'); } return ($timezone >= 0 ? '+' : '').ltrim($timezone, '+').':00'; } protected static function getDateTimeZoneNameFromMixed($timezone) { if ($timezone === null) { return date_default_timezone_get(); } if (\is_string($timezone)) { $timezone = preg_replace('/^\s*([+-]\d+)(\d{2})\s*$/', '$1:$2', $timezone); } if (is_numeric($timezone)) { return static::parseNumericTimezone($timezone); } return $timezone; } protected static function getDateTimeZoneFromName(&$name) { return @timezone_open($name = (string) static::getDateTimeZoneNameFromMixed($name)); } /** * Cast the current instance into the given class. * * @param string $className The $className::instance() method will be called to cast the current object. * * @return DateTimeZone */ public function cast(string $className) { if (!method_exists($className, 'instance')) { if (is_a($className, DateTimeZone::class, true)) { return new $className($this->getName()); } throw new InvalidCastException("$className has not the instance() method needed to cast the date."); } return $className::instance($this); } /** * Create a CarbonTimeZone from mixed input. * * @param DateTimeZone|string|int|null $object original value to get CarbonTimeZone from it. * @param DateTimeZone|string|int|null $objectDump dump of the object for error messages. * * @throws InvalidTimeZoneException * * @return false|static */ public static function instance($object = null, $objectDump = null) { $tz = $object; if ($tz instanceof static) { return $tz; } if ($tz === null) { return new static(); } if (!$tz instanceof DateTimeZone) { $tz = static::getDateTimeZoneFromName($object); } if ($tz !== false) { return new static($tz->getName()); } if (Carbon::isStrictModeEnabled()) { throw new InvalidTimeZoneException('Unknown or bad timezone ('.($objectDump ?: $object).')'); } return false; } /** * Returns abbreviated name of the current timezone according to DST setting. * * @param bool $dst * * @return string */ public function getAbbreviatedName($dst = false) { $name = $this->getName(); foreach ($this->listAbbreviations() as $abbreviation => $zones) { foreach ($zones as $zone) { if ($zone['timezone_id'] === $name && $zone['dst'] == $dst) { return $abbreviation; } } } return 'unknown'; } /** * @alias getAbbreviatedName * * Returns abbreviated name of the current timezone according to DST setting. * * @param bool $dst * * @return string */ public function getAbbr($dst = false) { return $this->getAbbreviatedName($dst); } /** * Get the offset as string "sHH:MM" (such as "+00:00" or "-12:30"). * * @param DateTimeInterface|null $date * * @return string */ public function toOffsetName(?DateTimeInterface $date = null) { return static::getOffsetNameFromMinuteOffset( $this->getOffset($date ?: Carbon::now($this)) / 60 ); } /** * Returns a new CarbonTimeZone object using the offset string instead of region string. * * @param DateTimeInterface|null $date * * @return CarbonTimeZone */ public function toOffsetTimeZone(?DateTimeInterface $date = null) { return new static($this->toOffsetName($date)); } /** * Returns the first region string (such as "America/Toronto") that matches the current timezone or * false if no match is found. * * @see timezone_name_from_abbr native PHP function. * * @param DateTimeInterface|null $date * @param int $isDst * * @return string|false */ public function toRegionName(?DateTimeInterface $date = null, $isDst = 1) { $name = $this->getName(); $firstChar = substr($name, 0, 1); if ($firstChar !== '+' && $firstChar !== '-') { return $name; } $date = $date ?: Carbon::now($this); // Integer construction no longer supported since PHP 8 // @codeCoverageIgnoreStart try { $offset = @$this->getOffset($date) ?: 0; } catch (Throwable $e) { $offset = 0; } // @codeCoverageIgnoreEnd $name = @timezone_name_from_abbr('', $offset, $isDst); if ($name) { return $name; } foreach (timezone_identifiers_list() as $timezone) { if (Carbon::instance($date)->tz($timezone)->getOffset() === $offset) { return $timezone; } } return false; } /** * Returns a new CarbonTimeZone object using the region string instead of offset string. * * @param DateTimeInterface|null $date * * @return CarbonTimeZone|false */ public function toRegionTimeZone(?DateTimeInterface $date = null) { $tz = $this->toRegionName($date); if ($tz !== false) { return new static($tz); } if (Carbon::isStrictModeEnabled()) { throw new InvalidTimeZoneException('Unknown timezone for offset '.$this->getOffset($date ?: Carbon::now($this)).' seconds.'); } return false; } /** * Cast to string (get timezone name). * * @return string */ public function __toString() { return $this->getName(); } /** * Return the type number: * * Type 1; A UTC offset, such as -0300 * Type 2; A timezone abbreviation, such as GMT * Type 3: A timezone identifier, such as Europe/London */ public function getType(): int { return preg_match('/"timezone_type";i:(\d)/', serialize($this), $match) ? (int) $match[1] : 3; } /** * Create a CarbonTimeZone from mixed input. * * @param DateTimeZone|string|int|null $object * * @return false|static */ public static function create($object = null) { return static::instance($object); } /** * Create a CarbonTimeZone from int/float hour offset. * * @param float $hourOffset number of hour of the timezone shift (can be decimal). * * @return false|static */ public static function createFromHourOffset(float $hourOffset) { return static::createFromMinuteOffset($hourOffset * Carbon::MINUTES_PER_HOUR); } /** * Create a CarbonTimeZone from int/float minute offset. * * @param float $minuteOffset number of total minutes of the timezone shift. * * @return false|static */ public static function createFromMinuteOffset(float $minuteOffset) { return static::instance(static::getOffsetNameFromMinuteOffset($minuteOffset)); } /** * Convert a total minutes offset into a standardized timezone offset string. * * @param float $minutes number of total minutes of the timezone shift. * * @return string */ public static function getOffsetNameFromMinuteOffset(float $minutes): string { $minutes = round($minutes); $unsignedMinutes = abs($minutes); return ($minutes < 0 ? '-' : '+'). str_pad((string) floor($unsignedMinutes / 60), 2, '0', STR_PAD_LEFT). ':'. str_pad((string) ($unsignedMinutes % 60), 2, '0', STR_PAD_LEFT); } } PK������<1Z s6$��$����Carbon/PHPStan/MacroScanner.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\PHPStan; use Carbon\CarbonInterface; use PHPStan\Reflection\ReflectionProvider; use ReflectionClass; use ReflectionException; final class MacroScanner { /** * @var \PHPStan\Reflection\ReflectionProvider */ private $reflectionProvider; /** * MacroScanner constructor. * * @param \PHPStan\Reflection\ReflectionProvider $reflectionProvider */ public function __construct(ReflectionProvider $reflectionProvider) { $this->reflectionProvider = $reflectionProvider; } /** * Return true if the given pair class-method is a Carbon macro. * * @param class-string $className * @param string $methodName * * @return bool */ public function hasMethod(string $className, string $methodName): bool { $classReflection = $this->reflectionProvider->getClass($className); if ( $classReflection->getName() !== CarbonInterface::class && !$classReflection->isSubclassOf(CarbonInterface::class) ) { return false; } return \is_callable([$className, 'hasMacro']) && $className::hasMacro($methodName); } /** * Return the Macro for a given pair class-method. * * @param class-string $className * @param string $methodName * * @throws ReflectionException * * @return Macro */ public function getMethod(string $className, string $methodName): Macro { $reflectionClass = new ReflectionClass($className); $property = $reflectionClass->getProperty('globalMacros'); $property->setAccessible(true); $macro = $property->getValue()[$methodName]; return new Macro( $className, $methodName, $macro ); } } PK������<1Zlq~ �� ��!��Carbon/PHPStan/MacroExtension.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\PHPStan; use PHPStan\Reflection\Assertions; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\MethodsClassReflectionExtension; use PHPStan\Reflection\Php\PhpMethodReflectionFactory; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Type\TypehintHelper; /** * Class MacroExtension. * * @codeCoverageIgnore Pure PHPStan wrapper. */ final class MacroExtension implements MethodsClassReflectionExtension { /** * @var PhpMethodReflectionFactory */ protected $methodReflectionFactory; /** * @var MacroScanner */ protected $scanner; /** * Extension constructor. * * @param PhpMethodReflectionFactory $methodReflectionFactory * @param ReflectionProvider $reflectionProvider */ public function __construct( PhpMethodReflectionFactory $methodReflectionFactory, ReflectionProvider $reflectionProvider ) { $this->scanner = new MacroScanner($reflectionProvider); $this->methodReflectionFactory = $methodReflectionFactory; } /** * {@inheritdoc} */ public function hasMethod(ClassReflection $classReflection, string $methodName): bool { return $this->scanner->hasMethod($classReflection->getName(), $methodName); } /** * {@inheritdoc} */ public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection { $builtinMacro = $this->scanner->getMethod($classReflection->getName(), $methodName); $supportAssertions = class_exists(Assertions::class); return $this->methodReflectionFactory->create( $classReflection, null, $builtinMacro, $classReflection->getActiveTemplateTypeMap(), [], TypehintHelper::decideTypeFromReflection($builtinMacro->getReturnType()), null, null, $builtinMacro->isDeprecated()->yes(), $builtinMacro->isInternal(), $builtinMacro->isFinal(), $supportAssertions ? null : $builtinMacro->getDocComment(), $supportAssertions ? Assertions::createEmpty() : null, null, $builtinMacro->getDocComment(), [] ); } } PK������<1ZR-������Carbon/PHPStan/Macro.phpnu�W+A��������<?php declare(strict_types=1); /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\PHPStan; use PHPStan\BetterReflection\Reflection\Adapter; use PHPStan\Reflection\Php\BuiltinMethodReflection; use ReflectionMethod; $method = new ReflectionMethod(BuiltinMethodReflection::class, 'getReflection'); require $method->hasReturnType() && $method->getReturnType()->getName() === Adapter\ReflectionMethod::class ? __DIR__.'/../../../lazy/Carbon/PHPStan/AbstractMacroStatic.php' : __DIR__.'/../../../lazy/Carbon/PHPStan/AbstractMacroBuiltin.php'; $method = new ReflectionMethod(BuiltinMethodReflection::class, 'getFileName'); require $method->hasReturnType() ? __DIR__.'/../../../lazy/Carbon/PHPStan/MacroStrongType.php' : __DIR__.'/../../../lazy/Carbon/PHPStan/MacroWeakType.php'; final class Macro extends LazyMacro { } PK������<1Zc���� ��Carbon/PHPStan/AbstractMacro.phpnu�W+A��������<?php declare(strict_types=1); /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\PHPStan; use Closure; use InvalidArgumentException; use PHPStan\BetterReflection\Reflection\Adapter\ReflectionParameter as AdapterReflectionParameter; use PHPStan\BetterReflection\Reflection\Adapter\ReflectionType as AdapterReflectionType; use PHPStan\BetterReflection\Reflection\ReflectionClass as BetterReflectionClass; use PHPStan\BetterReflection\Reflection\ReflectionFunction as BetterReflectionFunction; use PHPStan\BetterReflection\Reflection\ReflectionParameter as BetterReflectionParameter; use PHPStan\Reflection\Php\BuiltinMethodReflection; use PHPStan\TrinaryLogic; use ReflectionClass; use ReflectionFunction; use ReflectionMethod; use ReflectionParameter; use ReflectionType; use stdClass; use Throwable; abstract class AbstractMacro implements BuiltinMethodReflection { /** * The reflection function/method. * * @var ReflectionFunction|ReflectionMethod */ protected $reflectionFunction; /** * The class name. * * @var class-string */ private $className; /** * The method name. * * @var string */ private $methodName; /** * The parameters. * * @var ReflectionParameter[] */ private $parameters; /** * The is static. * * @var bool */ private $static = false; /** * Macro constructor. * * @param class-string $className * @param string $methodName * @param callable $macro */ public function __construct(string $className, string $methodName, $macro) { $this->className = $className; $this->methodName = $methodName; $rawReflectionFunction = \is_array($macro) ? new ReflectionMethod($macro[0], $macro[1]) : new ReflectionFunction($macro); $this->reflectionFunction = self::hasModernParser() ? $this->getReflectionFunction($macro) : $rawReflectionFunction; // @codeCoverageIgnore $this->parameters = array_map( function ($parameter) { if ($parameter instanceof BetterReflectionParameter) { return new AdapterReflectionParameter($parameter); } return $parameter; // @codeCoverageIgnore }, $this->reflectionFunction->getParameters() ); if ($rawReflectionFunction->isClosure()) { try { $closure = $rawReflectionFunction->getClosure(); $boundClosure = Closure::bind($closure, new stdClass()); $this->static = (!$boundClosure || (new ReflectionFunction($boundClosure))->getClosureThis() === null); } catch (Throwable $e) { $this->static = true; } } } private function getReflectionFunction($spec) { if (\is_array($spec) && \count($spec) === 2 && \is_string($spec[1])) { \assert($spec[1] !== ''); if (\is_object($spec[0])) { return BetterReflectionClass::createFromInstance($spec[0]) ->getMethod($spec[1]); } return BetterReflectionClass::createFromName($spec[0]) ->getMethod($spec[1]); } if (\is_string($spec)) { return BetterReflectionFunction::createFromName($spec); } if ($spec instanceof Closure) { return BetterReflectionFunction::createFromClosure($spec); } throw new InvalidArgumentException('Could not create reflection from the spec given'); // @codeCoverageIgnore } /** * {@inheritdoc} */ public function getDeclaringClass(): ReflectionClass { return new ReflectionClass($this->className); } /** * {@inheritdoc} */ public function isPrivate(): bool { return false; } /** * {@inheritdoc} */ public function isPublic(): bool { return true; } /** * {@inheritdoc} */ public function isFinal(): bool { return false; } /** * {@inheritdoc} */ public function isInternal(): bool { return false; } /** * {@inheritdoc} */ public function isAbstract(): bool { return false; } /** * {@inheritdoc} */ public function isStatic(): bool { return $this->static; } /** * {@inheritdoc} */ public function getDocComment(): ?string { return $this->reflectionFunction->getDocComment() ?: null; } /** * {@inheritdoc} */ public function getName(): string { return $this->methodName; } /** * {@inheritdoc} */ public function getParameters(): array { return $this->parameters; } /** * {@inheritdoc} */ public function getReturnType(): ?ReflectionType { $type = $this->reflectionFunction->getReturnType(); if ($type instanceof ReflectionType) { return $type; // @codeCoverageIgnore } return self::adaptType($type); } /** * {@inheritdoc} */ public function isDeprecated(): TrinaryLogic { return TrinaryLogic::createFromBoolean( $this->reflectionFunction->isDeprecated() || preg_match('/@deprecated/i', $this->getDocComment() ?: '') ); } /** * {@inheritdoc} */ public function isVariadic(): bool { return $this->reflectionFunction->isVariadic(); } /** * {@inheritdoc} */ public function getPrototype(): BuiltinMethodReflection { return $this; } public function getTentativeReturnType(): ?ReflectionType { return null; } public function returnsByReference(): TrinaryLogic { return TrinaryLogic::createNo(); } private static function adaptType($type) { $method = method_exists(AdapterReflectionType::class, 'fromTypeOrNull') ? 'fromTypeOrNull' : 'fromReturnTypeOrNull'; // @codeCoverageIgnore return AdapterReflectionType::$method($type); } private static function hasModernParser(): bool { static $modernParser = null; if ($modernParser !== null) { return $modernParser; } $modernParser = method_exists(AdapterReflectionType::class, 'fromTypeOrNull'); return $modernParser; } } PK������<1Zh '��'����Carbon/FactoryImmutable.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon; use Closure; use DateTimeImmutable; use DateTimeZone; use Psr\Clock\ClockInterface; /** * A factory to generate CarbonImmutable instances with common settings. * * <autodoc generated by `composer phpdoc`> * * @method bool canBeCreatedFromFormat($date, $format) Checks if the (date)time string is in a given format and valid to create a * new instance. * @method CarbonImmutable|false create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $tz = null) Create a new Carbon instance from a specific date and time. * If any of $year, $month or $day are set to null their now() values will * be used. * If $hour is null it will be set to its now() value and the default * values for $minute and $second will be their now() values. * If $hour is not null then the default values for $minute and $second * will be 0. * @method CarbonImmutable createFromDate($year = null, $month = null, $day = null, $tz = null) Create a Carbon instance from just a date. The time portion is set to now. * @method CarbonImmutable|false createFromFormat($format, $time, $tz = null) Create a Carbon instance from a specific format. * @method CarbonImmutable|false createFromIsoFormat($format, $time, $tz = null, $locale = 'en', $translator = null) Create a Carbon instance from a specific ISO format (same replacements as ->isoFormat()). * @method CarbonImmutable|false createFromLocaleFormat($format, $locale, $time, $tz = null) Create a Carbon instance from a specific format and a string in a given language. * @method CarbonImmutable|false createFromLocaleIsoFormat($format, $locale, $time, $tz = null) Create a Carbon instance from a specific ISO format and a string in a given language. * @method CarbonImmutable createFromTime($hour = 0, $minute = 0, $second = 0, $tz = null) Create a Carbon instance from just a time. The date portion is set to today. * @method CarbonImmutable createFromTimeString($time, $tz = null) Create a Carbon instance from a time string. The date portion is set to today. * @method CarbonImmutable createFromTimestamp($timestamp, $tz = null) Create a Carbon instance from a timestamp and set the timezone (use default one if not specified). * Timestamp input can be given as int, float or a string containing one or more numbers. * @method CarbonImmutable createFromTimestampMs($timestamp, $tz = null) Create a Carbon instance from a timestamp in milliseconds. * Timestamp input can be given as int, float or a string containing one or more numbers. * @method CarbonImmutable createFromTimestampMsUTC($timestamp) Create a Carbon instance from a timestamp in milliseconds. * Timestamp input can be given as int, float or a string containing one or more numbers. * @method CarbonImmutable createFromTimestampUTC($timestamp) Create a Carbon instance from an timestamp keeping the timezone to UTC. * Timestamp input can be given as int, float or a string containing one or more numbers. * @method CarbonImmutable createMidnightDate($year = null, $month = null, $day = null, $tz = null) Create a Carbon instance from just a date. The time portion is set to midnight. * @method CarbonImmutable|false createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null) Create a new safe Carbon instance from a specific date and time. * If any of $year, $month or $day are set to null their now() values will * be used. * If $hour is null it will be set to its now() value and the default * values for $minute and $second will be their now() values. * If $hour is not null then the default values for $minute and $second * will be 0. * If one of the set values is not valid, an InvalidDateException * will be thrown. * @method CarbonInterface createStrict(?int $year = 0, ?int $month = 1, ?int $day = 1, ?int $hour = 0, ?int $minute = 0, ?int $second = 0, $tz = null) Create a new Carbon instance from a specific date and time using strict validation. * @method CarbonImmutable disableHumanDiffOption($humanDiffOption) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * @method CarbonImmutable enableHumanDiffOption($humanDiffOption) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * @method mixed executeWithLocale($locale, $func) Set the current locale to the given, execute the passed function, reset the locale to previous one, * then return the result of the closure (or null if the closure was void). * @method CarbonImmutable fromSerialized($value) Create an instance from a serialized string. * @method void genericMacro($macro, $priority = 0) Register a custom macro. * @method array getAvailableLocales() Returns the list of internally available locales and already loaded custom locales. * (It will ignore custom translator dynamic loading.) * @method Language[] getAvailableLocalesInfo() Returns list of Language object for each available locale. This object allow you to get the ISO name, native * name, region and variant of the locale. * @method array getDays() Get the days of the week * @method string|null getFallbackLocale() Get the fallback locale. * @method array getFormatsToIsoReplacements() List of replacements from date() format to isoFormat(). * @method int getHumanDiffOptions() Return default humanDiff() options (merged flags as integer). * @method array getIsoUnits() Returns list of locale units for ISO formatting. * @method array getLastErrors() {@inheritdoc} * @method string getLocale() Get the current translator locale. * @method callable|null getMacro($name) Get the raw callable macro registered globally for a given name. * @method int getMidDayAt() get midday/noon hour * @method Closure|CarbonImmutable getTestNow() Get the Carbon instance (real or mock) to be returned when a "now" * instance is created. * @method string getTimeFormatByPrecision($unitPrecision) Return a format from H:i to H:i:s.u according to given unit precision. * @method string getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null) Returns raw translation message for a given key. * @method \Symfony\Component\Translation\TranslatorInterface getTranslator() Get the default translator instance in use. * @method int getWeekEndsAt() Get the last day of week * @method int getWeekStartsAt() Get the first day of week * @method array getWeekendDays() Get weekend days * @method bool hasFormat($date, $format) Checks if the (date)time string is in a given format. * @method bool hasFormatWithModifiers($date, $format) Checks if the (date)time string is in a given format. * @method bool hasMacro($name) Checks if macro is registered globally. * @method bool hasRelativeKeywords($time) Determine if a time string will produce a relative date. * @method bool hasTestNow() Determine if there is a valid test instance set. A valid test instance * is anything that is not null. * @method CarbonImmutable instance($date) Create a Carbon instance from a DateTime one. * @method bool isImmutable() Returns true if the current class/instance is immutable. * @method bool isModifiableUnit($unit) Returns true if a property can be changed via setter. * @method bool isMutable() Returns true if the current class/instance is mutable. * @method bool isStrictModeEnabled() Returns true if the strict mode is globally in use, false else. * (It can be overridden in specific instances.) * @method bool localeHasDiffOneDayWords($locale) Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow). * Support is considered enabled if the 3 words are translated in the given locale. * @method bool localeHasDiffSyntax($locale) Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after). * Support is considered enabled if the 4 sentences are translated in the given locale. * @method bool localeHasDiffTwoDayWords($locale) Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow). * Support is considered enabled if the 2 words are translated in the given locale. * @method bool localeHasPeriodSyntax($locale) Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X). * Support is considered enabled if the 4 sentences are translated in the given locale. * @method bool localeHasShortUnits($locale) Returns true if the given locale is internally supported and has short-units support. * Support is considered enabled if either year, day or hour has a short variant translated. * @method void macro($name, $macro) Register a custom macro. * @method CarbonImmutable|null make($var) Make a Carbon instance from given variable if possible. * Always return a new instance. Parse only strings and only these likely to be dates (skip intervals * and recurrences). Throw an exception for invalid format, but otherwise return null. * @method CarbonImmutable maxValue() Create a Carbon instance for the greatest supported date. * @method CarbonImmutable minValue() Create a Carbon instance for the lowest supported date. * @method void mixin($mixin) Mix another object into the class. * @method CarbonImmutable parse($time = null, $tz = null) Create a carbon instance from a string. * This is an alias for the constructor that allows better fluent syntax * as it allows you to do Carbon::parse('Monday next week')->fn() rather * than (new Carbon('Monday next week'))->fn(). * @method CarbonImmutable parseFromLocale($time, $locale = null, $tz = null) Create a carbon instance from a localized string (in French, Japanese, Arabic, etc.). * @method string pluralUnit(string $unit) Returns standardized plural of a given singular/plural unit name (in English). * @method CarbonImmutable|false rawCreateFromFormat($format, $time, $tz = null) Create a Carbon instance from a specific format. * @method CarbonImmutable rawParse($time = null, $tz = null) Create a carbon instance from a string. * This is an alias for the constructor that allows better fluent syntax * as it allows you to do Carbon::parse('Monday next week')->fn() rather * than (new Carbon('Monday next week'))->fn(). * @method CarbonImmutable resetMacros() Remove all macros and generic macros. * @method void resetMonthsOverflow() @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants * are available for quarters, years, decade, centuries, millennia (singular and plural forms). * @method void resetToStringFormat() Reset the format used to the default when type juggling a Carbon instance to a string * @method void resetYearsOverflow() @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants * are available for quarters, years, decade, centuries, millennia (singular and plural forms). * @method void serializeUsing($callback) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather transform Carbon object before the serialization. * JSON serialize all Carbon instances using the given callback. * @method CarbonImmutable setFallbackLocale($locale) Set the fallback locale. * @method CarbonImmutable setHumanDiffOptions($humanDiffOptions) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * @method bool setLocale($locale) Set the current translator locale and indicate if the source locale file exists. * Pass 'auto' as locale to use closest language from the current LC_TIME locale. * @method void setMidDayAt($hour) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather consider mid-day is always 12pm, then if you need to test if it's an other * hour, test it explicitly: * $date->format('G') == 13 * or to set explicitly to a given hour: * $date->setTime(13, 0, 0, 0) * Set midday/noon hour * @method CarbonImmutable setTestNow($testNow = null) Set a Carbon instance (real or mock) to be returned when a "now" * instance is created. The provided instance will be returned * specifically under the following conditions: * - A call to the static now() method, ex. Carbon::now() * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null) * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now') * - When a string containing the desired time is passed to Carbon::parse(). * Note the timezone parameter was left out of the examples above and * has no affect as the mock value will be returned regardless of its value. * Only the moment is mocked with setTestNow(), the timezone will still be the one passed * as parameter of date_default_timezone_get() as a fallback (see setTestNowAndTimezone()). * To clear the test instance call this method using the default * parameter of null. * /!\ Use this method for unit tests only. * @method CarbonImmutable setTestNowAndTimezone($testNow = null, $tz = null) Set a Carbon instance (real or mock) to be returned when a "now" * instance is created. The provided instance will be returned * specifically under the following conditions: * - A call to the static now() method, ex. Carbon::now() * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null) * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now') * - When a string containing the desired time is passed to Carbon::parse(). * It will also align default timezone (e.g. call date_default_timezone_set()) with * the second argument or if null, with the timezone of the given date object. * To clear the test instance call this method using the default * parameter of null. * /!\ Use this method for unit tests only. * @method void setToStringFormat($format) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather let Carbon object being cast to string with DEFAULT_TO_STRING_FORMAT, and * use other method or custom format passed to format() method if you need to dump another string * format. * Set the default format used when type juggling a Carbon instance to a string. * @method void setTranslator(TranslatorInterface $translator) Set the default translator instance to use. * @method CarbonImmutable setUtf8($utf8) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use UTF-8 language packages on every machine. * Set if UTF8 will be used for localized date/time. * @method void setWeekEndsAt($day) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * Use $weekStartsAt optional parameter instead when using startOfWeek, floorWeek, ceilWeek * or roundWeek method. You can also use the 'first_day_of_week' locale setting to change the * start of week according to current locale selected and implicitly the end of week. * Set the last day of week * @method void setWeekStartsAt($day) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * Use $weekEndsAt optional parameter instead when using endOfWeek method. You can also use the * 'first_day_of_week' locale setting to change the start of week according to current locale * selected and implicitly the end of week. * Set the first day of week * @method void setWeekendDays($days) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather consider week-end is always saturday and sunday, and if you have some custom * week-end days to handle, give to those days an other name and create a macro for them: * ``` * Carbon::macro('isDayOff', function ($date) { * return $date->isSunday() || $date->isMonday(); * }); * Carbon::macro('isNotDayOff', function ($date) { * return !$date->isDayOff(); * }); * if ($someDate->isDayOff()) ... * if ($someDate->isNotDayOff()) ... * // Add 5 not-off days * $count = 5; * while ($someDate->isDayOff() || ($count-- > 0)) { * $someDate->addDay(); * } * ``` * Set weekend days * @method bool shouldOverflowMonths() Get the month overflow global behavior (can be overridden in specific instances). * @method bool shouldOverflowYears() Get the month overflow global behavior (can be overridden in specific instances). * @method string singularUnit(string $unit) Returns standardized singular of a given singular/plural unit name (in English). * @method CarbonImmutable today($tz = null) Create a Carbon instance for today. * @method CarbonImmutable tomorrow($tz = null) Create a Carbon instance for tomorrow. * @method string translateTimeString($timeString, $from = null, $to = null, $mode = CarbonInterface::TRANSLATE_ALL) Translate a time string from a locale to an other. * @method string translateWith(TranslatorInterface $translator, string $key, array $parameters = [], $number = null) Translate using translation string or callback available. * @method void useMonthsOverflow($monthsOverflow = true) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants * are available for quarters, years, decade, centuries, millennia (singular and plural forms). * @method CarbonImmutable useStrictMode($strictModeEnabled = true) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * @method void useYearsOverflow($yearsOverflow = true) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants * are available for quarters, years, decade, centuries, millennia (singular and plural forms). * @method mixed withTestNow($testNow, $callback) Temporarily sets a static date to be used within the callback. * Using setTestNow to set the date, executing the callback, then * clearing the test instance. * /!\ Use this method for unit tests only. * @method CarbonImmutable yesterday($tz = null) Create a Carbon instance for yesterday. * * </autodoc> */ class FactoryImmutable extends Factory implements ClockInterface { protected $className = CarbonImmutable::class; /** * Get a Carbon instance for the current date and time. * * @param DateTimeZone|string|int|null $tz * * @return CarbonImmutable */ public function now($tz = null): DateTimeImmutable { $className = $this->className; return new $className(null, $tz); } } PK������<1Z Z:����Carbon/CarbonInterface.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon; use BadMethodCallException; use Carbon\Exceptions\BadComparisonUnitException; use Carbon\Exceptions\ImmutableException; use Carbon\Exceptions\InvalidDateException; use Carbon\Exceptions\InvalidFormatException; use Carbon\Exceptions\UnknownGetterException; use Carbon\Exceptions\UnknownMethodException; use Carbon\Exceptions\UnknownSetterException; use Closure; use DateInterval; use DateTime; use DateTimeImmutable; use DateTimeInterface; use DateTimeZone; use JsonSerializable; use ReflectionException; use ReturnTypeWillChange; use Symfony\Component\Translation\TranslatorInterface; use Throwable; /** * Common interface for Carbon and CarbonImmutable. * * <autodoc generated by `composer phpdoc`> * * @property int $year * @property int $yearIso * @property int $month * @property int $day * @property int $hour * @property int $minute * @property int $second * @property int $micro * @property int $microsecond * @property int|float|string $timestamp seconds since the Unix Epoch * @property string $englishDayOfWeek the day of week in English * @property string $shortEnglishDayOfWeek the abbreviated day of week in English * @property string $englishMonth the month in English * @property string $shortEnglishMonth the abbreviated month in English * @property int $milliseconds * @property int $millisecond * @property int $milli * @property int $week 1 through 53 * @property int $isoWeek 1 through 53 * @property int $weekYear year according to week format * @property int $isoWeekYear year according to ISO week format * @property int $dayOfYear 1 through 366 * @property int $age does a diffInYears() with default parameters * @property int $offset the timezone offset in seconds from UTC * @property int $offsetMinutes the timezone offset in minutes from UTC * @property int $offsetHours the timezone offset in hours from UTC * @property CarbonTimeZone $timezone the current timezone * @property CarbonTimeZone $tz alias of $timezone * @property-read int $dayOfWeek 0 (for Sunday) through 6 (for Saturday) * @property-read int $dayOfWeekIso 1 (for Monday) through 7 (for Sunday) * @property-read int $weekOfYear ISO-8601 week number of year, weeks starting on Monday * @property-read int $daysInMonth number of days in the given month * @property-read string $latinMeridiem "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark) * @property-read string $latinUpperMeridiem "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark) * @property-read string $timezoneAbbreviatedName the current timezone abbreviated name * @property-read string $tzAbbrName alias of $timezoneAbbreviatedName * @property-read string $dayName long name of weekday translated according to Carbon locale, in english if no translation available for current language * @property-read string $shortDayName short name of weekday translated according to Carbon locale, in english if no translation available for current language * @property-read string $minDayName very short name of weekday translated according to Carbon locale, in english if no translation available for current language * @property-read string $monthName long name of month translated according to Carbon locale, in english if no translation available for current language * @property-read string $shortMonthName short name of month translated according to Carbon locale, in english if no translation available for current language * @property-read string $meridiem lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language * @property-read string $upperMeridiem uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language * @property-read int $noZeroHour current hour from 1 to 24 * @property-read int $weeksInYear 51 through 53 * @property-read int $isoWeeksInYear 51 through 53 * @property-read int $weekOfMonth 1 through 5 * @property-read int $weekNumberInMonth 1 through 5 * @property-read int $firstWeekDay 0 through 6 * @property-read int $lastWeekDay 0 through 6 * @property-read int $daysInYear 365 or 366 * @property-read int $quarter the quarter of this instance, 1 - 4 * @property-read int $decade the decade of this instance * @property-read int $century the century of this instance * @property-read int $millennium the millennium of this instance * @property-read bool $dst daylight savings time indicator, true if DST, false otherwise * @property-read bool $local checks if the timezone is local, true if local, false otherwise * @property-read bool $utc checks if the timezone is UTC, true if UTC, false otherwise * @property-read string $timezoneName the current timezone name * @property-read string $tzName alias of $timezoneName * @property-read string $locale locale of the current instance * * @method bool isUtc() Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.) * @method bool isLocal() Check if the current instance has non-UTC timezone. * @method bool isValid() Check if the current instance is a valid date. * @method bool isDST() Check if the current instance is in a daylight saving time. * @method bool isSunday() Checks if the instance day is sunday. * @method bool isMonday() Checks if the instance day is monday. * @method bool isTuesday() Checks if the instance day is tuesday. * @method bool isWednesday() Checks if the instance day is wednesday. * @method bool isThursday() Checks if the instance day is thursday. * @method bool isFriday() Checks if the instance day is friday. * @method bool isSaturday() Checks if the instance day is saturday. * @method bool isSameYear(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same year as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentYear() Checks if the instance is in the same year as the current moment. * @method bool isNextYear() Checks if the instance is in the same year as the current moment next year. * @method bool isLastYear() Checks if the instance is in the same year as the current moment last year. * @method bool isSameWeek(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same week as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentWeek() Checks if the instance is in the same week as the current moment. * @method bool isNextWeek() Checks if the instance is in the same week as the current moment next week. * @method bool isLastWeek() Checks if the instance is in the same week as the current moment last week. * @method bool isSameDay(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same day as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentDay() Checks if the instance is in the same day as the current moment. * @method bool isNextDay() Checks if the instance is in the same day as the current moment next day. * @method bool isLastDay() Checks if the instance is in the same day as the current moment last day. * @method bool isSameHour(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same hour as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentHour() Checks if the instance is in the same hour as the current moment. * @method bool isNextHour() Checks if the instance is in the same hour as the current moment next hour. * @method bool isLastHour() Checks if the instance is in the same hour as the current moment last hour. * @method bool isSameMinute(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same minute as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentMinute() Checks if the instance is in the same minute as the current moment. * @method bool isNextMinute() Checks if the instance is in the same minute as the current moment next minute. * @method bool isLastMinute() Checks if the instance is in the same minute as the current moment last minute. * @method bool isSameSecond(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same second as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentSecond() Checks if the instance is in the same second as the current moment. * @method bool isNextSecond() Checks if the instance is in the same second as the current moment next second. * @method bool isLastSecond() Checks if the instance is in the same second as the current moment last second. * @method bool isSameMicro(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentMicro() Checks if the instance is in the same microsecond as the current moment. * @method bool isNextMicro() Checks if the instance is in the same microsecond as the current moment next microsecond. * @method bool isLastMicro() Checks if the instance is in the same microsecond as the current moment last microsecond. * @method bool isSameMicrosecond(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentMicrosecond() Checks if the instance is in the same microsecond as the current moment. * @method bool isNextMicrosecond() Checks if the instance is in the same microsecond as the current moment next microsecond. * @method bool isLastMicrosecond() Checks if the instance is in the same microsecond as the current moment last microsecond. * @method bool isCurrentMonth() Checks if the instance is in the same month as the current moment. * @method bool isNextMonth() Checks if the instance is in the same month as the current moment next month. * @method bool isLastMonth() Checks if the instance is in the same month as the current moment last month. * @method bool isCurrentQuarter() Checks if the instance is in the same quarter as the current moment. * @method bool isNextQuarter() Checks if the instance is in the same quarter as the current moment next quarter. * @method bool isLastQuarter() Checks if the instance is in the same quarter as the current moment last quarter. * @method bool isSameDecade(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same decade as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentDecade() Checks if the instance is in the same decade as the current moment. * @method bool isNextDecade() Checks if the instance is in the same decade as the current moment next decade. * @method bool isLastDecade() Checks if the instance is in the same decade as the current moment last decade. * @method bool isSameCentury(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same century as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentCentury() Checks if the instance is in the same century as the current moment. * @method bool isNextCentury() Checks if the instance is in the same century as the current moment next century. * @method bool isLastCentury() Checks if the instance is in the same century as the current moment last century. * @method bool isSameMillennium(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same millennium as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentMillennium() Checks if the instance is in the same millennium as the current moment. * @method bool isNextMillennium() Checks if the instance is in the same millennium as the current moment next millennium. * @method bool isLastMillennium() Checks if the instance is in the same millennium as the current moment last millennium. * @method CarbonInterface years(int $value) Set current instance year to the given value. * @method CarbonInterface year(int $value) Set current instance year to the given value. * @method CarbonInterface setYears(int $value) Set current instance year to the given value. * @method CarbonInterface setYear(int $value) Set current instance year to the given value. * @method CarbonInterface months(int $value) Set current instance month to the given value. * @method CarbonInterface month(int $value) Set current instance month to the given value. * @method CarbonInterface setMonths(int $value) Set current instance month to the given value. * @method CarbonInterface setMonth(int $value) Set current instance month to the given value. * @method CarbonInterface days(int $value) Set current instance day to the given value. * @method CarbonInterface day(int $value) Set current instance day to the given value. * @method CarbonInterface setDays(int $value) Set current instance day to the given value. * @method CarbonInterface setDay(int $value) Set current instance day to the given value. * @method CarbonInterface hours(int $value) Set current instance hour to the given value. * @method CarbonInterface hour(int $value) Set current instance hour to the given value. * @method CarbonInterface setHours(int $value) Set current instance hour to the given value. * @method CarbonInterface setHour(int $value) Set current instance hour to the given value. * @method CarbonInterface minutes(int $value) Set current instance minute to the given value. * @method CarbonInterface minute(int $value) Set current instance minute to the given value. * @method CarbonInterface setMinutes(int $value) Set current instance minute to the given value. * @method CarbonInterface setMinute(int $value) Set current instance minute to the given value. * @method CarbonInterface seconds(int $value) Set current instance second to the given value. * @method CarbonInterface second(int $value) Set current instance second to the given value. * @method CarbonInterface setSeconds(int $value) Set current instance second to the given value. * @method CarbonInterface setSecond(int $value) Set current instance second to the given value. * @method CarbonInterface millis(int $value) Set current instance millisecond to the given value. * @method CarbonInterface milli(int $value) Set current instance millisecond to the given value. * @method CarbonInterface setMillis(int $value) Set current instance millisecond to the given value. * @method CarbonInterface setMilli(int $value) Set current instance millisecond to the given value. * @method CarbonInterface milliseconds(int $value) Set current instance millisecond to the given value. * @method CarbonInterface millisecond(int $value) Set current instance millisecond to the given value. * @method CarbonInterface setMilliseconds(int $value) Set current instance millisecond to the given value. * @method CarbonInterface setMillisecond(int $value) Set current instance millisecond to the given value. * @method CarbonInterface micros(int $value) Set current instance microsecond to the given value. * @method CarbonInterface micro(int $value) Set current instance microsecond to the given value. * @method CarbonInterface setMicros(int $value) Set current instance microsecond to the given value. * @method CarbonInterface setMicro(int $value) Set current instance microsecond to the given value. * @method CarbonInterface microseconds(int $value) Set current instance microsecond to the given value. * @method CarbonInterface microsecond(int $value) Set current instance microsecond to the given value. * @method CarbonInterface setMicroseconds(int $value) Set current instance microsecond to the given value. * @method CarbonInterface setMicrosecond(int $value) Set current instance microsecond to the given value. * @method CarbonInterface addYears(int $value = 1) Add years (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addYear() Add one year to the instance (using date interval). * @method CarbonInterface subYears(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subYear() Sub one year to the instance (using date interval). * @method CarbonInterface addYearsWithOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addYearWithOverflow() Add one year to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subYearsWithOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subYearWithOverflow() Sub one year to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addYearsWithoutOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addYearWithoutOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subYearsWithoutOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subYearWithoutOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addYearsWithNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addYearWithNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subYearsWithNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subYearWithNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addYearsNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addYearNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subYearsNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subYearNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMonths(int $value = 1) Add months (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addMonth() Add one month to the instance (using date interval). * @method CarbonInterface subMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subMonth() Sub one month to the instance (using date interval). * @method CarbonInterface addMonthsWithOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addMonthWithOverflow() Add one month to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subMonthsWithOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subMonthWithOverflow() Sub one month to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addMonthsWithoutOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMonthWithoutOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMonthsWithoutOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMonthWithoutOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMonthsWithNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMonthWithNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMonthsWithNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMonthWithNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMonthsNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMonthNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMonthsNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMonthNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addDays(int $value = 1) Add days (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addDay() Add one day to the instance (using date interval). * @method CarbonInterface subDays(int $value = 1) Sub days (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subDay() Sub one day to the instance (using date interval). * @method CarbonInterface addHours(int $value = 1) Add hours (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addHour() Add one hour to the instance (using date interval). * @method CarbonInterface subHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subHour() Sub one hour to the instance (using date interval). * @method CarbonInterface addMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addMinute() Add one minute to the instance (using date interval). * @method CarbonInterface subMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subMinute() Sub one minute to the instance (using date interval). * @method CarbonInterface addSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addSecond() Add one second to the instance (using date interval). * @method CarbonInterface subSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subSecond() Sub one second to the instance (using date interval). * @method CarbonInterface addMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addMilli() Add one millisecond to the instance (using date interval). * @method CarbonInterface subMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subMilli() Sub one millisecond to the instance (using date interval). * @method CarbonInterface addMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addMillisecond() Add one millisecond to the instance (using date interval). * @method CarbonInterface subMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subMillisecond() Sub one millisecond to the instance (using date interval). * @method CarbonInterface addMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addMicro() Add one microsecond to the instance (using date interval). * @method CarbonInterface subMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subMicro() Sub one microsecond to the instance (using date interval). * @method CarbonInterface addMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addMicrosecond() Add one microsecond to the instance (using date interval). * @method CarbonInterface subMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subMicrosecond() Sub one microsecond to the instance (using date interval). * @method CarbonInterface addMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addMillennium() Add one millennium to the instance (using date interval). * @method CarbonInterface subMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subMillennium() Sub one millennium to the instance (using date interval). * @method CarbonInterface addMillenniaWithOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addMillenniumWithOverflow() Add one millennium to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subMillenniaWithOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subMillenniumWithOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addMillenniaWithoutOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMillenniumWithoutOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMillenniaWithoutOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMillenniumWithoutOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMillenniaWithNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMillenniumWithNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMillenniaWithNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMillenniumWithNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMillenniaNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMillenniumNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMillenniaNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMillenniumNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addCentury() Add one century to the instance (using date interval). * @method CarbonInterface subCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subCentury() Sub one century to the instance (using date interval). * @method CarbonInterface addCenturiesWithOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addCenturyWithOverflow() Add one century to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subCenturiesWithOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subCenturyWithOverflow() Sub one century to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addCenturiesWithoutOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addCenturyWithoutOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subCenturiesWithoutOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subCenturyWithoutOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addCenturiesWithNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addCenturyWithNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subCenturiesWithNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subCenturyWithNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addCenturiesNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addCenturyNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subCenturiesNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subCenturyNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addDecade() Add one decade to the instance (using date interval). * @method CarbonInterface subDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subDecade() Sub one decade to the instance (using date interval). * @method CarbonInterface addDecadesWithOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addDecadeWithOverflow() Add one decade to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subDecadesWithOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subDecadeWithOverflow() Sub one decade to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addDecadesWithoutOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addDecadeWithoutOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subDecadesWithoutOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subDecadeWithoutOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addDecadesWithNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addDecadeWithNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subDecadesWithNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subDecadeWithNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addDecadesNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addDecadeNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subDecadesNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subDecadeNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addQuarter() Add one quarter to the instance (using date interval). * @method CarbonInterface subQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subQuarter() Sub one quarter to the instance (using date interval). * @method CarbonInterface addQuartersWithOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addQuarterWithOverflow() Add one quarter to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subQuartersWithOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subQuarterWithOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addQuartersWithoutOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addQuarterWithoutOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subQuartersWithoutOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subQuarterWithoutOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addQuartersWithNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addQuarterWithNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subQuartersWithNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subQuarterWithNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addQuartersNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addQuarterNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subQuartersNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subQuarterNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addWeek() Add one week to the instance (using date interval). * @method CarbonInterface subWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subWeek() Sub one week to the instance (using date interval). * @method CarbonInterface addWeekdays(int $value = 1) Add weekdays (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addWeekday() Add one weekday to the instance (using date interval). * @method CarbonInterface subWeekdays(int $value = 1) Sub weekdays (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subWeekday() Sub one weekday to the instance (using date interval). * @method CarbonInterface addRealMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealMicro() Add one microsecond to the instance (using timestamp). * @method CarbonInterface subRealMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealMicro() Sub one microsecond to the instance (using timestamp). * @method CarbonPeriod microsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given. * @method CarbonInterface addRealMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealMicrosecond() Add one microsecond to the instance (using timestamp). * @method CarbonInterface subRealMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealMicrosecond() Sub one microsecond to the instance (using timestamp). * @method CarbonPeriod microsecondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given. * @method CarbonInterface addRealMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealMilli() Add one millisecond to the instance (using timestamp). * @method CarbonInterface subRealMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealMilli() Sub one millisecond to the instance (using timestamp). * @method CarbonPeriod millisUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given. * @method CarbonInterface addRealMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealMillisecond() Add one millisecond to the instance (using timestamp). * @method CarbonInterface subRealMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealMillisecond() Sub one millisecond to the instance (using timestamp). * @method CarbonPeriod millisecondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given. * @method CarbonInterface addRealSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealSecond() Add one second to the instance (using timestamp). * @method CarbonInterface subRealSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealSecond() Sub one second to the instance (using timestamp). * @method CarbonPeriod secondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each second or every X seconds if a factor is given. * @method CarbonInterface addRealMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealMinute() Add one minute to the instance (using timestamp). * @method CarbonInterface subRealMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealMinute() Sub one minute to the instance (using timestamp). * @method CarbonPeriod minutesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each minute or every X minutes if a factor is given. * @method CarbonInterface addRealHours(int $value = 1) Add hours (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealHour() Add one hour to the instance (using timestamp). * @method CarbonInterface subRealHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealHour() Sub one hour to the instance (using timestamp). * @method CarbonPeriod hoursUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each hour or every X hours if a factor is given. * @method CarbonInterface addRealDays(int $value = 1) Add days (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealDay() Add one day to the instance (using timestamp). * @method CarbonInterface subRealDays(int $value = 1) Sub days (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealDay() Sub one day to the instance (using timestamp). * @method CarbonPeriod daysUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each day or every X days if a factor is given. * @method CarbonInterface addRealWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealWeek() Add one week to the instance (using timestamp). * @method CarbonInterface subRealWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealWeek() Sub one week to the instance (using timestamp). * @method CarbonPeriod weeksUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each week or every X weeks if a factor is given. * @method CarbonInterface addRealMonths(int $value = 1) Add months (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealMonth() Add one month to the instance (using timestamp). * @method CarbonInterface subRealMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealMonth() Sub one month to the instance (using timestamp). * @method CarbonPeriod monthsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each month or every X months if a factor is given. * @method CarbonInterface addRealQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealQuarter() Add one quarter to the instance (using timestamp). * @method CarbonInterface subRealQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealQuarter() Sub one quarter to the instance (using timestamp). * @method CarbonPeriod quartersUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each quarter or every X quarters if a factor is given. * @method CarbonInterface addRealYears(int $value = 1) Add years (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealYear() Add one year to the instance (using timestamp). * @method CarbonInterface subRealYears(int $value = 1) Sub years (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealYear() Sub one year to the instance (using timestamp). * @method CarbonPeriod yearsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each year or every X years if a factor is given. * @method CarbonInterface addRealDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealDecade() Add one decade to the instance (using timestamp). * @method CarbonInterface subRealDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealDecade() Sub one decade to the instance (using timestamp). * @method CarbonPeriod decadesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each decade or every X decades if a factor is given. * @method CarbonInterface addRealCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealCentury() Add one century to the instance (using timestamp). * @method CarbonInterface subRealCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealCentury() Sub one century to the instance (using timestamp). * @method CarbonPeriod centuriesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each century or every X centuries if a factor is given. * @method CarbonInterface addRealMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealMillennium() Add one millennium to the instance (using timestamp). * @method CarbonInterface subRealMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealMillennium() Sub one millennium to the instance (using timestamp). * @method CarbonPeriod millenniaUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millennium or every X millennia if a factor is given. * @method CarbonInterface roundYear(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function. * @method CarbonInterface roundYears(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function. * @method CarbonInterface floorYear(float $precision = 1) Truncate the current instance year with given precision. * @method CarbonInterface floorYears(float $precision = 1) Truncate the current instance year with given precision. * @method CarbonInterface ceilYear(float $precision = 1) Ceil the current instance year with given precision. * @method CarbonInterface ceilYears(float $precision = 1) Ceil the current instance year with given precision. * @method CarbonInterface roundMonth(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function. * @method CarbonInterface roundMonths(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function. * @method CarbonInterface floorMonth(float $precision = 1) Truncate the current instance month with given precision. * @method CarbonInterface floorMonths(float $precision = 1) Truncate the current instance month with given precision. * @method CarbonInterface ceilMonth(float $precision = 1) Ceil the current instance month with given precision. * @method CarbonInterface ceilMonths(float $precision = 1) Ceil the current instance month with given precision. * @method CarbonInterface roundDay(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function. * @method CarbonInterface roundDays(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function. * @method CarbonInterface floorDay(float $precision = 1) Truncate the current instance day with given precision. * @method CarbonInterface floorDays(float $precision = 1) Truncate the current instance day with given precision. * @method CarbonInterface ceilDay(float $precision = 1) Ceil the current instance day with given precision. * @method CarbonInterface ceilDays(float $precision = 1) Ceil the current instance day with given precision. * @method CarbonInterface roundHour(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function. * @method CarbonInterface roundHours(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function. * @method CarbonInterface floorHour(float $precision = 1) Truncate the current instance hour with given precision. * @method CarbonInterface floorHours(float $precision = 1) Truncate the current instance hour with given precision. * @method CarbonInterface ceilHour(float $precision = 1) Ceil the current instance hour with given precision. * @method CarbonInterface ceilHours(float $precision = 1) Ceil the current instance hour with given precision. * @method CarbonInterface roundMinute(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function. * @method CarbonInterface roundMinutes(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function. * @method CarbonInterface floorMinute(float $precision = 1) Truncate the current instance minute with given precision. * @method CarbonInterface floorMinutes(float $precision = 1) Truncate the current instance minute with given precision. * @method CarbonInterface ceilMinute(float $precision = 1) Ceil the current instance minute with given precision. * @method CarbonInterface ceilMinutes(float $precision = 1) Ceil the current instance minute with given precision. * @method CarbonInterface roundSecond(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function. * @method CarbonInterface roundSeconds(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function. * @method CarbonInterface floorSecond(float $precision = 1) Truncate the current instance second with given precision. * @method CarbonInterface floorSeconds(float $precision = 1) Truncate the current instance second with given precision. * @method CarbonInterface ceilSecond(float $precision = 1) Ceil the current instance second with given precision. * @method CarbonInterface ceilSeconds(float $precision = 1) Ceil the current instance second with given precision. * @method CarbonInterface roundMillennium(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function. * @method CarbonInterface roundMillennia(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function. * @method CarbonInterface floorMillennium(float $precision = 1) Truncate the current instance millennium with given precision. * @method CarbonInterface floorMillennia(float $precision = 1) Truncate the current instance millennium with given precision. * @method CarbonInterface ceilMillennium(float $precision = 1) Ceil the current instance millennium with given precision. * @method CarbonInterface ceilMillennia(float $precision = 1) Ceil the current instance millennium with given precision. * @method CarbonInterface roundCentury(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function. * @method CarbonInterface roundCenturies(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function. * @method CarbonInterface floorCentury(float $precision = 1) Truncate the current instance century with given precision. * @method CarbonInterface floorCenturies(float $precision = 1) Truncate the current instance century with given precision. * @method CarbonInterface ceilCentury(float $precision = 1) Ceil the current instance century with given precision. * @method CarbonInterface ceilCenturies(float $precision = 1) Ceil the current instance century with given precision. * @method CarbonInterface roundDecade(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function. * @method CarbonInterface roundDecades(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function. * @method CarbonInterface floorDecade(float $precision = 1) Truncate the current instance decade with given precision. * @method CarbonInterface floorDecades(float $precision = 1) Truncate the current instance decade with given precision. * @method CarbonInterface ceilDecade(float $precision = 1) Ceil the current instance decade with given precision. * @method CarbonInterface ceilDecades(float $precision = 1) Ceil the current instance decade with given precision. * @method CarbonInterface roundQuarter(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function. * @method CarbonInterface roundQuarters(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function. * @method CarbonInterface floorQuarter(float $precision = 1) Truncate the current instance quarter with given precision. * @method CarbonInterface floorQuarters(float $precision = 1) Truncate the current instance quarter with given precision. * @method CarbonInterface ceilQuarter(float $precision = 1) Ceil the current instance quarter with given precision. * @method CarbonInterface ceilQuarters(float $precision = 1) Ceil the current instance quarter with given precision. * @method CarbonInterface roundMillisecond(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function. * @method CarbonInterface roundMilliseconds(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function. * @method CarbonInterface floorMillisecond(float $precision = 1) Truncate the current instance millisecond with given precision. * @method CarbonInterface floorMilliseconds(float $precision = 1) Truncate the current instance millisecond with given precision. * @method CarbonInterface ceilMillisecond(float $precision = 1) Ceil the current instance millisecond with given precision. * @method CarbonInterface ceilMilliseconds(float $precision = 1) Ceil the current instance millisecond with given precision. * @method CarbonInterface roundMicrosecond(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function. * @method CarbonInterface roundMicroseconds(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function. * @method CarbonInterface floorMicrosecond(float $precision = 1) Truncate the current instance microsecond with given precision. * @method CarbonInterface floorMicroseconds(float $precision = 1) Truncate the current instance microsecond with given precision. * @method CarbonInterface ceilMicrosecond(float $precision = 1) Ceil the current instance microsecond with given precision. * @method CarbonInterface ceilMicroseconds(float $precision = 1) Ceil the current instance microsecond with given precision. * @method string shortAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string longAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string shortRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string longRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string shortRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string longRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string shortRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string longRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * * </autodoc> */ interface CarbonInterface extends DateTimeInterface, JsonSerializable { /** * Diff wording options(expressed in octal). */ public const NO_ZERO_DIFF = 01; public const JUST_NOW = 02; public const ONE_DAY_WORDS = 04; public const TWO_DAY_WORDS = 010; public const SEQUENTIAL_PARTS_ONLY = 020; public const ROUND = 040; public const FLOOR = 0100; public const CEIL = 0200; /** * Diff syntax options. */ public const DIFF_ABSOLUTE = 1; // backward compatibility with true public const DIFF_RELATIVE_AUTO = 0; // backward compatibility with false public const DIFF_RELATIVE_TO_NOW = 2; public const DIFF_RELATIVE_TO_OTHER = 3; /** * Translate string options. */ public const TRANSLATE_MONTHS = 1; public const TRANSLATE_DAYS = 2; public const TRANSLATE_UNITS = 4; public const TRANSLATE_MERIDIEM = 8; public const TRANSLATE_DIFF = 0x10; public const TRANSLATE_ALL = self::TRANSLATE_MONTHS | self::TRANSLATE_DAYS | self::TRANSLATE_UNITS | self::TRANSLATE_MERIDIEM | self::TRANSLATE_DIFF; /** * The day constants. */ public const SUNDAY = 0; public const MONDAY = 1; public const TUESDAY = 2; public const WEDNESDAY = 3; public const THURSDAY = 4; public const FRIDAY = 5; public const SATURDAY = 6; /** * The month constants. * These aren't used by Carbon itself but exist for * convenience sake alone. */ public const JANUARY = 1; public const FEBRUARY = 2; public const MARCH = 3; public const APRIL = 4; public const MAY = 5; public const JUNE = 6; public const JULY = 7; public const AUGUST = 8; public const SEPTEMBER = 9; public const OCTOBER = 10; public const NOVEMBER = 11; public const DECEMBER = 12; /** * Number of X in Y. */ public const YEARS_PER_MILLENNIUM = 1000; public const YEARS_PER_CENTURY = 100; public const YEARS_PER_DECADE = 10; public const MONTHS_PER_YEAR = 12; public const MONTHS_PER_QUARTER = 3; public const QUARTERS_PER_YEAR = 4; public const WEEKS_PER_YEAR = 52; public const WEEKS_PER_MONTH = 4; public const DAYS_PER_YEAR = 365; public const DAYS_PER_WEEK = 7; public const HOURS_PER_DAY = 24; public const MINUTES_PER_HOUR = 60; public const SECONDS_PER_MINUTE = 60; public const MILLISECONDS_PER_SECOND = 1000; public const MICROSECONDS_PER_MILLISECOND = 1000; public const MICROSECONDS_PER_SECOND = 1000000; /** * Special settings to get the start of week from current locale culture. */ public const WEEK_DAY_AUTO = 'auto'; /** * RFC7231 DateTime format. * * @var string */ public const RFC7231_FORMAT = 'D, d M Y H:i:s \G\M\T'; /** * Default format to use for __toString method when type juggling occurs. * * @var string */ public const DEFAULT_TO_STRING_FORMAT = 'Y-m-d H:i:s'; /** * Format for converting mocked time, includes microseconds. * * @var string */ public const MOCK_DATETIME_FORMAT = 'Y-m-d H:i:s.u'; /** * Pattern detection for ->isoFormat and ::createFromIsoFormat. * * @var string */ public const ISO_FORMAT_REGEXP = '(O[YMDHhms]|[Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY?|g{1,5}|G{1,5}|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?)'; // <methods> /** * Dynamically handle calls to the class. * * @param string $method magic method name called * @param array $parameters parameters list * * @throws UnknownMethodException|BadMethodCallException|ReflectionException|Throwable * * @return mixed */ public function __call($method, $parameters); /** * Dynamically handle calls to the class. * * @param string $method magic method name called * @param array $parameters parameters list * * @throws BadMethodCallException * * @return mixed */ public static function __callStatic($method, $parameters); /** * Update constructedObjectId on cloned. */ public function __clone(); /** * Create a new Carbon instance. * * Please see the testing aids section (specifically static::setTestNow()) * for more on the possibility of this constructor returning a test instance. * * @param DateTimeInterface|string|null $time * @param DateTimeZone|string|null $tz * * @throws InvalidFormatException */ public function __construct($time = null, $tz = null); /** * Show truthy properties on var_dump(). * * @return array */ public function __debugInfo(); /** * Get a part of the Carbon object * * @param string $name * * @throws UnknownGetterException * * @return string|int|bool|DateTimeZone|null */ public function __get($name); /** * Check if an attribute exists on the object * * @param string $name * * @return bool */ public function __isset($name); /** * Set a part of the Carbon object * * @param string $name * @param string|int|DateTimeZone $value * * @throws UnknownSetterException|ReflectionException * * @return void */ public function __set($name, $value); /** * The __set_state handler. * * @param string|array $dump * * @return static */ #[ReturnTypeWillChange] public static function __set_state($dump); /** * Returns the list of properties to dump on serialize() called on. * * Only used by PHP < 7.4. * * @return array */ public function __sleep(); /** * Format the instance as a string using the set format * * @example * ``` * echo Carbon::now(); // Carbon instances can be cast to string * ``` * * @return string */ public function __toString(); /** * Add given units or interval to the current instance. * * @example $date->add('hour', 3) * @example $date->add(15, 'days') * @example $date->add(CarbonInterval::days(4)) * * @param string|DateInterval|Closure|CarbonConverterInterface $unit * @param int $value * @param bool|null $overflow * * @return static */ #[ReturnTypeWillChange] public function add($unit, $value = 1, $overflow = null); /** * Add seconds to the instance using timestamp. Positive $value travels * forward while negative $value travels into the past. * * @param string $unit * @param int $value * * @return static */ public function addRealUnit($unit, $value = 1); /** * Add given units to the current instance. * * @param string $unit * @param int $value * @param bool|null $overflow * * @return static */ public function addUnit($unit, $value = 1, $overflow = null); /** * Add any unit to a new value without overflowing current other unit given. * * @param string $valueUnit unit name to modify * @param int $value amount to add to the input unit * @param string $overflowUnit unit name to not overflow * * @return static */ public function addUnitNoOverflow($valueUnit, $value, $overflowUnit); /** * Get the difference in a human readable format in the current locale from an other * instance given to now * * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains: * - 'syntax' entry (see below) * - 'short' entry (see below) * - 'parts' entry (see below) * - 'options' entry (see below) * - 'join' entry determines how to join multiple parts of the string * ` - if $join is a string, it's used as a joiner glue * ` - if $join is a callable/closure, it get the list of string and should return a string * ` - if $join is an array, the first item will be the default glue, and the second item * ` will be used instead of the glue for the last item * ` - if $join is true, it will be guessed from the locale ('list' translation file entry) * ` - if $join is missing, a space will be used as glue * if int passed, it add modifiers: * Possible values: * - CarbonInterface::DIFF_ABSOLUTE no modifiers * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier * Default value: CarbonInterface::DIFF_ABSOLUTE * @param bool $short displays short format of time units * @param int $parts maximum number of parts to display (default value: 1: single part) * @param int $options human diff options * * @return string */ public function ago($syntax = null, $short = false, $parts = 1, $options = null); /** * Modify the current instance to the average of a given instance (default now) and the current instance * (second-precision). * * @param \Carbon\Carbon|\DateTimeInterface|null $date * * @return static */ public function average($date = null); /** * Clone the current instance if it's mutable. * * This method is convenient to ensure you don't mutate the initial object * but avoid to make a useless copy of it if it's already immutable. * * @return static */ public function avoidMutation(); /** * Determines if the instance is between two others. * * The third argument allow you to specify if bounds are included or not (true by default) * but for when you including/excluding bounds may produce different results in your application, * we recommend to use the explicit methods ->betweenIncluded() or ->betweenExcluded() instead. * * @example * ``` * Carbon::parse('2018-07-25')->between('2018-07-14', '2018-08-01'); // true * Carbon::parse('2018-07-25')->between('2018-08-01', '2018-08-20'); // false * Carbon::parse('2018-07-25')->between('2018-07-25', '2018-08-01'); // true * Carbon::parse('2018-07-25')->between('2018-07-25', '2018-08-01', false); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1 * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2 * @param bool $equal Indicates if an equal to comparison should be done * * @return bool */ public function between($date1, $date2, $equal = true): bool; /** * Determines if the instance is between two others, bounds excluded. * * @example * ``` * Carbon::parse('2018-07-25')->betweenExcluded('2018-07-14', '2018-08-01'); // true * Carbon::parse('2018-07-25')->betweenExcluded('2018-08-01', '2018-08-20'); // false * Carbon::parse('2018-07-25')->betweenExcluded('2018-07-25', '2018-08-01'); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1 * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2 * * @return bool */ public function betweenExcluded($date1, $date2): bool; /** * Determines if the instance is between two others, bounds included. * * @example * ``` * Carbon::parse('2018-07-25')->betweenIncluded('2018-07-14', '2018-08-01'); // true * Carbon::parse('2018-07-25')->betweenIncluded('2018-08-01', '2018-08-20'); // false * Carbon::parse('2018-07-25')->betweenIncluded('2018-07-25', '2018-08-01'); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1 * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2 * * @return bool */ public function betweenIncluded($date1, $date2): bool; /** * Returns either day of week + time (e.g. "Last Friday at 3:30 PM") if reference time is within 7 days, * or a calendar date (e.g. "10/29/2017") otherwise. * * Language, date and time formats will change according to the current locale. * * @param Carbon|\DateTimeInterface|string|null $referenceTime * @param array $formats * * @return string */ public function calendar($referenceTime = null, array $formats = []); /** * Checks if the (date)time string is in a given format and valid to create a * new instance. * * @example * ``` * Carbon::canBeCreatedFromFormat('11:12:45', 'h:i:s'); // true * Carbon::canBeCreatedFromFormat('13:12:45', 'h:i:s'); // false * ``` * * @param string $date * @param string $format * * @return bool */ public static function canBeCreatedFromFormat($date, $format); /** * Return the Carbon instance passed through, a now instance in the same timezone * if null given or parse the input if string given. * * @param Carbon|\Carbon\CarbonPeriod|\Carbon\CarbonInterval|\DateInterval|\DatePeriod|DateTimeInterface|string|null $date * * @return static */ public function carbonize($date = null); /** * Cast the current instance into the given class. * * @param string $className The $className::instance() method will be called to cast the current object. * * @return DateTimeInterface */ public function cast(string $className); /** * Ceil the current instance second with given precision if specified. * * @param float|int|string|\DateInterval|null $precision * * @return CarbonInterface */ public function ceil($precision = 1); /** * Ceil the current instance at the given unit with given precision if specified. * * @param string $unit * @param float|int $precision * * @return CarbonInterface */ public function ceilUnit($unit, $precision = 1); /** * Ceil the current instance week. * * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week * * @return CarbonInterface */ public function ceilWeek($weekStartsAt = null); /** * Similar to native modify() method of DateTime but can handle more grammars. * * @example * ``` * echo Carbon::now()->change('next 2pm'); * ``` * * @link https://php.net/manual/en/datetime.modify.php * * @param string $modifier * * @return static|false */ public function change($modifier); /** * Cleanup properties attached to the public scope of DateTime when a dump of the date is requested. * foreach ($date as $_) {} * serializer($date) * var_export($date) * get_object_vars($date) */ public function cleanupDumpProperties(); /** * @alias copy * * Get a copy of the instance. * * @return static */ public function clone(); /** * Get the closest date from the instance (second-precision). * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1 * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2 * * @return static */ public function closest($date1, $date2); /** * Get a copy of the instance. * * @return static */ public function copy(); /** * Create a new Carbon instance from a specific date and time. * * If any of $year, $month or $day are set to null their now() values will * be used. * * If $hour is null it will be set to its now() value and the default * values for $minute and $second will be their now() values. * * If $hour is not null then the default values for $minute and $second * will be 0. * * @param DateTimeInterface|int|null $year * @param int|null $month * @param int|null $day * @param int|null $hour * @param int|null $minute * @param int|null $second * @param DateTimeZone|string|null $tz * * @throws InvalidFormatException * * @return static|false */ public static function create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $tz = null); /** * Create a Carbon instance from just a date. The time portion is set to now. * * @param int|null $year * @param int|null $month * @param int|null $day * @param DateTimeZone|string|null $tz * * @throws InvalidFormatException * * @return static */ public static function createFromDate($year = null, $month = null, $day = null, $tz = null); /** * Create a Carbon instance from a specific format. * * @param string $format Datetime format * @param string $time * @param DateTimeZone|string|false|null $tz * * @throws InvalidFormatException * * @return static|false */ #[ReturnTypeWillChange] public static function createFromFormat($format, $time, $tz = null); /** * Create a Carbon instance from a specific ISO format (same replacements as ->isoFormat()). * * @param string $format Datetime format * @param string $time * @param DateTimeZone|string|false|null $tz optional timezone * @param string|null $locale locale to be used for LTS, LT, LL, LLL, etc. macro-formats (en by fault, unneeded if no such macro-format in use) * @param \Symfony\Component\Translation\TranslatorInterface $translator optional custom translator to use for macro-formats * * @throws InvalidFormatException * * @return static|false */ public static function createFromIsoFormat($format, $time, $tz = null, $locale = 'en', $translator = null); /** * Create a Carbon instance from a specific format and a string in a given language. * * @param string $format Datetime format * @param string $locale * @param string $time * @param DateTimeZone|string|false|null $tz * * @throws InvalidFormatException * * @return static|false */ public static function createFromLocaleFormat($format, $locale, $time, $tz = null); /** * Create a Carbon instance from a specific ISO format and a string in a given language. * * @param string $format Datetime ISO format * @param string $locale * @param string $time * @param DateTimeZone|string|false|null $tz * * @throws InvalidFormatException * * @return static|false */ public static function createFromLocaleIsoFormat($format, $locale, $time, $tz = null); /** * Create a Carbon instance from just a time. The date portion is set to today. * * @param int|null $hour * @param int|null $minute * @param int|null $second * @param DateTimeZone|string|null $tz * * @throws InvalidFormatException * * @return static */ public static function createFromTime($hour = 0, $minute = 0, $second = 0, $tz = null); /** * Create a Carbon instance from a time string. The date portion is set to today. * * @param string $time * @param DateTimeZone|string|null $tz * * @throws InvalidFormatException * * @return static */ public static function createFromTimeString($time, $tz = null); /** * Create a Carbon instance from a timestamp and set the timezone (use default one if not specified). * * Timestamp input can be given as int, float or a string containing one or more numbers. * * @param float|int|string $timestamp * @param \DateTimeZone|string|null $tz * * @return static */ #[ReturnTypeWillChange] public static function createFromTimestamp($timestamp, $tz = null); /** * Create a Carbon instance from a timestamp in milliseconds. * * Timestamp input can be given as int, float or a string containing one or more numbers. * * @param float|int|string $timestamp * @param \DateTimeZone|string|null $tz * * @return static */ public static function createFromTimestampMs($timestamp, $tz = null); /** * Create a Carbon instance from a timestamp in milliseconds. * * Timestamp input can be given as int, float or a string containing one or more numbers. * * @param float|int|string $timestamp * * @return static */ public static function createFromTimestampMsUTC($timestamp); /** * Create a Carbon instance from an timestamp keeping the timezone to UTC. * * Timestamp input can be given as int, float or a string containing one or more numbers. * * @param float|int|string $timestamp * * @return static */ public static function createFromTimestampUTC($timestamp); /** * Create a Carbon instance from just a date. The time portion is set to midnight. * * @param int|null $year * @param int|null $month * @param int|null $day * @param DateTimeZone|string|null $tz * * @throws InvalidFormatException * * @return static */ public static function createMidnightDate($year = null, $month = null, $day = null, $tz = null); /** * Create a new safe Carbon instance from a specific date and time. * * If any of $year, $month or $day are set to null their now() values will * be used. * * If $hour is null it will be set to its now() value and the default * values for $minute and $second will be their now() values. * * If $hour is not null then the default values for $minute and $second * will be 0. * * If one of the set values is not valid, an InvalidDateException * will be thrown. * * @param int|null $year * @param int|null $month * @param int|null $day * @param int|null $hour * @param int|null $minute * @param int|null $second * @param DateTimeZone|string|null $tz * * @throws InvalidDateException * * @return static|false */ public static function createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null); /** * Create a new Carbon instance from a specific date and time using strict validation. * * @see create() * * @param int|null $year * @param int|null $month * @param int|null $day * @param int|null $hour * @param int|null $minute * @param int|null $second * @param DateTimeZone|string|null $tz * * @throws InvalidFormatException * * @return static */ public static function createStrict(?int $year = 0, ?int $month = 1, ?int $day = 1, ?int $hour = 0, ?int $minute = 0, ?int $second = 0, $tz = null); /** * Get/set the day of year. * * @param int|null $value new value for day of year if using as setter. * * @return static|int */ public function dayOfYear($value = null); /** * Get the difference as a CarbonInterval instance. * Return relative interval (negative if $absolute flag is not set to true and the given date is before * current one). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return CarbonInterval */ public function diffAsCarbonInterval($date = null, $absolute = true, array $skip = []); /** * Get the difference by the given interval using a filter closure. * * @param CarbonInterval $ci An interval to traverse by * @param Closure $callback * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffFiltered(CarbonInterval $ci, Closure $callback, $date = null, $absolute = true); /** * Get the difference in a human readable format in the current locale from current instance to an other * instance given (or now if null given). * * @example * ``` * echo Carbon::tomorrow()->diffForHumans() . "\n"; * echo Carbon::tomorrow()->diffForHumans(['parts' => 2]) . "\n"; * echo Carbon::tomorrow()->diffForHumans(['parts' => 3, 'join' => true]) . "\n"; * echo Carbon::tomorrow()->diffForHumans(Carbon::yesterday()) . "\n"; * echo Carbon::tomorrow()->diffForHumans(Carbon::yesterday(), ['short' => true]) . "\n"; * ``` * * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below; * if null passed, now will be used as comparison reference; * if any other type, it will be converted to date and used as reference. * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains: * - 'syntax' entry (see below) * - 'short' entry (see below) * - 'parts' entry (see below) * - 'options' entry (see below) * - 'skip' entry, list of units to skip (array of strings or a single string, * ` it can be the unit name (singular or plural) or its shortcut * ` (y, m, w, d, h, min, s, ms, µs). * - 'aUnit' entry, prefer "an hour" over "1 hour" if true * - 'join' entry determines how to join multiple parts of the string * ` - if $join is a string, it's used as a joiner glue * ` - if $join is a callable/closure, it get the list of string and should return a string * ` - if $join is an array, the first item will be the default glue, and the second item * ` will be used instead of the glue for the last item * ` - if $join is true, it will be guessed from the locale ('list' translation file entry) * ` - if $join is missing, a space will be used as glue * - 'other' entry (see above) * - 'minimumUnit' entry determines the smallest unit of time to display can be long or * ` short form of the units, e.g. 'hour' or 'h' (default value: s) * if int passed, it add modifiers: * Possible values: * - CarbonInterface::DIFF_ABSOLUTE no modifiers * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier * Default value: CarbonInterface::DIFF_ABSOLUTE * @param bool $short displays short format of time units * @param int $parts maximum number of parts to display (default value: 1: single unit) * @param int $options human diff options * * @return string */ public function diffForHumans($other = null, $syntax = null, $short = false, $parts = 1, $options = null); /** * Get the difference in days rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInDays($date = null, $absolute = true); /** * Get the difference in days using a filter closure rounded down. * * @param Closure $callback * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInDaysFiltered(Closure $callback, $date = null, $absolute = true); /** * Get the difference in hours rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInHours($date = null, $absolute = true); /** * Get the difference in hours using a filter closure rounded down. * * @param Closure $callback * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInHoursFiltered(Closure $callback, $date = null, $absolute = true); /** * Get the difference in microseconds. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInMicroseconds($date = null, $absolute = true); /** * Get the difference in milliseconds rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInMilliseconds($date = null, $absolute = true); /** * Get the difference in minutes rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInMinutes($date = null, $absolute = true); /** * Get the difference in months rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInMonths($date = null, $absolute = true); /** * Get the difference in quarters rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInQuarters($date = null, $absolute = true); /** * Get the difference in hours rounded down using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInRealHours($date = null, $absolute = true); /** * Get the difference in microseconds using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInRealMicroseconds($date = null, $absolute = true); /** * Get the difference in milliseconds rounded down using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInRealMilliseconds($date = null, $absolute = true); /** * Get the difference in minutes rounded down using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInRealMinutes($date = null, $absolute = true); /** * Get the difference in seconds using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInRealSeconds($date = null, $absolute = true); /** * Get the difference in seconds rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInSeconds($date = null, $absolute = true); /** * Get the difference in weekdays rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInWeekdays($date = null, $absolute = true); /** * Get the difference in weekend days using a filter rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInWeekendDays($date = null, $absolute = true); /** * Get the difference in weeks rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInWeeks($date = null, $absolute = true); /** * Get the difference in years * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInYears($date = null, $absolute = true); /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * @see settings * * @param int $humanDiffOption */ public static function disableHumanDiffOption($humanDiffOption); /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * @see settings * * @param int $humanDiffOption */ public static function enableHumanDiffOption($humanDiffOption); /** * Modify to end of current given unit. * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16.334455') * ->startOf('month') * ->endOf('week', Carbon::FRIDAY); * ``` * * @param string $unit * @param array<int, mixed> $params * * @return static */ public function endOf($unit, ...$params); /** * Resets the date to end of the century and time to 23:59:59.999999 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfCentury(); * ``` * * @return static */ public function endOfCentury(); /** * Resets the time to 23:59:59.999999 end of day * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfDay(); * ``` * * @return static */ public function endOfDay(); /** * Resets the date to end of the decade and time to 23:59:59.999999 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfDecade(); * ``` * * @return static */ public function endOfDecade(); /** * Modify to end of current hour, minutes and seconds become 59 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfHour(); * ``` * * @return static */ public function endOfHour(); /** * Resets the date to end of the millennium and time to 23:59:59.999999 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfMillennium(); * ``` * * @return static */ public function endOfMillennium(); /** * Modify to end of current minute, seconds become 59 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfMinute(); * ``` * * @return static */ public function endOfMinute(); /** * Resets the date to end of the month and time to 23:59:59.999999 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfMonth(); * ``` * * @return static */ public function endOfMonth(); /** * Resets the date to end of the quarter and time to 23:59:59.999999 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfQuarter(); * ``` * * @return static */ public function endOfQuarter(); /** * Modify to end of current second, microseconds become 999999 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16.334455') * ->endOfSecond() * ->format('H:i:s.u'); * ``` * * @return static */ public function endOfSecond(); /** * Resets the date to end of week (defined in $weekEndsAt) and time to 23:59:59.999999 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfWeek() . "\n"; * echo Carbon::parse('2018-07-25 12:45:16')->locale('ar')->endOfWeek() . "\n"; * echo Carbon::parse('2018-07-25 12:45:16')->endOfWeek(Carbon::SATURDAY) . "\n"; * ``` * * @param int $weekEndsAt optional start allow you to specify the day of week to use to end the week * * @return static */ public function endOfWeek($weekEndsAt = null); /** * Resets the date to end of the year and time to 23:59:59.999999 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfYear(); * ``` * * @return static */ public function endOfYear(); /** * Determines if the instance is equal to another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->eq('2018-07-25 12:45:16'); // true * Carbon::parse('2018-07-25 12:45:16')->eq(Carbon::parse('2018-07-25 12:45:16')); // true * Carbon::parse('2018-07-25 12:45:16')->eq('2018-07-25 12:45:17'); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see equalTo() * * @return bool */ public function eq($date): bool; /** * Determines if the instance is equal to another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->equalTo('2018-07-25 12:45:16'); // true * Carbon::parse('2018-07-25 12:45:16')->equalTo(Carbon::parse('2018-07-25 12:45:16')); // true * Carbon::parse('2018-07-25 12:45:16')->equalTo('2018-07-25 12:45:17'); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @return bool */ public function equalTo($date): bool; /** * Set the current locale to the given, execute the passed function, reset the locale to previous one, * then return the result of the closure (or null if the closure was void). * * @param string $locale locale ex. en * @param callable $func * * @return mixed */ public static function executeWithLocale($locale, $func); /** * Get the farthest date from the instance (second-precision). * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1 * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2 * * @return static */ public function farthest($date1, $date2); /** * Modify to the first occurrence of a given day of the week * in the current month. If no dayOfWeek is provided, modify to the * first day of the current month. Use the supplied constants * to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param int|null $dayOfWeek * * @return static */ public function firstOfMonth($dayOfWeek = null); /** * Modify to the first occurrence of a given day of the week * in the current quarter. If no dayOfWeek is provided, modify to the * first day of the current quarter. Use the supplied constants * to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param int|null $dayOfWeek day of the week default null * * @return static */ public function firstOfQuarter($dayOfWeek = null); /** * Modify to the first occurrence of a given day of the week * in the current year. If no dayOfWeek is provided, modify to the * first day of the current year. Use the supplied constants * to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param int|null $dayOfWeek day of the week default null * * @return static */ public function firstOfYear($dayOfWeek = null); /** * Get the difference in days as float (microsecond-precision). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInDays($date = null, $absolute = true); /** * Get the difference in hours as float (microsecond-precision). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInHours($date = null, $absolute = true); /** * Get the difference in minutes as float (microsecond-precision). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInMinutes($date = null, $absolute = true); /** * Get the difference in months as float (microsecond-precision). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInMonths($date = null, $absolute = true); /** * Get the difference in days as float (microsecond-precision). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInRealDays($date = null, $absolute = true); /** * Get the difference in hours as float (microsecond-precision) using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInRealHours($date = null, $absolute = true); /** * Get the difference in minutes as float (microsecond-precision) using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInRealMinutes($date = null, $absolute = true); /** * Get the difference in months as float (microsecond-precision) using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInRealMonths($date = null, $absolute = true); /** * Get the difference in seconds as float (microsecond-precision) using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInRealSeconds($date = null, $absolute = true); /** * Get the difference in weeks as float (microsecond-precision). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInRealWeeks($date = null, $absolute = true); /** * Get the difference in year as float (microsecond-precision) using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInRealYears($date = null, $absolute = true); /** * Get the difference in seconds as float (microsecond-precision). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInSeconds($date = null, $absolute = true); /** * Get the difference in weeks as float (microsecond-precision). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInWeeks($date = null, $absolute = true); /** * Get the difference in year as float (microsecond-precision). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInYears($date = null, $absolute = true); /** * Round the current instance second with given precision if specified. * * @param float|int|string|\DateInterval|null $precision * * @return CarbonInterface */ public function floor($precision = 1); /** * Truncate the current instance at the given unit with given precision if specified. * * @param string $unit * @param float|int $precision * * @return CarbonInterface */ public function floorUnit($unit, $precision = 1); /** * Truncate the current instance week. * * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week * * @return CarbonInterface */ public function floorWeek($weekStartsAt = null); /** * Format the instance with the current locale. You can set the current * locale using setlocale() https://php.net/setlocale. * * @deprecated It uses OS language package and strftime() which is deprecated since PHP 8.1. * Use ->isoFormat() instead. * Deprecated since 2.55.0 * * @param string $format * * @return string */ public function formatLocalized($format); /** * @alias diffForHumans * * Get the difference in a human readable format in the current locale from current instance to an other * instance given (or now if null given). * * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below; * if null passed, now will be used as comparison reference; * if any other type, it will be converted to date and used as reference. * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains: * - 'syntax' entry (see below) * - 'short' entry (see below) * - 'parts' entry (see below) * - 'options' entry (see below) * - 'join' entry determines how to join multiple parts of the string * ` - if $join is a string, it's used as a joiner glue * ` - if $join is a callable/closure, it get the list of string and should return a string * ` - if $join is an array, the first item will be the default glue, and the second item * ` will be used instead of the glue for the last item * ` - if $join is true, it will be guessed from the locale ('list' translation file entry) * ` - if $join is missing, a space will be used as glue * - 'other' entry (see above) * if int passed, it add modifiers: * Possible values: * - CarbonInterface::DIFF_ABSOLUTE no modifiers * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier * Default value: CarbonInterface::DIFF_ABSOLUTE * @param bool $short displays short format of time units * @param int $parts maximum number of parts to display (default value: 1: single unit) * @param int $options human diff options * * @return string */ public function from($other = null, $syntax = null, $short = false, $parts = 1, $options = null); /** * Get the difference in a human readable format in the current locale from current * instance to now. * * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains: * - 'syntax' entry (see below) * - 'short' entry (see below) * - 'parts' entry (see below) * - 'options' entry (see below) * - 'join' entry determines how to join multiple parts of the string * ` - if $join is a string, it's used as a joiner glue * ` - if $join is a callable/closure, it get the list of string and should return a string * ` - if $join is an array, the first item will be the default glue, and the second item * ` will be used instead of the glue for the last item * ` - if $join is true, it will be guessed from the locale ('list' translation file entry) * ` - if $join is missing, a space will be used as glue * if int passed, it add modifiers: * Possible values: * - CarbonInterface::DIFF_ABSOLUTE no modifiers * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier * Default value: CarbonInterface::DIFF_ABSOLUTE * @param bool $short displays short format of time units * @param int $parts maximum number of parts to display (default value: 1: single unit) * @param int $options human diff options * * @return string */ public function fromNow($syntax = null, $short = false, $parts = 1, $options = null); /** * Create an instance from a serialized string. * * @param string $value * * @throws InvalidFormatException * * @return static */ public static function fromSerialized($value); /** * Register a custom macro. * * @param object|callable $macro * @param int $priority marco with higher priority is tried first * * @return void */ public static function genericMacro($macro, $priority = 0); /** * Get a part of the Carbon object * * @param string $name * * @throws UnknownGetterException * * @return string|int|bool|DateTimeZone|null */ public function get($name); /** * Returns the alternative number for a given date property if available in the current locale. * * @param string $key date property * * @return string */ public function getAltNumber(string $key): string; /** * Returns the list of internally available locales and already loaded custom locales. * (It will ignore custom translator dynamic loading.) * * @return array */ public static function getAvailableLocales(); /** * Returns list of Language object for each available locale. This object allow you to get the ISO name, native * name, region and variant of the locale. * * @return Language[] */ public static function getAvailableLocalesInfo(); /** * Returns list of calendar formats for ISO formatting. * * @param string|null $locale current locale used if null * * @return array */ public function getCalendarFormats($locale = null); /** * Get the days of the week * * @return array */ public static function getDays(); /** * Return the number of days since the start of the week (using the current locale or the first parameter * if explicitly given). * * @param int|null $weekStartsAt optional start allow you to specify the day of week to use to start the week, * if not provided, start of week is inferred from the locale * (Sunday for en_US, Monday for de_DE, etc.) * * @return int */ public function getDaysFromStartOfWeek(?int $weekStartsAt = null): int; /** * Get the fallback locale. * * @see https://symfony.com/doc/current/components/translation.html#fallback-locales * * @return string|null */ public static function getFallbackLocale(); /** * List of replacements from date() format to isoFormat(). * * @return array */ public static function getFormatsToIsoReplacements(); /** * Return default humanDiff() options (merged flags as integer). * * @return int */ public static function getHumanDiffOptions(); /** * Returns list of locale formats for ISO formatting. * * @param string|null $locale current locale used if null * * @return array */ public function getIsoFormats($locale = null); /** * Returns list of locale units for ISO formatting. * * @return array */ public static function getIsoUnits(); /** * {@inheritdoc} * * @return array */ #[ReturnTypeWillChange] public static function getLastErrors(); /** * Get the raw callable macro registered globally or locally for a given name. * * @param string $name * * @return callable|null */ public function getLocalMacro($name); /** * Get the translator of the current instance or the default if none set. * * @return \Symfony\Component\Translation\TranslatorInterface */ public function getLocalTranslator(); /** * Get the current translator locale. * * @return string */ public static function getLocale(); /** * Get the raw callable macro registered globally for a given name. * * @param string $name * * @return callable|null */ public static function getMacro($name); /** * get midday/noon hour * * @return int */ public static function getMidDayAt(); /** * Returns the offset hour and minute formatted with +/- and a given separator (":" by default). * For example, if the time zone is 9 hours 30 minutes, you'll get "+09:30", with "@@" as first * argument, "+09@@30", with "" as first argument, "+0930". Negative offset will return something * like "-12:00". * * @param string $separator string to place between hours and minutes (":" by default) * * @return string */ public function getOffsetString($separator = ':'); /** * Returns a unit of the instance padded with 0 by default or any other string if specified. * * @param string $unit Carbon unit name * @param int $length Length of the output (2 by default) * @param string $padString String to use for padding ("0" by default) * @param int $padType Side(s) to pad (STR_PAD_LEFT by default) * * @return string */ public function getPaddedUnit($unit, $length = 2, $padString = '0', $padType = 0); /** * Returns a timestamp rounded with the given precision (6 by default). * * @example getPreciseTimestamp() 1532087464437474 (microsecond maximum precision) * @example getPreciseTimestamp(6) 1532087464437474 * @example getPreciseTimestamp(5) 153208746443747 (1/100000 second precision) * @example getPreciseTimestamp(4) 15320874644375 (1/10000 second precision) * @example getPreciseTimestamp(3) 1532087464437 (millisecond precision) * @example getPreciseTimestamp(2) 153208746444 (1/100 second precision) * @example getPreciseTimestamp(1) 15320874644 (1/10 second precision) * @example getPreciseTimestamp(0) 1532087464 (second precision) * @example getPreciseTimestamp(-1) 153208746 (10 second precision) * @example getPreciseTimestamp(-2) 15320875 (100 second precision) * * @param int $precision * * @return float */ public function getPreciseTimestamp($precision = 6); /** * Returns current local settings. * * @return array */ public function getSettings(); /** * Get the Carbon instance (real or mock) to be returned when a "now" * instance is created. * * @return Closure|static the current instance used for testing */ public static function getTestNow(); /** * Return a format from H:i to H:i:s.u according to given unit precision. * * @param string $unitPrecision "minute", "second", "millisecond" or "microsecond" * * @return string */ public static function getTimeFormatByPrecision($unitPrecision); /** * Returns the timestamp with millisecond precision. * * @return int */ public function getTimestampMs(); /** * Get the translation of the current week day name (with context for languages with multiple forms). * * @param string|null $context whole format string * @param string $keySuffix "", "_short" or "_min" * @param string|null $defaultValue default value if translation missing * * @return string */ public function getTranslatedDayName($context = null, $keySuffix = '', $defaultValue = null); /** * Get the translation of the current abbreviated week day name (with context for languages with multiple forms). * * @param string|null $context whole format string * * @return string */ public function getTranslatedMinDayName($context = null); /** * Get the translation of the current month day name (with context for languages with multiple forms). * * @param string|null $context whole format string * @param string $keySuffix "" or "_short" * @param string|null $defaultValue default value if translation missing * * @return string */ public function getTranslatedMonthName($context = null, $keySuffix = '', $defaultValue = null); /** * Get the translation of the current short week day name (with context for languages with multiple forms). * * @param string|null $context whole format string * * @return string */ public function getTranslatedShortDayName($context = null); /** * Get the translation of the current short month day name (with context for languages with multiple forms). * * @param string|null $context whole format string * * @return string */ public function getTranslatedShortMonthName($context = null); /** * Returns raw translation message for a given key. * * @param string $key key to find * @param string|null $locale current locale used if null * @param string|null $default default value if translation returns the key * @param \Symfony\Component\Translation\TranslatorInterface $translator an optional translator to use * * @return string */ public function getTranslationMessage(string $key, ?string $locale = null, ?string $default = null, $translator = null); /** * Returns raw translation message for a given key. * * @param \Symfony\Component\Translation\TranslatorInterface $translator the translator to use * @param string $key key to find * @param string|null $locale current locale used if null * @param string|null $default default value if translation returns the key * * @return string */ public static function getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null); /** * Get the default translator instance in use. * * @return \Symfony\Component\Translation\TranslatorInterface */ public static function getTranslator(); /** * Get the last day of week * * @return int */ public static function getWeekEndsAt(); /** * Get the first day of week * * @return int */ public static function getWeekStartsAt(); /** * Get weekend days * * @return array */ public static function getWeekendDays(); /** * Determines if the instance is greater (after) than another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:15'); // true * Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:16'); // false * Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:17'); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @return bool */ public function greaterThan($date): bool; /** * Determines if the instance is greater (after) than or equal to another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->greaterThanOrEqualTo('2018-07-25 12:45:15'); // true * Carbon::parse('2018-07-25 12:45:16')->greaterThanOrEqualTo('2018-07-25 12:45:16'); // true * Carbon::parse('2018-07-25 12:45:16')->greaterThanOrEqualTo('2018-07-25 12:45:17'); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @return bool */ public function greaterThanOrEqualTo($date): bool; /** * Determines if the instance is greater (after) than another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->gt('2018-07-25 12:45:15'); // true * Carbon::parse('2018-07-25 12:45:16')->gt('2018-07-25 12:45:16'); // false * Carbon::parse('2018-07-25 12:45:16')->gt('2018-07-25 12:45:17'); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see greaterThan() * * @return bool */ public function gt($date): bool; /** * Determines if the instance is greater (after) than or equal to another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->gte('2018-07-25 12:45:15'); // true * Carbon::parse('2018-07-25 12:45:16')->gte('2018-07-25 12:45:16'); // true * Carbon::parse('2018-07-25 12:45:16')->gte('2018-07-25 12:45:17'); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see greaterThanOrEqualTo() * * @return bool */ public function gte($date): bool; /** * Checks if the (date)time string is in a given format. * * @example * ``` * Carbon::hasFormat('11:12:45', 'h:i:s'); // true * Carbon::hasFormat('13:12:45', 'h:i:s'); // false * ``` * * @param string $date * @param string $format * * @return bool */ public static function hasFormat($date, $format); /** * Checks if the (date)time string is in a given format. * * @example * ``` * Carbon::hasFormatWithModifiers('31/08/2015', 'd#m#Y'); // true * Carbon::hasFormatWithModifiers('31/08/2015', 'm#d#Y'); // false * ``` * * @param string $date * @param string $format * * @return bool */ public static function hasFormatWithModifiers($date, $format): bool; /** * Checks if macro is registered globally or locally. * * @param string $name * * @return bool */ public function hasLocalMacro($name); /** * Return true if the current instance has its own translator. * * @return bool */ public function hasLocalTranslator(); /** * Checks if macro is registered globally. * * @param string $name * * @return bool */ public static function hasMacro($name); /** * Determine if a time string will produce a relative date. * * @param string $time * * @return bool true if time match a relative date, false if absolute or invalid time string */ public static function hasRelativeKeywords($time); /** * Determine if there is a valid test instance set. A valid test instance * is anything that is not null. * * @return bool true if there is a test instance, otherwise false */ public static function hasTestNow(); /** * Create a Carbon instance from a DateTime one. * * @param DateTimeInterface $date * * @return static */ public static function instance($date); /** * Returns true if the current date matches the given string. * * @example * ``` * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2019')); // true * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2018')); // false * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2019-06')); // true * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('06-02')); // true * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2019-06-02')); // true * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('Sunday')); // true * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('June')); // true * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12:23')); // true * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12:23:45')); // true * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12:23:00')); // false * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12h')); // true * var_dump(Carbon::parse('2019-06-02 15:23:45')->is('3pm')); // true * var_dump(Carbon::parse('2019-06-02 15:23:45')->is('3am')); // false * ``` * * @param string $tester day name, month name, hour, date, etc. as string * * @return bool */ public function is(string $tester); /** * Determines if the instance is greater (after) than another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->isAfter('2018-07-25 12:45:15'); // true * Carbon::parse('2018-07-25 12:45:16')->isAfter('2018-07-25 12:45:16'); // false * Carbon::parse('2018-07-25 12:45:16')->isAfter('2018-07-25 12:45:17'); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see greaterThan() * * @return bool */ public function isAfter($date): bool; /** * Determines if the instance is less (before) than another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->isBefore('2018-07-25 12:45:15'); // false * Carbon::parse('2018-07-25 12:45:16')->isBefore('2018-07-25 12:45:16'); // false * Carbon::parse('2018-07-25 12:45:16')->isBefore('2018-07-25 12:45:17'); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see lessThan() * * @return bool */ public function isBefore($date): bool; /** * Determines if the instance is between two others * * @example * ``` * Carbon::parse('2018-07-25')->isBetween('2018-07-14', '2018-08-01'); // true * Carbon::parse('2018-07-25')->isBetween('2018-08-01', '2018-08-20'); // false * Carbon::parse('2018-07-25')->isBetween('2018-07-25', '2018-08-01'); // true * Carbon::parse('2018-07-25')->isBetween('2018-07-25', '2018-08-01', false); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1 * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2 * @param bool $equal Indicates if an equal to comparison should be done * * @return bool */ public function isBetween($date1, $date2, $equal = true): bool; /** * Check if its the birthday. Compares the date/month values of the two dates. * * @example * ``` * Carbon::now()->subYears(5)->isBirthday(); // true * Carbon::now()->subYears(5)->subDay()->isBirthday(); // false * Carbon::parse('2019-06-05')->isBirthday(Carbon::parse('2001-06-05')); // true * Carbon::parse('2019-06-05')->isBirthday(Carbon::parse('2001-06-06')); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day. * * @return bool */ public function isBirthday($date = null); /** * Determines if the instance is in the current unit given. * * @example * ``` * Carbon::now()->isCurrentUnit('hour'); // true * Carbon::now()->subHours(2)->isCurrentUnit('hour'); // false * ``` * * @param string $unit The unit to test. * * @throws BadMethodCallException * * @return bool */ public function isCurrentUnit($unit); /** * Checks if this day is a specific day of the week. * * @example * ``` * Carbon::parse('2019-07-17')->isDayOfWeek(Carbon::WEDNESDAY); // true * Carbon::parse('2019-07-17')->isDayOfWeek(Carbon::FRIDAY); // false * Carbon::parse('2019-07-17')->isDayOfWeek('Wednesday'); // true * Carbon::parse('2019-07-17')->isDayOfWeek('Friday'); // false * ``` * * @param int $dayOfWeek * * @return bool */ public function isDayOfWeek($dayOfWeek); /** * Check if the instance is end of day. * * @example * ``` * Carbon::parse('2019-02-28 23:59:59.999999')->isEndOfDay(); // true * Carbon::parse('2019-02-28 23:59:59.123456')->isEndOfDay(); // true * Carbon::parse('2019-02-28 23:59:59')->isEndOfDay(); // true * Carbon::parse('2019-02-28 23:59:58.999999')->isEndOfDay(); // false * Carbon::parse('2019-02-28 23:59:59.999999')->isEndOfDay(true); // true * Carbon::parse('2019-02-28 23:59:59.123456')->isEndOfDay(true); // false * Carbon::parse('2019-02-28 23:59:59')->isEndOfDay(true); // false * ``` * * @param bool $checkMicroseconds check time at microseconds precision * * @return bool */ public function isEndOfDay($checkMicroseconds = false); /** * Returns true if the date was created using CarbonImmutable::endOfTime() * * @return bool */ public function isEndOfTime(): bool; /** * Determines if the instance is in the future, ie. greater (after) than now. * * @example * ``` * Carbon::now()->addHours(5)->isFuture(); // true * Carbon::now()->subHours(5)->isFuture(); // false * ``` * * @return bool */ public function isFuture(); /** * Returns true if the current class/instance is immutable. * * @return bool */ public static function isImmutable(); /** * Check if today is the last day of the Month * * @example * ``` * Carbon::parse('2019-02-28')->isLastOfMonth(); // true * Carbon::parse('2019-03-28')->isLastOfMonth(); // false * Carbon::parse('2019-03-30')->isLastOfMonth(); // false * Carbon::parse('2019-03-31')->isLastOfMonth(); // true * Carbon::parse('2019-04-30')->isLastOfMonth(); // true * ``` * * @return bool */ public function isLastOfMonth(); /** * Determines if the instance is a leap year. * * @example * ``` * Carbon::parse('2020-01-01')->isLeapYear(); // true * Carbon::parse('2019-01-01')->isLeapYear(); // false * ``` * * @return bool */ public function isLeapYear(); /** * Determines if the instance is a long year (using ISO 8601 year). * * @example * ``` * Carbon::parse('2015-01-01')->isLongIsoYear(); // true * Carbon::parse('2016-01-01')->isLongIsoYear(); // true * Carbon::parse('2016-01-03')->isLongIsoYear(); // false * Carbon::parse('2019-12-29')->isLongIsoYear(); // false * Carbon::parse('2019-12-30')->isLongIsoYear(); // true * ``` * * @see https://en.wikipedia.org/wiki/ISO_8601#Week_dates * * @return bool */ public function isLongIsoYear(); /** * Determines if the instance is a long year (using calendar year). * * ⚠️ This method completely ignores month and day to use the numeric year number, * it's not correct if the exact date matters. For instance as `2019-12-30` is already * in the first week of the 2020 year, if you want to know from this date if ISO week * year 2020 is a long year, use `isLongIsoYear` instead. * * @example * ``` * Carbon::create(2015)->isLongYear(); // true * Carbon::create(2016)->isLongYear(); // false * ``` * * @see https://en.wikipedia.org/wiki/ISO_8601#Week_dates * * @return bool */ public function isLongYear(); /** * Check if the instance is midday. * * @example * ``` * Carbon::parse('2019-02-28 11:59:59.999999')->isMidday(); // false * Carbon::parse('2019-02-28 12:00:00')->isMidday(); // true * Carbon::parse('2019-02-28 12:00:00.999999')->isMidday(); // true * Carbon::parse('2019-02-28 12:00:01')->isMidday(); // false * ``` * * @return bool */ public function isMidday(); /** * Check if the instance is start of day / midnight. * * @example * ``` * Carbon::parse('2019-02-28 00:00:00')->isMidnight(); // true * Carbon::parse('2019-02-28 00:00:00.999999')->isMidnight(); // true * Carbon::parse('2019-02-28 00:00:01')->isMidnight(); // false * ``` * * @return bool */ public function isMidnight(); /** * Returns true if a property can be changed via setter. * * @param string $unit * * @return bool */ public static function isModifiableUnit($unit); /** * Returns true if the current class/instance is mutable. * * @return bool */ public static function isMutable(); /** * Determines if the instance is in the past, ie. less (before) than now. * * @example * ``` * Carbon::now()->subHours(5)->isPast(); // true * Carbon::now()->addHours(5)->isPast(); // false * ``` * * @return bool */ public function isPast(); /** * Compares the formatted values of the two dates. * * @example * ``` * Carbon::parse('2019-06-13')->isSameAs('Y-d', Carbon::parse('2019-12-13')); // true * Carbon::parse('2019-06-13')->isSameAs('Y-d', Carbon::parse('2019-06-14')); // false * ``` * * @param string $format date formats to compare. * @param \Carbon\Carbon|\DateTimeInterface|string|null $date instance to compare with or null to use current day. * * @return bool */ public function isSameAs($format, $date = null); /** * Checks if the passed in date is in the same month as the instance´s month. * * @example * ``` * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2019-01-01')); // true * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2019-02-01')); // false * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2018-01-01')); // false * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2018-01-01'), false); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date. * @param bool $ofSameYear Check if it is the same month in the same year. * * @return bool */ public function isSameMonth($date = null, $ofSameYear = true); /** * Checks if the passed in date is in the same quarter as the instance quarter (and year if needed). * * @example * ``` * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2019-03-01')); // true * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2019-04-01')); // false * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2018-03-01')); // false * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2018-03-01'), false); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|string|null $date The instance to compare with or null to use current day. * @param bool $ofSameYear Check if it is the same month in the same year. * * @return bool */ public function isSameQuarter($date = null, $ofSameYear = true); /** * Determines if the instance is in the current unit given. * * @example * ``` * Carbon::parse('2019-01-13')->isSameUnit('year', Carbon::parse('2019-12-25')); // true * Carbon::parse('2018-12-13')->isSameUnit('year', Carbon::parse('2019-12-25')); // false * ``` * * @param string $unit singular unit string * @param \Carbon\Carbon|\DateTimeInterface|null $date instance to compare with or null to use current day. * * @throws BadComparisonUnitException * * @return bool */ public function isSameUnit($unit, $date = null); /** * Check if the instance is start of day / midnight. * * @example * ``` * Carbon::parse('2019-02-28 00:00:00')->isStartOfDay(); // true * Carbon::parse('2019-02-28 00:00:00.999999')->isStartOfDay(); // true * Carbon::parse('2019-02-28 00:00:01')->isStartOfDay(); // false * Carbon::parse('2019-02-28 00:00:00.000000')->isStartOfDay(true); // true * Carbon::parse('2019-02-28 00:00:00.000012')->isStartOfDay(true); // false * ``` * * @param bool $checkMicroseconds check time at microseconds precision * * @return bool */ public function isStartOfDay($checkMicroseconds = false); /** * Returns true if the date was created using CarbonImmutable::startOfTime() * * @return bool */ public function isStartOfTime(): bool; /** * Returns true if the strict mode is globally in use, false else. * (It can be overridden in specific instances.) * * @return bool */ public static function isStrictModeEnabled(); /** * Determines if the instance is today. * * @example * ``` * Carbon::today()->isToday(); // true * Carbon::tomorrow()->isToday(); // false * ``` * * @return bool */ public function isToday(); /** * Determines if the instance is tomorrow. * * @example * ``` * Carbon::tomorrow()->isTomorrow(); // true * Carbon::yesterday()->isTomorrow(); // false * ``` * * @return bool */ public function isTomorrow(); /** * Determines if the instance is a weekday. * * @example * ``` * Carbon::parse('2019-07-14')->isWeekday(); // false * Carbon::parse('2019-07-15')->isWeekday(); // true * ``` * * @return bool */ public function isWeekday(); /** * Determines if the instance is a weekend day. * * @example * ``` * Carbon::parse('2019-07-14')->isWeekend(); // true * Carbon::parse('2019-07-15')->isWeekend(); // false * ``` * * @return bool */ public function isWeekend(); /** * Determines if the instance is yesterday. * * @example * ``` * Carbon::yesterday()->isYesterday(); // true * Carbon::tomorrow()->isYesterday(); // false * ``` * * @return bool */ public function isYesterday(); /** * Format in the current language using ISO replacement patterns. * * @param string $format * @param string|null $originalFormat provide context if a chunk has been passed alone * * @return string */ public function isoFormat(string $format, ?string $originalFormat = null): string; /** * Get/set the week number using given first day of week and first * day of year included in the first week. Or use ISO format if no settings * given. * * @param int|null $week * @param int|null $dayOfWeek * @param int|null $dayOfYear * * @return int|static */ public function isoWeek($week = null, $dayOfWeek = null, $dayOfYear = null); /** * Set/get the week number of year using given first day of week and first * day of year included in the first week. Or use ISO format if no settings * given. * * @param int|null $year if null, act as a getter, if not null, set the year and return current instance. * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday) * @param int|null $dayOfYear first day of year included in the week #1 * * @return int|static */ public function isoWeekYear($year = null, $dayOfWeek = null, $dayOfYear = null); /** * Get/set the ISO weekday from 1 (Monday) to 7 (Sunday). * * @param int|null $value new value for weekday if using as setter. * * @return static|int */ public function isoWeekday($value = null); /** * Get the number of weeks of the current week-year using given first day of week and first * day of year included in the first week. Or use ISO format if no settings * given. * * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday) * @param int|null $dayOfYear first day of year included in the week #1 * * @return int */ public function isoWeeksInYear($dayOfWeek = null, $dayOfYear = null); /** * Prepare the object for JSON serialization. * * @return array|string */ #[ReturnTypeWillChange] public function jsonSerialize(); /** * Modify to the last occurrence of a given day of the week * in the current month. If no dayOfWeek is provided, modify to the * last day of the current month. Use the supplied constants * to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param int|null $dayOfWeek * * @return static */ public function lastOfMonth($dayOfWeek = null); /** * Modify to the last occurrence of a given day of the week * in the current quarter. If no dayOfWeek is provided, modify to the * last day of the current quarter. Use the supplied constants * to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param int|null $dayOfWeek day of the week default null * * @return static */ public function lastOfQuarter($dayOfWeek = null); /** * Modify to the last occurrence of a given day of the week * in the current year. If no dayOfWeek is provided, modify to the * last day of the current year. Use the supplied constants * to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param int|null $dayOfWeek day of the week default null * * @return static */ public function lastOfYear($dayOfWeek = null); /** * Determines if the instance is less (before) than another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->lessThan('2018-07-25 12:45:15'); // false * Carbon::parse('2018-07-25 12:45:16')->lessThan('2018-07-25 12:45:16'); // false * Carbon::parse('2018-07-25 12:45:16')->lessThan('2018-07-25 12:45:17'); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @return bool */ public function lessThan($date): bool; /** * Determines if the instance is less (before) or equal to another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->lessThanOrEqualTo('2018-07-25 12:45:15'); // false * Carbon::parse('2018-07-25 12:45:16')->lessThanOrEqualTo('2018-07-25 12:45:16'); // true * Carbon::parse('2018-07-25 12:45:16')->lessThanOrEqualTo('2018-07-25 12:45:17'); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @return bool */ public function lessThanOrEqualTo($date): bool; /** * Get/set the locale for the current instance. * * @param string|null $locale * @param string ...$fallbackLocales * * @return $this|string */ public function locale(?string $locale = null, ...$fallbackLocales); /** * Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow). * Support is considered enabled if the 3 words are translated in the given locale. * * @param string $locale locale ex. en * * @return bool */ public static function localeHasDiffOneDayWords($locale); /** * Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after). * Support is considered enabled if the 4 sentences are translated in the given locale. * * @param string $locale locale ex. en * * @return bool */ public static function localeHasDiffSyntax($locale); /** * Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow). * Support is considered enabled if the 2 words are translated in the given locale. * * @param string $locale locale ex. en * * @return bool */ public static function localeHasDiffTwoDayWords($locale); /** * Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X). * Support is considered enabled if the 4 sentences are translated in the given locale. * * @param string $locale locale ex. en * * @return bool */ public static function localeHasPeriodSyntax($locale); /** * Returns true if the given locale is internally supported and has short-units support. * Support is considered enabled if either year, day or hour has a short variant translated. * * @param string $locale locale ex. en * * @return bool */ public static function localeHasShortUnits($locale); /** * Determines if the instance is less (before) than another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->lt('2018-07-25 12:45:15'); // false * Carbon::parse('2018-07-25 12:45:16')->lt('2018-07-25 12:45:16'); // false * Carbon::parse('2018-07-25 12:45:16')->lt('2018-07-25 12:45:17'); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see lessThan() * * @return bool */ public function lt($date): bool; /** * Determines if the instance is less (before) or equal to another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->lte('2018-07-25 12:45:15'); // false * Carbon::parse('2018-07-25 12:45:16')->lte('2018-07-25 12:45:16'); // true * Carbon::parse('2018-07-25 12:45:16')->lte('2018-07-25 12:45:17'); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see lessThanOrEqualTo() * * @return bool */ public function lte($date): bool; /** * Register a custom macro. * * @example * ``` * $userSettings = [ * 'locale' => 'pt', * 'timezone' => 'America/Sao_Paulo', * ]; * Carbon::macro('userFormat', function () use ($userSettings) { * return $this->copy()->locale($userSettings['locale'])->tz($userSettings['timezone'])->calendar(); * }); * echo Carbon::yesterday()->hours(11)->userFormat(); * ``` * * @param string $name * @param object|callable $macro * * @return void */ public static function macro($name, $macro); /** * Make a Carbon instance from given variable if possible. * * Always return a new instance. Parse only strings and only these likely to be dates (skip intervals * and recurrences). Throw an exception for invalid format, but otherwise return null. * * @param mixed $var * * @throws InvalidFormatException * * @return static|null */ public static function make($var); /** * Get the maximum instance between a given instance (default now) and the current instance. * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @return static */ public function max($date = null); /** * Create a Carbon instance for the greatest supported date. * * @return static */ public static function maxValue(); /** * Get the maximum instance between a given instance (default now) and the current instance. * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see max() * * @return static */ public function maximum($date = null); /** * Return the meridiem of the current time in the current locale. * * @param bool $isLower if true, returns lowercase variant if available in the current locale. * * @return string */ public function meridiem(bool $isLower = false): string; /** * Modify to midday, default to self::$midDayAt * * @return static */ public function midDay(); /** * Get the minimum instance between a given instance (default now) and the current instance. * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @return static */ public function min($date = null); /** * Create a Carbon instance for the lowest supported date. * * @return static */ public static function minValue(); /** * Get the minimum instance between a given instance (default now) and the current instance. * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see min() * * @return static */ public function minimum($date = null); /** * Mix another object into the class. * * @example * ``` * Carbon::mixin(new class { * public function addMoon() { * return function () { * return $this->addDays(30); * }; * } * public function subMoon() { * return function () { * return $this->subDays(30); * }; * } * }); * $fullMoon = Carbon::create('2018-12-22'); * $nextFullMoon = $fullMoon->addMoon(); * $blackMoon = Carbon::create('2019-01-06'); * $previousBlackMoon = $blackMoon->subMoon(); * echo "$nextFullMoon\n"; * echo "$previousBlackMoon\n"; * ``` * * @param object|string $mixin * * @throws ReflectionException * * @return void */ public static function mixin($mixin); /** * Calls \DateTime::modify if mutable or \DateTimeImmutable::modify else. * * @see https://php.net/manual/en/datetime.modify.php * * @return static|false */ #[ReturnTypeWillChange] public function modify($modify); /** * Determines if the instance is not equal to another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->ne('2018-07-25 12:45:16'); // false * Carbon::parse('2018-07-25 12:45:16')->ne(Carbon::parse('2018-07-25 12:45:16')); // false * Carbon::parse('2018-07-25 12:45:16')->ne('2018-07-25 12:45:17'); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see notEqualTo() * * @return bool */ public function ne($date): bool; /** * Modify to the next occurrence of a given modifier such as a day of * the week. If no modifier is provided, modify to the next occurrence * of the current day of the week. Use the supplied constants * to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param string|int|null $modifier * * @return static|false */ public function next($modifier = null); /** * Go forward to the next weekday. * * @return static */ public function nextWeekday(); /** * Go forward to the next weekend day. * * @return static */ public function nextWeekendDay(); /** * Determines if the instance is not equal to another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->notEqualTo('2018-07-25 12:45:16'); // false * Carbon::parse('2018-07-25 12:45:16')->notEqualTo(Carbon::parse('2018-07-25 12:45:16')); // false * Carbon::parse('2018-07-25 12:45:16')->notEqualTo('2018-07-25 12:45:17'); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @return bool */ public function notEqualTo($date): bool; /** * Get a Carbon instance for the current date and time. * * @param DateTimeZone|string|null $tz * * @return static */ public static function now($tz = null); /** * Returns a present instance in the same timezone. * * @return static */ public function nowWithSameTz(); /** * Modify to the given occurrence of a given day of the week * in the current month. If the calculated occurrence is outside the scope * of the current month, then return false and no modifications are made. * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param int $nth * @param int $dayOfWeek * * @return mixed */ public function nthOfMonth($nth, $dayOfWeek); /** * Modify to the given occurrence of a given day of the week * in the current quarter. If the calculated occurrence is outside the scope * of the current quarter, then return false and no modifications are made. * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param int $nth * @param int $dayOfWeek * * @return mixed */ public function nthOfQuarter($nth, $dayOfWeek); /** * Modify to the given occurrence of a given day of the week * in the current year. If the calculated occurrence is outside the scope * of the current year, then return false and no modifications are made. * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param int $nth * @param int $dayOfWeek * * @return mixed */ public function nthOfYear($nth, $dayOfWeek); /** * Return a property with its ordinal. * * @param string $key * @param string|null $period * * @return string */ public function ordinal(string $key, ?string $period = null): string; /** * Create a carbon instance from a string. * * This is an alias for the constructor that allows better fluent syntax * as it allows you to do Carbon::parse('Monday next week')->fn() rather * than (new Carbon('Monday next week'))->fn(). * * @param string|DateTimeInterface|null $time * @param DateTimeZone|string|null $tz * * @throws InvalidFormatException * * @return static */ public static function parse($time = null, $tz = null); /** * Create a carbon instance from a localized string (in French, Japanese, Arabic, etc.). * * @param string $time date/time string in the given language (may also contain English). * @param string|null $locale if locale is null or not specified, current global locale will be * used instead. * @param DateTimeZone|string|null $tz optional timezone for the new instance. * * @throws InvalidFormatException * * @return static */ public static function parseFromLocale($time, $locale = null, $tz = null); /** * Returns standardized plural of a given singular/plural unit name (in English). * * @param string $unit * * @return string */ public static function pluralUnit(string $unit): string; /** * Modify to the previous occurrence of a given modifier such as a day of * the week. If no dayOfWeek is provided, modify to the previous occurrence * of the current day of the week. Use the supplied constants * to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param string|int|null $modifier * * @return static|false */ public function previous($modifier = null); /** * Go backward to the previous weekday. * * @return static */ public function previousWeekday(); /** * Go backward to the previous weekend day. * * @return static */ public function previousWeekendDay(); /** * Create a iterable CarbonPeriod object from current date to a given end date (and optional interval). * * @param \DateTimeInterface|Carbon|CarbonImmutable|null $end period end date * @param int|\DateInterval|string|null $interval period default interval or number of the given $unit * @param string|null $unit if specified, $interval must be an integer * * @return CarbonPeriod */ public function range($end = null, $interval = null, $unit = null); /** * Call native PHP DateTime/DateTimeImmutable add() method. * * @param DateInterval $interval * * @return static */ public function rawAdd(DateInterval $interval); /** * Create a Carbon instance from a specific format. * * @param string $format Datetime format * @param string $time * @param DateTimeZone|string|false|null $tz * * @throws InvalidFormatException * * @return static|false */ public static function rawCreateFromFormat($format, $time, $tz = null); /** * @see https://php.net/manual/en/datetime.format.php * * @param string $format * * @return string */ public function rawFormat($format); /** * Create a carbon instance from a string. * * This is an alias for the constructor that allows better fluent syntax * as it allows you to do Carbon::parse('Monday next week')->fn() rather * than (new Carbon('Monday next week'))->fn(). * * @param string|DateTimeInterface|null $time * @param DateTimeZone|string|null $tz * * @throws InvalidFormatException * * @return static */ public static function rawParse($time = null, $tz = null); /** * Call native PHP DateTime/DateTimeImmutable sub() method. * * @param DateInterval $interval * * @return static */ public function rawSub(DateInterval $interval); /** * Remove all macros and generic macros. */ public static function resetMacros(); /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants * are available for quarters, years, decade, centuries, millennia (singular and plural forms). * @see settings * * Reset the month overflow behavior. * * @return void */ public static function resetMonthsOverflow(); /** * Reset the format used to the default when type juggling a Carbon instance to a string * * @return void */ public static function resetToStringFormat(); /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants * are available for quarters, years, decade, centuries, millennia (singular and plural forms). * @see settings * * Reset the month overflow behavior. * * @return void */ public static function resetYearsOverflow(); /** * Round the current instance second with given precision if specified. * * @param float|int|string|\DateInterval|null $precision * @param string $function * * @return CarbonInterface */ public function round($precision = 1, $function = 'round'); /** * Round the current instance at the given unit with given precision if specified and the given function. * * @param string $unit * @param float|int $precision * @param string $function * * @return CarbonInterface */ public function roundUnit($unit, $precision = 1, $function = 'round'); /** * Round the current instance week. * * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week * * @return CarbonInterface */ public function roundWeek($weekStartsAt = null); /** * The number of seconds since midnight. * * @return int */ public function secondsSinceMidnight(); /** * The number of seconds until 23:59:59. * * @return int */ public function secondsUntilEndOfDay(); /** * Return a serialized string of the instance. * * @return string */ public function serialize(); /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather transform Carbon object before the serialization. * * JSON serialize all Carbon instances using the given callback. * * @param callable $callback * * @return void */ public static function serializeUsing($callback); /** * Set a part of the Carbon object * * @param string|array $name * @param string|int|DateTimeZone $value * * @throws ImmutableException|UnknownSetterException * * @return $this */ public function set($name, $value = null); /** * Set the date with gregorian year, month and day numbers. * * @see https://php.net/manual/en/datetime.setdate.php * * @param int $year * @param int $month * @param int $day * * @return static */ #[ReturnTypeWillChange] public function setDate($year, $month, $day); /** * Set the year, month, and date for this instance to that of the passed instance. * * @param Carbon|DateTimeInterface $date now if null * * @return static */ public function setDateFrom($date = null); /** * Set the date and time all together. * * @param int $year * @param int $month * @param int $day * @param int $hour * @param int $minute * @param int $second * @param int $microseconds * * @return static */ public function setDateTime($year, $month, $day, $hour, $minute, $second = 0, $microseconds = 0); /** * Set the date and time for this instance to that of the passed instance. * * @param Carbon|DateTimeInterface $date * * @return static */ public function setDateTimeFrom($date = null); /** * Set the day (keeping the current time) to the start of the week + the number of days passed as the first * parameter. First day of week is driven by the locale unless explicitly set with the second parameter. * * @param int $numberOfDays number of days to add after the start of the current week * @param int|null $weekStartsAt optional start allow you to specify the day of week to use to start the week, * if not provided, start of week is inferred from the locale * (Sunday for en_US, Monday for de_DE, etc.) * * @return static */ public function setDaysFromStartOfWeek(int $numberOfDays, ?int $weekStartsAt = null); /** * Set the fallback locale. * * @see https://symfony.com/doc/current/components/translation.html#fallback-locales * * @param string $locale */ public static function setFallbackLocale($locale); /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * @see settings * * @param int $humanDiffOptions */ public static function setHumanDiffOptions($humanDiffOptions); /** * Set a date according to the ISO 8601 standard - using weeks and day offsets rather than specific dates. * * @see https://php.net/manual/en/datetime.setisodate.php * * @param int $year * @param int $week * @param int $day * * @return static */ #[ReturnTypeWillChange] public function setISODate($year, $week, $day = 1); /** * Set the translator for the current instance. * * @param \Symfony\Component\Translation\TranslatorInterface $translator * * @return $this */ public function setLocalTranslator(TranslatorInterface $translator); /** * Set the current translator locale and indicate if the source locale file exists. * Pass 'auto' as locale to use closest language from the current LC_TIME locale. * * @param string $locale locale ex. en * * @return bool */ public static function setLocale($locale); /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather consider mid-day is always 12pm, then if you need to test if it's an other * hour, test it explicitly: * $date->format('G') == 13 * or to set explicitly to a given hour: * $date->setTime(13, 0, 0, 0) * * Set midday/noon hour * * @param int $hour midday hour * * @return void */ public static function setMidDayAt($hour); /** * Set a Carbon instance (real or mock) to be returned when a "now" * instance is created. The provided instance will be returned * specifically under the following conditions: * - A call to the static now() method, ex. Carbon::now() * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null) * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now') * - When a string containing the desired time is passed to Carbon::parse(). * * Note the timezone parameter was left out of the examples above and * has no affect as the mock value will be returned regardless of its value. * * Only the moment is mocked with setTestNow(), the timezone will still be the one passed * as parameter of date_default_timezone_get() as a fallback (see setTestNowAndTimezone()). * * To clear the test instance call this method using the default * parameter of null. * * /!\ Use this method for unit tests only. * * @param DateTimeInterface|Closure|static|string|false|null $testNow real or mock Carbon instance */ public static function setTestNow($testNow = null); /** * Set a Carbon instance (real or mock) to be returned when a "now" * instance is created. The provided instance will be returned * specifically under the following conditions: * - A call to the static now() method, ex. Carbon::now() * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null) * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now') * - When a string containing the desired time is passed to Carbon::parse(). * * It will also align default timezone (e.g. call date_default_timezone_set()) with * the second argument or if null, with the timezone of the given date object. * * To clear the test instance call this method using the default * parameter of null. * * /!\ Use this method for unit tests only. * * @param DateTimeInterface|Closure|static|string|false|null $testNow real or mock Carbon instance */ public static function setTestNowAndTimezone($testNow = null, $tz = null); /** * Resets the current time of the DateTime object to a different time. * * @see https://php.net/manual/en/datetime.settime.php * * @param int $hour * @param int $minute * @param int $second * @param int $microseconds * * @return static */ #[ReturnTypeWillChange] public function setTime($hour, $minute, $second = 0, $microseconds = 0); /** * Set the hour, minute, second and microseconds for this instance to that of the passed instance. * * @param Carbon|DateTimeInterface $date now if null * * @return static */ public function setTimeFrom($date = null); /** * Set the time by time string. * * @param string $time * * @return static */ public function setTimeFromTimeString($time); /** * Set the instance's timestamp. * * Timestamp input can be given as int, float or a string containing one or more numbers. * * @param float|int|string $unixTimestamp * * @return static */ #[ReturnTypeWillChange] public function setTimestamp($unixTimestamp); /** * Set the instance's timezone from a string or object. * * @param DateTimeZone|string $value * * @return static */ #[ReturnTypeWillChange] public function setTimezone($value); /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather let Carbon object being cast to string with DEFAULT_TO_STRING_FORMAT, and * use other method or custom format passed to format() method if you need to dump another string * format. * * Set the default format used when type juggling a Carbon instance to a string. * * @param string|Closure|null $format * * @return void */ public static function setToStringFormat($format); /** * Set the default translator instance to use. * * @param \Symfony\Component\Translation\TranslatorInterface $translator * * @return void */ public static function setTranslator(TranslatorInterface $translator); /** * Set specified unit to new given value. * * @param string $unit year, month, day, hour, minute, second or microsecond * @param int $value new value for given unit * * @return static */ public function setUnit($unit, $value = null); /** * Set any unit to a new value without overflowing current other unit given. * * @param string $valueUnit unit name to modify * @param int $value new value for the input unit * @param string $overflowUnit unit name to not overflow * * @return static */ public function setUnitNoOverflow($valueUnit, $value, $overflowUnit); /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use UTF-8 language packages on every machine. * * Set if UTF8 will be used for localized date/time. * * @param bool $utf8 */ public static function setUtf8($utf8); /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * Use $weekStartsAt optional parameter instead when using startOfWeek, floorWeek, ceilWeek * or roundWeek method. You can also use the 'first_day_of_week' locale setting to change the * start of week according to current locale selected and implicitly the end of week. * * Set the last day of week * * @param int|string $day week end day (or 'auto' to get the day before the first day of week * from Carbon::getLocale() culture). * * @return void */ public static function setWeekEndsAt($day); /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * Use $weekEndsAt optional parameter instead when using endOfWeek method. You can also use the * 'first_day_of_week' locale setting to change the start of week according to current locale * selected and implicitly the end of week. * * Set the first day of week * * @param int|string $day week start day (or 'auto' to get the first day of week from Carbon::getLocale() culture). * * @return void */ public static function setWeekStartsAt($day); /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather consider week-end is always saturday and sunday, and if you have some custom * week-end days to handle, give to those days an other name and create a macro for them: * * ``` * Carbon::macro('isDayOff', function ($date) { * return $date->isSunday() || $date->isMonday(); * }); * Carbon::macro('isNotDayOff', function ($date) { * return !$date->isDayOff(); * }); * if ($someDate->isDayOff()) ... * if ($someDate->isNotDayOff()) ... * // Add 5 not-off days * $count = 5; * while ($someDate->isDayOff() || ($count-- > 0)) { * $someDate->addDay(); * } * ``` * * Set weekend days * * @param array $days * * @return void */ public static function setWeekendDays($days); /** * Set specific options. * - strictMode: true|false|null * - monthOverflow: true|false|null * - yearOverflow: true|false|null * - humanDiffOptions: int|null * - toStringFormat: string|Closure|null * - toJsonFormat: string|Closure|null * - locale: string|null * - timezone: \DateTimeZone|string|int|null * - macros: array|null * - genericMacros: array|null * * @param array $settings * * @return $this|static */ public function settings(array $settings); /** * Set the instance's timezone from a string or object and add/subtract the offset difference. * * @param DateTimeZone|string $value * * @return static */ public function shiftTimezone($value); /** * Get the month overflow global behavior (can be overridden in specific instances). * * @return bool */ public static function shouldOverflowMonths(); /** * Get the month overflow global behavior (can be overridden in specific instances). * * @return bool */ public static function shouldOverflowYears(); /** * @alias diffForHumans * * Get the difference in a human readable format in the current locale from current instance to an other * instance given (or now if null given). */ public function since($other = null, $syntax = null, $short = false, $parts = 1, $options = null); /** * Returns standardized singular of a given singular/plural unit name (in English). * * @param string $unit * * @return string */ public static function singularUnit(string $unit): string; /** * Modify to start of current given unit. * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16.334455') * ->startOf('month') * ->endOf('week', Carbon::FRIDAY); * ``` * * @param string $unit * @param array<int, mixed> $params * * @return static */ public function startOf($unit, ...$params); /** * Resets the date to the first day of the century and the time to 00:00:00 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfCentury(); * ``` * * @return static */ public function startOfCentury(); /** * Resets the time to 00:00:00 start of day * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfDay(); * ``` * * @return static */ public function startOfDay(); /** * Resets the date to the first day of the decade and the time to 00:00:00 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfDecade(); * ``` * * @return static */ public function startOfDecade(); /** * Modify to start of current hour, minutes and seconds become 0 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfHour(); * ``` * * @return static */ public function startOfHour(); /** * Resets the date to the first day of the millennium and the time to 00:00:00 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfMillennium(); * ``` * * @return static */ public function startOfMillennium(); /** * Modify to start of current minute, seconds become 0 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfMinute(); * ``` * * @return static */ public function startOfMinute(); /** * Resets the date to the first day of the month and the time to 00:00:00 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfMonth(); * ``` * * @return static */ public function startOfMonth(); /** * Resets the date to the first day of the quarter and the time to 00:00:00 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfQuarter(); * ``` * * @return static */ public function startOfQuarter(); /** * Modify to start of current second, microseconds become 0 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16.334455') * ->startOfSecond() * ->format('H:i:s.u'); * ``` * * @return static */ public function startOfSecond(); /** * Resets the date to the first day of week (defined in $weekStartsAt) and the time to 00:00:00 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfWeek() . "\n"; * echo Carbon::parse('2018-07-25 12:45:16')->locale('ar')->startOfWeek() . "\n"; * echo Carbon::parse('2018-07-25 12:45:16')->startOfWeek(Carbon::SUNDAY) . "\n"; * ``` * * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week * * @return static */ public function startOfWeek($weekStartsAt = null); /** * Resets the date to the first day of the year and the time to 00:00:00 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfYear(); * ``` * * @return static */ public function startOfYear(); /** * Subtract given units or interval to the current instance. * * @example $date->sub('hour', 3) * @example $date->sub(15, 'days') * @example $date->sub(CarbonInterval::days(4)) * * @param string|DateInterval|Closure|CarbonConverterInterface $unit * @param int $value * @param bool|null $overflow * * @return static */ #[ReturnTypeWillChange] public function sub($unit, $value = 1, $overflow = null); public function subRealUnit($unit, $value = 1); /** * Subtract given units to the current instance. * * @param string $unit * @param int $value * @param bool|null $overflow * * @return static */ public function subUnit($unit, $value = 1, $overflow = null); /** * Subtract any unit to a new value without overflowing current other unit given. * * @param string $valueUnit unit name to modify * @param int $value amount to subtract to the input unit * @param string $overflowUnit unit name to not overflow * * @return static */ public function subUnitNoOverflow($valueUnit, $value, $overflowUnit); /** * Subtract given units or interval to the current instance. * * @see sub() * * @param string|DateInterval $unit * @param int $value * @param bool|null $overflow * * @return static */ public function subtract($unit, $value = 1, $overflow = null); /** * Get the difference in a human readable format in the current locale from current instance to an other * instance given (or now if null given). * * @return string */ public function timespan($other = null, $timezone = null); /** * Set the instance's timestamp. * * Timestamp input can be given as int, float or a string containing one or more numbers. * * @param float|int|string $unixTimestamp * * @return static */ public function timestamp($unixTimestamp); /** * @alias setTimezone * * @param DateTimeZone|string $value * * @return static */ public function timezone($value); /** * Get the difference in a human readable format in the current locale from an other * instance given (or now if null given) to current instance. * * When comparing a value in the past to default now: * 1 hour from now * 5 months from now * * When comparing a value in the future to default now: * 1 hour ago * 5 months ago * * When comparing a value in the past to another value: * 1 hour after * 5 months after * * When comparing a value in the future to another value: * 1 hour before * 5 months before * * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below; * if null passed, now will be used as comparison reference; * if any other type, it will be converted to date and used as reference. * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains: * - 'syntax' entry (see below) * - 'short' entry (see below) * - 'parts' entry (see below) * - 'options' entry (see below) * - 'join' entry determines how to join multiple parts of the string * ` - if $join is a string, it's used as a joiner glue * ` - if $join is a callable/closure, it get the list of string and should return a string * ` - if $join is an array, the first item will be the default glue, and the second item * ` will be used instead of the glue for the last item * ` - if $join is true, it will be guessed from the locale ('list' translation file entry) * ` - if $join is missing, a space will be used as glue * - 'other' entry (see above) * if int passed, it add modifiers: * Possible values: * - CarbonInterface::DIFF_ABSOLUTE no modifiers * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier * Default value: CarbonInterface::DIFF_ABSOLUTE * @param bool $short displays short format of time units * @param int $parts maximum number of parts to display (default value: 1: single unit) * @param int $options human diff options * * @return string */ public function to($other = null, $syntax = null, $short = false, $parts = 1, $options = null); /** * Get default array representation. * * @example * ``` * var_dump(Carbon::now()->toArray()); * ``` * * @return array */ public function toArray(); /** * Format the instance as ATOM * * @example * ``` * echo Carbon::now()->toAtomString(); * ``` * * @return string */ public function toAtomString(); /** * Format the instance as COOKIE * * @example * ``` * echo Carbon::now()->toCookieString(); * ``` * * @return string */ public function toCookieString(); /** * @alias toDateTime * * Return native DateTime PHP object matching the current instance. * * @example * ``` * var_dump(Carbon::now()->toDate()); * ``` * * @return DateTime */ public function toDate(); /** * Format the instance as date * * @example * ``` * echo Carbon::now()->toDateString(); * ``` * * @return string */ public function toDateString(); /** * Return native DateTime PHP object matching the current instance. * * @example * ``` * var_dump(Carbon::now()->toDateTime()); * ``` * * @return DateTime */ public function toDateTime(); /** * Return native toDateTimeImmutable PHP object matching the current instance. * * @example * ``` * var_dump(Carbon::now()->toDateTimeImmutable()); * ``` * * @return DateTimeImmutable */ public function toDateTimeImmutable(); /** * Format the instance as date and time T-separated with no timezone * * @example * ``` * echo Carbon::now()->toDateTimeLocalString(); * echo "\n"; * echo Carbon::now()->toDateTimeLocalString('minute'); // You can specify precision among: minute, second, millisecond and microsecond * ``` * * @param string $unitPrecision * * @return string */ public function toDateTimeLocalString($unitPrecision = 'second'); /** * Format the instance as date and time * * @example * ``` * echo Carbon::now()->toDateTimeString(); * ``` * * @param string $unitPrecision * * @return string */ public function toDateTimeString($unitPrecision = 'second'); /** * Format the instance with day, date and time * * @example * ``` * echo Carbon::now()->toDayDateTimeString(); * ``` * * @return string */ public function toDayDateTimeString(); /** * Format the instance as a readable date * * @example * ``` * echo Carbon::now()->toFormattedDateString(); * ``` * * @return string */ public function toFormattedDateString(); /** * Format the instance with the day, and a readable date * * @example * ``` * echo Carbon::now()->toFormattedDayDateString(); * ``` * * @return string */ public function toFormattedDayDateString(): string; /** * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z, if $keepOffset truthy, offset will be kept: * 1977-04-22T01:00:00-05:00). * * @example * ``` * echo Carbon::now('America/Toronto')->toISOString() . "\n"; * echo Carbon::now('America/Toronto')->toISOString(true) . "\n"; * ``` * * @param bool $keepOffset Pass true to keep the date offset. Else forced to UTC. * * @return null|string */ public function toISOString($keepOffset = false); /** * Return a immutable copy of the instance. * * @return CarbonImmutable */ public function toImmutable(); /** * Format the instance as ISO8601 * * @example * ``` * echo Carbon::now()->toIso8601String(); * ``` * * @return string */ public function toIso8601String(); /** * Convert the instance to UTC and return as Zulu ISO8601 * * @example * ``` * echo Carbon::now()->toIso8601ZuluString(); * ``` * * @param string $unitPrecision * * @return string */ public function toIso8601ZuluString($unitPrecision = 'second'); /** * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z) with UTC timezone. * * @example * ``` * echo Carbon::now('America/Toronto')->toJSON(); * ``` * * @return null|string */ public function toJSON(); /** * Return a mutable copy of the instance. * * @return Carbon */ public function toMutable(); /** * Get the difference in a human readable format in the current locale from an other * instance given to now * * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains: * - 'syntax' entry (see below) * - 'short' entry (see below) * - 'parts' entry (see below) * - 'options' entry (see below) * - 'join' entry determines how to join multiple parts of the string * ` - if $join is a string, it's used as a joiner glue * ` - if $join is a callable/closure, it get the list of string and should return a string * ` - if $join is an array, the first item will be the default glue, and the second item * ` will be used instead of the glue for the last item * ` - if $join is true, it will be guessed from the locale ('list' translation file entry) * ` - if $join is missing, a space will be used as glue * if int passed, it add modifiers: * Possible values: * - CarbonInterface::DIFF_ABSOLUTE no modifiers * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier * Default value: CarbonInterface::DIFF_ABSOLUTE * @param bool $short displays short format of time units * @param int $parts maximum number of parts to display (default value: 1: single part) * @param int $options human diff options * * @return string */ public function toNow($syntax = null, $short = false, $parts = 1, $options = null); /** * Get default object representation. * * @example * ``` * var_dump(Carbon::now()->toObject()); * ``` * * @return object */ public function toObject(); /** * Create a iterable CarbonPeriod object from current date to a given end date (and optional interval). * * @param \DateTimeInterface|Carbon|CarbonImmutable|int|null $end period end date or recurrences count if int * @param int|\DateInterval|string|null $interval period default interval or number of the given $unit * @param string|null $unit if specified, $interval must be an integer * * @return CarbonPeriod */ public function toPeriod($end = null, $interval = null, $unit = null); /** * Format the instance as RFC1036 * * @example * ``` * echo Carbon::now()->toRfc1036String(); * ``` * * @return string */ public function toRfc1036String(); /** * Format the instance as RFC1123 * * @example * ``` * echo Carbon::now()->toRfc1123String(); * ``` * * @return string */ public function toRfc1123String(); /** * Format the instance as RFC2822 * * @example * ``` * echo Carbon::now()->toRfc2822String(); * ``` * * @return string */ public function toRfc2822String(); /** * Format the instance as RFC3339 * * @param bool $extended * * @example * ``` * echo Carbon::now()->toRfc3339String() . "\n"; * echo Carbon::now()->toRfc3339String(true) . "\n"; * ``` * * @return string */ public function toRfc3339String($extended = false); /** * Format the instance as RFC7231 * * @example * ``` * echo Carbon::now()->toRfc7231String(); * ``` * * @return string */ public function toRfc7231String(); /** * Format the instance as RFC822 * * @example * ``` * echo Carbon::now()->toRfc822String(); * ``` * * @return string */ public function toRfc822String(); /** * Format the instance as RFC850 * * @example * ``` * echo Carbon::now()->toRfc850String(); * ``` * * @return string */ public function toRfc850String(); /** * Format the instance as RSS * * @example * ``` * echo Carbon::now()->toRssString(); * ``` * * @return string */ public function toRssString(); /** * Returns english human readable complete date string. * * @example * ``` * echo Carbon::now()->toString(); * ``` * * @return string */ public function toString(); /** * Format the instance as time * * @example * ``` * echo Carbon::now()->toTimeString(); * ``` * * @param string $unitPrecision * * @return string */ public function toTimeString($unitPrecision = 'second'); /** * Format the instance as W3C * * @example * ``` * echo Carbon::now()->toW3cString(); * ``` * * @return string */ public function toW3cString(); /** * Create a Carbon instance for today. * * @param DateTimeZone|string|null $tz * * @return static */ public static function today($tz = null); /** * Create a Carbon instance for tomorrow. * * @param DateTimeZone|string|null $tz * * @return static */ public static function tomorrow($tz = null); /** * Translate using translation string or callback available. * * @param string $key * @param array $parameters * @param string|int|float|null $number * @param \Symfony\Component\Translation\TranslatorInterface|null $translator * @param bool $altNumbers * * @return string */ public function translate(string $key, array $parameters = [], $number = null, ?TranslatorInterface $translator = null, bool $altNumbers = false): string; /** * Returns the alternative number for a given integer if available in the current locale. * * @param int $number * * @return string */ public function translateNumber(int $number): string; /** * Translate a time string from a locale to an other. * * @param string $timeString date/time/duration string to translate (may also contain English) * @param string|null $from input locale of the $timeString parameter (`Carbon::getLocale()` by default) * @param string|null $to output locale of the result returned (`"en"` by default) * @param int $mode specify what to translate with options: * - self::TRANSLATE_ALL (default) * - CarbonInterface::TRANSLATE_MONTHS * - CarbonInterface::TRANSLATE_DAYS * - CarbonInterface::TRANSLATE_UNITS * - CarbonInterface::TRANSLATE_MERIDIEM * You can use pipe to group: CarbonInterface::TRANSLATE_MONTHS | CarbonInterface::TRANSLATE_DAYS * * @return string */ public static function translateTimeString($timeString, $from = null, $to = null, $mode = self::TRANSLATE_ALL); /** * Translate a time string from the current locale (`$date->locale()`) to an other. * * @param string $timeString time string to translate * @param string|null $to output locale of the result returned ("en" by default) * * @return string */ public function translateTimeStringTo($timeString, $to = null); /** * Translate using translation string or callback available. * * @param \Symfony\Component\Translation\TranslatorInterface $translator * @param string $key * @param array $parameters * @param null $number * * @return string */ public static function translateWith(TranslatorInterface $translator, string $key, array $parameters = [], $number = null): string; /** * Format as ->format() do (using date replacements patterns from https://php.net/manual/en/function.date.php) * but translate words whenever possible (months, day names, etc.) using the current locale. * * @param string $format * * @return string */ public function translatedFormat(string $format): string; /** * Set the timezone or returns the timezone name if no arguments passed. * * @param DateTimeZone|string $value * * @return static|string */ public function tz($value = null); /** * @alias getTimestamp * * Returns the UNIX timestamp for the current date. * * @return int */ public function unix(); /** * @alias to * * Get the difference in a human readable format in the current locale from an other * instance given (or now if null given) to current instance. * * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below; * if null passed, now will be used as comparison reference; * if any other type, it will be converted to date and used as reference. * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains: * - 'syntax' entry (see below) * - 'short' entry (see below) * - 'parts' entry (see below) * - 'options' entry (see below) * - 'join' entry determines how to join multiple parts of the string * ` - if $join is a string, it's used as a joiner glue * ` - if $join is a callable/closure, it get the list of string and should return a string * ` - if $join is an array, the first item will be the default glue, and the second item * ` will be used instead of the glue for the last item * ` - if $join is true, it will be guessed from the locale ('list' translation file entry) * ` - if $join is missing, a space will be used as glue * - 'other' entry (see above) * if int passed, it add modifiers: * Possible values: * - CarbonInterface::DIFF_ABSOLUTE no modifiers * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier * Default value: CarbonInterface::DIFF_ABSOLUTE * @param bool $short displays short format of time units * @param int $parts maximum number of parts to display (default value: 1: single unit) * @param int $options human diff options * * @return string */ public function until($other = null, $syntax = null, $short = false, $parts = 1, $options = null); /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants * are available for quarters, years, decade, centuries, millennia (singular and plural forms). * @see settings * * Indicates if months should be calculated with overflow. * * @param bool $monthsOverflow * * @return void */ public static function useMonthsOverflow($monthsOverflow = true); /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * @see settings * * Enable the strict mode (or disable with passing false). * * @param bool $strictModeEnabled */ public static function useStrictMode($strictModeEnabled = true); /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants * are available for quarters, years, decade, centuries, millennia (singular and plural forms). * @see settings * * Indicates if years should be calculated with overflow. * * @param bool $yearsOverflow * * @return void */ public static function useYearsOverflow($yearsOverflow = true); /** * Set the instance's timezone to UTC. * * @return static */ public function utc(); /** * Returns the minutes offset to UTC if no arguments passed, else set the timezone with given minutes shift passed. * * @param int|null $minuteOffset * * @return int|static */ public function utcOffset(?int $minuteOffset = null); /** * Returns the milliseconds timestamps used amongst other by Date javascript objects. * * @return float */ public function valueOf(); /** * Get/set the week number using given first day of week and first * day of year included in the first week. Or use US format if no settings * given (Sunday / Jan 6). * * @param int|null $week * @param int|null $dayOfWeek * @param int|null $dayOfYear * * @return int|static */ public function week($week = null, $dayOfWeek = null, $dayOfYear = null); /** * Set/get the week number of year using given first day of week and first * day of year included in the first week. Or use US format if no settings * given (Sunday / Jan 6). * * @param int|null $year if null, act as a getter, if not null, set the year and return current instance. * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday) * @param int|null $dayOfYear first day of year included in the week #1 * * @return int|static */ public function weekYear($year = null, $dayOfWeek = null, $dayOfYear = null); /** * Get/set the weekday from 0 (Sunday) to 6 (Saturday). * * @param int|null $value new value for weekday if using as setter. * * @return static|int */ public function weekday($value = null); /** * Get the number of weeks of the current week-year using given first day of week and first * day of year included in the first week. Or use US format if no settings * given (Sunday / Jan 6). * * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday) * @param int|null $dayOfYear first day of year included in the week #1 * * @return int */ public function weeksInYear($dayOfWeek = null, $dayOfYear = null); /** * Temporarily sets a static date to be used within the callback. * Using setTestNow to set the date, executing the callback, then * clearing the test instance. * * /!\ Use this method for unit tests only. * * @template T * * @param DateTimeInterface|Closure|static|string|false|null $testNow real or mock Carbon instance * @param Closure(): T $callback * * @return T */ public static function withTestNow($testNow, $callback); /** * Create a Carbon instance for yesterday. * * @param DateTimeZone|string|null $tz * * @return static */ public static function yesterday($tz = null); // </methods> } PK������<1ZayK �� ��"��Carbon/Laravel/ServiceProvider.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Laravel; use Carbon\Carbon; use Carbon\CarbonImmutable; use Carbon\CarbonInterval; use Carbon\CarbonPeriod; use Illuminate\Contracts\Events\Dispatcher as DispatcherContract; use Illuminate\Events\Dispatcher; use Illuminate\Events\EventDispatcher; use Illuminate\Support\Carbon as IlluminateCarbon; use Illuminate\Support\Facades\Date; use Throwable; class ServiceProvider extends \Illuminate\Support\ServiceProvider { /** @var callable|null */ protected $appGetter = null; /** @var callable|null */ protected $localeGetter = null; public function setAppGetter(?callable $appGetter): void { $this->appGetter = $appGetter; } public function setLocaleGetter(?callable $localeGetter): void { $this->localeGetter = $localeGetter; } public function boot() { $this->updateLocale(); if (!$this->app->bound('events')) { return; } $service = $this; $events = $this->app['events']; if ($this->isEventDispatcher($events)) { $events->listen(class_exists('Illuminate\Foundation\Events\LocaleUpdated') ? 'Illuminate\Foundation\Events\LocaleUpdated' : 'locale.changed', function () use ($service) { $service->updateLocale(); }); } } public function updateLocale() { $locale = $this->getLocale(); if ($locale === null) { return; } Carbon::setLocale($locale); CarbonImmutable::setLocale($locale); CarbonPeriod::setLocale($locale); CarbonInterval::setLocale($locale); if (class_exists(IlluminateCarbon::class)) { IlluminateCarbon::setLocale($locale); } if (class_exists(Date::class)) { try { $root = Date::getFacadeRoot(); $root->setLocale($locale); } catch (Throwable $e) { // Non Carbon class in use in Date facade } } } public function register() { // Needed for Laravel < 5.3 compatibility } protected function getLocale() { if ($this->localeGetter) { return ($this->localeGetter)(); } $app = $this->getApp(); $app = $app && method_exists($app, 'getLocale') ? $app : $this->getGlobalApp('translator'); return $app ? $app->getLocale() : null; } protected function getApp() { if ($this->appGetter) { return ($this->appGetter)(); } return $this->app ?? $this->getGlobalApp(); } protected function getGlobalApp(...$args) { return \function_exists('app') ? \app(...$args) : null; } protected function isEventDispatcher($instance) { return $instance instanceof EventDispatcher || $instance instanceof Dispatcher || $instance instanceof DispatcherContract; } } PK������<1Z? �� ����Carbon/TranslatorImmutable.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon; use Carbon\Exceptions\ImmutableException; use Symfony\Component\Config\ConfigCacheFactoryInterface; use Symfony\Component\Translation\Formatter\MessageFormatterInterface; class TranslatorImmutable extends Translator { /** @var bool */ private $constructed = false; public function __construct($locale, ?MessageFormatterInterface $formatter = null, $cacheDir = null, $debug = false) { parent::__construct($locale, $formatter, $cacheDir, $debug); $this->constructed = true; } /** * @codeCoverageIgnore */ public function setDirectories(array $directories) { $this->disallowMutation(__METHOD__); return parent::setDirectories($directories); } public function setLocale($locale) { $this->disallowMutation(__METHOD__); return parent::setLocale($locale); } /** * @codeCoverageIgnore */ public function setMessages($locale, $messages) { $this->disallowMutation(__METHOD__); return parent::setMessages($locale, $messages); } /** * @codeCoverageIgnore */ public function setTranslations($messages) { $this->disallowMutation(__METHOD__); return parent::setTranslations($messages); } /** * @codeCoverageIgnore */ public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory): void { $this->disallowMutation(__METHOD__); parent::setConfigCacheFactory($configCacheFactory); } public function resetMessages($locale = null) { $this->disallowMutation(__METHOD__); return parent::resetMessages($locale); } /** * @codeCoverageIgnore */ public function setFallbackLocales(array $locales) { $this->disallowMutation(__METHOD__); parent::setFallbackLocales($locales); } private function disallowMutation($method) { if ($this->constructed) { throw new ImmutableException($method.' not allowed on '.static::class); } } } PK������<1ZI&��&����Carbon/Translator.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon; use ReflectionMethod; use Symfony\Component\Translation; use Symfony\Contracts\Translation\TranslatorInterface; $transMethod = new ReflectionMethod( class_exists(TranslatorInterface::class) ? TranslatorInterface::class : Translation\Translator::class, 'trans' ); require $transMethod->hasReturnType() ? __DIR__.'/../../lazy/Carbon/TranslatorStrongType.php' : __DIR__.'/../../lazy/Carbon/TranslatorWeakType.php'; class Translator extends LazyTranslator { // Proxy dynamically loaded LazyTranslator in a static way } PK������<1Z f��f�� ��Carbon/CarbonPeriodImmutable.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon; class CarbonPeriodImmutable extends CarbonPeriod { /** * Default date class of iteration items. * * @var string */ protected const DEFAULT_DATE_CLASS = CarbonImmutable::class; /** * Date class of iteration items. * * @var string */ protected $dateClass = CarbonImmutable::class; /** * Prepare the instance to be set (self if mutable to be mutated, * copy if immutable to generate a new instance). * * @return static */ protected function copyIfImmutable() { return $this->constructed ? clone $this : $this; } } PK������<1Z,9E�E���Carbon/CarbonInterval.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon; use Carbon\Exceptions\BadFluentConstructorException; use Carbon\Exceptions\BadFluentSetterException; use Carbon\Exceptions\InvalidCastException; use Carbon\Exceptions\InvalidIntervalException; use Carbon\Exceptions\OutOfRangeException; use Carbon\Exceptions\ParseErrorException; use Carbon\Exceptions\UnitNotConfiguredException; use Carbon\Exceptions\UnknownGetterException; use Carbon\Exceptions\UnknownSetterException; use Carbon\Exceptions\UnknownUnitException; use Carbon\Traits\IntervalRounding; use Carbon\Traits\IntervalStep; use Carbon\Traits\MagicParameter; use Carbon\Traits\Mixin; use Carbon\Traits\Options; use Carbon\Traits\ToStringFormat; use Closure; use DateInterval; use DateMalformedIntervalStringException; use DateTimeInterface; use DateTimeZone; use Exception; use InvalidArgumentException; use ReflectionException; use ReturnTypeWillChange; use RuntimeException; use Throwable; /** * A simple API extension for DateInterval. * The implementation provides helpers to handle weeks but only days are saved. * Weeks are calculated based on the total days of the current instance. * * @property int $years Total years of the current interval. * @property int $months Total months of the current interval. * @property int $weeks Total weeks of the current interval calculated from the days. * @property int $dayz Total days of the current interval (weeks * 7 + days). * @property int $hours Total hours of the current interval. * @property int $minutes Total minutes of the current interval. * @property int $seconds Total seconds of the current interval. * @property int $microseconds Total microseconds of the current interval. * @property int $milliseconds Total milliseconds of the current interval. * @property int $microExcludeMilli Remaining microseconds without the milliseconds. * @property int $dayzExcludeWeeks Total days remaining in the final week of the current instance (days % 7). * @property int $daysExcludeWeeks alias of dayzExcludeWeeks * @property-read float $totalYears Number of years equivalent to the interval. * @property-read float $totalMonths Number of months equivalent to the interval. * @property-read float $totalWeeks Number of weeks equivalent to the interval. * @property-read float $totalDays Number of days equivalent to the interval. * @property-read float $totalDayz Alias for totalDays. * @property-read float $totalHours Number of hours equivalent to the interval. * @property-read float $totalMinutes Number of minutes equivalent to the interval. * @property-read float $totalSeconds Number of seconds equivalent to the interval. * @property-read float $totalMilliseconds Number of milliseconds equivalent to the interval. * @property-read float $totalMicroseconds Number of microseconds equivalent to the interval. * @property-read string $locale locale of the current instance * * @method static CarbonInterval years($years = 1) Create instance specifying a number of years or modify the number of years if called on an instance. * @method static CarbonInterval year($years = 1) Alias for years() * @method static CarbonInterval months($months = 1) Create instance specifying a number of months or modify the number of months if called on an instance. * @method static CarbonInterval month($months = 1) Alias for months() * @method static CarbonInterval weeks($weeks = 1) Create instance specifying a number of weeks or modify the number of weeks if called on an instance. * @method static CarbonInterval week($weeks = 1) Alias for weeks() * @method static CarbonInterval days($days = 1) Create instance specifying a number of days or modify the number of days if called on an instance. * @method static CarbonInterval dayz($days = 1) Alias for days() * @method static CarbonInterval daysExcludeWeeks($days = 1) Create instance specifying a number of days or modify the number of days (keeping the current number of weeks) if called on an instance. * @method static CarbonInterval dayzExcludeWeeks($days = 1) Alias for daysExcludeWeeks() * @method static CarbonInterval day($days = 1) Alias for days() * @method static CarbonInterval hours($hours = 1) Create instance specifying a number of hours or modify the number of hours if called on an instance. * @method static CarbonInterval hour($hours = 1) Alias for hours() * @method static CarbonInterval minutes($minutes = 1) Create instance specifying a number of minutes or modify the number of minutes if called on an instance. * @method static CarbonInterval minute($minutes = 1) Alias for minutes() * @method static CarbonInterval seconds($seconds = 1) Create instance specifying a number of seconds or modify the number of seconds if called on an instance. * @method static CarbonInterval second($seconds = 1) Alias for seconds() * @method static CarbonInterval milliseconds($milliseconds = 1) Create instance specifying a number of milliseconds or modify the number of milliseconds if called on an instance. * @method static CarbonInterval millisecond($milliseconds = 1) Alias for milliseconds() * @method static CarbonInterval microseconds($microseconds = 1) Create instance specifying a number of microseconds or modify the number of microseconds if called on an instance. * @method static CarbonInterval microsecond($microseconds = 1) Alias for microseconds() * @method $this addYears(int $years) Add given number of years to the current interval * @method $this subYears(int $years) Subtract given number of years to the current interval * @method $this addMonths(int $months) Add given number of months to the current interval * @method $this subMonths(int $months) Subtract given number of months to the current interval * @method $this addWeeks(int|float $weeks) Add given number of weeks to the current interval * @method $this subWeeks(int|float $weeks) Subtract given number of weeks to the current interval * @method $this addDays(int|float $days) Add given number of days to the current interval * @method $this subDays(int|float $days) Subtract given number of days to the current interval * @method $this addHours(int|float $hours) Add given number of hours to the current interval * @method $this subHours(int|float $hours) Subtract given number of hours to the current interval * @method $this addMinutes(int|float $minutes) Add given number of minutes to the current interval * @method $this subMinutes(int|float $minutes) Subtract given number of minutes to the current interval * @method $this addSeconds(int|float $seconds) Add given number of seconds to the current interval * @method $this subSeconds(int|float $seconds) Subtract given number of seconds to the current interval * @method $this addMilliseconds(int|float $milliseconds) Add given number of milliseconds to the current interval * @method $this subMilliseconds(int|float $milliseconds) Subtract given number of milliseconds to the current interval * @method $this addMicroseconds(int|float $microseconds) Add given number of microseconds to the current interval * @method $this subMicroseconds(int|float $microseconds) Subtract given number of microseconds to the current interval * @method $this roundYear(int|float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function. * @method $this roundYears(int|float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function. * @method $this floorYear(int|float $precision = 1) Truncate the current instance year with given precision. * @method $this floorYears(int|float $precision = 1) Truncate the current instance year with given precision. * @method $this ceilYear(int|float $precision = 1) Ceil the current instance year with given precision. * @method $this ceilYears(int|float $precision = 1) Ceil the current instance year with given precision. * @method $this roundMonth(int|float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function. * @method $this roundMonths(int|float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function. * @method $this floorMonth(int|float $precision = 1) Truncate the current instance month with given precision. * @method $this floorMonths(int|float $precision = 1) Truncate the current instance month with given precision. * @method $this ceilMonth(int|float $precision = 1) Ceil the current instance month with given precision. * @method $this ceilMonths(int|float $precision = 1) Ceil the current instance month with given precision. * @method $this roundWeek(int|float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function. * @method $this roundWeeks(int|float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function. * @method $this floorWeek(int|float $precision = 1) Truncate the current instance day with given precision. * @method $this floorWeeks(int|float $precision = 1) Truncate the current instance day with given precision. * @method $this ceilWeek(int|float $precision = 1) Ceil the current instance day with given precision. * @method $this ceilWeeks(int|float $precision = 1) Ceil the current instance day with given precision. * @method $this roundDay(int|float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function. * @method $this roundDays(int|float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function. * @method $this floorDay(int|float $precision = 1) Truncate the current instance day with given precision. * @method $this floorDays(int|float $precision = 1) Truncate the current instance day with given precision. * @method $this ceilDay(int|float $precision = 1) Ceil the current instance day with given precision. * @method $this ceilDays(int|float $precision = 1) Ceil the current instance day with given precision. * @method $this roundHour(int|float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function. * @method $this roundHours(int|float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function. * @method $this floorHour(int|float $precision = 1) Truncate the current instance hour with given precision. * @method $this floorHours(int|float $precision = 1) Truncate the current instance hour with given precision. * @method $this ceilHour(int|float $precision = 1) Ceil the current instance hour with given precision. * @method $this ceilHours(int|float $precision = 1) Ceil the current instance hour with given precision. * @method $this roundMinute(int|float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function. * @method $this roundMinutes(int|float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function. * @method $this floorMinute(int|float $precision = 1) Truncate the current instance minute with given precision. * @method $this floorMinutes(int|float $precision = 1) Truncate the current instance minute with given precision. * @method $this ceilMinute(int|float $precision = 1) Ceil the current instance minute with given precision. * @method $this ceilMinutes(int|float $precision = 1) Ceil the current instance minute with given precision. * @method $this roundSecond(int|float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function. * @method $this roundSeconds(int|float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function. * @method $this floorSecond(int|float $precision = 1) Truncate the current instance second with given precision. * @method $this floorSeconds(int|float $precision = 1) Truncate the current instance second with given precision. * @method $this ceilSecond(int|float $precision = 1) Ceil the current instance second with given precision. * @method $this ceilSeconds(int|float $precision = 1) Ceil the current instance second with given precision. * @method $this roundMillennium(int|float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function. * @method $this roundMillennia(int|float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function. * @method $this floorMillennium(int|float $precision = 1) Truncate the current instance millennium with given precision. * @method $this floorMillennia(int|float $precision = 1) Truncate the current instance millennium with given precision. * @method $this ceilMillennium(int|float $precision = 1) Ceil the current instance millennium with given precision. * @method $this ceilMillennia(int|float $precision = 1) Ceil the current instance millennium with given precision. * @method $this roundCentury(int|float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function. * @method $this roundCenturies(int|float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function. * @method $this floorCentury(int|float $precision = 1) Truncate the current instance century with given precision. * @method $this floorCenturies(int|float $precision = 1) Truncate the current instance century with given precision. * @method $this ceilCentury(int|float $precision = 1) Ceil the current instance century with given precision. * @method $this ceilCenturies(int|float $precision = 1) Ceil the current instance century with given precision. * @method $this roundDecade(int|float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function. * @method $this roundDecades(int|float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function. * @method $this floorDecade(int|float $precision = 1) Truncate the current instance decade with given precision. * @method $this floorDecades(int|float $precision = 1) Truncate the current instance decade with given precision. * @method $this ceilDecade(int|float $precision = 1) Ceil the current instance decade with given precision. * @method $this ceilDecades(int|float $precision = 1) Ceil the current instance decade with given precision. * @method $this roundQuarter(int|float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function. * @method $this roundQuarters(int|float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function. * @method $this floorQuarter(int|float $precision = 1) Truncate the current instance quarter with given precision. * @method $this floorQuarters(int|float $precision = 1) Truncate the current instance quarter with given precision. * @method $this ceilQuarter(int|float $precision = 1) Ceil the current instance quarter with given precision. * @method $this ceilQuarters(int|float $precision = 1) Ceil the current instance quarter with given precision. * @method $this roundMillisecond(int|float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function. * @method $this roundMilliseconds(int|float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function. * @method $this floorMillisecond(int|float $precision = 1) Truncate the current instance millisecond with given precision. * @method $this floorMilliseconds(int|float $precision = 1) Truncate the current instance millisecond with given precision. * @method $this ceilMillisecond(int|float $precision = 1) Ceil the current instance millisecond with given precision. * @method $this ceilMilliseconds(int|float $precision = 1) Ceil the current instance millisecond with given precision. * @method $this roundMicrosecond(int|float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function. * @method $this roundMicroseconds(int|float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function. * @method $this floorMicrosecond(int|float $precision = 1) Truncate the current instance microsecond with given precision. * @method $this floorMicroseconds(int|float $precision = 1) Truncate the current instance microsecond with given precision. * @method $this ceilMicrosecond(int|float $precision = 1) Ceil the current instance microsecond with given precision. * @method $this ceilMicroseconds(int|float $precision = 1) Ceil the current instance microsecond with given precision. */ class CarbonInterval extends DateInterval implements CarbonConverterInterface { use IntervalRounding; use IntervalStep; use MagicParameter; use Mixin { Mixin::mixin as baseMixin; } use Options; use ToStringFormat; /** * Interval spec period designators */ public const PERIOD_PREFIX = 'P'; public const PERIOD_YEARS = 'Y'; public const PERIOD_MONTHS = 'M'; public const PERIOD_DAYS = 'D'; public const PERIOD_TIME_PREFIX = 'T'; public const PERIOD_HOURS = 'H'; public const PERIOD_MINUTES = 'M'; public const PERIOD_SECONDS = 'S'; /** * A translator to ... er ... translate stuff * * @var \Symfony\Component\Translation\TranslatorInterface */ protected static $translator; /** * @var array|null */ protected static $cascadeFactors; /** * @var array */ protected static $formats = [ 'y' => 'y', 'Y' => 'y', 'o' => 'y', 'm' => 'm', 'n' => 'm', 'W' => 'weeks', 'd' => 'd', 'j' => 'd', 'z' => 'd', 'h' => 'h', 'g' => 'h', 'H' => 'h', 'G' => 'h', 'i' => 'i', 's' => 's', 'u' => 'micro', 'v' => 'milli', ]; /** * @var array|null */ private static $flipCascadeFactors; /** * @var bool */ private static $floatSettersEnabled = false; /** * The registered macros. * * @var array */ protected static $macros = []; /** * Timezone handler for settings() method. * * @var mixed */ protected $tzName; /** * Set the instance's timezone from a string or object. * * @param \DateTimeZone|string $tzName * * @return static */ public function setTimezone($tzName) { $this->tzName = $tzName; return $this; } /** * @internal * * Set the instance's timezone from a string or object and add/subtract the offset difference. * * @param \DateTimeZone|string $tzName * * @return static */ public function shiftTimezone($tzName) { $this->tzName = $tzName; return $this; } /** * Mapping of units and factors for cascading. * * Should only be modified by changing the factors or referenced constants. * * @return array */ public static function getCascadeFactors() { return static::$cascadeFactors ?: static::getDefaultCascadeFactors(); } protected static function getDefaultCascadeFactors(): array { return [ 'milliseconds' => [Carbon::MICROSECONDS_PER_MILLISECOND, 'microseconds'], 'seconds' => [Carbon::MILLISECONDS_PER_SECOND, 'milliseconds'], 'minutes' => [Carbon::SECONDS_PER_MINUTE, 'seconds'], 'hours' => [Carbon::MINUTES_PER_HOUR, 'minutes'], 'dayz' => [Carbon::HOURS_PER_DAY, 'hours'], 'weeks' => [Carbon::DAYS_PER_WEEK, 'dayz'], 'months' => [Carbon::WEEKS_PER_MONTH, 'weeks'], 'years' => [Carbon::MONTHS_PER_YEAR, 'months'], ]; } private static function standardizeUnit($unit) { $unit = rtrim($unit, 'sz').'s'; return $unit === 'days' ? 'dayz' : $unit; } private static function getFlipCascadeFactors() { if (!self::$flipCascadeFactors) { self::$flipCascadeFactors = []; foreach (static::getCascadeFactors() as $to => [$factor, $from]) { self::$flipCascadeFactors[self::standardizeUnit($from)] = [self::standardizeUnit($to), $factor]; } } return self::$flipCascadeFactors; } /** * Set default cascading factors for ->cascade() method. * * @param array $cascadeFactors */ public static function setCascadeFactors(array $cascadeFactors) { self::$flipCascadeFactors = null; static::$cascadeFactors = $cascadeFactors; } /** * This option allow you to opt-in for the Carbon 3 behavior where float * values will no longer be cast to integer (so truncated). * * ⚠️ This settings will be applied globally, which mean your whole application * code including the third-party dependencies that also may use Carbon will * adopt the new behavior. */ public static function enableFloatSetters(bool $floatSettersEnabled = true): void { self::$floatSettersEnabled = $floatSettersEnabled; } /////////////////////////////////////////////////////////////////// //////////////////////////// CONSTRUCTORS ///////////////////////// /////////////////////////////////////////////////////////////////// /** * Create a new CarbonInterval instance. * * @param Closure|DateInterval|string|int|null $years * @param int|float|null $months * @param int|float|null $weeks * @param int|float|null $days * @param int|float|null $hours * @param int|float|null $minutes * @param int|float|null $seconds * @param int|float|null $microseconds * * @throws Exception when the interval_spec (passed as $years) cannot be parsed as an interval. */ public function __construct($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null) { if ($years instanceof Closure) { $this->step = $years; $years = null; } if ($years instanceof DateInterval) { parent::__construct(static::getDateIntervalSpec($years)); $this->f = $years->f; self::copyNegativeUnits($years, $this); return; } $spec = $years; $isStringSpec = (\is_string($spec) && !preg_match('/^[\d.]/', $spec)); if (!$isStringSpec || (float) $years) { $spec = static::PERIOD_PREFIX; $spec .= $years > 0 ? $years.static::PERIOD_YEARS : ''; $spec .= $months > 0 ? $months.static::PERIOD_MONTHS : ''; $specDays = 0; $specDays += $weeks > 0 ? $weeks * static::getDaysPerWeek() : 0; $specDays += $days > 0 ? $days : 0; $spec .= $specDays > 0 ? $specDays.static::PERIOD_DAYS : ''; if ($hours > 0 || $minutes > 0 || $seconds > 0) { $spec .= static::PERIOD_TIME_PREFIX; $spec .= $hours > 0 ? $hours.static::PERIOD_HOURS : ''; $spec .= $minutes > 0 ? $minutes.static::PERIOD_MINUTES : ''; $spec .= $seconds > 0 ? $seconds.static::PERIOD_SECONDS : ''; } if ($spec === static::PERIOD_PREFIX) { // Allow the zero interval. $spec .= '0'.static::PERIOD_YEARS; } } try { parent::__construct($spec); } catch (Throwable $exception) { try { parent::__construct('PT0S'); if ($isStringSpec) { if (!preg_match('/^P (?:(?<year>[+-]?\d*(?:\.\d+)?)Y)? (?:(?<month>[+-]?\d*(?:\.\d+)?)M)? (?:(?<week>[+-]?\d*(?:\.\d+)?)W)? (?:(?<day>[+-]?\d*(?:\.\d+)?)D)? (?:T (?:(?<hour>[+-]?\d*(?:\.\d+)?)H)? (?:(?<minute>[+-]?\d*(?:\.\d+)?)M)? (?:(?<second>[+-]?\d*(?:\.\d+)?)S)? )? $/x', $spec, $match)) { throw new InvalidArgumentException("Invalid duration: $spec"); } $years = (float) ($match['year'] ?? 0); $this->assertSafeForInteger('year', $years); $months = (float) ($match['month'] ?? 0); $this->assertSafeForInteger('month', $months); $weeks = (float) ($match['week'] ?? 0); $this->assertSafeForInteger('week', $weeks); $days = (float) ($match['day'] ?? 0); $this->assertSafeForInteger('day', $days); $hours = (float) ($match['hour'] ?? 0); $this->assertSafeForInteger('hour', $hours); $minutes = (float) ($match['minute'] ?? 0); $this->assertSafeForInteger('minute', $minutes); $seconds = (float) ($match['second'] ?? 0); $this->assertSafeForInteger('second', $seconds); } $totalDays = (($weeks * static::getDaysPerWeek()) + $days); $this->assertSafeForInteger('days total (including weeks)', $totalDays); $this->y = (int) $years; $this->m = (int) $months; $this->d = (int) $totalDays; $this->h = (int) $hours; $this->i = (int) $minutes; $this->s = (int) $seconds; if ( ((float) $this->y) !== $years || ((float) $this->m) !== $months || ((float) $this->d) !== $totalDays || ((float) $this->h) !== $hours || ((float) $this->i) !== $minutes || ((float) $this->s) !== $seconds ) { $this->add(static::fromString( ($years - $this->y).' years '. ($months - $this->m).' months '. ($totalDays - $this->d).' days '. ($hours - $this->h).' hours '. ($minutes - $this->i).' minutes '. ($seconds - $this->s).' seconds ' )); } } catch (Throwable $secondException) { throw $secondException instanceof OutOfRangeException ? $secondException : $exception; } } if ($microseconds !== null) { $this->f = $microseconds / Carbon::MICROSECONDS_PER_SECOND; } } /** * Returns the factor for a given source-to-target couple. * * @param string $source * @param string $target * * @return int|float|null */ public static function getFactor($source, $target) { $source = self::standardizeUnit($source); $target = self::standardizeUnit($target); $factors = self::getFlipCascadeFactors(); if (isset($factors[$source])) { [$to, $factor] = $factors[$source]; if ($to === $target) { return $factor; } return $factor * static::getFactor($to, $target); } return null; } /** * Returns the factor for a given source-to-target couple if set, * else try to find the appropriate constant as the factor, such as Carbon::DAYS_PER_WEEK. * * @param string $source * @param string $target * * @return int|float|null */ public static function getFactorWithDefault($source, $target) { $factor = self::getFactor($source, $target); if ($factor) { return $factor; } static $defaults = [ 'month' => ['year' => Carbon::MONTHS_PER_YEAR], 'week' => ['month' => Carbon::WEEKS_PER_MONTH], 'day' => ['week' => Carbon::DAYS_PER_WEEK], 'hour' => ['day' => Carbon::HOURS_PER_DAY], 'minute' => ['hour' => Carbon::MINUTES_PER_HOUR], 'second' => ['minute' => Carbon::SECONDS_PER_MINUTE], 'millisecond' => ['second' => Carbon::MILLISECONDS_PER_SECOND], 'microsecond' => ['millisecond' => Carbon::MICROSECONDS_PER_MILLISECOND], ]; return $defaults[$source][$target] ?? null; } /** * Returns current config for days per week. * * @return int|float */ public static function getDaysPerWeek() { return static::getFactor('dayz', 'weeks') ?: Carbon::DAYS_PER_WEEK; } /** * Returns current config for hours per day. * * @return int|float */ public static function getHoursPerDay() { return static::getFactor('hours', 'dayz') ?: Carbon::HOURS_PER_DAY; } /** * Returns current config for minutes per hour. * * @return int|float */ public static function getMinutesPerHour() { return static::getFactor('minutes', 'hours') ?: Carbon::MINUTES_PER_HOUR; } /** * Returns current config for seconds per minute. * * @return int|float */ public static function getSecondsPerMinute() { return static::getFactor('seconds', 'minutes') ?: Carbon::SECONDS_PER_MINUTE; } /** * Returns current config for microseconds per second. * * @return int|float */ public static function getMillisecondsPerSecond() { return static::getFactor('milliseconds', 'seconds') ?: Carbon::MILLISECONDS_PER_SECOND; } /** * Returns current config for microseconds per second. * * @return int|float */ public static function getMicrosecondsPerMillisecond() { return static::getFactor('microseconds', 'milliseconds') ?: Carbon::MICROSECONDS_PER_MILLISECOND; } /** * Create a new CarbonInterval instance from specific values. * This is an alias for the constructor that allows better fluent * syntax as it allows you to do CarbonInterval::create(1)->fn() rather than * (new CarbonInterval(1))->fn(). * * @param int $years * @param int $months * @param int $weeks * @param int $days * @param int $hours * @param int $minutes * @param int $seconds * @param int $microseconds * * @throws Exception when the interval_spec (passed as $years) cannot be parsed as an interval. * * @return static */ public static function create($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null) { return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $microseconds); } /** * Parse a string into a new CarbonInterval object according to the specified format. * * @example * ``` * echo Carboninterval::createFromFormat('H:i', '1:30'); * ``` * * @param string $format Format of the $interval input string * @param string|null $interval Input string to convert into an interval * * @throws \Carbon\Exceptions\ParseErrorException when the $interval cannot be parsed as an interval. * * @return static */ public static function createFromFormat(string $format, ?string $interval) { $instance = new static(0); $length = mb_strlen($format); if (preg_match('/s([,.])([uv])$/', $format, $match)) { $interval = explode($match[1], $interval); $index = \count($interval) - 1; $interval[$index] = str_pad($interval[$index], $match[2] === 'v' ? 3 : 6, '0'); $interval = implode($match[1], $interval); } $interval = $interval ?? ''; for ($index = 0; $index < $length; $index++) { $expected = mb_substr($format, $index, 1); $nextCharacter = mb_substr($interval, 0, 1); $unit = static::$formats[$expected] ?? null; if ($unit) { if (!preg_match('/^-?\d+/', $interval, $match)) { throw new ParseErrorException('number', $nextCharacter); } $interval = mb_substr($interval, mb_strlen($match[0])); $instance->$unit += (int) ($match[0]); continue; } if ($nextCharacter !== $expected) { throw new ParseErrorException( "'$expected'", $nextCharacter, 'Allowed substitutes for interval formats are '.implode(', ', array_keys(static::$formats))."\n". 'See https://php.net/manual/en/function.date.php for their meaning' ); } $interval = mb_substr($interval, 1); } if ($interval !== '') { throw new ParseErrorException( 'end of string', $interval ); } return $instance; } /** * Get a copy of the instance. * * @return static */ public function copy() { $date = new static(0); $date->copyProperties($this); $date->step = $this->step; return $date; } /** * Get a copy of the instance. * * @return static */ public function clone() { return $this->copy(); } /** * Provide static helpers to create instances. Allows CarbonInterval::years(3). * * Note: This is done using the magic method to allow static and instance methods to * have the same names. * * @param string $method magic method name called * @param array $parameters parameters list * * @return static|null */ public static function __callStatic($method, $parameters) { try { $interval = new static(0); $localStrictModeEnabled = $interval->localStrictModeEnabled; $interval->localStrictModeEnabled = true; $result = static::hasMacro($method) ? static::bindMacroContext(null, function () use (&$method, &$parameters, &$interval) { return $interval->callMacro($method, $parameters); }) : $interval->$method(...$parameters); $interval->localStrictModeEnabled = $localStrictModeEnabled; return $result; } catch (BadFluentSetterException $exception) { if (Carbon::isStrictModeEnabled()) { throw new BadFluentConstructorException($method, 0, $exception); } return null; } } /** * Evaluate the PHP generated by var_export() and recreate the exported CarbonInterval instance. * * @param array $dump data as exported by var_export() * * @return static */ #[ReturnTypeWillChange] public static function __set_state($dump) { /** @noinspection PhpVoidFunctionResultUsedInspection */ /** @var DateInterval $dateInterval */ $dateInterval = parent::__set_state($dump); return static::instance($dateInterval); } /** * Return the current context from inside a macro callee or a new one if static. * * @return static */ protected static function this() { return end(static::$macroContextStack) ?: new static(0); } /** * Creates a CarbonInterval from string. * * Format: * * Suffix | Unit | Example | DateInterval expression * -------|---------|---------|------------------------ * y | years | 1y | P1Y * mo | months | 3mo | P3M * w | weeks | 2w | P2W * d | days | 28d | P28D * h | hours | 4h | PT4H * m | minutes | 12m | PT12M * s | seconds | 59s | PT59S * * e. g. `1w 3d 4h 32m 23s` is converted to 10 days 4 hours 32 minutes and 23 seconds. * * Special cases: * - An empty string will return a zero interval * - Fractions are allowed for weeks, days, hours and minutes and will be converted * and rounded to the next smaller value (caution: 0.5w = 4d) * * @param string $intervalDefinition * * @return static */ public static function fromString($intervalDefinition) { if (empty($intervalDefinition)) { return new static(0); } $years = 0; $months = 0; $weeks = 0; $days = 0; $hours = 0; $minutes = 0; $seconds = 0; $milliseconds = 0; $microseconds = 0; $pattern = '/(\d+(?:\.\d+)?)\h*([^\d\h]*)/i'; preg_match_all($pattern, $intervalDefinition, $parts, PREG_SET_ORDER); while ([$part, $value, $unit] = array_shift($parts)) { $intValue = (int) $value; $fraction = (float) $value - $intValue; // Fix calculation precision switch (round($fraction, 6)) { case 1: $fraction = 0; $intValue++; break; case 0: $fraction = 0; break; } switch ($unit === 'µs' ? 'µs' : strtolower($unit)) { case 'millennia': case 'millennium': $years += $intValue * CarbonInterface::YEARS_PER_MILLENNIUM; break; case 'century': case 'centuries': $years += $intValue * CarbonInterface::YEARS_PER_CENTURY; break; case 'decade': case 'decades': $years += $intValue * CarbonInterface::YEARS_PER_DECADE; break; case 'year': case 'years': case 'y': case 'yr': case 'yrs': $years += $intValue; break; case 'quarter': case 'quarters': $months += $intValue * CarbonInterface::MONTHS_PER_QUARTER; break; case 'month': case 'months': case 'mo': case 'mos': $months += $intValue; break; case 'week': case 'weeks': case 'w': $weeks += $intValue; if ($fraction) { $parts[] = [null, $fraction * static::getDaysPerWeek(), 'd']; } break; case 'day': case 'days': case 'd': $days += $intValue; if ($fraction) { $parts[] = [null, $fraction * static::getHoursPerDay(), 'h']; } break; case 'hour': case 'hours': case 'h': $hours += $intValue; if ($fraction) { $parts[] = [null, $fraction * static::getMinutesPerHour(), 'm']; } break; case 'minute': case 'minutes': case 'm': $minutes += $intValue; if ($fraction) { $parts[] = [null, $fraction * static::getSecondsPerMinute(), 's']; } break; case 'second': case 'seconds': case 's': $seconds += $intValue; if ($fraction) { $parts[] = [null, $fraction * static::getMillisecondsPerSecond(), 'ms']; } break; case 'millisecond': case 'milliseconds': case 'milli': case 'ms': $milliseconds += $intValue; if ($fraction) { $microseconds += round($fraction * static::getMicrosecondsPerMillisecond()); } break; case 'microsecond': case 'microseconds': case 'micro': case 'µs': $microseconds += $intValue; break; default: throw new InvalidIntervalException( \sprintf('Invalid part %s in definition %s', $part, $intervalDefinition) ); } } return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $milliseconds * Carbon::MICROSECONDS_PER_MILLISECOND + $microseconds); } /** * Creates a CarbonInterval from string using a different locale. * * @param string $interval interval string in the given language (may also contain English). * @param string|null $locale if locale is null or not specified, current global locale will be used instead. * * @return static */ public static function parseFromLocale($interval, $locale = null) { return static::fromString(Carbon::translateTimeString($interval, $locale ?: static::getLocale(), 'en')); } private static function castIntervalToClass(DateInterval $interval, string $className, array $skip = []) { $mainClass = DateInterval::class; if (!is_a($className, $mainClass, true)) { throw new InvalidCastException("$className is not a sub-class of $mainClass."); } $microseconds = $interval->f; $instance = new $className(static::getDateIntervalSpec($interval, false, $skip)); if ($microseconds) { $instance->f = $microseconds; } if ($interval instanceof self && is_a($className, self::class, true)) { self::copyStep($interval, $instance); } self::copyNegativeUnits($interval, $instance); return $instance; } private static function copyNegativeUnits(DateInterval $from, DateInterval $to): void { $to->invert = $from->invert; foreach (['y', 'm', 'd', 'h', 'i', 's'] as $unit) { if ($from->$unit < 0) { $to->$unit *= -1; } } } private static function copyStep(self $from, self $to): void { $to->setStep($from->getStep()); } /** * Cast the current instance into the given class. * * @param string $className The $className::instance() method will be called to cast the current object. * * @return DateInterval */ public function cast(string $className) { return self::castIntervalToClass($this, $className); } /** * Create a CarbonInterval instance from a DateInterval one. Can not instance * DateInterval objects created from DateTime::diff() as you can't externally * set the $days field. * * @param DateInterval $interval * @param bool $skipCopy set to true to return the passed object * (without copying it) if it's already of the * current class * * @return static */ public static function instance(DateInterval $interval, array $skip = [], bool $skipCopy = false) { if ($skipCopy && $interval instanceof static) { return $interval; } return self::castIntervalToClass($interval, static::class, $skip); } /** * Make a CarbonInterval instance from given variable if possible. * * Always return a new instance. Parse only strings and only these likely to be intervals (skip dates * and recurrences). Throw an exception for invalid format, but otherwise return null. * * @param mixed|int|DateInterval|string|Closure|null $interval interval or number of the given $unit * @param string|null $unit if specified, $interval must be an integer * @param bool $skipCopy set to true to return the passed object * (without copying it) if it's already of the * current class * * @return static|null */ public static function make($interval, $unit = null, bool $skipCopy = false) { if ($unit) { $interval = "$interval ".Carbon::pluralUnit($unit); } if ($interval instanceof DateInterval) { return static::instance($interval, [], $skipCopy); } if ($interval instanceof Closure) { return new static($interval); } if (!\is_string($interval)) { return null; } return static::makeFromString($interval); } protected static function makeFromString(string $interval) { $interval = preg_replace('/\s+/', ' ', trim($interval)); if (preg_match('/^P[T\d]/', $interval)) { return new static($interval); } if (preg_match('/^(?:\h*\d+(?:\.\d+)?\h*[a-z]+)+$/i', $interval)) { return static::fromString($interval); } // @codeCoverageIgnoreStart try { /** @var static $interval */ $interval = static::createFromDateString($interval); } catch (DateMalformedIntervalStringException $e) { return null; } // @codeCoverageIgnoreEnd return !$interval || $interval->isEmpty() ? null : $interval; } protected function resolveInterval($interval) { if (!($interval instanceof self)) { return self::make($interval); } return $interval; } /** * Sets up a DateInterval from the relative parts of the string. * * @param string $time * * @return static * * @link https://php.net/manual/en/dateinterval.createfromdatestring.php */ #[ReturnTypeWillChange] public static function createFromDateString($time) { $interval = @parent::createFromDateString(strtr($time, [ ',' => ' ', ' and ' => ' ', ])); if ($interval instanceof DateInterval) { $interval = static::instance($interval); } return $interval; } /////////////////////////////////////////////////////////////////// ///////////////////////// GETTERS AND SETTERS ///////////////////// /////////////////////////////////////////////////////////////////// /** * Get a part of the CarbonInterval object. * * @param string $name * * @throws UnknownGetterException * * @return int|float|string */ public function get($name) { if (str_starts_with($name, 'total')) { return $this->total(substr($name, 5)); } switch ($name) { case 'years': return $this->y; case 'months': return $this->m; case 'dayz': return $this->d; case 'hours': return $this->h; case 'minutes': return $this->i; case 'seconds': return $this->s; case 'milli': case 'milliseconds': return (int) (round($this->f * Carbon::MICROSECONDS_PER_SECOND) / Carbon::MICROSECONDS_PER_MILLISECOND); case 'micro': case 'microseconds': return (int) round($this->f * Carbon::MICROSECONDS_PER_SECOND); case 'microExcludeMilli': return (int) round($this->f * Carbon::MICROSECONDS_PER_SECOND) % Carbon::MICROSECONDS_PER_MILLISECOND; case 'weeks': return (int) ($this->d / (int) static::getDaysPerWeek()); case 'daysExcludeWeeks': case 'dayzExcludeWeeks': return $this->d % (int) static::getDaysPerWeek(); case 'locale': return $this->getTranslatorLocale(); default: throw new UnknownGetterException($name); } } /** * Get a part of the CarbonInterval object. * * @param string $name * * @throws UnknownGetterException * * @return int|float|string */ public function __get($name) { return $this->get($name); } /** * Set a part of the CarbonInterval object. * * @param string|array $name * @param int $value * * @throws UnknownSetterException * * @return $this */ public function set($name, $value = null) { $properties = \is_array($name) ? $name : [$name => $value]; foreach ($properties as $key => $value) { switch (Carbon::singularUnit(rtrim($key, 'z'))) { case 'year': $this->checkIntegerValue($key, $value); $this->y = $value; $this->handleDecimalPart('year', $value, $this->y); break; case 'month': $this->checkIntegerValue($key, $value); $this->m = $value; $this->handleDecimalPart('month', $value, $this->m); break; case 'week': $this->checkIntegerValue($key, $value); $days = $value * (int) static::getDaysPerWeek(); $this->assertSafeForInteger('days total (including weeks)', $days); $this->d = $days; $this->handleDecimalPart('day', $days, $this->d); break; case 'day': $this->checkIntegerValue($key, $value); $this->d = $value; $this->handleDecimalPart('day', $value, $this->d); break; case 'daysexcludeweek': case 'dayzexcludeweek': $this->checkIntegerValue($key, $value); $days = $this->weeks * (int) static::getDaysPerWeek() + $value; $this->assertSafeForInteger('days total (including weeks)', $days); $this->d = $days; $this->handleDecimalPart('day', $days, $this->d); break; case 'hour': $this->checkIntegerValue($key, $value); $this->h = $value; $this->handleDecimalPart('hour', $value, $this->h); break; case 'minute': $this->checkIntegerValue($key, $value); $this->i = $value; $this->handleDecimalPart('minute', $value, $this->i); break; case 'second': $this->checkIntegerValue($key, $value); $this->s = $value; $this->handleDecimalPart('second', $value, $this->s); break; case 'milli': case 'millisecond': $this->microseconds = $value * Carbon::MICROSECONDS_PER_MILLISECOND + $this->microseconds % Carbon::MICROSECONDS_PER_MILLISECOND; break; case 'micro': case 'microsecond': $this->f = $value / Carbon::MICROSECONDS_PER_SECOND; break; default: if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) { throw new UnknownSetterException($key); } $this->$key = $value; } } return $this; } /** * Set a part of the CarbonInterval object. * * @param string $name * @param int $value * * @throws UnknownSetterException */ public function __set($name, $value) { $this->set($name, $value); } /** * Allow setting of weeks and days to be cumulative. * * @param int $weeks Number of weeks to set * @param int $days Number of days to set * * @return static */ public function weeksAndDays($weeks, $days) { $this->dayz = ($weeks * static::getDaysPerWeek()) + $days; return $this; } /** * Returns true if the interval is empty for each unit. * * @return bool */ public function isEmpty() { return $this->years === 0 && $this->months === 0 && $this->dayz === 0 && !$this->days && $this->hours === 0 && $this->minutes === 0 && $this->seconds === 0 && $this->microseconds === 0; } /** * Register a custom macro. * * @example * ``` * CarbonInterval::macro('twice', function () { * return $this->times(2); * }); * echo CarbonInterval::hours(2)->twice(); * ``` * * @param string $name * @param object|callable $macro * * @return void */ public static function macro($name, $macro) { static::$macros[$name] = $macro; } /** * Register macros from a mixin object. * * @example * ``` * CarbonInterval::mixin(new class { * public function daysToHours() { * return function () { * $this->hours += $this->days; * $this->days = 0; * * return $this; * }; * } * public function hoursToDays() { * return function () { * $this->days += $this->hours; * $this->hours = 0; * * return $this; * }; * } * }); * echo CarbonInterval::hours(5)->hoursToDays() . "\n"; * echo CarbonInterval::days(5)->daysToHours() . "\n"; * ``` * * @param object|string $mixin * * @throws ReflectionException * * @return void */ public static function mixin($mixin) { static::baseMixin($mixin); } /** * Check if macro is registered. * * @param string $name * * @return bool */ public static function hasMacro($name) { return isset(static::$macros[$name]); } /** * Call given macro. * * @param string $name * @param array $parameters * * @return mixed */ protected function callMacro($name, $parameters) { $macro = static::$macros[$name]; if ($macro instanceof Closure) { $boundMacro = @$macro->bindTo($this, static::class) ?: @$macro->bindTo(null, static::class); return ($boundMacro ?: $macro)(...$parameters); } return $macro(...$parameters); } /** * Allow fluent calls on the setters... CarbonInterval::years(3)->months(5)->day(). * * Note: This is done using the magic method to allow static and instance methods to * have the same names. * * @param string $method magic method name called * @param array $parameters parameters list * * @throws BadFluentSetterException|Throwable * * @return static */ public function __call($method, $parameters) { if (static::hasMacro($method)) { return static::bindMacroContext($this, function () use (&$method, &$parameters) { return $this->callMacro($method, $parameters); }); } $roundedValue = $this->callRoundMethod($method, $parameters); if ($roundedValue !== null) { return $roundedValue; } if (preg_match('/^(?<method>add|sub)(?<unit>[A-Z].*)$/', $method, $match)) { $value = $this->getMagicParameter($parameters, 0, Carbon::pluralUnit($match['unit']), 0); return $this->{$match['method']}($value, $match['unit']); } $value = $this->getMagicParameter($parameters, 0, Carbon::pluralUnit($method), 1); try { $this->set($method, $value); } catch (UnknownSetterException $exception) { if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) { throw new BadFluentSetterException($method, 0, $exception); } } return $this; } protected function getForHumansInitialVariables($syntax, $short) { if (\is_array($syntax)) { return $syntax; } if (\is_int($short)) { return [ 'parts' => $short, 'short' => false, ]; } if (\is_bool($syntax)) { return [ 'short' => $syntax, 'syntax' => CarbonInterface::DIFF_ABSOLUTE, ]; } return []; } /** * @param mixed $syntax * @param mixed $short * @param mixed $parts * @param mixed $options * * @return array */ protected function getForHumansParameters($syntax = null, $short = false, $parts = -1, $options = null) { $optionalSpace = ' '; $default = $this->getTranslationMessage('list.0') ?? $this->getTranslationMessage('list') ?? ' '; $join = $default === '' ? '' : ' '; $altNumbers = false; $aUnit = false; $minimumUnit = 's'; $skip = []; extract($this->getForHumansInitialVariables($syntax, $short)); $skip = array_map('strtolower', array_filter((array) $skip, static function ($value) { return \is_string($value) && $value !== ''; })); if ($syntax === null) { $syntax = CarbonInterface::DIFF_ABSOLUTE; } if ($parts === -1) { $parts = INF; } if ($options === null) { $options = static::getHumanDiffOptions(); } if ($join === false) { $join = ' '; } elseif ($join === true) { $join = [ $default, $this->getTranslationMessage('list.1') ?? $default, ]; } if ($altNumbers && $altNumbers !== true) { $language = new Language($this->locale); $altNumbers = \in_array($language->getCode(), (array) $altNumbers, true); } if (\is_array($join)) { [$default, $last] = $join; if ($default !== ' ') { $optionalSpace = ''; } $join = function ($list) use ($default, $last) { if (\count($list) < 2) { return implode('', $list); } $end = array_pop($list); return implode($default, $list).$last.$end; }; } if (\is_string($join)) { if ($join !== ' ') { $optionalSpace = ''; } $glue = $join; $join = function ($list) use ($glue) { return implode($glue, $list); }; } $interpolations = [ ':optional-space' => $optionalSpace, ]; return [$syntax, $short, $parts, $options, $join, $aUnit, $altNumbers, $interpolations, $minimumUnit, $skip]; } protected static function getRoundingMethodFromOptions(int $options): ?string { if ($options & CarbonInterface::ROUND) { return 'round'; } if ($options & CarbonInterface::CEIL) { return 'ceil'; } if ($options & CarbonInterface::FLOOR) { return 'floor'; } return null; } /** * Returns interval values as an array where key are the unit names and values the counts. * * @return int[] */ public function toArray() { return [ 'years' => $this->years, 'months' => $this->months, 'weeks' => $this->weeks, 'days' => $this->daysExcludeWeeks, 'hours' => $this->hours, 'minutes' => $this->minutes, 'seconds' => $this->seconds, 'microseconds' => $this->microseconds, ]; } /** * Returns interval non-zero values as an array where key are the unit names and values the counts. * * @return int[] */ public function getNonZeroValues() { return array_filter($this->toArray(), 'intval'); } /** * Returns interval values as an array where key are the unit names and values the counts * from the biggest non-zero one the the smallest non-zero one. * * @return int[] */ public function getValuesSequence() { $nonZeroValues = $this->getNonZeroValues(); if ($nonZeroValues === []) { return []; } $keys = array_keys($nonZeroValues); $firstKey = $keys[0]; $lastKey = $keys[\count($keys) - 1]; $values = []; $record = false; foreach ($this->toArray() as $unit => $count) { if ($unit === $firstKey) { $record = true; } if ($record) { $values[$unit] = $count; } if ($unit === $lastKey) { $record = false; } } return $values; } /** * Get the current interval in a human readable format in the current locale. * * @example * ``` * echo CarbonInterval::fromString('4d 3h 40m')->forHumans() . "\n"; * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['parts' => 2]) . "\n"; * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['parts' => 3, 'join' => true]) . "\n"; * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['short' => true]) . "\n"; * echo CarbonInterval::fromString('1d 24h')->forHumans(['join' => ' or ']) . "\n"; * echo CarbonInterval::fromString('1d 24h')->forHumans(['minimumUnit' => 'hour']) . "\n"; * ``` * * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains: * - 'syntax' entry (see below) * - 'short' entry (see below) * - 'parts' entry (see below) * - 'options' entry (see below) * - 'skip' entry, list of units to skip (array of strings or a single string, * ` it can be the unit name (singular or plural) or its shortcut * ` (y, m, w, d, h, min, s, ms, µs). * - 'aUnit' entry, prefer "an hour" over "1 hour" if true * - 'join' entry determines how to join multiple parts of the string * ` - if $join is a string, it's used as a joiner glue * ` - if $join is a callable/closure, it get the list of string and should return a string * ` - if $join is an array, the first item will be the default glue, and the second item * ` will be used instead of the glue for the last item * ` - if $join is true, it will be guessed from the locale ('list' translation file entry) * ` - if $join is missing, a space will be used as glue * - 'minimumUnit' entry determines the smallest unit of time to display can be long or * ` short form of the units, e.g. 'hour' or 'h' (default value: s) * if int passed, it add modifiers: * Possible values: * - CarbonInterface::DIFF_ABSOLUTE no modifiers * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier * Default value: CarbonInterface::DIFF_ABSOLUTE * @param bool $short displays short format of time units * @param int $parts maximum number of parts to display (default value: -1: no limits) * @param int $options human diff options * * @throws Exception * * @return string */ public function forHumans($syntax = null, $short = false, $parts = -1, $options = null) { [$syntax, $short, $parts, $options, $join, $aUnit, $altNumbers, $interpolations, $minimumUnit, $skip] = $this ->getForHumansParameters($syntax, $short, $parts, $options); $interval = []; $syntax = (int) ($syntax ?? CarbonInterface::DIFF_ABSOLUTE); $absolute = $syntax === CarbonInterface::DIFF_ABSOLUTE; $relativeToNow = $syntax === CarbonInterface::DIFF_RELATIVE_TO_NOW; $count = 1; $unit = $short ? 's' : 'second'; $isFuture = $this->invert === 1; $transId = $relativeToNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before'); $declensionMode = null; /** @var \Symfony\Component\Translation\Translator $translator */ $translator = $this->getLocalTranslator(); $handleDeclensions = function ($unit, $count, $index = 0, $parts = 1) use ($interpolations, $transId, $translator, $altNumbers, $absolute, &$declensionMode) { if (!$absolute) { $declensionMode = $declensionMode ?? $this->translate($transId.'_mode'); if ($this->needsDeclension($declensionMode, $index, $parts)) { // Some languages have special pluralization for past and future tense. $key = $unit.'_'.$transId; $result = $this->translate($key, $interpolations, $count, $translator, $altNumbers); if ($result !== $key) { return $result; } } } $result = $this->translate($unit, $interpolations, $count, $translator, $altNumbers); if ($result !== $unit) { return $result; } return null; }; $intervalValues = $this; $method = static::getRoundingMethodFromOptions($options); if ($method) { $previousCount = INF; while ( \count($intervalValues->getNonZeroValues()) > $parts && ($count = \count($keys = array_keys($intervalValues->getValuesSequence()))) > 1 ) { $index = min($count, $previousCount - 1) - 2; if ($index < 0) { break; } $intervalValues = $this->copy()->roundUnit( $keys[$index], 1, $method ); $previousCount = $count; } } $diffIntervalArray = [ ['value' => $intervalValues->years, 'unit' => 'year', 'unitShort' => 'y'], ['value' => $intervalValues->months, 'unit' => 'month', 'unitShort' => 'm'], ['value' => $intervalValues->weeks, 'unit' => 'week', 'unitShort' => 'w'], ['value' => $intervalValues->daysExcludeWeeks, 'unit' => 'day', 'unitShort' => 'd'], ['value' => $intervalValues->hours, 'unit' => 'hour', 'unitShort' => 'h'], ['value' => $intervalValues->minutes, 'unit' => 'minute', 'unitShort' => 'min'], ['value' => $intervalValues->seconds, 'unit' => 'second', 'unitShort' => 's'], ['value' => $intervalValues->milliseconds, 'unit' => 'millisecond', 'unitShort' => 'ms'], ['value' => $intervalValues->microExcludeMilli, 'unit' => 'microsecond', 'unitShort' => 'µs'], ]; if (!empty($skip)) { foreach ($diffIntervalArray as $index => &$unitData) { $nextIndex = $index + 1; if ($unitData['value'] && isset($diffIntervalArray[$nextIndex]) && \count(array_intersect([$unitData['unit'], $unitData['unit'].'s', $unitData['unitShort']], $skip)) ) { $diffIntervalArray[$nextIndex]['value'] += $unitData['value'] * self::getFactorWithDefault($diffIntervalArray[$nextIndex]['unit'], $unitData['unit']); $unitData['value'] = 0; } } } $transChoice = function ($short, $unitData, $index, $parts) use ($absolute, $handleDeclensions, $translator, $aUnit, $altNumbers, $interpolations) { $count = $unitData['value']; if ($short) { $result = $handleDeclensions($unitData['unitShort'], $count, $index, $parts); if ($result !== null) { return $result; } } elseif ($aUnit) { $result = $handleDeclensions('a_'.$unitData['unit'], $count, $index, $parts); if ($result !== null) { return $result; } } if (!$absolute) { return $handleDeclensions($unitData['unit'], $count, $index, $parts); } return $this->translate($unitData['unit'], $interpolations, $count, $translator, $altNumbers); }; $fallbackUnit = ['second', 's']; foreach ($diffIntervalArray as $diffIntervalData) { if ($diffIntervalData['value'] > 0) { $unit = $short ? $diffIntervalData['unitShort'] : $diffIntervalData['unit']; $count = $diffIntervalData['value']; $interval[] = [$short, $diffIntervalData]; } elseif ($options & CarbonInterface::SEQUENTIAL_PARTS_ONLY && \count($interval) > 0) { break; } // break the loop after we get the required number of parts in array if (\count($interval) >= $parts) { break; } // break the loop after we have reached the minimum unit if (\in_array($minimumUnit, [$diffIntervalData['unit'], $diffIntervalData['unitShort']], true)) { $fallbackUnit = [$diffIntervalData['unit'], $diffIntervalData['unitShort']]; break; } } $actualParts = \count($interval); foreach ($interval as $index => &$item) { $item = $transChoice($item[0], $item[1], $index, $actualParts); } if (\count($interval) === 0) { if ($relativeToNow && $options & CarbonInterface::JUST_NOW) { $key = 'diff_now'; $translation = $this->translate($key, $interpolations, null, $translator); if ($translation !== $key) { return $translation; } } $count = $options & CarbonInterface::NO_ZERO_DIFF ? 1 : 0; $unit = $fallbackUnit[$short ? 1 : 0]; $interval[] = $this->translate($unit, $interpolations, $count, $translator, $altNumbers); } // join the interval parts by a space $time = $join($interval); unset($diffIntervalArray, $interval); if ($absolute) { return $time; } $isFuture = $this->invert === 1; $transId = $relativeToNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before'); if ($parts === 1) { if ($relativeToNow && $unit === 'day') { if ($count === 1 && $options & CarbonInterface::ONE_DAY_WORDS) { $key = $isFuture ? 'diff_tomorrow' : 'diff_yesterday'; $translation = $this->translate($key, $interpolations, null, $translator); if ($translation !== $key) { return $translation; } } if ($count === 2 && $options & CarbonInterface::TWO_DAY_WORDS) { $key = $isFuture ? 'diff_after_tomorrow' : 'diff_before_yesterday'; $translation = $this->translate($key, $interpolations, null, $translator); if ($translation !== $key) { return $translation; } } } $aTime = $aUnit ? $handleDeclensions('a_'.$unit, $count) : null; $time = $aTime ?: $handleDeclensions($unit, $count) ?: $time; } $time = [':time' => $time]; return $this->translate($transId, array_merge($time, $interpolations, $time), null, $translator); } /** * Format the instance as a string using the forHumans() function. * * @throws Exception * * @return string */ public function __toString() { $format = $this->localToStringFormat ?? static::$toStringFormat; if (!$format) { return $this->forHumans(); } if ($format instanceof Closure) { return $format($this); } return $this->format($format); } /** * Return native DateInterval PHP object matching the current instance. * * @example * ``` * var_dump(CarbonInterval::hours(2)->toDateInterval()); * ``` * * @return DateInterval */ public function toDateInterval() { return self::castIntervalToClass($this, DateInterval::class); } /** * Convert the interval to a CarbonPeriod. * * @param DateTimeInterface|string|int ...$params Start date, [end date or recurrences] and optional settings. * * @return CarbonPeriod */ public function toPeriod(...$params) { if ($this->tzName) { $tz = \is_string($this->tzName) ? new DateTimeZone($this->tzName) : $this->tzName; if ($tz instanceof DateTimeZone) { array_unshift($params, $tz); } } return CarbonPeriod::create($this, ...$params); } /** * Invert the interval. * * @param bool|int $inverted if a parameter is passed, the passed value cast as 1 or 0 is used * as the new value of the ->invert property. * * @return $this */ public function invert($inverted = null) { $this->invert = (\func_num_args() === 0 ? !$this->invert : $inverted) ? 1 : 0; return $this; } protected function solveNegativeInterval() { if (!$this->isEmpty() && $this->years <= 0 && $this->months <= 0 && $this->dayz <= 0 && $this->hours <= 0 && $this->minutes <= 0 && $this->seconds <= 0 && $this->microseconds <= 0) { $this->years *= -1; $this->months *= -1; $this->dayz *= -1; $this->hours *= -1; $this->minutes *= -1; $this->seconds *= -1; $this->microseconds *= -1; $this->invert(); } return $this; } /** * Add the passed interval to the current instance. * * @param string|DateInterval $unit * @param int|float $value * * @return $this */ public function add($unit, $value = 1) { if (is_numeric($unit)) { [$value, $unit] = [$unit, $value]; } if (\is_string($unit) && !preg_match('/^\s*\d/', $unit)) { $unit = "$value $unit"; $value = 1; } $interval = static::make($unit); if (!$interval) { throw new InvalidIntervalException('This type of data cannot be added/subtracted.'); } if ($value !== 1) { $interval->times($value); } $sign = ($this->invert === 1) !== ($interval->invert === 1) ? -1 : 1; $this->years += $interval->y * $sign; $this->months += $interval->m * $sign; $this->dayz += ($interval->days === false ? $interval->d : $interval->days) * $sign; $this->hours += $interval->h * $sign; $this->minutes += $interval->i * $sign; $this->seconds += $interval->s * $sign; $this->microseconds += $interval->microseconds * $sign; $this->solveNegativeInterval(); return $this; } /** * Subtract the passed interval to the current instance. * * @param string|DateInterval $unit * @param int|float $value * * @return $this */ public function sub($unit, $value = 1) { if (is_numeric($unit)) { [$value, $unit] = [$unit, $value]; } return $this->add($unit, -(float) $value); } /** * Subtract the passed interval to the current instance. * * @param string|DateInterval $unit * @param int|float $value * * @return $this */ public function subtract($unit, $value = 1) { return $this->sub($unit, $value); } /** * Add given parameters to the current interval. * * @param int $years * @param int $months * @param int|float $weeks * @param int|float $days * @param int|float $hours * @param int|float $minutes * @param int|float $seconds * @param int|float $microseconds * * @return $this */ public function plus( $years = 0, $months = 0, $weeks = 0, $days = 0, $hours = 0, $minutes = 0, $seconds = 0, $microseconds = 0 ): self { return $this->add(" $years years $months months $weeks weeks $days days $hours hours $minutes minutes $seconds seconds $microseconds microseconds "); } /** * Add given parameters to the current interval. * * @param int $years * @param int $months * @param int|float $weeks * @param int|float $days * @param int|float $hours * @param int|float $minutes * @param int|float $seconds * @param int|float $microseconds * * @return $this */ public function minus( $years = 0, $months = 0, $weeks = 0, $days = 0, $hours = 0, $minutes = 0, $seconds = 0, $microseconds = 0 ): self { return $this->sub(" $years years $months months $weeks weeks $days days $hours hours $minutes minutes $seconds seconds $microseconds microseconds "); } /** * Multiply current instance given number of times. times() is naive, it multiplies each unit * (so day can be greater than 31, hour can be greater than 23, etc.) and the result is rounded * separately for each unit. * * Use times() when you want a fast and approximated calculation that does not cascade units. * * For a precise and cascaded calculation, * * @see multiply() * * @param float|int $factor * * @return $this */ public function times($factor) { if ($factor < 0) { $this->invert = $this->invert ? 0 : 1; $factor = -$factor; } $this->years = (int) round($this->years * $factor); $this->months = (int) round($this->months * $factor); $this->dayz = (int) round($this->dayz * $factor); $this->hours = (int) round($this->hours * $factor); $this->minutes = (int) round($this->minutes * $factor); $this->seconds = (int) round($this->seconds * $factor); $this->microseconds = (int) round($this->microseconds * $factor); return $this; } /** * Divide current instance by a given divider. shares() is naive, it divides each unit separately * and the result is rounded for each unit. So 5 hours and 20 minutes shared by 3 becomes 2 hours * and 7 minutes. * * Use shares() when you want a fast and approximated calculation that does not cascade units. * * For a precise and cascaded calculation, * * @see divide() * * @param float|int $divider * * @return $this */ public function shares($divider) { return $this->times(1 / $divider); } protected function copyProperties(self $interval, $ignoreSign = false) { $this->years = $interval->years; $this->months = $interval->months; $this->dayz = $interval->dayz; $this->hours = $interval->hours; $this->minutes = $interval->minutes; $this->seconds = $interval->seconds; $this->microseconds = $interval->microseconds; if (!$ignoreSign) { $this->invert = $interval->invert; } return $this; } /** * Multiply and cascade current instance by a given factor. * * @param float|int $factor * * @return $this */ public function multiply($factor) { if ($factor < 0) { $this->invert = $this->invert ? 0 : 1; $factor = -$factor; } $yearPart = (int) floor($this->years * $factor); // Split calculation to prevent imprecision if ($yearPart) { $this->years -= $yearPart / $factor; } return $this->copyProperties( static::create($yearPart) ->microseconds(abs($this->totalMicroseconds) * $factor) ->cascade(), true ); } /** * Divide and cascade current instance by a given divider. * * @param float|int $divider * * @return $this */ public function divide($divider) { return $this->multiply(1 / $divider); } /** * Get the interval_spec string of a date interval. * * @param DateInterval $interval * * @return string */ public static function getDateIntervalSpec(DateInterval $interval, bool $microseconds = false, array $skip = []) { $date = array_filter([ static::PERIOD_YEARS => abs($interval->y), static::PERIOD_MONTHS => abs($interval->m), static::PERIOD_DAYS => abs($interval->d), ]); if ( $interval->days >= CarbonInterface::DAYS_PER_WEEK * CarbonInterface::WEEKS_PER_MONTH && (!isset($date[static::PERIOD_YEARS]) || \count(array_intersect(['y', 'year', 'years'], $skip))) && (!isset($date[static::PERIOD_MONTHS]) || \count(array_intersect(['m', 'month', 'months'], $skip))) ) { $date = [ static::PERIOD_DAYS => abs($interval->days), ]; } $seconds = abs($interval->s); if ($microseconds && $interval->f > 0) { $seconds = \sprintf('%d.%06d', $seconds, abs($interval->f) * 1000000); } $time = array_filter([ static::PERIOD_HOURS => abs($interval->h), static::PERIOD_MINUTES => abs($interval->i), static::PERIOD_SECONDS => $seconds, ]); $specString = static::PERIOD_PREFIX; foreach ($date as $key => $value) { $specString .= $value.$key; } if (\count($time) > 0) { $specString .= static::PERIOD_TIME_PREFIX; foreach ($time as $key => $value) { $specString .= $value.$key; } } return $specString === static::PERIOD_PREFIX ? 'PT0S' : $specString; } /** * Get the interval_spec string. * * @return string */ public function spec(bool $microseconds = false) { return static::getDateIntervalSpec($this, $microseconds); } /** * Comparing 2 date intervals. * * @param DateInterval $first * @param DateInterval $second * * @return int */ public static function compareDateIntervals(DateInterval $first, DateInterval $second) { $current = Carbon::now(); $passed = $current->avoidMutation()->add($second); $current->add($first); if ($current < $passed) { return -1; } if ($current > $passed) { return 1; } return 0; } /** * Comparing with passed interval. * * @param DateInterval $interval * * @return int */ public function compare(DateInterval $interval) { return static::compareDateIntervals($this, $interval); } private function invertCascade(array $values) { return $this->set(array_map(function ($value) { return -$value; }, $values))->doCascade(true)->invert(); } private function doCascade(bool $deep) { $originalData = $this->toArray(); $originalData['milliseconds'] = (int) ($originalData['microseconds'] / static::getMicrosecondsPerMillisecond()); $originalData['microseconds'] = $originalData['microseconds'] % static::getMicrosecondsPerMillisecond(); $originalData['weeks'] = (int) ($this->d / static::getDaysPerWeek()); $originalData['daysExcludeWeeks'] = fmod($this->d, static::getDaysPerWeek()); unset($originalData['days']); $newData = $originalData; $previous = []; foreach (self::getFlipCascadeFactors() as $source => [$target, $factor]) { foreach (['source', 'target'] as $key) { if ($$key === 'dayz') { $$key = 'daysExcludeWeeks'; } } $value = $newData[$source]; $modulo = fmod($factor + fmod($value, $factor), $factor); $newData[$source] = $modulo; $newData[$target] += ($value - $modulo) / $factor; $decimalPart = fmod($newData[$source], 1); if ($decimalPart !== 0.0) { $unit = $source; foreach ($previous as [$subUnit, $subFactor]) { $newData[$unit] -= $decimalPart; $newData[$subUnit] += $decimalPart * $subFactor; $decimalPart = fmod($newData[$subUnit], 1); if ($decimalPart === 0.0) { break; } $unit = $subUnit; } } array_unshift($previous, [$source, $factor]); } $positive = null; if (!$deep) { foreach ($newData as $value) { if ($value) { if ($positive === null) { $positive = ($value > 0); continue; } if (($value > 0) !== $positive) { return $this->invertCascade($originalData) ->solveNegativeInterval(); } } } } return $this->set($newData) ->solveNegativeInterval(); } /** * Convert overflowed values into bigger units. * * @return $this */ public function cascade() { return $this->doCascade(false); } public function hasNegativeValues(): bool { foreach ($this->toArray() as $value) { if ($value < 0) { return true; } } return false; } public function hasPositiveValues(): bool { foreach ($this->toArray() as $value) { if ($value > 0) { return true; } } return false; } /** * Get amount of given unit equivalent to the interval. * * @param string $unit * * @throws UnknownUnitException|UnitNotConfiguredException * * @return float */ public function total($unit) { $realUnit = $unit = strtolower($unit); if (\in_array($unit, ['days', 'weeks'])) { $realUnit = 'dayz'; } elseif (!\in_array($unit, ['microseconds', 'milliseconds', 'seconds', 'minutes', 'hours', 'dayz', 'months', 'years'])) { throw new UnknownUnitException($unit); } $result = 0; $cumulativeFactor = 0; $unitFound = false; $factors = self::getFlipCascadeFactors(); $daysPerWeek = (int) static::getDaysPerWeek(); $values = [ 'years' => $this->years, 'months' => $this->months, 'weeks' => (int) ($this->d / $daysPerWeek), 'dayz' => fmod($this->d, $daysPerWeek), 'hours' => $this->hours, 'minutes' => $this->minutes, 'seconds' => $this->seconds, 'milliseconds' => (int) ($this->microseconds / Carbon::MICROSECONDS_PER_MILLISECOND), 'microseconds' => $this->microseconds % Carbon::MICROSECONDS_PER_MILLISECOND, ]; if (isset($factors['dayz']) && $factors['dayz'][0] !== 'weeks') { $values['dayz'] += $values['weeks'] * $daysPerWeek; $values['weeks'] = 0; } foreach ($factors as $source => [$target, $factor]) { if ($source === $realUnit) { $unitFound = true; $value = $values[$source]; $result += $value; $cumulativeFactor = 1; } if ($factor === false) { if ($unitFound) { break; } $result = 0; $cumulativeFactor = 0; continue; } if ($target === $realUnit) { $unitFound = true; } if ($cumulativeFactor) { $cumulativeFactor *= $factor; $result += $values[$target] * $cumulativeFactor; continue; } $value = $values[$source]; $result = ($result + $value) / $factor; } if (isset($target) && !$cumulativeFactor) { $result += $values[$target]; } if (!$unitFound) { throw new UnitNotConfiguredException($unit); } if ($this->invert) { $result *= -1; } if ($unit === 'weeks') { $result /= $daysPerWeek; } // Cast as int numbers with no decimal part return fmod($result, 1) === 0.0 ? (int) $result : $result; } /** * Determines if the instance is equal to another * * @param CarbonInterval|DateInterval|mixed $interval * * @see equalTo() * * @return bool */ public function eq($interval): bool { return $this->equalTo($interval); } /** * Determines if the instance is equal to another * * @param CarbonInterval|DateInterval|mixed $interval * * @return bool */ public function equalTo($interval): bool { $interval = $this->resolveInterval($interval); return $interval !== null && $this->totalMicroseconds === $interval->totalMicroseconds; } /** * Determines if the instance is not equal to another * * @param CarbonInterval|DateInterval|mixed $interval * * @see notEqualTo() * * @return bool */ public function ne($interval): bool { return $this->notEqualTo($interval); } /** * Determines if the instance is not equal to another * * @param CarbonInterval|DateInterval|mixed $interval * * @return bool */ public function notEqualTo($interval): bool { return !$this->eq($interval); } /** * Determines if the instance is greater (longer) than another * * @param CarbonInterval|DateInterval|mixed $interval * * @see greaterThan() * * @return bool */ public function gt($interval): bool { return $this->greaterThan($interval); } /** * Determines if the instance is greater (longer) than another * * @param CarbonInterval|DateInterval|mixed $interval * * @return bool */ public function greaterThan($interval): bool { $interval = $this->resolveInterval($interval); return $interval === null || $this->totalMicroseconds > $interval->totalMicroseconds; } /** * Determines if the instance is greater (longer) than or equal to another * * @param CarbonInterval|DateInterval|mixed $interval * * @see greaterThanOrEqualTo() * * @return bool */ public function gte($interval): bool { return $this->greaterThanOrEqualTo($interval); } /** * Determines if the instance is greater (longer) than or equal to another * * @param CarbonInterval|DateInterval|mixed $interval * * @return bool */ public function greaterThanOrEqualTo($interval): bool { return $this->greaterThan($interval) || $this->equalTo($interval); } /** * Determines if the instance is less (shorter) than another * * @param CarbonInterval|DateInterval|mixed $interval * * @see lessThan() * * @return bool */ public function lt($interval): bool { return $this->lessThan($interval); } /** * Determines if the instance is less (shorter) than another * * @param CarbonInterval|DateInterval|mixed $interval * * @return bool */ public function lessThan($interval): bool { $interval = $this->resolveInterval($interval); return $interval !== null && $this->totalMicroseconds < $interval->totalMicroseconds; } /** * Determines if the instance is less (shorter) than or equal to another * * @param CarbonInterval|DateInterval|mixed $interval * * @see lessThanOrEqualTo() * * @return bool */ public function lte($interval): bool { return $this->lessThanOrEqualTo($interval); } /** * Determines if the instance is less (shorter) than or equal to another * * @param CarbonInterval|DateInterval|mixed $interval * * @return bool */ public function lessThanOrEqualTo($interval): bool { return $this->lessThan($interval) || $this->equalTo($interval); } /** * Determines if the instance is between two others. * * The third argument allow you to specify if bounds are included or not (true by default) * but for when you including/excluding bounds may produce different results in your application, * we recommend to use the explicit methods ->betweenIncluded() or ->betweenExcluded() instead. * * @example * ``` * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(3)); // true * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::hours(36)); // false * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(2)); // true * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(2), false); // false * ``` * * @param CarbonInterval|DateInterval|mixed $interval1 * @param CarbonInterval|DateInterval|mixed $interval2 * @param bool $equal Indicates if an equal to comparison should be done * * @return bool */ public function between($interval1, $interval2, $equal = true): bool { return $equal ? $this->greaterThanOrEqualTo($interval1) && $this->lessThanOrEqualTo($interval2) : $this->greaterThan($interval1) && $this->lessThan($interval2); } /** * Determines if the instance is between two others, bounds excluded. * * @example * ``` * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(3)); // true * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::hours(36)); // false * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(2)); // true * ``` * * @param CarbonInterval|DateInterval|mixed $interval1 * @param CarbonInterval|DateInterval|mixed $interval2 * * @return bool */ public function betweenIncluded($interval1, $interval2): bool { return $this->between($interval1, $interval2, true); } /** * Determines if the instance is between two others, bounds excluded. * * @example * ``` * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(3)); // true * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::hours(36)); // false * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(2)); // false * ``` * * @param CarbonInterval|DateInterval|mixed $interval1 * @param CarbonInterval|DateInterval|mixed $interval2 * * @return bool */ public function betweenExcluded($interval1, $interval2): bool { return $this->between($interval1, $interval2, false); } /** * Determines if the instance is between two others * * @example * ``` * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(3)); // true * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::hours(36)); // false * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(2)); // true * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(2), false); // false * ``` * * @param CarbonInterval|DateInterval|mixed $interval1 * @param CarbonInterval|DateInterval|mixed $interval2 * @param bool $equal Indicates if an equal to comparison should be done * * @return bool */ public function isBetween($interval1, $interval2, $equal = true): bool { return $this->between($interval1, $interval2, $equal); } /** * Round the current instance at the given unit with given precision if specified and the given function. * * @param string $unit * @param float|int|string|DateInterval|null $precision * @param string $function * * @throws Exception * * @return $this */ public function roundUnit($unit, $precision = 1, $function = 'round') { if (static::getCascadeFactors() !== static::getDefaultCascadeFactors()) { $value = $function($this->total($unit) / $precision) * $precision; $inverted = $value < 0; return $this->copyProperties(self::fromString( number_format(abs($value), 12, '.', '').' '.$unit )->invert($inverted)->cascade()); } $base = CarbonImmutable::parse('2000-01-01 00:00:00', 'UTC') ->roundUnit($unit, $precision, $function); $next = $base->add($this); $inverted = $next < $base; if ($inverted) { $next = $base->sub($this); } $this->copyProperties( $next ->roundUnit($unit, $precision, $function) ->diffAsCarbonInterval($base) ); return $this->invert($inverted); } /** * Truncate the current instance at the given unit with given precision if specified. * * @param string $unit * @param float|int|string|DateInterval|null $precision * * @throws Exception * * @return $this */ public function floorUnit($unit, $precision = 1) { return $this->roundUnit($unit, $precision, 'floor'); } /** * Ceil the current instance at the given unit with given precision if specified. * * @param string $unit * @param float|int|string|DateInterval|null $precision * * @throws Exception * * @return $this */ public function ceilUnit($unit, $precision = 1) { return $this->roundUnit($unit, $precision, 'ceil'); } /** * Round the current instance second with given precision if specified. * * @param float|int|string|DateInterval|null $precision * @param string $function * * @throws Exception * * @return $this */ public function round($precision = 1, $function = 'round') { return $this->roundWith($precision, $function); } /** * Round the current instance second with given precision if specified. * * @param float|int|string|DateInterval|null $precision * * @throws Exception * * @return $this */ public function floor($precision = 1) { return $this->round($precision, 'floor'); } /** * Ceil the current instance second with given precision if specified. * * @param float|int|string|DateInterval|null $precision * * @throws Exception * * @return $this */ public function ceil($precision = 1) { return $this->round($precision, 'ceil'); } private function needsDeclension(string $mode, int $index, int $parts): bool { switch ($mode) { case 'last': return $index === $parts - 1; default: return true; } } private function checkIntegerValue(string $name, $value) { if (\is_int($value)) { return; } $this->assertSafeForInteger($name, $value); if (\is_float($value) && (((float) (int) $value) === $value)) { return; } if (!self::$floatSettersEnabled) { $type = \gettype($value); @trigger_error( "Since 2.70.0, it's deprecated to pass $type value for $name.\n". "It's truncated when stored as an integer interval unit.\n". "From 3.0.0, decimal part will no longer be truncated and will be cascaded to smaller units.\n". "- To maintain the current behavior, use explicit cast: $name((int) \$value)\n". "- To adopt the new behavior globally, call CarbonInterval::enableFloatSetters()\n", \E_USER_DEPRECATED ); } } /** * Throw an exception if precision loss when storing the given value as an integer would be >= 1.0. */ private function assertSafeForInteger(string $name, $value) { if ($value && !\is_int($value) && ($value >= 0x7fffffffffffffff || $value <= -0x7fffffffffffffff)) { throw new OutOfRangeException($name, -0x7fffffffffffffff, 0x7fffffffffffffff, $value); } } private function handleDecimalPart(string $unit, $value, $integerValue) { if (self::$floatSettersEnabled) { $floatValue = (float) $value; $base = (float) $integerValue; if ($floatValue === $base) { return; } $units = [ 'y' => 'year', 'm' => 'month', 'd' => 'day', 'h' => 'hour', 'i' => 'minute', 's' => 'second', ]; $upper = true; foreach ($units as $property => $name) { if ($name === $unit) { $upper = false; continue; } if (!$upper && $this->$property !== 0) { throw new RuntimeException( "You cannot set $unit to a float value as $name would be overridden, ". 'set it first to 0 explicitly if you really want to erase its value' ); } } $this->add($unit, $floatValue - $base); } } } PK������<1Z:P%��%����Carbon/Traits/Rounding.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; use Carbon\CarbonInterface; use Carbon\Exceptions\UnknownUnitException; /** * Trait Rounding. * * Round, ceil, floor units. * * Depends on the following methods: * * @method static copy() * @method static startOfWeek(int $weekStartsAt = null) */ trait Rounding { use IntervalRounding; /** * Round the current instance at the given unit with given precision if specified and the given function. * * @param string $unit * @param float|int $precision * @param string $function * * @return CarbonInterface */ public function roundUnit($unit, $precision = 1, $function = 'round') { $metaUnits = [ // @call roundUnit 'millennium' => [static::YEARS_PER_MILLENNIUM, 'year'], // @call roundUnit 'century' => [static::YEARS_PER_CENTURY, 'year'], // @call roundUnit 'decade' => [static::YEARS_PER_DECADE, 'year'], // @call roundUnit 'quarter' => [static::MONTHS_PER_QUARTER, 'month'], // @call roundUnit 'millisecond' => [1000, 'microsecond'], ]; $normalizedUnit = static::singularUnit($unit); $ranges = array_merge(static::getRangesByUnit($this->daysInMonth), [ // @call roundUnit 'microsecond' => [0, 999999], ]); $factor = 1; if ($normalizedUnit === 'week') { $normalizedUnit = 'day'; $precision *= static::DAYS_PER_WEEK; } if (isset($metaUnits[$normalizedUnit])) { [$factor, $normalizedUnit] = $metaUnits[$normalizedUnit]; } $precision *= $factor; if (!isset($ranges[$normalizedUnit])) { throw new UnknownUnitException($unit); } $found = false; $fraction = 0; $arguments = null; $initialValue = null; $factor = $this->year < 0 ? -1 : 1; $changes = []; $minimumInc = null; foreach ($ranges as $unit => [$minimum, $maximum]) { if ($normalizedUnit === $unit) { $arguments = [$this->$unit, $minimum]; $initialValue = $this->$unit; $fraction = $precision - floor($precision); $found = true; continue; } if ($found) { $delta = $maximum + 1 - $minimum; $factor /= $delta; $fraction *= $delta; $inc = ($this->$unit - $minimum) * $factor; if ($inc !== 0.0) { $minimumInc = $minimumInc ?? ($arguments[0] / pow(2, 52)); // If value is still the same when adding a non-zero increment/decrement, // it means precision got lost in the addition if (abs($inc) < $minimumInc) { $inc = $minimumInc * ($inc < 0 ? -1 : 1); } // If greater than $precision, assume precision loss caused an overflow if ($function !== 'floor' || abs($arguments[0] + $inc - $initialValue) >= $precision) { $arguments[0] += $inc; } } $changes[$unit] = round( $minimum + ($fraction ? $fraction * $function(($this->$unit - $minimum) / $fraction) : 0) ); // Cannot use modulo as it lose double precision while ($changes[$unit] >= $delta) { $changes[$unit] -= $delta; } $fraction -= floor($fraction); } } [$value, $minimum] = $arguments; $normalizedValue = floor($function(($value - $minimum) / $precision) * $precision + $minimum); /** @var CarbonInterface $result */ $result = $this; foreach ($changes as $unit => $value) { $result = $result->$unit($value); } return $result->$normalizedUnit($normalizedValue); } /** * Truncate the current instance at the given unit with given precision if specified. * * @param string $unit * @param float|int $precision * * @return CarbonInterface */ public function floorUnit($unit, $precision = 1) { return $this->roundUnit($unit, $precision, 'floor'); } /** * Ceil the current instance at the given unit with given precision if specified. * * @param string $unit * @param float|int $precision * * @return CarbonInterface */ public function ceilUnit($unit, $precision = 1) { return $this->roundUnit($unit, $precision, 'ceil'); } /** * Round the current instance second with given precision if specified. * * @param float|int|string|\DateInterval|null $precision * @param string $function * * @return CarbonInterface */ public function round($precision = 1, $function = 'round') { return $this->roundWith($precision, $function); } /** * Round the current instance second with given precision if specified. * * @param float|int|string|\DateInterval|null $precision * * @return CarbonInterface */ public function floor($precision = 1) { return $this->round($precision, 'floor'); } /** * Ceil the current instance second with given precision if specified. * * @param float|int|string|\DateInterval|null $precision * * @return CarbonInterface */ public function ceil($precision = 1) { return $this->round($precision, 'ceil'); } /** * Round the current instance week. * * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week * * @return CarbonInterface */ public function roundWeek($weekStartsAt = null) { return $this->closest( $this->avoidMutation()->floorWeek($weekStartsAt), $this->avoidMutation()->ceilWeek($weekStartsAt) ); } /** * Truncate the current instance week. * * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week * * @return CarbonInterface */ public function floorWeek($weekStartsAt = null) { return $this->startOfWeek($weekStartsAt); } /** * Ceil the current instance week. * * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week * * @return CarbonInterface */ public function ceilWeek($weekStartsAt = null) { if ($this->isMutable()) { $startOfWeek = $this->avoidMutation()->startOfWeek($weekStartsAt); return $startOfWeek != $this ? $this->startOfWeek($weekStartsAt)->addWeek() : $this; } $startOfWeek = $this->startOfWeek($weekStartsAt); return $startOfWeek != $this ? $startOfWeek->addWeek() : $this->avoidMutation(); } } PK������<1Z=z��z����Carbon/Traits/Creator.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; use Carbon\Carbon; use Carbon\CarbonImmutable; use Carbon\CarbonInterface; use Carbon\Exceptions\InvalidDateException; use Carbon\Exceptions\InvalidFormatException; use Carbon\Exceptions\OutOfRangeException; use Carbon\Translator; use Closure; use DateMalformedStringException; use DateTimeImmutable; use DateTimeInterface; use DateTimeZone; use Exception; use ReturnTypeWillChange; /** * Trait Creator. * * Static creators. * * Depends on the following methods: * * @method static Carbon|CarbonImmutable getTestNow() */ trait Creator { use ObjectInitialisation; /** * The errors that can occur. * * @var array */ protected static $lastErrors; /** * Create a new Carbon instance. * * Please see the testing aids section (specifically static::setTestNow()) * for more on the possibility of this constructor returning a test instance. * * @param DateTimeInterface|string|null $time * @param DateTimeZone|string|null $tz * * @throws InvalidFormatException */ public function __construct($time = null, $tz = null) { if ($time instanceof DateTimeInterface) { $time = $this->constructTimezoneFromDateTime($time, $tz)->format('Y-m-d H:i:s.u'); } if (is_numeric($time) && (!\is_string($time) || !preg_match('/^\d{1,14}$/', $time))) { $time = static::createFromTimestampUTC($time)->format('Y-m-d\TH:i:s.uP'); } // If the class has a test now set and we are trying to create a now() // instance then override as required $isNow = empty($time) || $time === 'now'; if (method_exists(static::class, 'hasTestNow') && method_exists(static::class, 'getTestNow') && static::hasTestNow() && ($isNow || static::hasRelativeKeywords($time)) ) { static::mockConstructorParameters($time, $tz); } // Work-around for PHP bug https://bugs.php.net/bug.php?id=67127 if (!str_contains((string) .1, '.')) { $locale = setlocale(LC_NUMERIC, '0'); // @codeCoverageIgnore setlocale(LC_NUMERIC, 'C'); // @codeCoverageIgnore } try { parent::__construct($time ?: 'now', static::safeCreateDateTimeZone($tz) ?: null); } catch (Exception $exception) { throw new InvalidFormatException($exception->getMessage(), 0, $exception); } $this->constructedObjectId = spl_object_hash($this); if (isset($locale)) { setlocale(LC_NUMERIC, $locale); // @codeCoverageIgnore } self::setLastErrors(parent::getLastErrors()); } /** * Get timezone from a datetime instance. * * @param DateTimeInterface $date * @param DateTimeZone|string|null $tz * * @return DateTimeInterface */ private function constructTimezoneFromDateTime(DateTimeInterface $date, &$tz) { if ($tz !== null) { $safeTz = static::safeCreateDateTimeZone($tz); if ($safeTz) { return ($date instanceof DateTimeImmutable ? $date : clone $date)->setTimezone($safeTz); } return $date; } $tz = $date->getTimezone(); return $date; } /** * Update constructedObjectId on cloned. */ public function __clone() { $this->constructedObjectId = spl_object_hash($this); } /** * Create a Carbon instance from a DateTime one. * * @param DateTimeInterface $date * * @return static */ public static function instance($date) { if ($date instanceof static) { return clone $date; } static::expectDateTime($date); $instance = new static($date->format('Y-m-d H:i:s.u'), $date->getTimezone()); if ($date instanceof CarbonInterface) { $settings = $date->getSettings(); if (!$date->hasLocalTranslator()) { unset($settings['locale']); } $instance->settings($settings); } return $instance; } /** * Create a carbon instance from a string. * * This is an alias for the constructor that allows better fluent syntax * as it allows you to do Carbon::parse('Monday next week')->fn() rather * than (new Carbon('Monday next week'))->fn(). * * @param string|DateTimeInterface|null $time * @param DateTimeZone|string|null $tz * * @throws InvalidFormatException * * @return static */ public static function rawParse($time = null, $tz = null) { if ($time instanceof DateTimeInterface) { return static::instance($time); } try { return new static($time, $tz); } catch (Exception $exception) { // @codeCoverageIgnoreStart try { $date = @static::now($tz)->change($time); } catch (DateMalformedStringException $ignoredException) { $date = null; } // @codeCoverageIgnoreEnd if (!$date) { throw new InvalidFormatException("Could not parse '$time': ".$exception->getMessage(), 0, $exception); } return $date; } } /** * Create a carbon instance from a string. * * This is an alias for the constructor that allows better fluent syntax * as it allows you to do Carbon::parse('Monday next week')->fn() rather * than (new Carbon('Monday next week'))->fn(). * * @param string|DateTimeInterface|null $time * @param DateTimeZone|string|null $tz * * @throws InvalidFormatException * * @return static */ public static function parse($time = null, $tz = null) { $function = static::$parseFunction; if (!$function) { return static::rawParse($time, $tz); } if (\is_string($function) && method_exists(static::class, $function)) { $function = [static::class, $function]; } return $function(...\func_get_args()); } /** * Create a carbon instance from a localized string (in French, Japanese, Arabic, etc.). * * @param string $time date/time string in the given language (may also contain English). * @param string|null $locale if locale is null or not specified, current global locale will be * used instead. * @param DateTimeZone|string|null $tz optional timezone for the new instance. * * @throws InvalidFormatException * * @return static */ public static function parseFromLocale($time, $locale = null, $tz = null) { return static::rawParse(static::translateTimeString($time, $locale, 'en'), $tz); } /** * Get a Carbon instance for the current date and time. * * @param DateTimeZone|string|null $tz * * @return static */ public static function now($tz = null) { return new static(null, $tz); } /** * Create a Carbon instance for today. * * @param DateTimeZone|string|null $tz * * @return static */ public static function today($tz = null) { return static::rawParse('today', $tz); } /** * Create a Carbon instance for tomorrow. * * @param DateTimeZone|string|null $tz * * @return static */ public static function tomorrow($tz = null) { return static::rawParse('tomorrow', $tz); } /** * Create a Carbon instance for yesterday. * * @param DateTimeZone|string|null $tz * * @return static */ public static function yesterday($tz = null) { return static::rawParse('yesterday', $tz); } /** * Create a Carbon instance for the greatest supported date. * * @return static */ public static function maxValue() { if (self::$PHPIntSize === 4) { // 32 bit return static::createFromTimestamp(PHP_INT_MAX); // @codeCoverageIgnore } // 64 bit return static::create(9999, 12, 31, 23, 59, 59); } /** * Create a Carbon instance for the lowest supported date. * * @return static */ public static function minValue() { if (self::$PHPIntSize === 4) { // 32 bit return static::createFromTimestamp(~PHP_INT_MAX); // @codeCoverageIgnore } // 64 bit return static::create(1, 1, 1, 0, 0, 0); } private static function assertBetween($unit, $value, $min, $max) { if (static::isStrictModeEnabled() && ($value < $min || $value > $max)) { throw new OutOfRangeException($unit, $min, $max, $value); } } private static function createNowInstance($tz) { if (!static::hasTestNow()) { return static::now($tz); } $now = static::getTestNow(); if ($now instanceof Closure) { return $now(static::now($tz)); } return $now->avoidMutation()->tz($tz); } /** * Create a new Carbon instance from a specific date and time. * * If any of $year, $month or $day are set to null their now() values will * be used. * * If $hour is null it will be set to its now() value and the default * values for $minute and $second will be their now() values. * * If $hour is not null then the default values for $minute and $second * will be 0. * * @param DateTimeInterface|int|null $year * @param int|null $month * @param int|null $day * @param int|null $hour * @param int|null $minute * @param int|null $second * @param DateTimeZone|string|null $tz * * @throws InvalidFormatException * * @return static|false */ public static function create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $tz = null) { if ((\is_string($year) && !is_numeric($year)) || $year instanceof DateTimeInterface) { return static::parse($year, $tz ?: (\is_string($month) || $month instanceof DateTimeZone ? $month : null)); } $defaults = null; $getDefault = function ($unit) use ($tz, &$defaults) { if ($defaults === null) { $now = self::createNowInstance($tz); $defaults = array_combine([ 'year', 'month', 'day', 'hour', 'minute', 'second', ], explode('-', $now->rawFormat('Y-n-j-G-i-s.u'))); } return $defaults[$unit]; }; $year = $year ?? $getDefault('year'); $month = $month ?? $getDefault('month'); $day = $day ?? $getDefault('day'); $hour = $hour ?? $getDefault('hour'); $minute = $minute ?? $getDefault('minute'); $second = (float) ($second ?? $getDefault('second')); self::assertBetween('month', $month, 0, 99); self::assertBetween('day', $day, 0, 99); self::assertBetween('hour', $hour, 0, 99); self::assertBetween('minute', $minute, 0, 99); self::assertBetween('second', $second, 0, 99); $fixYear = null; if ($year < 0) { $fixYear = $year; $year = 0; } elseif ($year > 9999) { $fixYear = $year - 9999; $year = 9999; } $second = ($second < 10 ? '0' : '').number_format($second, 6); $instance = static::rawCreateFromFormat('!Y-n-j G:i:s.u', \sprintf('%s-%s-%s %s:%02s:%02s', $year, $month, $day, $hour, $minute, $second), $tz); if ($fixYear !== null) { $instance = $instance->addYears($fixYear); } return $instance; } /** * Create a new safe Carbon instance from a specific date and time. * * If any of $year, $month or $day are set to null their now() values will * be used. * * If $hour is null it will be set to its now() value and the default * values for $minute and $second will be their now() values. * * If $hour is not null then the default values for $minute and $second * will be 0. * * If one of the set values is not valid, an InvalidDateException * will be thrown. * * @param int|null $year * @param int|null $month * @param int|null $day * @param int|null $hour * @param int|null $minute * @param int|null $second * @param DateTimeZone|string|null $tz * * @throws InvalidDateException * * @return static|false */ public static function createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null) { $fields = static::getRangesByUnit(); foreach ($fields as $field => $range) { if ($$field !== null && (!\is_int($$field) || $$field < $range[0] || $$field > $range[1])) { if (static::isStrictModeEnabled()) { throw new InvalidDateException($field, $$field); } return false; } } $instance = static::create($year, $month, $day, $hour, $minute, $second, $tz); foreach (array_reverse($fields) as $field => $range) { if ($$field !== null && (!\is_int($$field) || $$field !== $instance->$field)) { if (static::isStrictModeEnabled()) { throw new InvalidDateException($field, $$field); } return false; } } return $instance; } /** * Create a new Carbon instance from a specific date and time using strict validation. * * @see create() * * @param int|null $year * @param int|null $month * @param int|null $day * @param int|null $hour * @param int|null $minute * @param int|null $second * @param DateTimeZone|string|null $tz * * @throws InvalidFormatException * * @return static */ public static function createStrict(?int $year = 0, ?int $month = 1, ?int $day = 1, ?int $hour = 0, ?int $minute = 0, ?int $second = 0, $tz = null): self { $initialStrictMode = static::isStrictModeEnabled(); static::useStrictMode(true); try { $date = static::create($year, $month, $day, $hour, $minute, $second, $tz); } finally { static::useStrictMode($initialStrictMode); } return $date; } /** * Create a Carbon instance from just a date. The time portion is set to now. * * @param int|null $year * @param int|null $month * @param int|null $day * @param DateTimeZone|string|null $tz * * @throws InvalidFormatException * * @return static */ public static function createFromDate($year = null, $month = null, $day = null, $tz = null) { return static::create($year, $month, $day, null, null, null, $tz); } /** * Create a Carbon instance from just a date. The time portion is set to midnight. * * @param int|null $year * @param int|null $month * @param int|null $day * @param DateTimeZone|string|null $tz * * @throws InvalidFormatException * * @return static */ public static function createMidnightDate($year = null, $month = null, $day = null, $tz = null) { return static::create($year, $month, $day, 0, 0, 0, $tz); } /** * Create a Carbon instance from just a time. The date portion is set to today. * * @param int|null $hour * @param int|null $minute * @param int|null $second * @param DateTimeZone|string|null $tz * * @throws InvalidFormatException * * @return static */ public static function createFromTime($hour = 0, $minute = 0, $second = 0, $tz = null) { return static::create(null, null, null, $hour, $minute, $second, $tz); } /** * Create a Carbon instance from a time string. The date portion is set to today. * * @param string $time * @param DateTimeZone|string|null $tz * * @throws InvalidFormatException * * @return static */ public static function createFromTimeString($time, $tz = null) { return static::today($tz)->setTimeFromTimeString($time); } /** * @param string $format Datetime format * @param string $time * @param DateTimeZone|string|false|null $originalTz * * @return DateTimeInterface|false */ private static function createFromFormatAndTimezone($format, $time, $originalTz) { // Work-around for https://bugs.php.net/bug.php?id=75577 // @codeCoverageIgnoreStart if (version_compare(PHP_VERSION, '7.3.0-dev', '<')) { $format = str_replace('.v', '.u', $format); } // @codeCoverageIgnoreEnd if ($originalTz === null) { return parent::createFromFormat($format, (string) $time); } $tz = \is_int($originalTz) ? @timezone_name_from_abbr('', (int) ($originalTz * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE), 1) : $originalTz; $tz = static::safeCreateDateTimeZone($tz, $originalTz); if ($tz === false) { return false; } return parent::createFromFormat($format, (string) $time, $tz); } /** * Create a Carbon instance from a specific format. * * @param string $format Datetime format * @param string $time * @param DateTimeZone|string|false|null $tz * * @throws InvalidFormatException * * @return static|false */ public static function rawCreateFromFormat($format, $time, $tz = null) { // Work-around for https://bugs.php.net/bug.php?id=80141 $format = preg_replace('/(?<!\\\\)((?:\\\\{2})*)c/', '$1Y-m-d\TH:i:sP', $format); if (preg_match('/(?<!\\\\)(?:\\\\{2})*(a|A)/', $format, $aMatches, PREG_OFFSET_CAPTURE) && preg_match('/(?<!\\\\)(?:\\\\{2})*(h|g|H|G)/', $format, $hMatches, PREG_OFFSET_CAPTURE) && $aMatches[1][1] < $hMatches[1][1] && preg_match('/(am|pm|AM|PM)/', $time) ) { $format = preg_replace('/^(.*)(?<!\\\\)((?:\\\\{2})*)(a|A)(.*)$/U', '$1$2$4 $3', $format); $time = preg_replace('/^(.*)(am|pm|AM|PM)(.*)$/U', '$1$3 $2', $time); } if ($tz === false) { $tz = null; } // First attempt to create an instance, so that error messages are based on the unmodified format. $date = self::createFromFormatAndTimezone($format, $time, $tz); $lastErrors = parent::getLastErrors(); /** @var \Carbon\CarbonImmutable|\Carbon\Carbon|null $mock */ $mock = static::getMockedTestNow($tz); if ($mock && $date instanceof DateTimeInterface) { // Set timezone from mock if custom timezone was neither given directly nor as a part of format. // First let's skip the part that will be ignored by the parser. $nonEscaped = '(?<!\\\\)(\\\\{2})*'; $nonIgnored = preg_replace("/^.*{$nonEscaped}!/s", '', $format); if ($tz === null && !preg_match("/{$nonEscaped}[eOPT]/", $nonIgnored)) { $tz = clone $mock->getTimezone(); } $mock = $mock->copy(); // Prepend mock datetime only if the format does not contain non escaped unix epoch reset flag. if (!preg_match("/{$nonEscaped}[!|]/", $format)) { if (preg_match('/[HhGgisvuB]/', $format)) { $mock = $mock->setTime(0, 0); } $format = static::MOCK_DATETIME_FORMAT.' '.$format; $time = ($mock instanceof self ? $mock->rawFormat(static::MOCK_DATETIME_FORMAT) : $mock->format(static::MOCK_DATETIME_FORMAT)).' '.$time; } // Regenerate date from the modified format to base result on the mocked instance instead of now. $date = self::createFromFormatAndTimezone($format, $time, $tz); } if ($date instanceof DateTimeInterface) { $instance = static::instance($date); $instance::setLastErrors($lastErrors); return $instance; } if (static::isStrictModeEnabled()) { throw new InvalidFormatException(implode(PHP_EOL, $lastErrors['errors'])); } return false; } /** * Create a Carbon instance from a specific format. * * @param string $format Datetime format * @param string $time * @param DateTimeZone|string|false|null $tz * * @throws InvalidFormatException * * @return static|false */ #[ReturnTypeWillChange] public static function createFromFormat($format, $time, $tz = null) { $function = static::$createFromFormatFunction; if (!$function) { return static::rawCreateFromFormat($format, $time, $tz); } if (\is_string($function) && method_exists(static::class, $function)) { $function = [static::class, $function]; } return $function(...\func_get_args()); } /** * Create a Carbon instance from a specific ISO format (same replacements as ->isoFormat()). * * @param string $format Datetime format * @param string $time * @param DateTimeZone|string|false|null $tz optional timezone * @param string|null $locale locale to be used for LTS, LT, LL, LLL, etc. macro-formats (en by fault, unneeded if no such macro-format in use) * @param \Symfony\Component\Translation\TranslatorInterface $translator optional custom translator to use for macro-formats * * @throws InvalidFormatException * * @return static|false */ public static function createFromIsoFormat($format, $time, $tz = null, $locale = 'en', $translator = null) { $format = preg_replace_callback('/(?<!\\\\)(\\\\{2})*(LTS|LT|[Ll]{1,4})/', function ($match) use ($locale, $translator) { [$code] = $match; static $formats = null; if ($formats === null) { $translator = $translator ?: Translator::get($locale); $formats = [ 'LT' => static::getTranslationMessageWith($translator, 'formats.LT', $locale, 'h:mm A'), 'LTS' => static::getTranslationMessageWith($translator, 'formats.LTS', $locale, 'h:mm:ss A'), 'L' => static::getTranslationMessageWith($translator, 'formats.L', $locale, 'MM/DD/YYYY'), 'LL' => static::getTranslationMessageWith($translator, 'formats.LL', $locale, 'MMMM D, YYYY'), 'LLL' => static::getTranslationMessageWith($translator, 'formats.LLL', $locale, 'MMMM D, YYYY h:mm A'), 'LLLL' => static::getTranslationMessageWith($translator, 'formats.LLLL', $locale, 'dddd, MMMM D, YYYY h:mm A'), ]; } return $formats[$code] ?? preg_replace_callback( '/MMMM|MM|DD|dddd/', function ($code) { return mb_substr($code[0], 1); }, $formats[strtoupper($code)] ?? '' ); }, $format); $format = preg_replace_callback('/(?<!\\\\)(\\\\{2})*('.CarbonInterface::ISO_FORMAT_REGEXP.'|[A-Za-z])/', function ($match) { [$code] = $match; static $replacements = null; if ($replacements === null) { $replacements = [ 'OD' => 'd', 'OM' => 'M', 'OY' => 'Y', 'OH' => 'G', 'Oh' => 'g', 'Om' => 'i', 'Os' => 's', 'D' => 'd', 'DD' => 'd', 'Do' => 'd', 'd' => '!', 'dd' => '!', 'ddd' => 'D', 'dddd' => 'D', 'DDD' => 'z', 'DDDD' => 'z', 'DDDo' => 'z', 'e' => '!', 'E' => '!', 'H' => 'G', 'HH' => 'H', 'h' => 'g', 'hh' => 'h', 'k' => 'G', 'kk' => 'G', 'hmm' => 'gi', 'hmmss' => 'gis', 'Hmm' => 'Gi', 'Hmmss' => 'Gis', 'm' => 'i', 'mm' => 'i', 'a' => 'a', 'A' => 'a', 's' => 's', 'ss' => 's', 'S' => '*', 'SS' => '*', 'SSS' => '*', 'SSSS' => '*', 'SSSSS' => '*', 'SSSSSS' => 'u', 'SSSSSSS' => 'u*', 'SSSSSSSS' => 'u*', 'SSSSSSSSS' => 'u*', 'M' => 'm', 'MM' => 'm', 'MMM' => 'M', 'MMMM' => 'M', 'Mo' => 'm', 'Q' => '!', 'Qo' => '!', 'G' => '!', 'GG' => '!', 'GGG' => '!', 'GGGG' => '!', 'GGGGG' => '!', 'g' => '!', 'gg' => '!', 'ggg' => '!', 'gggg' => '!', 'ggggg' => '!', 'W' => '!', 'WW' => '!', 'Wo' => '!', 'w' => '!', 'ww' => '!', 'wo' => '!', 'x' => 'U???', 'X' => 'U', 'Y' => 'Y', 'YY' => 'y', 'YYYY' => 'Y', 'YYYYY' => 'Y', 'YYYYYY' => 'Y', 'z' => 'e', 'zz' => 'e', 'Z' => 'e', 'ZZ' => 'e', ]; } $format = $replacements[$code] ?? '?'; if ($format === '!') { throw new InvalidFormatException("Format $code not supported for creation."); } return $format; }, $format); return static::rawCreateFromFormat($format, $time, $tz); } /** * Create a Carbon instance from a specific format and a string in a given language. * * @param string $format Datetime format * @param string $locale * @param string $time * @param DateTimeZone|string|false|null $tz * * @throws InvalidFormatException * * @return static|false */ public static function createFromLocaleFormat($format, $locale, $time, $tz = null) { $format = preg_replace_callback( '/(?:\\\\[a-zA-Z]|[bfkqCEJKQRV]){2,}/', static function (array $match) use ($locale): string { $word = str_replace('\\', '', $match[0]); $translatedWord = static::translateTimeString($word, $locale, 'en'); return $word === $translatedWord ? $match[0] : preg_replace('/[a-zA-Z]/', '\\\\$0', $translatedWord); }, $format ); return static::rawCreateFromFormat($format, static::translateTimeString($time, $locale, 'en'), $tz); } /** * Create a Carbon instance from a specific ISO format and a string in a given language. * * @param string $format Datetime ISO format * @param string $locale * @param string $time * @param DateTimeZone|string|false|null $tz * * @throws InvalidFormatException * * @return static|false */ public static function createFromLocaleIsoFormat($format, $locale, $time, $tz = null) { $time = static::translateTimeString($time, $locale, 'en', CarbonInterface::TRANSLATE_MONTHS | CarbonInterface::TRANSLATE_DAYS | CarbonInterface::TRANSLATE_MERIDIEM); return static::createFromIsoFormat($format, $time, $tz, $locale); } /** * Make a Carbon instance from given variable if possible. * * Always return a new instance. Parse only strings and only these likely to be dates (skip intervals * and recurrences). Throw an exception for invalid format, but otherwise return null. * * @param mixed $var * * @throws InvalidFormatException * * @return static|null */ public static function make($var) { if ($var instanceof DateTimeInterface) { return static::instance($var); } $date = null; if (\is_string($var)) { $var = trim($var); if (!preg_match('/^P[\dT]/', $var) && !preg_match('/^R\d/', $var) && preg_match('/[a-z\d]/i', $var) ) { $date = static::parse($var); } } return $date; } /** * Set last errors. * * @param array|bool $lastErrors * * @return void */ private static function setLastErrors($lastErrors) { if (\is_array($lastErrors) || $lastErrors === false) { static::$lastErrors = \is_array($lastErrors) ? $lastErrors : [ 'warning_count' => 0, 'warnings' => [], 'error_count' => 0, 'errors' => [], ]; } } /** * {@inheritdoc} * * @return array */ #[ReturnTypeWillChange] public static function getLastErrors() { return static::$lastErrors; } } PK������<1Z_م�م���Carbon/Traits/Date.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; use BadMethodCallException; use Carbon\Carbon; use Carbon\CarbonInterface; use Carbon\CarbonPeriod; use Carbon\CarbonTimeZone; use Carbon\Exceptions\BadComparisonUnitException; use Carbon\Exceptions\ImmutableException; use Carbon\Exceptions\InvalidTimeZoneException; use Carbon\Exceptions\InvalidTypeException; use Carbon\Exceptions\UnknownGetterException; use Carbon\Exceptions\UnknownMethodException; use Carbon\Exceptions\UnknownSetterException; use Carbon\Exceptions\UnknownUnitException; use Closure; use DateInterval; use DatePeriod; use DateTime; use DateTimeImmutable; use DateTimeInterface; use DateTimeZone; use InvalidArgumentException; use ReflectionException; use ReturnTypeWillChange; use Throwable; /** * A simple API extension for DateTime. * * @mixin DeprecatedProperties * * <autodoc generated by `composer phpdoc`> * * @property int $year * @property int $yearIso * @property int $month * @property int $day * @property int $hour * @property int $minute * @property int $second * @property int $micro * @property int $microsecond * @property int|float|string $timestamp seconds since the Unix Epoch * @property string $englishDayOfWeek the day of week in English * @property string $shortEnglishDayOfWeek the abbreviated day of week in English * @property string $englishMonth the month in English * @property string $shortEnglishMonth the abbreviated month in English * @property int $milliseconds * @property int $millisecond * @property int $milli * @property int $week 1 through 53 * @property int $isoWeek 1 through 53 * @property int $weekYear year according to week format * @property int $isoWeekYear year according to ISO week format * @property int $dayOfYear 1 through 366 * @property int $age does a diffInYears() with default parameters * @property int $offset the timezone offset in seconds from UTC * @property int $offsetMinutes the timezone offset in minutes from UTC * @property int $offsetHours the timezone offset in hours from UTC * @property CarbonTimeZone $timezone the current timezone * @property CarbonTimeZone $tz alias of $timezone * @property-read int $dayOfWeek 0 (for Sunday) through 6 (for Saturday) * @property-read int $dayOfWeekIso 1 (for Monday) through 7 (for Sunday) * @property-read int $weekOfYear ISO-8601 week number of year, weeks starting on Monday * @property-read int $daysInMonth number of days in the given month * @property-read string $latinMeridiem "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark) * @property-read string $latinUpperMeridiem "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark) * @property-read string $timezoneAbbreviatedName the current timezone abbreviated name * @property-read string $tzAbbrName alias of $timezoneAbbreviatedName * @property-read string $dayName long name of weekday translated according to Carbon locale, in english if no translation available for current language * @property-read string $shortDayName short name of weekday translated according to Carbon locale, in english if no translation available for current language * @property-read string $minDayName very short name of weekday translated according to Carbon locale, in english if no translation available for current language * @property-read string $monthName long name of month translated according to Carbon locale, in english if no translation available for current language * @property-read string $shortMonthName short name of month translated according to Carbon locale, in english if no translation available for current language * @property-read string $meridiem lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language * @property-read string $upperMeridiem uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language * @property-read int $noZeroHour current hour from 1 to 24 * @property-read int $weeksInYear 51 through 53 * @property-read int $isoWeeksInYear 51 through 53 * @property-read int $weekOfMonth 1 through 5 * @property-read int $weekNumberInMonth 1 through 5 * @property-read int $firstWeekDay 0 through 6 * @property-read int $lastWeekDay 0 through 6 * @property-read int $daysInYear 365 or 366 * @property-read int $quarter the quarter of this instance, 1 - 4 * @property-read int $decade the decade of this instance * @property-read int $century the century of this instance * @property-read int $millennium the millennium of this instance * @property-read bool $dst daylight savings time indicator, true if DST, false otherwise * @property-read bool $local checks if the timezone is local, true if local, false otherwise * @property-read bool $utc checks if the timezone is UTC, true if UTC, false otherwise * @property-read string $timezoneName the current timezone name * @property-read string $tzName alias of $timezoneName * @property-read string $locale locale of the current instance * * @method bool isUtc() Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.) * @method bool isLocal() Check if the current instance has non-UTC timezone. * @method bool isValid() Check if the current instance is a valid date. * @method bool isDST() Check if the current instance is in a daylight saving time. * @method bool isSunday() Checks if the instance day is sunday. * @method bool isMonday() Checks if the instance day is monday. * @method bool isTuesday() Checks if the instance day is tuesday. * @method bool isWednesday() Checks if the instance day is wednesday. * @method bool isThursday() Checks if the instance day is thursday. * @method bool isFriday() Checks if the instance day is friday. * @method bool isSaturday() Checks if the instance day is saturday. * @method bool isSameYear(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same year as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentYear() Checks if the instance is in the same year as the current moment. * @method bool isNextYear() Checks if the instance is in the same year as the current moment next year. * @method bool isLastYear() Checks if the instance is in the same year as the current moment last year. * @method bool isSameWeek(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same week as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentWeek() Checks if the instance is in the same week as the current moment. * @method bool isNextWeek() Checks if the instance is in the same week as the current moment next week. * @method bool isLastWeek() Checks if the instance is in the same week as the current moment last week. * @method bool isSameDay(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same day as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentDay() Checks if the instance is in the same day as the current moment. * @method bool isNextDay() Checks if the instance is in the same day as the current moment next day. * @method bool isLastDay() Checks if the instance is in the same day as the current moment last day. * @method bool isSameHour(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same hour as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentHour() Checks if the instance is in the same hour as the current moment. * @method bool isNextHour() Checks if the instance is in the same hour as the current moment next hour. * @method bool isLastHour() Checks if the instance is in the same hour as the current moment last hour. * @method bool isSameMinute(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same minute as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentMinute() Checks if the instance is in the same minute as the current moment. * @method bool isNextMinute() Checks if the instance is in the same minute as the current moment next minute. * @method bool isLastMinute() Checks if the instance is in the same minute as the current moment last minute. * @method bool isSameSecond(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same second as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentSecond() Checks if the instance is in the same second as the current moment. * @method bool isNextSecond() Checks if the instance is in the same second as the current moment next second. * @method bool isLastSecond() Checks if the instance is in the same second as the current moment last second. * @method bool isSameMicro(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentMicro() Checks if the instance is in the same microsecond as the current moment. * @method bool isNextMicro() Checks if the instance is in the same microsecond as the current moment next microsecond. * @method bool isLastMicro() Checks if the instance is in the same microsecond as the current moment last microsecond. * @method bool isSameMicrosecond(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentMicrosecond() Checks if the instance is in the same microsecond as the current moment. * @method bool isNextMicrosecond() Checks if the instance is in the same microsecond as the current moment next microsecond. * @method bool isLastMicrosecond() Checks if the instance is in the same microsecond as the current moment last microsecond. * @method bool isCurrentMonth() Checks if the instance is in the same month as the current moment. * @method bool isNextMonth() Checks if the instance is in the same month as the current moment next month. * @method bool isLastMonth() Checks if the instance is in the same month as the current moment last month. * @method bool isCurrentQuarter() Checks if the instance is in the same quarter as the current moment. * @method bool isNextQuarter() Checks if the instance is in the same quarter as the current moment next quarter. * @method bool isLastQuarter() Checks if the instance is in the same quarter as the current moment last quarter. * @method bool isSameDecade(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same decade as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentDecade() Checks if the instance is in the same decade as the current moment. * @method bool isNextDecade() Checks if the instance is in the same decade as the current moment next decade. * @method bool isLastDecade() Checks if the instance is in the same decade as the current moment last decade. * @method bool isSameCentury(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same century as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentCentury() Checks if the instance is in the same century as the current moment. * @method bool isNextCentury() Checks if the instance is in the same century as the current moment next century. * @method bool isLastCentury() Checks if the instance is in the same century as the current moment last century. * @method bool isSameMillennium(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same millennium as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentMillennium() Checks if the instance is in the same millennium as the current moment. * @method bool isNextMillennium() Checks if the instance is in the same millennium as the current moment next millennium. * @method bool isLastMillennium() Checks if the instance is in the same millennium as the current moment last millennium. * @method CarbonInterface years(int $value) Set current instance year to the given value. * @method CarbonInterface year(int $value) Set current instance year to the given value. * @method CarbonInterface setYears(int $value) Set current instance year to the given value. * @method CarbonInterface setYear(int $value) Set current instance year to the given value. * @method CarbonInterface months(int $value) Set current instance month to the given value. * @method CarbonInterface month(int $value) Set current instance month to the given value. * @method CarbonInterface setMonths(int $value) Set current instance month to the given value. * @method CarbonInterface setMonth(int $value) Set current instance month to the given value. * @method CarbonInterface days(int $value) Set current instance day to the given value. * @method CarbonInterface day(int $value) Set current instance day to the given value. * @method CarbonInterface setDays(int $value) Set current instance day to the given value. * @method CarbonInterface setDay(int $value) Set current instance day to the given value. * @method CarbonInterface hours(int $value) Set current instance hour to the given value. * @method CarbonInterface hour(int $value) Set current instance hour to the given value. * @method CarbonInterface setHours(int $value) Set current instance hour to the given value. * @method CarbonInterface setHour(int $value) Set current instance hour to the given value. * @method CarbonInterface minutes(int $value) Set current instance minute to the given value. * @method CarbonInterface minute(int $value) Set current instance minute to the given value. * @method CarbonInterface setMinutes(int $value) Set current instance minute to the given value. * @method CarbonInterface setMinute(int $value) Set current instance minute to the given value. * @method CarbonInterface seconds(int $value) Set current instance second to the given value. * @method CarbonInterface second(int $value) Set current instance second to the given value. * @method CarbonInterface setSeconds(int $value) Set current instance second to the given value. * @method CarbonInterface setSecond(int $value) Set current instance second to the given value. * @method CarbonInterface millis(int $value) Set current instance millisecond to the given value. * @method CarbonInterface milli(int $value) Set current instance millisecond to the given value. * @method CarbonInterface setMillis(int $value) Set current instance millisecond to the given value. * @method CarbonInterface setMilli(int $value) Set current instance millisecond to the given value. * @method CarbonInterface milliseconds(int $value) Set current instance millisecond to the given value. * @method CarbonInterface millisecond(int $value) Set current instance millisecond to the given value. * @method CarbonInterface setMilliseconds(int $value) Set current instance millisecond to the given value. * @method CarbonInterface setMillisecond(int $value) Set current instance millisecond to the given value. * @method CarbonInterface micros(int $value) Set current instance microsecond to the given value. * @method CarbonInterface micro(int $value) Set current instance microsecond to the given value. * @method CarbonInterface setMicros(int $value) Set current instance microsecond to the given value. * @method CarbonInterface setMicro(int $value) Set current instance microsecond to the given value. * @method CarbonInterface microseconds(int $value) Set current instance microsecond to the given value. * @method CarbonInterface microsecond(int $value) Set current instance microsecond to the given value. * @method CarbonInterface setMicroseconds(int $value) Set current instance microsecond to the given value. * @method CarbonInterface setMicrosecond(int $value) Set current instance microsecond to the given value. * @method CarbonInterface addYears(int $value = 1) Add years (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addYear() Add one year to the instance (using date interval). * @method CarbonInterface subYears(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subYear() Sub one year to the instance (using date interval). * @method CarbonInterface addYearsWithOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addYearWithOverflow() Add one year to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subYearsWithOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subYearWithOverflow() Sub one year to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addYearsWithoutOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addYearWithoutOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subYearsWithoutOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subYearWithoutOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addYearsWithNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addYearWithNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subYearsWithNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subYearWithNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addYearsNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addYearNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subYearsNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subYearNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMonths(int $value = 1) Add months (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addMonth() Add one month to the instance (using date interval). * @method CarbonInterface subMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subMonth() Sub one month to the instance (using date interval). * @method CarbonInterface addMonthsWithOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addMonthWithOverflow() Add one month to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subMonthsWithOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subMonthWithOverflow() Sub one month to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addMonthsWithoutOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMonthWithoutOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMonthsWithoutOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMonthWithoutOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMonthsWithNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMonthWithNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMonthsWithNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMonthWithNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMonthsNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMonthNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMonthsNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMonthNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addDays(int $value = 1) Add days (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addDay() Add one day to the instance (using date interval). * @method CarbonInterface subDays(int $value = 1) Sub days (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subDay() Sub one day to the instance (using date interval). * @method CarbonInterface addHours(int $value = 1) Add hours (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addHour() Add one hour to the instance (using date interval). * @method CarbonInterface subHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subHour() Sub one hour to the instance (using date interval). * @method CarbonInterface addMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addMinute() Add one minute to the instance (using date interval). * @method CarbonInterface subMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subMinute() Sub one minute to the instance (using date interval). * @method CarbonInterface addSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addSecond() Add one second to the instance (using date interval). * @method CarbonInterface subSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subSecond() Sub one second to the instance (using date interval). * @method CarbonInterface addMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addMilli() Add one millisecond to the instance (using date interval). * @method CarbonInterface subMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subMilli() Sub one millisecond to the instance (using date interval). * @method CarbonInterface addMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addMillisecond() Add one millisecond to the instance (using date interval). * @method CarbonInterface subMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subMillisecond() Sub one millisecond to the instance (using date interval). * @method CarbonInterface addMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addMicro() Add one microsecond to the instance (using date interval). * @method CarbonInterface subMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subMicro() Sub one microsecond to the instance (using date interval). * @method CarbonInterface addMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addMicrosecond() Add one microsecond to the instance (using date interval). * @method CarbonInterface subMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subMicrosecond() Sub one microsecond to the instance (using date interval). * @method CarbonInterface addMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addMillennium() Add one millennium to the instance (using date interval). * @method CarbonInterface subMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subMillennium() Sub one millennium to the instance (using date interval). * @method CarbonInterface addMillenniaWithOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addMillenniumWithOverflow() Add one millennium to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subMillenniaWithOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subMillenniumWithOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addMillenniaWithoutOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMillenniumWithoutOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMillenniaWithoutOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMillenniumWithoutOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMillenniaWithNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMillenniumWithNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMillenniaWithNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMillenniumWithNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMillenniaNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addMillenniumNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMillenniaNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subMillenniumNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addCentury() Add one century to the instance (using date interval). * @method CarbonInterface subCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subCentury() Sub one century to the instance (using date interval). * @method CarbonInterface addCenturiesWithOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addCenturyWithOverflow() Add one century to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subCenturiesWithOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subCenturyWithOverflow() Sub one century to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addCenturiesWithoutOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addCenturyWithoutOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subCenturiesWithoutOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subCenturyWithoutOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addCenturiesWithNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addCenturyWithNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subCenturiesWithNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subCenturyWithNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addCenturiesNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addCenturyNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subCenturiesNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subCenturyNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addDecade() Add one decade to the instance (using date interval). * @method CarbonInterface subDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subDecade() Sub one decade to the instance (using date interval). * @method CarbonInterface addDecadesWithOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addDecadeWithOverflow() Add one decade to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subDecadesWithOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subDecadeWithOverflow() Sub one decade to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addDecadesWithoutOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addDecadeWithoutOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subDecadesWithoutOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subDecadeWithoutOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addDecadesWithNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addDecadeWithNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subDecadesWithNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subDecadeWithNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addDecadesNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addDecadeNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subDecadesNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subDecadeNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addQuarter() Add one quarter to the instance (using date interval). * @method CarbonInterface subQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subQuarter() Sub one quarter to the instance (using date interval). * @method CarbonInterface addQuartersWithOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addQuarterWithOverflow() Add one quarter to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subQuartersWithOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface subQuarterWithOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly allowed. * @method CarbonInterface addQuartersWithoutOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addQuarterWithoutOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subQuartersWithoutOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subQuarterWithoutOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addQuartersWithNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addQuarterWithNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subQuartersWithNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subQuarterWithNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addQuartersNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addQuarterNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subQuartersNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface subQuarterNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonInterface addWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addWeek() Add one week to the instance (using date interval). * @method CarbonInterface subWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subWeek() Sub one week to the instance (using date interval). * @method CarbonInterface addWeekdays(int $value = 1) Add weekdays (the $value count passed in) to the instance (using date interval). * @method CarbonInterface addWeekday() Add one weekday to the instance (using date interval). * @method CarbonInterface subWeekdays(int $value = 1) Sub weekdays (the $value count passed in) to the instance (using date interval). * @method CarbonInterface subWeekday() Sub one weekday to the instance (using date interval). * @method CarbonInterface addRealMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealMicro() Add one microsecond to the instance (using timestamp). * @method CarbonInterface subRealMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealMicro() Sub one microsecond to the instance (using timestamp). * @method CarbonPeriod microsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given. * @method CarbonInterface addRealMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealMicrosecond() Add one microsecond to the instance (using timestamp). * @method CarbonInterface subRealMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealMicrosecond() Sub one microsecond to the instance (using timestamp). * @method CarbonPeriod microsecondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given. * @method CarbonInterface addRealMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealMilli() Add one millisecond to the instance (using timestamp). * @method CarbonInterface subRealMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealMilli() Sub one millisecond to the instance (using timestamp). * @method CarbonPeriod millisUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given. * @method CarbonInterface addRealMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealMillisecond() Add one millisecond to the instance (using timestamp). * @method CarbonInterface subRealMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealMillisecond() Sub one millisecond to the instance (using timestamp). * @method CarbonPeriod millisecondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given. * @method CarbonInterface addRealSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealSecond() Add one second to the instance (using timestamp). * @method CarbonInterface subRealSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealSecond() Sub one second to the instance (using timestamp). * @method CarbonPeriod secondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each second or every X seconds if a factor is given. * @method CarbonInterface addRealMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealMinute() Add one minute to the instance (using timestamp). * @method CarbonInterface subRealMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealMinute() Sub one minute to the instance (using timestamp). * @method CarbonPeriod minutesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each minute or every X minutes if a factor is given. * @method CarbonInterface addRealHours(int $value = 1) Add hours (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealHour() Add one hour to the instance (using timestamp). * @method CarbonInterface subRealHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealHour() Sub one hour to the instance (using timestamp). * @method CarbonPeriod hoursUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each hour or every X hours if a factor is given. * @method CarbonInterface addRealDays(int $value = 1) Add days (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealDay() Add one day to the instance (using timestamp). * @method CarbonInterface subRealDays(int $value = 1) Sub days (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealDay() Sub one day to the instance (using timestamp). * @method CarbonPeriod daysUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each day or every X days if a factor is given. * @method CarbonInterface addRealWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealWeek() Add one week to the instance (using timestamp). * @method CarbonInterface subRealWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealWeek() Sub one week to the instance (using timestamp). * @method CarbonPeriod weeksUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each week or every X weeks if a factor is given. * @method CarbonInterface addRealMonths(int $value = 1) Add months (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealMonth() Add one month to the instance (using timestamp). * @method CarbonInterface subRealMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealMonth() Sub one month to the instance (using timestamp). * @method CarbonPeriod monthsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each month or every X months if a factor is given. * @method CarbonInterface addRealQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealQuarter() Add one quarter to the instance (using timestamp). * @method CarbonInterface subRealQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealQuarter() Sub one quarter to the instance (using timestamp). * @method CarbonPeriod quartersUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each quarter or every X quarters if a factor is given. * @method CarbonInterface addRealYears(int $value = 1) Add years (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealYear() Add one year to the instance (using timestamp). * @method CarbonInterface subRealYears(int $value = 1) Sub years (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealYear() Sub one year to the instance (using timestamp). * @method CarbonPeriod yearsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each year or every X years if a factor is given. * @method CarbonInterface addRealDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealDecade() Add one decade to the instance (using timestamp). * @method CarbonInterface subRealDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealDecade() Sub one decade to the instance (using timestamp). * @method CarbonPeriod decadesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each decade or every X decades if a factor is given. * @method CarbonInterface addRealCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealCentury() Add one century to the instance (using timestamp). * @method CarbonInterface subRealCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealCentury() Sub one century to the instance (using timestamp). * @method CarbonPeriod centuriesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each century or every X centuries if a factor is given. * @method CarbonInterface addRealMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface addRealMillennium() Add one millennium to the instance (using timestamp). * @method CarbonInterface subRealMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using timestamp). * @method CarbonInterface subRealMillennium() Sub one millennium to the instance (using timestamp). * @method CarbonPeriod millenniaUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millennium or every X millennia if a factor is given. * @method CarbonInterface roundYear(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function. * @method CarbonInterface roundYears(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function. * @method CarbonInterface floorYear(float $precision = 1) Truncate the current instance year with given precision. * @method CarbonInterface floorYears(float $precision = 1) Truncate the current instance year with given precision. * @method CarbonInterface ceilYear(float $precision = 1) Ceil the current instance year with given precision. * @method CarbonInterface ceilYears(float $precision = 1) Ceil the current instance year with given precision. * @method CarbonInterface roundMonth(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function. * @method CarbonInterface roundMonths(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function. * @method CarbonInterface floorMonth(float $precision = 1) Truncate the current instance month with given precision. * @method CarbonInterface floorMonths(float $precision = 1) Truncate the current instance month with given precision. * @method CarbonInterface ceilMonth(float $precision = 1) Ceil the current instance month with given precision. * @method CarbonInterface ceilMonths(float $precision = 1) Ceil the current instance month with given precision. * @method CarbonInterface roundDay(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function. * @method CarbonInterface roundDays(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function. * @method CarbonInterface floorDay(float $precision = 1) Truncate the current instance day with given precision. * @method CarbonInterface floorDays(float $precision = 1) Truncate the current instance day with given precision. * @method CarbonInterface ceilDay(float $precision = 1) Ceil the current instance day with given precision. * @method CarbonInterface ceilDays(float $precision = 1) Ceil the current instance day with given precision. * @method CarbonInterface roundHour(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function. * @method CarbonInterface roundHours(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function. * @method CarbonInterface floorHour(float $precision = 1) Truncate the current instance hour with given precision. * @method CarbonInterface floorHours(float $precision = 1) Truncate the current instance hour with given precision. * @method CarbonInterface ceilHour(float $precision = 1) Ceil the current instance hour with given precision. * @method CarbonInterface ceilHours(float $precision = 1) Ceil the current instance hour with given precision. * @method CarbonInterface roundMinute(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function. * @method CarbonInterface roundMinutes(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function. * @method CarbonInterface floorMinute(float $precision = 1) Truncate the current instance minute with given precision. * @method CarbonInterface floorMinutes(float $precision = 1) Truncate the current instance minute with given precision. * @method CarbonInterface ceilMinute(float $precision = 1) Ceil the current instance minute with given precision. * @method CarbonInterface ceilMinutes(float $precision = 1) Ceil the current instance minute with given precision. * @method CarbonInterface roundSecond(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function. * @method CarbonInterface roundSeconds(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function. * @method CarbonInterface floorSecond(float $precision = 1) Truncate the current instance second with given precision. * @method CarbonInterface floorSeconds(float $precision = 1) Truncate the current instance second with given precision. * @method CarbonInterface ceilSecond(float $precision = 1) Ceil the current instance second with given precision. * @method CarbonInterface ceilSeconds(float $precision = 1) Ceil the current instance second with given precision. * @method CarbonInterface roundMillennium(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function. * @method CarbonInterface roundMillennia(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function. * @method CarbonInterface floorMillennium(float $precision = 1) Truncate the current instance millennium with given precision. * @method CarbonInterface floorMillennia(float $precision = 1) Truncate the current instance millennium with given precision. * @method CarbonInterface ceilMillennium(float $precision = 1) Ceil the current instance millennium with given precision. * @method CarbonInterface ceilMillennia(float $precision = 1) Ceil the current instance millennium with given precision. * @method CarbonInterface roundCentury(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function. * @method CarbonInterface roundCenturies(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function. * @method CarbonInterface floorCentury(float $precision = 1) Truncate the current instance century with given precision. * @method CarbonInterface floorCenturies(float $precision = 1) Truncate the current instance century with given precision. * @method CarbonInterface ceilCentury(float $precision = 1) Ceil the current instance century with given precision. * @method CarbonInterface ceilCenturies(float $precision = 1) Ceil the current instance century with given precision. * @method CarbonInterface roundDecade(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function. * @method CarbonInterface roundDecades(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function. * @method CarbonInterface floorDecade(float $precision = 1) Truncate the current instance decade with given precision. * @method CarbonInterface floorDecades(float $precision = 1) Truncate the current instance decade with given precision. * @method CarbonInterface ceilDecade(float $precision = 1) Ceil the current instance decade with given precision. * @method CarbonInterface ceilDecades(float $precision = 1) Ceil the current instance decade with given precision. * @method CarbonInterface roundQuarter(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function. * @method CarbonInterface roundQuarters(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function. * @method CarbonInterface floorQuarter(float $precision = 1) Truncate the current instance quarter with given precision. * @method CarbonInterface floorQuarters(float $precision = 1) Truncate the current instance quarter with given precision. * @method CarbonInterface ceilQuarter(float $precision = 1) Ceil the current instance quarter with given precision. * @method CarbonInterface ceilQuarters(float $precision = 1) Ceil the current instance quarter with given precision. * @method CarbonInterface roundMillisecond(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function. * @method CarbonInterface roundMilliseconds(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function. * @method CarbonInterface floorMillisecond(float $precision = 1) Truncate the current instance millisecond with given precision. * @method CarbonInterface floorMilliseconds(float $precision = 1) Truncate the current instance millisecond with given precision. * @method CarbonInterface ceilMillisecond(float $precision = 1) Ceil the current instance millisecond with given precision. * @method CarbonInterface ceilMilliseconds(float $precision = 1) Ceil the current instance millisecond with given precision. * @method CarbonInterface roundMicrosecond(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function. * @method CarbonInterface roundMicroseconds(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function. * @method CarbonInterface floorMicrosecond(float $precision = 1) Truncate the current instance microsecond with given precision. * @method CarbonInterface floorMicroseconds(float $precision = 1) Truncate the current instance microsecond with given precision. * @method CarbonInterface ceilMicrosecond(float $precision = 1) Ceil the current instance microsecond with given precision. * @method CarbonInterface ceilMicroseconds(float $precision = 1) Ceil the current instance microsecond with given precision. * @method string shortAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string longAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string shortRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string longRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string shortRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string longRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string shortRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string longRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * * </autodoc> */ trait Date { use Boundaries; use Comparison; use Converter; use Creator; use Difference; use Macro; use MagicParameter; use Modifiers; use Mutability; use ObjectInitialisation; use Options; use Rounding; use Serialization; use Test; use Timestamp; use Units; use Week; /** * Names of days of the week. * * @var array */ protected static $days = [ // @call isDayOfWeek CarbonInterface::SUNDAY => 'Sunday', // @call isDayOfWeek CarbonInterface::MONDAY => 'Monday', // @call isDayOfWeek CarbonInterface::TUESDAY => 'Tuesday', // @call isDayOfWeek CarbonInterface::WEDNESDAY => 'Wednesday', // @call isDayOfWeek CarbonInterface::THURSDAY => 'Thursday', // @call isDayOfWeek CarbonInterface::FRIDAY => 'Friday', // @call isDayOfWeek CarbonInterface::SATURDAY => 'Saturday', ]; /** * Will UTF8 encoding be used to print localized date/time ? * * @var bool */ protected static $utf8 = false; /** * List of unit and magic methods associated as doc-comments. * * @var array */ protected static $units = [ // @call setUnit // @call addUnit 'year', // @call setUnit // @call addUnit 'month', // @call setUnit // @call addUnit 'day', // @call setUnit // @call addUnit 'hour', // @call setUnit // @call addUnit 'minute', // @call setUnit // @call addUnit 'second', // @call setUnit // @call addUnit 'milli', // @call setUnit // @call addUnit 'millisecond', // @call setUnit // @call addUnit 'micro', // @call setUnit // @call addUnit 'microsecond', ]; /** * Creates a DateTimeZone from a string, DateTimeZone or integer offset. * * @param DateTimeZone|string|int|null $object original value to get CarbonTimeZone from it. * @param DateTimeZone|string|int|null $objectDump dump of the object for error messages. * * @throws InvalidTimeZoneException * * @return CarbonTimeZone|false */ protected static function safeCreateDateTimeZone($object, $objectDump = null) { return CarbonTimeZone::instance($object, $objectDump); } /** * Get the TimeZone associated with the Carbon instance (as CarbonTimeZone). * * @return CarbonTimeZone * * @link https://php.net/manual/en/datetime.gettimezone.php */ #[ReturnTypeWillChange] public function getTimezone() { return CarbonTimeZone::instance(parent::getTimezone()); } /** * List of minimum and maximums for each unit. * * @param int $daysInMonth * * @return array */ protected static function getRangesByUnit(int $daysInMonth = 31): array { return [ // @call roundUnit 'year' => [1, 9999], // @call roundUnit 'month' => [1, static::MONTHS_PER_YEAR], // @call roundUnit 'day' => [1, $daysInMonth], // @call roundUnit 'hour' => [0, static::HOURS_PER_DAY - 1], // @call roundUnit 'minute' => [0, static::MINUTES_PER_HOUR - 1], // @call roundUnit 'second' => [0, static::SECONDS_PER_MINUTE - 1], ]; } /** * Get a copy of the instance. * * @return static */ public function copy() { return clone $this; } /** * @alias copy * * Get a copy of the instance. * * @return static */ public function clone() { return clone $this; } /** * Clone the current instance if it's mutable. * * This method is convenient to ensure you don't mutate the initial object * but avoid to make a useless copy of it if it's already immutable. * * @return static */ public function avoidMutation(): self { if ($this instanceof DateTimeImmutable) { return $this; } return clone $this; } /** * Returns a present instance in the same timezone. * * @return static */ public function nowWithSameTz() { return static::now($this->getTimezone()); } /** * Throws an exception if the given object is not a DateTime and does not implement DateTimeInterface. * * @param mixed $date * @param string|array $other * * @throws InvalidTypeException */ protected static function expectDateTime($date, $other = []) { $message = 'Expected '; foreach ((array) $other as $expect) { $message .= "$expect, "; } if (!$date instanceof DateTime && !$date instanceof DateTimeInterface) { throw new InvalidTypeException( $message.'DateTime or DateTimeInterface, '. (\is_object($date) ? \get_class($date) : \gettype($date)).' given' ); } } /** * Return the Carbon instance passed through, a now instance in the same timezone * if null given or parse the input if string given. * * @param Carbon|DateTimeInterface|string|null $date * * @return static */ protected function resolveCarbon($date = null) { if (!$date) { return $this->nowWithSameTz(); } if (\is_string($date)) { return static::parse($date, $this->getTimezone()); } static::expectDateTime($date, ['null', 'string']); return $date instanceof self ? $date : static::instance($date); } /** * Return the Carbon instance passed through, a now instance in UTC * if null given or parse the input if string given (using current timezone * then switching to UTC). * * @param Carbon|DateTimeInterface|string|null $date * * @return static */ protected function resolveUTC($date = null): self { if (!$date) { return static::now('UTC'); } if (\is_string($date)) { return static::parse($date, $this->getTimezone())->utc(); } static::expectDateTime($date, ['null', 'string']); return $date instanceof self ? $date : static::instance($date)->utc(); } /** * Return the Carbon instance passed through, a now instance in the same timezone * if null given or parse the input if string given. * * @param Carbon|\Carbon\CarbonPeriod|\Carbon\CarbonInterval|\DateInterval|\DatePeriod|DateTimeInterface|string|null $date * * @return static */ public function carbonize($date = null) { if ($date instanceof DateInterval) { return $this->avoidMutation()->add($date); } if ($date instanceof DatePeriod || $date instanceof CarbonPeriod) { $date = $date->getStartDate(); } return $this->resolveCarbon($date); } /////////////////////////////////////////////////////////////////// ///////////////////////// GETTERS AND SETTERS ///////////////////// /////////////////////////////////////////////////////////////////// /** * Get a part of the Carbon object * * @param string $name * * @throws UnknownGetterException * * @return string|int|bool|DateTimeZone|null */ public function __get($name) { return $this->get($name); } /** * Get a part of the Carbon object * * @param string $name * * @throws UnknownGetterException * * @return string|int|bool|DateTimeZone|null */ public function get($name) { static $formats = [ // @property int 'year' => 'Y', // @property int 'yearIso' => 'o', // @property int // @call isSameUnit 'month' => 'n', // @property int 'day' => 'j', // @property int 'hour' => 'G', // @property int 'minute' => 'i', // @property int 'second' => 's', // @property int 'micro' => 'u', // @property int 'microsecond' => 'u', // @property-read int 0 (for Sunday) through 6 (for Saturday) 'dayOfWeek' => 'w', // @property-read int 1 (for Monday) through 7 (for Sunday) 'dayOfWeekIso' => 'N', // @property-read int ISO-8601 week number of year, weeks starting on Monday 'weekOfYear' => 'W', // @property-read int number of days in the given month 'daysInMonth' => 't', // @property int|float|string seconds since the Unix Epoch 'timestamp' => 'U', // @property-read string "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark) 'latinMeridiem' => 'a', // @property-read string "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark) 'latinUpperMeridiem' => 'A', // @property string the day of week in English 'englishDayOfWeek' => 'l', // @property string the abbreviated day of week in English 'shortEnglishDayOfWeek' => 'D', // @property string the month in English 'englishMonth' => 'F', // @property string the abbreviated month in English 'shortEnglishMonth' => 'M', // @property string the day of week in current locale LC_TIME // @deprecated // reason: It uses OS language package and strftime() which is deprecated since PHP 8.1. // replacement: Use ->isoFormat('MMM') instead. // since: 2.55.0 'localeDayOfWeek' => '%A', // @property string the abbreviated day of week in current locale LC_TIME // @deprecated // reason: It uses OS language package and strftime() which is deprecated since PHP 8.1. // replacement: Use ->isoFormat('dddd') instead. // since: 2.55.0 'shortLocaleDayOfWeek' => '%a', // @property string the month in current locale LC_TIME // @deprecated // reason: It uses OS language package and strftime() which is deprecated since PHP 8.1. // replacement: Use ->isoFormat('ddd') instead. // since: 2.55.0 'localeMonth' => '%B', // @property string the abbreviated month in current locale LC_TIME // @deprecated // reason: It uses OS language package and strftime() which is deprecated since PHP 8.1. // replacement: Use ->isoFormat('MMMM') instead. // since: 2.55.0 'shortLocaleMonth' => '%b', // @property-read string $timezoneAbbreviatedName the current timezone abbreviated name 'timezoneAbbreviatedName' => 'T', // @property-read string $tzAbbrName alias of $timezoneAbbreviatedName 'tzAbbrName' => 'T', ]; switch (true) { case isset($formats[$name]): $format = $formats[$name]; $method = str_starts_with($format, '%') ? 'formatLocalized' : 'rawFormat'; $value = $this->$method($format); return is_numeric($value) ? (int) $value : $value; // @property-read string long name of weekday translated according to Carbon locale, in english if no translation available for current language case $name === 'dayName': return $this->getTranslatedDayName(); // @property-read string short name of weekday translated according to Carbon locale, in english if no translation available for current language case $name === 'shortDayName': return $this->getTranslatedShortDayName(); // @property-read string very short name of weekday translated according to Carbon locale, in english if no translation available for current language case $name === 'minDayName': return $this->getTranslatedMinDayName(); // @property-read string long name of month translated according to Carbon locale, in english if no translation available for current language case $name === 'monthName': return $this->getTranslatedMonthName(); // @property-read string short name of month translated according to Carbon locale, in english if no translation available for current language case $name === 'shortMonthName': return $this->getTranslatedShortMonthName(); // @property-read string lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language case $name === 'meridiem': return $this->meridiem(true); // @property-read string uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language case $name === 'upperMeridiem': return $this->meridiem(); // @property-read int current hour from 1 to 24 case $name === 'noZeroHour': return $this->hour ?: 24; // @property int case $name === 'milliseconds': // @property int case $name === 'millisecond': // @property int case $name === 'milli': return (int) floor(((int) $this->rawFormat('u')) / 1000); // @property int 1 through 53 case $name === 'week': return (int) $this->week(); // @property int 1 through 53 case $name === 'isoWeek': return (int) $this->isoWeek(); // @property int year according to week format case $name === 'weekYear': return (int) $this->weekYear(); // @property int year according to ISO week format case $name === 'isoWeekYear': return (int) $this->isoWeekYear(); // @property-read int 51 through 53 case $name === 'weeksInYear': return $this->weeksInYear(); // @property-read int 51 through 53 case $name === 'isoWeeksInYear': return $this->isoWeeksInYear(); // @property-read int 1 through 5 case $name === 'weekOfMonth': return (int) ceil($this->day / static::DAYS_PER_WEEK); // @property-read int 1 through 5 case $name === 'weekNumberInMonth': return (int) ceil(($this->day + $this->avoidMutation()->startOfMonth()->dayOfWeekIso - 1) / static::DAYS_PER_WEEK); // @property-read int 0 through 6 case $name === 'firstWeekDay': return $this->localTranslator ? ($this->getTranslationMessage('first_day_of_week') ?? 0) : static::getWeekStartsAt(); // @property-read int 0 through 6 case $name === 'lastWeekDay': return $this->localTranslator ? (($this->getTranslationMessage('first_day_of_week') ?? 0) + static::DAYS_PER_WEEK - 1) % static::DAYS_PER_WEEK : static::getWeekEndsAt(); // @property int 1 through 366 case $name === 'dayOfYear': return 1 + (int) ($this->rawFormat('z')); // @property-read int 365 or 366 case $name === 'daysInYear': return $this->isLeapYear() ? 366 : 365; // @property int does a diffInYears() with default parameters case $name === 'age': return $this->diffInYears(); // @property-read int the quarter of this instance, 1 - 4 // @call isSameUnit case $name === 'quarter': return (int) ceil($this->month / static::MONTHS_PER_QUARTER); // @property-read int the decade of this instance // @call isSameUnit case $name === 'decade': return (int) ceil($this->year / static::YEARS_PER_DECADE); // @property-read int the century of this instance // @call isSameUnit case $name === 'century': $factor = 1; $year = $this->year; if ($year < 0) { $year = -$year; $factor = -1; } return (int) ($factor * ceil($year / static::YEARS_PER_CENTURY)); // @property-read int the millennium of this instance // @call isSameUnit case $name === 'millennium': $factor = 1; $year = $this->year; if ($year < 0) { $year = -$year; $factor = -1; } return (int) ($factor * ceil($year / static::YEARS_PER_MILLENNIUM)); // @property int the timezone offset in seconds from UTC case $name === 'offset': return $this->getOffset(); // @property int the timezone offset in minutes from UTC case $name === 'offsetMinutes': return $this->getOffset() / static::SECONDS_PER_MINUTE; // @property int the timezone offset in hours from UTC case $name === 'offsetHours': return $this->getOffset() / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR; // @property-read bool daylight savings time indicator, true if DST, false otherwise case $name === 'dst': return $this->rawFormat('I') === '1'; // @property-read bool checks if the timezone is local, true if local, false otherwise case $name === 'local': return $this->getOffset() === $this->avoidMutation()->setTimezone(date_default_timezone_get())->getOffset(); // @property-read bool checks if the timezone is UTC, true if UTC, false otherwise case $name === 'utc': return $this->getOffset() === 0; // @property CarbonTimeZone $timezone the current timezone // @property CarbonTimeZone $tz alias of $timezone case $name === 'timezone' || $name === 'tz': return CarbonTimeZone::instance($this->getTimezone()); // @property-read string $timezoneName the current timezone name // @property-read string $tzName alias of $timezoneName case $name === 'timezoneName' || $name === 'tzName': return $this->getTimezone()->getName(); // @property-read string locale of the current instance case $name === 'locale': return $this->getTranslatorLocale(); default: $macro = $this->getLocalMacro('get'.ucfirst($name)); if ($macro) { return $this->executeCallableWithContext($macro); } throw new UnknownGetterException($name); } } /** * Check if an attribute exists on the object * * @param string $name * * @return bool */ public function __isset($name) { try { $this->__get($name); } catch (UnknownGetterException | ReflectionException $e) { return false; } return true; } /** * Set a part of the Carbon object * * @param string $name * @param string|int|DateTimeZone $value * * @throws UnknownSetterException|ReflectionException * * @return void */ public function __set($name, $value) { if ($this->constructedObjectId === spl_object_hash($this)) { $this->set($name, $value); return; } $this->$name = $value; } /** * Set a part of the Carbon object * * @param string|array $name * @param string|int|DateTimeZone $value * * @throws ImmutableException|UnknownSetterException * * @return $this */ public function set($name, $value = null) { if ($this->isImmutable()) { throw new ImmutableException(\sprintf('%s class', static::class)); } if (\is_array($name)) { foreach ($name as $key => $value) { $this->set($key, $value); } return $this; } switch ($name) { case 'milliseconds': case 'millisecond': case 'milli': case 'microseconds': case 'microsecond': case 'micro': if (str_starts_with($name, 'milli')) { $value *= 1000; } while ($value < 0) { $this->subSecond(); $value += static::MICROSECONDS_PER_SECOND; } while ($value >= static::MICROSECONDS_PER_SECOND) { $this->addSecond(); $value -= static::MICROSECONDS_PER_SECOND; } $this->modify($this->rawFormat('H:i:s.').str_pad((string) round($value), 6, '0', STR_PAD_LEFT)); break; case 'year': case 'month': case 'day': case 'hour': case 'minute': case 'second': [$year, $month, $day, $hour, $minute, $second] = array_map('intval', explode('-', $this->rawFormat('Y-n-j-G-i-s'))); $$name = $value; $this->setDateTime($year, $month, $day, $hour, $minute, $second); break; case 'week': $this->week($value); break; case 'isoWeek': $this->isoWeek($value); break; case 'weekYear': $this->weekYear($value); break; case 'isoWeekYear': $this->isoWeekYear($value); break; case 'dayOfYear': $this->addDays($value - $this->dayOfYear); break; case 'timestamp': $this->setTimestamp($value); break; case 'offset': $this->setTimezone(static::safeCreateDateTimeZone($value / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR)); break; case 'offsetMinutes': $this->setTimezone(static::safeCreateDateTimeZone($value / static::MINUTES_PER_HOUR)); break; case 'offsetHours': $this->setTimezone(static::safeCreateDateTimeZone($value)); break; case 'timezone': case 'tz': $this->setTimezone($value); break; default: $macro = $this->getLocalMacro('set'.ucfirst($name)); if ($macro) { $this->executeCallableWithContext($macro, $value); break; } if ($this->localStrictModeEnabled ?? static::isStrictModeEnabled()) { throw new UnknownSetterException($name); } $this->$name = $value; } return $this; } protected function getTranslatedFormByRegExp($baseKey, $keySuffix, $context, $subKey, $defaultValue) { $key = $baseKey.$keySuffix; $standaloneKey = "{$key}_standalone"; $baseTranslation = $this->getTranslationMessage($key); if ($baseTranslation instanceof Closure) { return $baseTranslation($this, $context, $subKey) ?: $defaultValue; } if ( $this->getTranslationMessage("$standaloneKey.$subKey") && (!$context || (($regExp = $this->getTranslationMessage("{$baseKey}_regexp")) && !preg_match($regExp, $context))) ) { $key = $standaloneKey; } return $this->getTranslationMessage("$key.$subKey", null, $defaultValue); } /** * Get the translation of the current week day name (with context for languages with multiple forms). * * @param string|null $context whole format string * @param string $keySuffix "", "_short" or "_min" * @param string|null $defaultValue default value if translation missing * * @return string */ public function getTranslatedDayName($context = null, $keySuffix = '', $defaultValue = null) { return $this->getTranslatedFormByRegExp('weekdays', $keySuffix, $context, $this->dayOfWeek, $defaultValue ?: $this->englishDayOfWeek); } /** * Get the translation of the current short week day name (with context for languages with multiple forms). * * @param string|null $context whole format string * * @return string */ public function getTranslatedShortDayName($context = null) { return $this->getTranslatedDayName($context, '_short', $this->shortEnglishDayOfWeek); } /** * Get the translation of the current abbreviated week day name (with context for languages with multiple forms). * * @param string|null $context whole format string * * @return string */ public function getTranslatedMinDayName($context = null) { return $this->getTranslatedDayName($context, '_min', $this->shortEnglishDayOfWeek); } /** * Get the translation of the current month day name (with context for languages with multiple forms). * * @param string|null $context whole format string * @param string $keySuffix "" or "_short" * @param string|null $defaultValue default value if translation missing * * @return string */ public function getTranslatedMonthName($context = null, $keySuffix = '', $defaultValue = null) { return $this->getTranslatedFormByRegExp('months', $keySuffix, $context, $this->month - 1, $defaultValue ?: $this->englishMonth); } /** * Get the translation of the current short month day name (with context for languages with multiple forms). * * @param string|null $context whole format string * * @return string */ public function getTranslatedShortMonthName($context = null) { return $this->getTranslatedMonthName($context, '_short', $this->shortEnglishMonth); } /** * Get/set the day of year. * * @param int|null $value new value for day of year if using as setter. * * @return static|int */ public function dayOfYear($value = null) { $dayOfYear = $this->dayOfYear; return $value === null ? $dayOfYear : $this->addDays($value - $dayOfYear); } /** * Get/set the weekday from 0 (Sunday) to 6 (Saturday). * * @param int|null $value new value for weekday if using as setter. * * @return static|int */ public function weekday($value = null) { if ($value === null) { return $this->dayOfWeek; } $firstDay = (int) ($this->getTranslationMessage('first_day_of_week') ?? 0); $dayOfWeek = ($this->dayOfWeek + 7 - $firstDay) % 7; return $this->addDays((($value + 7 - $firstDay) % 7) - $dayOfWeek); } /** * Get/set the ISO weekday from 1 (Monday) to 7 (Sunday). * * @param int|null $value new value for weekday if using as setter. * * @return static|int */ public function isoWeekday($value = null) { $dayOfWeekIso = $this->dayOfWeekIso; return $value === null ? $dayOfWeekIso : $this->addDays($value - $dayOfWeekIso); } /** * Return the number of days since the start of the week (using the current locale or the first parameter * if explicitly given). * * @param int|null $weekStartsAt optional start allow you to specify the day of week to use to start the week, * if not provided, start of week is inferred from the locale * (Sunday for en_US, Monday for de_DE, etc.) * * @return int */ public function getDaysFromStartOfWeek(?int $weekStartsAt = null): int { $firstDay = (int) ($weekStartsAt ?? $this->getTranslationMessage('first_day_of_week') ?? 0); return ($this->dayOfWeek + 7 - $firstDay) % 7; } /** * Set the day (keeping the current time) to the start of the week + the number of days passed as the first * parameter. First day of week is driven by the locale unless explicitly set with the second parameter. * * @param int $numberOfDays number of days to add after the start of the current week * @param int|null $weekStartsAt optional start allow you to specify the day of week to use to start the week, * if not provided, start of week is inferred from the locale * (Sunday for en_US, Monday for de_DE, etc.) * * @return static */ public function setDaysFromStartOfWeek(int $numberOfDays, ?int $weekStartsAt = null) { return $this->addDays($numberOfDays - $this->getDaysFromStartOfWeek($weekStartsAt)); } /** * Set any unit to a new value without overflowing current other unit given. * * @param string $valueUnit unit name to modify * @param int $value new value for the input unit * @param string $overflowUnit unit name to not overflow * * @return static */ public function setUnitNoOverflow($valueUnit, $value, $overflowUnit) { try { $original = $this->avoidMutation(); /** @var static $date */ $date = $this->$valueUnit($value); $end = $original->avoidMutation()->endOf($overflowUnit); $start = $original->avoidMutation()->startOf($overflowUnit); if ($date < $start) { $date = $date->setDateTimeFrom($start); } elseif ($date > $end) { $date = $date->setDateTimeFrom($end); } return $date; } catch (BadMethodCallException | ReflectionException $exception) { throw new UnknownUnitException($valueUnit, 0, $exception); } } /** * Add any unit to a new value without overflowing current other unit given. * * @param string $valueUnit unit name to modify * @param int $value amount to add to the input unit * @param string $overflowUnit unit name to not overflow * * @return static */ public function addUnitNoOverflow($valueUnit, $value, $overflowUnit) { return $this->setUnitNoOverflow($valueUnit, $this->$valueUnit + $value, $overflowUnit); } /** * Subtract any unit to a new value without overflowing current other unit given. * * @param string $valueUnit unit name to modify * @param int $value amount to subtract to the input unit * @param string $overflowUnit unit name to not overflow * * @return static */ public function subUnitNoOverflow($valueUnit, $value, $overflowUnit) { return $this->setUnitNoOverflow($valueUnit, $this->$valueUnit - $value, $overflowUnit); } /** * Returns the minutes offset to UTC if no arguments passed, else set the timezone with given minutes shift passed. * * @param int|null $minuteOffset * * @return int|static */ public function utcOffset(?int $minuteOffset = null) { if (\func_num_args() < 1) { return $this->offsetMinutes; } return $this->setTimezone(CarbonTimeZone::createFromMinuteOffset($minuteOffset)); } /** * Set the date with gregorian year, month and day numbers. * * @see https://php.net/manual/en/datetime.setdate.php * * @param int $year * @param int $month * @param int $day * * @return static */ #[ReturnTypeWillChange] public function setDate($year, $month, $day) { return parent::setDate((int) $year, (int) $month, (int) $day); } /** * Set a date according to the ISO 8601 standard - using weeks and day offsets rather than specific dates. * * @see https://php.net/manual/en/datetime.setisodate.php * * @param int $year * @param int $week * @param int $day * * @return static */ #[ReturnTypeWillChange] public function setISODate($year, $week, $day = 1) { return parent::setISODate((int) $year, (int) $week, (int) $day); } /** * Set the date and time all together. * * @param int $year * @param int $month * @param int $day * @param int $hour * @param int $minute * @param int $second * @param int $microseconds * * @return static */ public function setDateTime($year, $month, $day, $hour, $minute, $second = 0, $microseconds = 0) { return $this->setDate($year, $month, $day)->setTime((int) $hour, (int) $minute, (int) $second, (int) $microseconds); } /** * Resets the current time of the DateTime object to a different time. * * @see https://php.net/manual/en/datetime.settime.php * * @param int $hour * @param int $minute * @param int $second * @param int $microseconds * * @return static */ #[ReturnTypeWillChange] public function setTime($hour, $minute, $second = 0, $microseconds = 0) { return parent::setTime((int) $hour, (int) $minute, (int) $second, (int) $microseconds); } /** * Set the instance's timestamp. * * Timestamp input can be given as int, float or a string containing one or more numbers. * * @param float|int|string $unixTimestamp * * @return static */ #[ReturnTypeWillChange] public function setTimestamp($unixTimestamp) { [$timestamp, $microseconds] = self::getIntegerAndDecimalParts($unixTimestamp); return parent::setTimestamp((int) $timestamp)->setMicroseconds((int) $microseconds); } /** * Set the time by time string. * * @param string $time * * @return static */ public function setTimeFromTimeString($time) { if (!str_contains($time, ':')) { $time .= ':0'; } return $this->modify($time); } /** * @alias setTimezone * * @param DateTimeZone|string $value * * @return static */ public function timezone($value) { return $this->setTimezone($value); } /** * Set the timezone or returns the timezone name if no arguments passed. * * @param DateTimeZone|string $value * * @return static|string */ public function tz($value = null) { if (\func_num_args() < 1) { return $this->tzName; } return $this->setTimezone($value); } /** * Set the instance's timezone from a string or object. * * @param DateTimeZone|string $value * * @return static */ #[ReturnTypeWillChange] public function setTimezone($value) { $tz = static::safeCreateDateTimeZone($value); if ($tz === false && !self::isStrictModeEnabled()) { $tz = new CarbonTimeZone(); } return parent::setTimezone($tz); } /** * Set the instance's timezone from a string or object and add/subtract the offset difference. * * @param DateTimeZone|string $value * * @return static */ public function shiftTimezone($value) { $dateTimeString = $this->format('Y-m-d H:i:s.u'); return $this ->setTimezone($value) ->modify($dateTimeString); } /** * Set the instance's timezone to UTC. * * @return static */ public function utc() { return $this->setTimezone('UTC'); } /** * Set the year, month, and date for this instance to that of the passed instance. * * @param Carbon|DateTimeInterface $date now if null * * @return static */ public function setDateFrom($date = null) { $date = $this->resolveCarbon($date); return $this->setDate($date->year, $date->month, $date->day); } /** * Set the hour, minute, second and microseconds for this instance to that of the passed instance. * * @param Carbon|DateTimeInterface $date now if null * * @return static */ public function setTimeFrom($date = null) { $date = $this->resolveCarbon($date); return $this->setTime($date->hour, $date->minute, $date->second, $date->microsecond); } /** * Set the date and time for this instance to that of the passed instance. * * @param Carbon|DateTimeInterface $date * * @return static */ public function setDateTimeFrom($date = null) { $date = $this->resolveCarbon($date); return $this->modify($date->rawFormat('Y-m-d H:i:s.u')); } /** * Get the days of the week * * @return array */ public static function getDays() { return static::$days; } /////////////////////////////////////////////////////////////////// /////////////////////// WEEK SPECIAL DAYS ///////////////////////// /////////////////////////////////////////////////////////////////// private static function getFirstDayOfWeek(): int { return (int) static::getTranslationMessageWith( static::getTranslator(), 'first_day_of_week' ); } /** * Get the first day of week * * @return int */ public static function getWeekStartsAt() { if (static::$weekStartsAt === static::WEEK_DAY_AUTO) { return self::getFirstDayOfWeek(); } return static::$weekStartsAt; } /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * Use $weekEndsAt optional parameter instead when using endOfWeek method. You can also use the * 'first_day_of_week' locale setting to change the start of week according to current locale * selected and implicitly the end of week. * * Set the first day of week * * @param int|string $day week start day (or 'auto' to get the first day of week from Carbon::getLocale() culture). * * @return void */ public static function setWeekStartsAt($day) { static::$weekStartsAt = $day === static::WEEK_DAY_AUTO ? $day : max(0, (7 + $day) % 7); } /** * Get the last day of week * * @return int */ public static function getWeekEndsAt() { if (static::$weekStartsAt === static::WEEK_DAY_AUTO) { return (int) (static::DAYS_PER_WEEK - 1 + self::getFirstDayOfWeek()) % static::DAYS_PER_WEEK; } return static::$weekEndsAt; } /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * Use $weekStartsAt optional parameter instead when using startOfWeek, floorWeek, ceilWeek * or roundWeek method. You can also use the 'first_day_of_week' locale setting to change the * start of week according to current locale selected and implicitly the end of week. * * Set the last day of week * * @param int|string $day week end day (or 'auto' to get the day before the first day of week * from Carbon::getLocale() culture). * * @return void */ public static function setWeekEndsAt($day) { static::$weekEndsAt = $day === static::WEEK_DAY_AUTO ? $day : max(0, (7 + $day) % 7); } /** * Get weekend days * * @return array */ public static function getWeekendDays() { return static::$weekendDays; } /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather consider week-end is always saturday and sunday, and if you have some custom * week-end days to handle, give to those days an other name and create a macro for them: * * ``` * Carbon::macro('isDayOff', function ($date) { * return $date->isSunday() || $date->isMonday(); * }); * Carbon::macro('isNotDayOff', function ($date) { * return !$date->isDayOff(); * }); * if ($someDate->isDayOff()) ... * if ($someDate->isNotDayOff()) ... * // Add 5 not-off days * $count = 5; * while ($someDate->isDayOff() || ($count-- > 0)) { * $someDate->addDay(); * } * ``` * * Set weekend days * * @param array $days * * @return void */ public static function setWeekendDays($days) { static::$weekendDays = $days; } /** * Determine if a time string will produce a relative date. * * @param string $time * * @return bool true if time match a relative date, false if absolute or invalid time string */ public static function hasRelativeKeywords($time) { if (!$time || strtotime($time) === false) { return false; } $date1 = new DateTime('2000-01-01T00:00:00Z'); $date1->modify($time); $date2 = new DateTime('2001-12-25T00:00:00Z'); $date2->modify($time); return $date1 != $date2; } /////////////////////////////////////////////////////////////////// /////////////////////// STRING FORMATTING ///////////////////////// /////////////////////////////////////////////////////////////////// /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use UTF-8 language packages on every machine. * * Set if UTF8 will be used for localized date/time. * * @param bool $utf8 */ public static function setUtf8($utf8) { static::$utf8 = $utf8; } /** * Format the instance with the current locale. You can set the current * locale using setlocale() https://php.net/setlocale. * * @deprecated It uses OS language package and strftime() which is deprecated since PHP 8.1. * Use ->isoFormat() instead. * Deprecated since 2.55.0 * * @param string $format * * @return string */ public function formatLocalized($format) { // Check for Windows to find and replace the %e modifier correctly. if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { $format = preg_replace('#(?<!%)((?:%%)*)%e#', '\1%#d', $format); // @codeCoverageIgnore } $time = strtotime($this->toDateTimeString()); $formatted = ($this->localStrictModeEnabled ?? static::isStrictModeEnabled()) ? strftime($format, $time) : @strftime($format, $time); return static::$utf8 ? ( \function_exists('mb_convert_encoding') ? mb_convert_encoding($formatted, 'UTF-8', mb_list_encodings()) : utf8_encode($formatted) ) : $formatted; } /** * Returns list of locale formats for ISO formatting. * * @param string|null $locale current locale used if null * * @return array */ public function getIsoFormats($locale = null) { return [ 'LT' => $this->getTranslationMessage('formats.LT', $locale, 'h:mm A'), 'LTS' => $this->getTranslationMessage('formats.LTS', $locale, 'h:mm:ss A'), 'L' => $this->getTranslationMessage('formats.L', $locale, 'MM/DD/YYYY'), 'LL' => $this->getTranslationMessage('formats.LL', $locale, 'MMMM D, YYYY'), 'LLL' => $this->getTranslationMessage('formats.LLL', $locale, 'MMMM D, YYYY h:mm A'), 'LLLL' => $this->getTranslationMessage('formats.LLLL', $locale, 'dddd, MMMM D, YYYY h:mm A'), 'l' => $this->getTranslationMessage('formats.l', $locale), 'll' => $this->getTranslationMessage('formats.ll', $locale), 'lll' => $this->getTranslationMessage('formats.lll', $locale), 'llll' => $this->getTranslationMessage('formats.llll', $locale), ]; } /** * Returns list of calendar formats for ISO formatting. * * @param string|null $locale current locale used if null * * @return array */ public function getCalendarFormats($locale = null) { return [ 'sameDay' => $this->getTranslationMessage('calendar.sameDay', $locale, '[Today at] LT'), 'nextDay' => $this->getTranslationMessage('calendar.nextDay', $locale, '[Tomorrow at] LT'), 'nextWeek' => $this->getTranslationMessage('calendar.nextWeek', $locale, 'dddd [at] LT'), 'lastDay' => $this->getTranslationMessage('calendar.lastDay', $locale, '[Yesterday at] LT'), 'lastWeek' => $this->getTranslationMessage('calendar.lastWeek', $locale, '[Last] dddd [at] LT'), 'sameElse' => $this->getTranslationMessage('calendar.sameElse', $locale, 'L'), ]; } /** * Returns list of locale units for ISO formatting. * * @return array */ public static function getIsoUnits() { static $units = null; if ($units === null) { $units = [ 'OD' => ['getAltNumber', ['day']], 'OM' => ['getAltNumber', ['month']], 'OY' => ['getAltNumber', ['year']], 'OH' => ['getAltNumber', ['hour']], 'Oh' => ['getAltNumber', ['h']], 'Om' => ['getAltNumber', ['minute']], 'Os' => ['getAltNumber', ['second']], 'D' => 'day', 'DD' => ['rawFormat', ['d']], 'Do' => ['ordinal', ['day', 'D']], 'd' => 'dayOfWeek', 'dd' => function (CarbonInterface $date, $originalFormat = null) { return $date->getTranslatedMinDayName($originalFormat); }, 'ddd' => function (CarbonInterface $date, $originalFormat = null) { return $date->getTranslatedShortDayName($originalFormat); }, 'dddd' => function (CarbonInterface $date, $originalFormat = null) { return $date->getTranslatedDayName($originalFormat); }, 'DDD' => 'dayOfYear', 'DDDD' => ['getPaddedUnit', ['dayOfYear', 3]], 'DDDo' => ['ordinal', ['dayOfYear', 'DDD']], 'e' => ['weekday', []], 'E' => 'dayOfWeekIso', 'H' => ['rawFormat', ['G']], 'HH' => ['rawFormat', ['H']], 'h' => ['rawFormat', ['g']], 'hh' => ['rawFormat', ['h']], 'k' => 'noZeroHour', 'kk' => ['getPaddedUnit', ['noZeroHour']], 'hmm' => ['rawFormat', ['gi']], 'hmmss' => ['rawFormat', ['gis']], 'Hmm' => ['rawFormat', ['Gi']], 'Hmmss' => ['rawFormat', ['Gis']], 'm' => 'minute', 'mm' => ['rawFormat', ['i']], 'a' => 'meridiem', 'A' => 'upperMeridiem', 's' => 'second', 'ss' => ['getPaddedUnit', ['second']], 'S' => function (CarbonInterface $date) { return (string) floor($date->micro / 100000); }, 'SS' => function (CarbonInterface $date) { return str_pad((string) floor($date->micro / 10000), 2, '0', STR_PAD_LEFT); }, 'SSS' => function (CarbonInterface $date) { return str_pad((string) floor($date->micro / 1000), 3, '0', STR_PAD_LEFT); }, 'SSSS' => function (CarbonInterface $date) { return str_pad((string) floor($date->micro / 100), 4, '0', STR_PAD_LEFT); }, 'SSSSS' => function (CarbonInterface $date) { return str_pad((string) floor($date->micro / 10), 5, '0', STR_PAD_LEFT); }, 'SSSSSS' => ['getPaddedUnit', ['micro', 6]], 'SSSSSSS' => function (CarbonInterface $date) { return str_pad((string) floor($date->micro * 10), 7, '0', STR_PAD_LEFT); }, 'SSSSSSSS' => function (CarbonInterface $date) { return str_pad((string) floor($date->micro * 100), 8, '0', STR_PAD_LEFT); }, 'SSSSSSSSS' => function (CarbonInterface $date) { return str_pad((string) floor($date->micro * 1000), 9, '0', STR_PAD_LEFT); }, 'M' => 'month', 'MM' => ['rawFormat', ['m']], 'MMM' => function (CarbonInterface $date, $originalFormat = null) { $month = $date->getTranslatedShortMonthName($originalFormat); $suffix = $date->getTranslationMessage('mmm_suffix'); if ($suffix && $month !== $date->monthName) { $month .= $suffix; } return $month; }, 'MMMM' => function (CarbonInterface $date, $originalFormat = null) { return $date->getTranslatedMonthName($originalFormat); }, 'Mo' => ['ordinal', ['month', 'M']], 'Q' => 'quarter', 'Qo' => ['ordinal', ['quarter', 'M']], 'G' => 'isoWeekYear', 'GG' => ['getPaddedUnit', ['isoWeekYear']], 'GGG' => ['getPaddedUnit', ['isoWeekYear', 3]], 'GGGG' => ['getPaddedUnit', ['isoWeekYear', 4]], 'GGGGG' => ['getPaddedUnit', ['isoWeekYear', 5]], 'g' => 'weekYear', 'gg' => ['getPaddedUnit', ['weekYear']], 'ggg' => ['getPaddedUnit', ['weekYear', 3]], 'gggg' => ['getPaddedUnit', ['weekYear', 4]], 'ggggg' => ['getPaddedUnit', ['weekYear', 5]], 'W' => 'isoWeek', 'WW' => ['getPaddedUnit', ['isoWeek']], 'Wo' => ['ordinal', ['isoWeek', 'W']], 'w' => 'week', 'ww' => ['getPaddedUnit', ['week']], 'wo' => ['ordinal', ['week', 'w']], 'x' => ['valueOf', []], 'X' => 'timestamp', 'Y' => 'year', 'YY' => ['rawFormat', ['y']], 'YYYY' => ['getPaddedUnit', ['year', 4]], 'YYYYY' => ['getPaddedUnit', ['year', 5]], 'YYYYYY' => function (CarbonInterface $date) { return ($date->year < 0 ? '' : '+').$date->getPaddedUnit('year', 6); }, 'z' => ['rawFormat', ['T']], 'zz' => 'tzName', 'Z' => ['getOffsetString', []], 'ZZ' => ['getOffsetString', ['']], ]; } return $units; } /** * Returns a unit of the instance padded with 0 by default or any other string if specified. * * @param string $unit Carbon unit name * @param int $length Length of the output (2 by default) * @param string $padString String to use for padding ("0" by default) * @param int $padType Side(s) to pad (STR_PAD_LEFT by default) * * @return string */ public function getPaddedUnit($unit, $length = 2, $padString = '0', $padType = STR_PAD_LEFT) { return ($this->$unit < 0 ? '-' : '').str_pad((string) abs($this->$unit), $length, $padString, $padType); } /** * Return a property with its ordinal. * * @param string $key * @param string|null $period * * @return string */ public function ordinal(string $key, ?string $period = null): string { $number = $this->$key; $result = $this->translate('ordinal', [ ':number' => $number, ':period' => (string) $period, ]); return (string) ($result === 'ordinal' ? $number : $result); } /** * Return the meridiem of the current time in the current locale. * * @param bool $isLower if true, returns lowercase variant if available in the current locale. * * @return string */ public function meridiem(bool $isLower = false): string { $hour = $this->hour; $index = $hour < 12 ? 0 : 1; if ($isLower) { $key = 'meridiem.'.($index + 2); $result = $this->translate($key); if ($result !== $key) { return $result; } } $key = "meridiem.$index"; $result = $this->translate($key); if ($result === $key) { $result = $this->translate('meridiem', [ ':hour' => $this->hour, ':minute' => $this->minute, ':isLower' => $isLower, ]); if ($result === 'meridiem') { return $isLower ? $this->latinMeridiem : $this->latinUpperMeridiem; } } elseif ($isLower) { $result = mb_strtolower($result); } return $result; } /** * Returns the alternative number for a given date property if available in the current locale. * * @param string $key date property * * @return string */ public function getAltNumber(string $key): string { return $this->translateNumber(\strlen($key) > 1 ? $this->$key : $this->rawFormat('h')); } /** * Format in the current language using ISO replacement patterns. * * @param string $format * @param string|null $originalFormat provide context if a chunk has been passed alone * * @return string */ public function isoFormat(string $format, ?string $originalFormat = null): string { $result = ''; $length = mb_strlen($format); $originalFormat = $originalFormat ?: $format; $inEscaped = false; $formats = null; $units = null; for ($i = 0; $i < $length; $i++) { $char = mb_substr($format, $i, 1); if ($char === '\\') { $result .= mb_substr($format, ++$i, 1); continue; } if ($char === '[' && !$inEscaped) { $inEscaped = true; continue; } if ($char === ']' && $inEscaped) { $inEscaped = false; continue; } if ($inEscaped) { $result .= $char; continue; } $input = mb_substr($format, $i); if (preg_match('/^(LTS|LT|l{1,4}|L{1,4})/', $input, $match)) { if ($formats === null) { $formats = $this->getIsoFormats(); } $code = $match[0]; $sequence = $formats[$code] ?? preg_replace_callback( '/MMMM|MM|DD|dddd/', function ($code) { return mb_substr($code[0], 1); }, $formats[strtoupper($code)] ?? '' ); $rest = mb_substr($format, $i + mb_strlen($code)); $format = mb_substr($format, 0, $i).$sequence.$rest; $length = mb_strlen($format); $input = $sequence.$rest; } if (preg_match('/^'.CarbonInterface::ISO_FORMAT_REGEXP.'/', $input, $match)) { $code = $match[0]; if ($units === null) { $units = static::getIsoUnits(); } $sequence = $units[$code] ?? ''; if ($sequence instanceof Closure) { $sequence = $sequence($this, $originalFormat); } elseif (\is_array($sequence)) { try { $sequence = $this->{$sequence[0]}(...$sequence[1]); } catch (ReflectionException | InvalidArgumentException | BadMethodCallException $e) { $sequence = ''; } } elseif (\is_string($sequence)) { $sequence = $this->$sequence ?? $code; } $format = mb_substr($format, 0, $i).$sequence.mb_substr($format, $i + mb_strlen($code)); $i += mb_strlen((string) $sequence) - 1; $length = mb_strlen($format); $char = $sequence; } $result .= $char; } return $result; } /** * List of replacements from date() format to isoFormat(). * * @return array */ public static function getFormatsToIsoReplacements() { static $replacements = null; if ($replacements === null) { $replacements = [ 'd' => true, 'D' => 'ddd', 'j' => true, 'l' => 'dddd', 'N' => true, 'S' => function ($date) { $day = $date->rawFormat('j'); return str_replace((string) $day, '', $date->isoFormat('Do')); }, 'w' => true, 'z' => true, 'W' => true, 'F' => 'MMMM', 'm' => true, 'M' => 'MMM', 'n' => true, 't' => true, 'L' => true, 'o' => true, 'Y' => true, 'y' => true, 'a' => 'a', 'A' => 'A', 'B' => true, 'g' => true, 'G' => true, 'h' => true, 'H' => true, 'i' => true, 's' => true, 'u' => true, 'v' => true, 'E' => true, 'I' => true, 'O' => true, 'P' => true, 'Z' => true, 'c' => true, 'r' => true, 'U' => true, 'T' => true, ]; } return $replacements; } /** * Format as ->format() do (using date replacements patterns from https://php.net/manual/en/function.date.php) * but translate words whenever possible (months, day names, etc.) using the current locale. * * @param string $format * * @return string */ public function translatedFormat(string $format): string { $replacements = static::getFormatsToIsoReplacements(); $context = ''; $isoFormat = ''; $length = mb_strlen($format); for ($i = 0; $i < $length; $i++) { $char = mb_substr($format, $i, 1); if ($char === '\\') { $replacement = mb_substr($format, $i, 2); $isoFormat .= $replacement; $i++; continue; } if (!isset($replacements[$char])) { $replacement = preg_match('/^[A-Za-z]$/', $char) ? "\\$char" : $char; $isoFormat .= $replacement; $context .= $replacement; continue; } $replacement = $replacements[$char]; if ($replacement === true) { static $contextReplacements = null; if ($contextReplacements === null) { $contextReplacements = [ 'm' => 'MM', 'd' => 'DD', 't' => 'D', 'j' => 'D', 'N' => 'e', 'w' => 'e', 'n' => 'M', 'o' => 'YYYY', 'Y' => 'YYYY', 'y' => 'YY', 'g' => 'h', 'G' => 'H', 'h' => 'hh', 'H' => 'HH', 'i' => 'mm', 's' => 'ss', ]; } $isoFormat .= '['.$this->rawFormat($char).']'; $context .= $contextReplacements[$char] ?? ' '; continue; } if ($replacement instanceof Closure) { $replacement = '['.$replacement($this).']'; $isoFormat .= $replacement; $context .= $replacement; continue; } $isoFormat .= $replacement; $context .= $replacement; } return $this->isoFormat($isoFormat, $context); } /** * Returns the offset hour and minute formatted with +/- and a given separator (":" by default). * For example, if the time zone is 9 hours 30 minutes, you'll get "+09:30", with "@@" as first * argument, "+09@@30", with "" as first argument, "+0930". Negative offset will return something * like "-12:00". * * @param string $separator string to place between hours and minutes (":" by default) * * @return string */ public function getOffsetString($separator = ':') { $second = $this->getOffset(); $symbol = $second < 0 ? '-' : '+'; $minute = abs($second) / static::SECONDS_PER_MINUTE; $hour = str_pad((string) floor($minute / static::MINUTES_PER_HOUR), 2, '0', STR_PAD_LEFT); $minute = str_pad((string) (((int) $minute) % static::MINUTES_PER_HOUR), 2, '0', STR_PAD_LEFT); return "$symbol$hour$separator$minute"; } protected static function executeStaticCallable($macro, ...$parameters) { return static::bindMacroContext(null, function () use (&$macro, &$parameters) { if ($macro instanceof Closure) { $boundMacro = @Closure::bind($macro, null, static::class); return ($boundMacro ?: $macro)(...$parameters); } return $macro(...$parameters); }); } /** * Dynamically handle calls to the class. * * @param string $method magic method name called * @param array $parameters parameters list * * @throws BadMethodCallException * * @return mixed */ public static function __callStatic($method, $parameters) { if (!static::hasMacro($method)) { foreach (static::getGenericMacros() as $callback) { try { return static::executeStaticCallable($callback, $method, ...$parameters); } catch (BadMethodCallException $exception) { continue; } } if (static::isStrictModeEnabled()) { throw new UnknownMethodException(\sprintf('%s::%s', static::class, $method)); } return null; } return static::executeStaticCallable(static::$globalMacros[$method], ...$parameters); } /** * Set specified unit to new given value. * * @param string $unit year, month, day, hour, minute, second or microsecond * @param int $value new value for given unit * * @return static */ public function setUnit($unit, $value = null) { $unit = static::singularUnit($unit); $dateUnits = ['year', 'month', 'day']; if (\in_array($unit, $dateUnits)) { return $this->setDate(...array_map(function ($name) use ($unit, $value) { return (int) ($name === $unit ? $value : $this->$name); }, $dateUnits)); } $units = ['hour', 'minute', 'second', 'micro']; if ($unit === 'millisecond' || $unit === 'milli') { $value *= 1000; $unit = 'micro'; } elseif ($unit === 'microsecond') { $unit = 'micro'; } return $this->setTime(...array_map(function ($name) use ($unit, $value) { return (int) ($name === $unit ? $value : $this->$name); }, $units)); } /** * Returns standardized singular of a given singular/plural unit name (in English). * * @param string $unit * * @return string */ public static function singularUnit(string $unit): string { $unit = rtrim(mb_strtolower($unit), 's'); if ($unit === 'centurie') { return 'century'; } if ($unit === 'millennia') { return 'millennium'; } return $unit; } /** * Returns standardized plural of a given singular/plural unit name (in English). * * @param string $unit * * @return string */ public static function pluralUnit(string $unit): string { $unit = rtrim(strtolower($unit), 's'); if ($unit === 'century') { return 'centuries'; } if ($unit === 'millennium' || $unit === 'millennia') { return 'millennia'; } return "{$unit}s"; } protected function executeCallable($macro, ...$parameters) { if ($macro instanceof Closure) { $boundMacro = @$macro->bindTo($this, static::class) ?: @$macro->bindTo(null, static::class); return ($boundMacro ?: $macro)(...$parameters); } return $macro(...$parameters); } protected function executeCallableWithContext($macro, ...$parameters) { return static::bindMacroContext($this, function () use (&$macro, &$parameters) { return $this->executeCallable($macro, ...$parameters); }); } protected static function getGenericMacros() { foreach (static::$globalGenericMacros as $list) { foreach ($list as $macro) { yield $macro; } } } /** * Dynamically handle calls to the class. * * @param string $method magic method name called * @param array $parameters parameters list * * @throws UnknownMethodException|BadMethodCallException|ReflectionException|Throwable * * @return mixed */ public function __call($method, $parameters) { $diffSizes = [ // @mode diffForHumans 'short' => true, // @mode diffForHumans 'long' => false, ]; $diffSyntaxModes = [ // @call diffForHumans 'Absolute' => CarbonInterface::DIFF_ABSOLUTE, // @call diffForHumans 'Relative' => CarbonInterface::DIFF_RELATIVE_AUTO, // @call diffForHumans 'RelativeToNow' => CarbonInterface::DIFF_RELATIVE_TO_NOW, // @call diffForHumans 'RelativeToOther' => CarbonInterface::DIFF_RELATIVE_TO_OTHER, ]; $sizePattern = implode('|', array_keys($diffSizes)); $syntaxPattern = implode('|', array_keys($diffSyntaxModes)); if (preg_match("/^(?<size>$sizePattern)(?<syntax>$syntaxPattern)DiffForHumans$/", $method, $match)) { $dates = array_filter($parameters, function ($parameter) { return $parameter instanceof DateTimeInterface; }); $other = null; if (\count($dates)) { $key = key($dates); $other = current($dates); array_splice($parameters, $key, 1); } return $this->diffForHumans($other, $diffSyntaxModes[$match['syntax']], $diffSizes[$match['size']], ...$parameters); } $roundedValue = $this->callRoundMethod($method, $parameters); if ($roundedValue !== null) { return $roundedValue; } $unit = rtrim($method, 's'); if (str_starts_with($unit, 'is')) { $word = substr($unit, 2); if (\in_array($word, static::$days, true)) { return $this->isDayOfWeek($word); } switch ($word) { // @call is Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.) case 'Utc': case 'UTC': return $this->utc; // @call is Check if the current instance has non-UTC timezone. case 'Local': return $this->local; // @call is Check if the current instance is a valid date. case 'Valid': return $this->year !== 0; // @call is Check if the current instance is in a daylight saving time. case 'DST': return $this->dst; } } $action = substr($unit, 0, 3); $overflow = null; if ($action === 'set') { $unit = strtolower(substr($unit, 3)); } if (\in_array($unit, static::$units, true)) { return $this->setUnit($unit, ...$parameters); } if ($action === 'add' || $action === 'sub') { $unit = substr($unit, 3); if (str_starts_with($unit, 'Real')) { $unit = static::singularUnit(substr($unit, 4)); return $this->{"{$action}RealUnit"}($unit, ...$parameters); } if (preg_match('/^(Month|Quarter|Year|Decade|Century|Centurie|Millennium|Millennia)s?(No|With|Without|WithNo)Overflow$/', $unit, $match)) { $unit = $match[1]; $overflow = $match[2] === 'With'; } $unit = static::singularUnit($unit); } if (static::isModifiableUnit($unit)) { return $this->{"{$action}Unit"}($unit, $this->getMagicParameter($parameters, 0, 'value', 1), $overflow); } $sixFirstLetters = substr($unit, 0, 6); $factor = -1; if ($sixFirstLetters === 'isLast') { $sixFirstLetters = 'isNext'; $factor = 1; } if ($sixFirstLetters === 'isNext') { $lowerUnit = strtolower(substr($unit, 6)); if (static::isModifiableUnit($lowerUnit)) { return $this->copy()->addUnit($lowerUnit, $factor, false)->isSameUnit($lowerUnit, ...$parameters); } } if ($sixFirstLetters === 'isSame') { try { return $this->isSameUnit(strtolower(substr($unit, 6)), ...$parameters); } catch (BadComparisonUnitException $exception) { // Try next } } if (str_starts_with($unit, 'isCurrent')) { try { return $this->isCurrentUnit(strtolower(substr($unit, 9))); } catch (BadComparisonUnitException | BadMethodCallException $exception) { // Try next } } if (str_ends_with($method, 'Until')) { try { $unit = static::singularUnit(substr($method, 0, -5)); return $this->range( $this->getMagicParameter($parameters, 0, 'endDate', $this), $this->getMagicParameter($parameters, 1, 'factor', 1), $unit ); } catch (InvalidArgumentException $exception) { // Try macros } } return static::bindMacroContext($this, function () use (&$method, &$parameters) { $macro = $this->getLocalMacro($method); if (!$macro) { foreach ([$this->localGenericMacros ?: [], static::getGenericMacros()] as $list) { foreach ($list as $callback) { try { return $this->executeCallable($callback, $method, ...$parameters); } catch (BadMethodCallException $exception) { continue; } } } if ($this->localStrictModeEnabled ?? static::isStrictModeEnabled()) { throw new UnknownMethodException($method); } return null; } return $this->executeCallable($macro, ...$parameters); }); } } PK������<1ZljSG��G��&��Carbon/Traits/DeprecatedProperties.phpnu�W+A��������<?php declare(strict_types=1); /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; trait DeprecatedProperties { /** * the day of week in current locale LC_TIME * * @var string * * @deprecated It uses OS language package and strftime() which is deprecated since PHP 8.1. * Use ->isoFormat('MMM') instead. * Deprecated since 2.55.0 */ public $localeDayOfWeek; /** * the abbreviated day of week in current locale LC_TIME * * @var string * * @deprecated It uses OS language package and strftime() which is deprecated since PHP 8.1. * Use ->isoFormat('dddd') instead. * Deprecated since 2.55.0 */ public $shortLocaleDayOfWeek; /** * the month in current locale LC_TIME * * @var string * * @deprecated It uses OS language package and strftime() which is deprecated since PHP 8.1. * Use ->isoFormat('ddd') instead. * Deprecated since 2.55.0 */ public $localeMonth; /** * the abbreviated month in current locale LC_TIME * * @var string * * @deprecated It uses OS language package and strftime() which is deprecated since PHP 8.1. * Use ->isoFormat('MMMM') instead. * Deprecated since 2.55.0 */ public $shortLocaleMonth; } PK������<1Zs+5��5����Carbon/Traits/Mutability.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; use Carbon\Carbon; use Carbon\CarbonImmutable; /** * Trait Mutability. * * Utils to know if the current object is mutable or immutable and convert it. */ trait Mutability { use Cast; /** * Returns true if the current class/instance is mutable. * * @return bool */ public static function isMutable() { return false; } /** * Returns true if the current class/instance is immutable. * * @return bool */ public static function isImmutable() { return !static::isMutable(); } /** * Return a mutable copy of the instance. * * @return Carbon */ public function toMutable() { /** @var Carbon $date */ $date = $this->cast(Carbon::class); return $date; } /** * Return a immutable copy of the instance. * * @return CarbonImmutable */ public function toImmutable() { /** @var CarbonImmutable $date */ $date = $this->cast(CarbonImmutable::class); return $date; } } PK������<1Z[u������Carbon/Traits/Mixin.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; use Carbon\CarbonInterface; use Carbon\CarbonInterval; use Carbon\CarbonPeriod; use Closure; use Generator; use ReflectionClass; use ReflectionException; use ReflectionMethod; use Throwable; /** * Trait Mixin. * * Allows mixing in entire classes with multiple macros. */ trait Mixin { /** * Stack of macro instance contexts. * * @var array */ protected static $macroContextStack = []; /** * Mix another object into the class. * * @example * ``` * Carbon::mixin(new class { * public function addMoon() { * return function () { * return $this->addDays(30); * }; * } * public function subMoon() { * return function () { * return $this->subDays(30); * }; * } * }); * $fullMoon = Carbon::create('2018-12-22'); * $nextFullMoon = $fullMoon->addMoon(); * $blackMoon = Carbon::create('2019-01-06'); * $previousBlackMoon = $blackMoon->subMoon(); * echo "$nextFullMoon\n"; * echo "$previousBlackMoon\n"; * ``` * * @param object|string $mixin * * @throws ReflectionException * * @return void */ public static function mixin($mixin) { \is_string($mixin) && trait_exists($mixin) ? self::loadMixinTrait($mixin) : self::loadMixinClass($mixin); } /** * @param object|string $mixin * * @throws ReflectionException */ private static function loadMixinClass($mixin) { $methods = (new ReflectionClass($mixin))->getMethods( ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED ); foreach ($methods as $method) { if ($method->isConstructor() || $method->isDestructor()) { continue; } $method->setAccessible(true); static::macro($method->name, $method->invoke($mixin)); } } /** * @param string $trait */ private static function loadMixinTrait($trait) { $context = eval(self::getAnonymousClassCodeForTrait($trait)); $className = \get_class($context); $baseClass = static::class; foreach (self::getMixableMethods($context) as $name) { $closureBase = Closure::fromCallable([$context, $name]); static::macro($name, function (...$parameters) use ($closureBase, $className, $baseClass) { $downContext = isset($this) ? ($this) : new $baseClass(); $context = isset($this) ? $this->cast($className) : new $className(); try { // @ is required to handle error if not converted into exceptions $closure = @$closureBase->bindTo($context); } catch (Throwable $throwable) { // @codeCoverageIgnore $closure = $closureBase; // @codeCoverageIgnore } // in case of errors not converted into exceptions $closure = $closure ?: $closureBase; $result = $closure(...$parameters); if (!($result instanceof $className)) { return $result; } if ($downContext instanceof CarbonInterface && $result instanceof CarbonInterface) { if ($context !== $result) { $downContext = $downContext->copy(); } return $downContext ->setTimezone($result->getTimezone()) ->modify($result->format('Y-m-d H:i:s.u')) ->settings($result->getSettings()); } if ($downContext instanceof CarbonInterval && $result instanceof CarbonInterval) { if ($context !== $result) { $downContext = $downContext->copy(); } $downContext->copyProperties($result); self::copyStep($downContext, $result); self::copyNegativeUnits($downContext, $result); return $downContext->settings($result->getSettings()); } if ($downContext instanceof CarbonPeriod && $result instanceof CarbonPeriod) { if ($context !== $result) { $downContext = $downContext->copy(); } return $downContext ->setDates($result->getStartDate(), $result->getEndDate()) ->setRecurrences($result->getRecurrences()) ->setOptions($result->getOptions()) ->settings($result->getSettings()); } return $result; }); } } private static function getAnonymousClassCodeForTrait(string $trait) { return 'return new class() extends '.static::class.' {use '.$trait.';};'; } private static function getMixableMethods(self $context): Generator { foreach (get_class_methods($context) as $name) { if (method_exists(static::class, $name)) { continue; } yield $name; } } /** * Stack a Carbon context from inside calls of self::this() and execute a given action. * * @param static|null $context * @param callable $callable * * @throws Throwable * * @return mixed */ protected static function bindMacroContext($context, callable $callable) { static::$macroContextStack[] = $context; try { return $callable(); } finally { array_pop(static::$macroContextStack); } } /** * Return the current context from inside a macro callee or a null if static. * * @return static|null */ protected static function context() { return end(static::$macroContextStack) ?: null; } /** * Return the current context from inside a macro callee or a new one if static. * * @return static */ protected static function this() { return end(static::$macroContextStack) ?: new static(); } } PK������<1Z?1G��G����Carbon/Traits/Test.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; use Carbon\CarbonInterface; use Carbon\CarbonTimeZone; use Closure; use DateTimeImmutable; use DateTimeInterface; use InvalidArgumentException; use Throwable; trait Test { /////////////////////////////////////////////////////////////////// ///////////////////////// TESTING AIDS //////////////////////////// /////////////////////////////////////////////////////////////////// /** * A test Carbon instance to be returned when now instances are created. * * @var Closure|static|null */ protected static $testNow; /** * The timezone to resto to when clearing the time mock. * * @var string|null */ protected static $testDefaultTimezone; /** * Set a Carbon instance (real or mock) to be returned when a "now" * instance is created. The provided instance will be returned * specifically under the following conditions: * - A call to the static now() method, ex. Carbon::now() * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null) * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now') * - When a string containing the desired time is passed to Carbon::parse(). * * Note the timezone parameter was left out of the examples above and * has no affect as the mock value will be returned regardless of its value. * * Only the moment is mocked with setTestNow(), the timezone will still be the one passed * as parameter of date_default_timezone_get() as a fallback (see setTestNowAndTimezone()). * * To clear the test instance call this method using the default * parameter of null. * * /!\ Use this method for unit tests only. * * @param DateTimeInterface|Closure|static|string|false|null $testNow real or mock Carbon instance */ public static function setTestNow($testNow = null) { static::$testNow = $testNow instanceof self || $testNow instanceof Closure ? $testNow : static::make($testNow); } /** * Set a Carbon instance (real or mock) to be returned when a "now" * instance is created. The provided instance will be returned * specifically under the following conditions: * - A call to the static now() method, ex. Carbon::now() * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null) * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now') * - When a string containing the desired time is passed to Carbon::parse(). * * It will also align default timezone (e.g. call date_default_timezone_set()) with * the second argument or if null, with the timezone of the given date object. * * To clear the test instance call this method using the default * parameter of null. * * /!\ Use this method for unit tests only. * * @param DateTimeInterface|Closure|static|string|false|null $testNow real or mock Carbon instance */ public static function setTestNowAndTimezone($testNow = null, $tz = null) { if ($testNow) { self::$testDefaultTimezone = self::$testDefaultTimezone ?? date_default_timezone_get(); } $useDateInstanceTimezone = $testNow instanceof DateTimeInterface; if ($useDateInstanceTimezone) { self::setDefaultTimezone($testNow->getTimezone()->getName(), $testNow); } static::setTestNow($testNow); if (!$useDateInstanceTimezone) { $now = static::getMockedTestNow(\func_num_args() === 1 ? null : $tz); $tzName = $now ? $now->tzName : null; self::setDefaultTimezone($tzName ?? self::$testDefaultTimezone ?? 'UTC', $now); } if (!$testNow) { self::$testDefaultTimezone = null; } } /** * Temporarily sets a static date to be used within the callback. * Using setTestNow to set the date, executing the callback, then * clearing the test instance. * * /!\ Use this method for unit tests only. * * @template T * * @param DateTimeInterface|Closure|static|string|false|null $testNow real or mock Carbon instance * @param Closure(): T $callback * * @return T */ public static function withTestNow($testNow, $callback) { static::setTestNow($testNow); try { $result = $callback(); } finally { static::setTestNow(); } return $result; } /** * Get the Carbon instance (real or mock) to be returned when a "now" * instance is created. * * @return Closure|static the current instance used for testing */ public static function getTestNow() { return static::$testNow; } /** * Determine if there is a valid test instance set. A valid test instance * is anything that is not null. * * @return bool true if there is a test instance, otherwise false */ public static function hasTestNow() { return static::getTestNow() !== null; } /** * Get the mocked date passed in setTestNow() and if it's a Closure, execute it. * * @param string|\DateTimeZone $tz * * @return \Carbon\CarbonImmutable|\Carbon\Carbon|null */ protected static function getMockedTestNow($tz) { $testNow = static::getTestNow(); if ($testNow instanceof Closure) { $realNow = new DateTimeImmutable('now'); $testNow = $testNow(static::parse( $realNow->format('Y-m-d H:i:s.u'), $tz ?: $realNow->getTimezone() )); } /* @var \Carbon\CarbonImmutable|\Carbon\Carbon|null $testNow */ return $testNow instanceof CarbonInterface ? $testNow->avoidMutation()->tz($tz) : $testNow; } protected static function mockConstructorParameters(&$time, $tz) { /** @var \Carbon\CarbonImmutable|\Carbon\Carbon $testInstance */ $testInstance = clone static::getMockedTestNow($tz); if (static::hasRelativeKeywords($time)) { $testInstance = $testInstance->modify($time); } $time = $testInstance instanceof self ? $testInstance->rawFormat(static::MOCK_DATETIME_FORMAT) : $testInstance->format(static::MOCK_DATETIME_FORMAT); } private static function setDefaultTimezone($timezone, ?DateTimeInterface $date = null) { $previous = null; $success = false; try { $success = date_default_timezone_set($timezone); } catch (Throwable $exception) { $previous = $exception; } if (!$success) { $suggestion = @CarbonTimeZone::create($timezone)->toRegionName($date); throw new InvalidArgumentException( "Timezone ID '$timezone' is invalid". ($suggestion && $suggestion !== $timezone ? ", did you mean '$suggestion'?" : '.')."\n". "It must be one of the IDs from DateTimeZone::listIdentifiers(),\n". 'For the record, hours/minutes offset are relevant only for a particular moment, '. 'but not as a default timezone.', 0, $previous ); } } } PK������<1Z kJ3��J3����Carbon/Traits/Options.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; use Carbon\CarbonInterface; use DateTimeInterface; use Throwable; /** * Trait Options. * * Embed base methods to change settings of Carbon classes. * * Depends on the following methods: * * @method static shiftTimezone($timezone) Set the timezone */ trait Options { use Localization; /** * Customizable PHP_INT_SIZE override. * * @var int */ public static $PHPIntSize = PHP_INT_SIZE; /** * First day of week. * * @var int|string */ protected static $weekStartsAt = CarbonInterface::MONDAY; /** * Last day of week. * * @var int|string */ protected static $weekEndsAt = CarbonInterface::SUNDAY; /** * Days of weekend. * * @var array */ protected static $weekendDays = [ CarbonInterface::SATURDAY, CarbonInterface::SUNDAY, ]; /** * Format regex patterns. * * @var array<string, string> */ protected static $regexFormats = [ 'd' => '(3[01]|[12][0-9]|0[1-9])', 'D' => '(Sun|Mon|Tue|Wed|Thu|Fri|Sat)', 'j' => '([123][0-9]|[1-9])', 'l' => '([a-zA-Z]{2,})', 'N' => '([1-7])', 'S' => '(st|nd|rd|th)', 'w' => '([0-6])', 'z' => '(36[0-5]|3[0-5][0-9]|[12][0-9]{2}|[1-9]?[0-9])', 'W' => '(5[012]|[1-4][0-9]|0?[1-9])', 'F' => '([a-zA-Z]{2,})', 'm' => '(1[012]|0[1-9])', 'M' => '([a-zA-Z]{3})', 'n' => '(1[012]|[1-9])', 't' => '(2[89]|3[01])', 'L' => '(0|1)', 'o' => '([1-9][0-9]{0,4})', 'Y' => '([1-9]?[0-9]{4})', 'y' => '([0-9]{2})', 'a' => '(am|pm)', 'A' => '(AM|PM)', 'B' => '([0-9]{3})', 'g' => '(1[012]|[1-9])', 'G' => '(2[0-3]|1?[0-9])', 'h' => '(1[012]|0[1-9])', 'H' => '(2[0-3]|[01][0-9])', 'i' => '([0-5][0-9])', 's' => '([0-5][0-9])', 'u' => '([0-9]{1,6})', 'v' => '([0-9]{1,3})', 'e' => '([a-zA-Z]{1,5})|([a-zA-Z]*\\/[a-zA-Z]*)', 'I' => '(0|1)', 'O' => '([+-](1[0123]|0[0-9])[0134][05])', 'P' => '([+-](1[0123]|0[0-9]):[0134][05])', 'p' => '(Z|[+-](1[0123]|0[0-9]):[0134][05])', 'T' => '([a-zA-Z]{1,5})', 'Z' => '(-?[1-5]?[0-9]{1,4})', 'U' => '([0-9]*)', // The formats below are combinations of the above formats. 'c' => '(([1-9]?[0-9]{4})-(1[012]|0[1-9])-(3[01]|[12][0-9]|0[1-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])[+-](1[012]|0[0-9]):([0134][05]))', // Y-m-dTH:i:sP 'r' => '(([a-zA-Z]{3}), ([123][0-9]|0[1-9]) ([a-zA-Z]{3}) ([1-9]?[0-9]{4}) (2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9]) [+-](1[012]|0[0-9])([0134][05]))', // D, d M Y H:i:s O ]; /** * Format modifiers (such as available in createFromFormat) regex patterns. * * @var array */ protected static $regexFormatModifiers = [ '*' => '.+', ' ' => '[ ]', '#' => '[;:\\/.,()-]', '?' => '([^a]|[a])', '!' => '', '|' => '', '+' => '', ]; /** * Indicates if months should be calculated with overflow. * Global setting. * * @var bool */ protected static $monthsOverflow = true; /** * Indicates if years should be calculated with overflow. * Global setting. * * @var bool */ protected static $yearsOverflow = true; /** * Indicates if the strict mode is in use. * Global setting. * * @var bool */ protected static $strictModeEnabled = true; /** * Function to call instead of format. * * @var string|callable|null */ protected static $formatFunction; /** * Function to call instead of createFromFormat. * * @var string|callable|null */ protected static $createFromFormatFunction; /** * Function to call instead of parse. * * @var string|callable|null */ protected static $parseFunction; /** * Indicates if months should be calculated with overflow. * Specific setting. * * @var bool|null */ protected $localMonthsOverflow; /** * Indicates if years should be calculated with overflow. * Specific setting. * * @var bool|null */ protected $localYearsOverflow; /** * Indicates if the strict mode is in use. * Specific setting. * * @var bool|null */ protected $localStrictModeEnabled; /** * Options for diffForHumans and forHumans methods. * * @var bool|null */ protected $localHumanDiffOptions; /** * Format to use on string cast. * * @var string|null */ protected $localToStringFormat; /** * Format to use on JSON serialization. * * @var string|null */ protected $localSerializer; /** * Instance-specific macros. * * @var array|null */ protected $localMacros; /** * Instance-specific generic macros. * * @var array|null */ protected $localGenericMacros; /** * Function to call instead of format. * * @var string|callable|null */ protected $localFormatFunction; /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * @see settings * * Enable the strict mode (or disable with passing false). * * @param bool $strictModeEnabled */ public static function useStrictMode($strictModeEnabled = true) { static::$strictModeEnabled = $strictModeEnabled; } /** * Returns true if the strict mode is globally in use, false else. * (It can be overridden in specific instances.) * * @return bool */ public static function isStrictModeEnabled() { return static::$strictModeEnabled; } /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants * are available for quarters, years, decade, centuries, millennia (singular and plural forms). * @see settings * * Indicates if months should be calculated with overflow. * * @param bool $monthsOverflow * * @return void */ public static function useMonthsOverflow($monthsOverflow = true) { static::$monthsOverflow = $monthsOverflow; } /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants * are available for quarters, years, decade, centuries, millennia (singular and plural forms). * @see settings * * Reset the month overflow behavior. * * @return void */ public static function resetMonthsOverflow() { static::$monthsOverflow = true; } /** * Get the month overflow global behavior (can be overridden in specific instances). * * @return bool */ public static function shouldOverflowMonths() { return static::$monthsOverflow; } /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants * are available for quarters, years, decade, centuries, millennia (singular and plural forms). * @see settings * * Indicates if years should be calculated with overflow. * * @param bool $yearsOverflow * * @return void */ public static function useYearsOverflow($yearsOverflow = true) { static::$yearsOverflow = $yearsOverflow; } /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants * are available for quarters, years, decade, centuries, millennia (singular and plural forms). * @see settings * * Reset the month overflow behavior. * * @return void */ public static function resetYearsOverflow() { static::$yearsOverflow = true; } /** * Get the month overflow global behavior (can be overridden in specific instances). * * @return bool */ public static function shouldOverflowYears() { return static::$yearsOverflow; } /** * Set specific options. * - strictMode: true|false|null * - monthOverflow: true|false|null * - yearOverflow: true|false|null * - humanDiffOptions: int|null * - toStringFormat: string|Closure|null * - toJsonFormat: string|Closure|null * - locale: string|null * - timezone: \DateTimeZone|string|int|null * - macros: array|null * - genericMacros: array|null * * @param array $settings * * @return $this|static */ public function settings(array $settings) { $this->localStrictModeEnabled = $settings['strictMode'] ?? null; $this->localMonthsOverflow = $settings['monthOverflow'] ?? null; $this->localYearsOverflow = $settings['yearOverflow'] ?? null; $this->localHumanDiffOptions = $settings['humanDiffOptions'] ?? null; $this->localToStringFormat = $settings['toStringFormat'] ?? null; $this->localSerializer = $settings['toJsonFormat'] ?? null; $this->localMacros = $settings['macros'] ?? null; $this->localGenericMacros = $settings['genericMacros'] ?? null; $this->localFormatFunction = $settings['formatFunction'] ?? null; if (isset($settings['locale'])) { $locales = $settings['locale']; if (!\is_array($locales)) { $locales = [$locales]; } $this->locale(...$locales); } if (isset($settings['innerTimezone'])) { return $this->setTimezone($settings['innerTimezone']); } if (isset($settings['timezone'])) { return $this->shiftTimezone($settings['timezone']); } return $this; } /** * Returns current local settings. * * @return array */ public function getSettings() { $settings = []; $map = [ 'localStrictModeEnabled' => 'strictMode', 'localMonthsOverflow' => 'monthOverflow', 'localYearsOverflow' => 'yearOverflow', 'localHumanDiffOptions' => 'humanDiffOptions', 'localToStringFormat' => 'toStringFormat', 'localSerializer' => 'toJsonFormat', 'localMacros' => 'macros', 'localGenericMacros' => 'genericMacros', 'locale' => 'locale', 'tzName' => 'timezone', 'localFormatFunction' => 'formatFunction', ]; foreach ($map as $property => $key) { $value = $this->$property ?? null; if ($value !== null && ($key !== 'locale' || $value !== 'en' || $this->localTranslator)) { $settings[$key] = $value; } } return $settings; } /** * Show truthy properties on var_dump(). * * @return array */ public function __debugInfo() { $infos = array_filter(get_object_vars($this), static function ($var) { return $var; }); foreach (['dumpProperties', 'constructedObjectId', 'constructed'] as $property) { if (isset($infos[$property])) { unset($infos[$property]); } } $this->addExtraDebugInfos($infos); return $infos; } protected function addExtraDebugInfos(&$infos): void { if ($this instanceof DateTimeInterface) { try { if (!isset($infos['date'])) { $infos['date'] = $this->format(CarbonInterface::MOCK_DATETIME_FORMAT); } if (!isset($infos['timezone'])) { $infos['timezone'] = $this->tzName; } } catch (Throwable $exception) { // noop } } } } PK������<1ZgC������Carbon/Traits/Comparison.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; use BadMethodCallException; use Carbon\CarbonInterface; use Carbon\Exceptions\BadComparisonUnitException; use InvalidArgumentException; /** * Trait Comparison. * * Comparison utils and testers. All the following methods return booleans. * nowWithSameTz * * Depends on the following methods: * * @method static resolveCarbon($date) * @method static copy() * @method static nowWithSameTz() * @method static static yesterday($timezone = null) * @method static static tomorrow($timezone = null) */ trait Comparison { /** @var bool */ protected $endOfTime = false; /** @var bool */ protected $startOfTime = false; /** * Determines if the instance is equal to another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->eq('2018-07-25 12:45:16'); // true * Carbon::parse('2018-07-25 12:45:16')->eq(Carbon::parse('2018-07-25 12:45:16')); // true * Carbon::parse('2018-07-25 12:45:16')->eq('2018-07-25 12:45:17'); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see equalTo() * * @return bool */ public function eq($date): bool { return $this->equalTo($date); } /** * Determines if the instance is equal to another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->equalTo('2018-07-25 12:45:16'); // true * Carbon::parse('2018-07-25 12:45:16')->equalTo(Carbon::parse('2018-07-25 12:45:16')); // true * Carbon::parse('2018-07-25 12:45:16')->equalTo('2018-07-25 12:45:17'); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @return bool */ public function equalTo($date): bool { $this->discourageNull($date); $this->discourageBoolean($date); return $this == $this->resolveCarbon($date); } /** * Determines if the instance is not equal to another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->ne('2018-07-25 12:45:16'); // false * Carbon::parse('2018-07-25 12:45:16')->ne(Carbon::parse('2018-07-25 12:45:16')); // false * Carbon::parse('2018-07-25 12:45:16')->ne('2018-07-25 12:45:17'); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see notEqualTo() * * @return bool */ public function ne($date): bool { return $this->notEqualTo($date); } /** * Determines if the instance is not equal to another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->notEqualTo('2018-07-25 12:45:16'); // false * Carbon::parse('2018-07-25 12:45:16')->notEqualTo(Carbon::parse('2018-07-25 12:45:16')); // false * Carbon::parse('2018-07-25 12:45:16')->notEqualTo('2018-07-25 12:45:17'); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @return bool */ public function notEqualTo($date): bool { return !$this->equalTo($date); } /** * Determines if the instance is greater (after) than another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->gt('2018-07-25 12:45:15'); // true * Carbon::parse('2018-07-25 12:45:16')->gt('2018-07-25 12:45:16'); // false * Carbon::parse('2018-07-25 12:45:16')->gt('2018-07-25 12:45:17'); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see greaterThan() * * @return bool */ public function gt($date): bool { return $this->greaterThan($date); } /** * Determines if the instance is greater (after) than another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:15'); // true * Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:16'); // false * Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:17'); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @return bool */ public function greaterThan($date): bool { $this->discourageNull($date); $this->discourageBoolean($date); return $this > $this->resolveCarbon($date); } /** * Determines if the instance is greater (after) than another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->isAfter('2018-07-25 12:45:15'); // true * Carbon::parse('2018-07-25 12:45:16')->isAfter('2018-07-25 12:45:16'); // false * Carbon::parse('2018-07-25 12:45:16')->isAfter('2018-07-25 12:45:17'); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see greaterThan() * * @return bool */ public function isAfter($date): bool { return $this->greaterThan($date); } /** * Determines if the instance is greater (after) than or equal to another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->gte('2018-07-25 12:45:15'); // true * Carbon::parse('2018-07-25 12:45:16')->gte('2018-07-25 12:45:16'); // true * Carbon::parse('2018-07-25 12:45:16')->gte('2018-07-25 12:45:17'); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see greaterThanOrEqualTo() * * @return bool */ public function gte($date): bool { return $this->greaterThanOrEqualTo($date); } /** * Determines if the instance is greater (after) than or equal to another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->greaterThanOrEqualTo('2018-07-25 12:45:15'); // true * Carbon::parse('2018-07-25 12:45:16')->greaterThanOrEqualTo('2018-07-25 12:45:16'); // true * Carbon::parse('2018-07-25 12:45:16')->greaterThanOrEqualTo('2018-07-25 12:45:17'); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @return bool */ public function greaterThanOrEqualTo($date): bool { $this->discourageNull($date); $this->discourageBoolean($date); return $this >= $this->resolveCarbon($date); } /** * Determines if the instance is less (before) than another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->lt('2018-07-25 12:45:15'); // false * Carbon::parse('2018-07-25 12:45:16')->lt('2018-07-25 12:45:16'); // false * Carbon::parse('2018-07-25 12:45:16')->lt('2018-07-25 12:45:17'); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see lessThan() * * @return bool */ public function lt($date): bool { return $this->lessThan($date); } /** * Determines if the instance is less (before) than another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->lessThan('2018-07-25 12:45:15'); // false * Carbon::parse('2018-07-25 12:45:16')->lessThan('2018-07-25 12:45:16'); // false * Carbon::parse('2018-07-25 12:45:16')->lessThan('2018-07-25 12:45:17'); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @return bool */ public function lessThan($date): bool { $this->discourageNull($date); $this->discourageBoolean($date); return $this < $this->resolveCarbon($date); } /** * Determines if the instance is less (before) than another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->isBefore('2018-07-25 12:45:15'); // false * Carbon::parse('2018-07-25 12:45:16')->isBefore('2018-07-25 12:45:16'); // false * Carbon::parse('2018-07-25 12:45:16')->isBefore('2018-07-25 12:45:17'); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see lessThan() * * @return bool */ public function isBefore($date): bool { return $this->lessThan($date); } /** * Determines if the instance is less (before) or equal to another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->lte('2018-07-25 12:45:15'); // false * Carbon::parse('2018-07-25 12:45:16')->lte('2018-07-25 12:45:16'); // true * Carbon::parse('2018-07-25 12:45:16')->lte('2018-07-25 12:45:17'); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see lessThanOrEqualTo() * * @return bool */ public function lte($date): bool { return $this->lessThanOrEqualTo($date); } /** * Determines if the instance is less (before) or equal to another * * @example * ``` * Carbon::parse('2018-07-25 12:45:16')->lessThanOrEqualTo('2018-07-25 12:45:15'); // false * Carbon::parse('2018-07-25 12:45:16')->lessThanOrEqualTo('2018-07-25 12:45:16'); // true * Carbon::parse('2018-07-25 12:45:16')->lessThanOrEqualTo('2018-07-25 12:45:17'); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @return bool */ public function lessThanOrEqualTo($date): bool { $this->discourageNull($date); $this->discourageBoolean($date); return $this <= $this->resolveCarbon($date); } /** * Determines if the instance is between two others. * * The third argument allow you to specify if bounds are included or not (true by default) * but for when you including/excluding bounds may produce different results in your application, * we recommend to use the explicit methods ->betweenIncluded() or ->betweenExcluded() instead. * * @example * ``` * Carbon::parse('2018-07-25')->between('2018-07-14', '2018-08-01'); // true * Carbon::parse('2018-07-25')->between('2018-08-01', '2018-08-20'); // false * Carbon::parse('2018-07-25')->between('2018-07-25', '2018-08-01'); // true * Carbon::parse('2018-07-25')->between('2018-07-25', '2018-08-01', false); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1 * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2 * @param bool $equal Indicates if an equal to comparison should be done * * @return bool */ public function between($date1, $date2, $equal = true): bool { $date1 = $this->resolveCarbon($date1); $date2 = $this->resolveCarbon($date2); if ($date1->greaterThan($date2)) { [$date1, $date2] = [$date2, $date1]; } if ($equal) { return $this >= $date1 && $this <= $date2; } return $this > $date1 && $this < $date2; } /** * Determines if the instance is between two others, bounds included. * * @example * ``` * Carbon::parse('2018-07-25')->betweenIncluded('2018-07-14', '2018-08-01'); // true * Carbon::parse('2018-07-25')->betweenIncluded('2018-08-01', '2018-08-20'); // false * Carbon::parse('2018-07-25')->betweenIncluded('2018-07-25', '2018-08-01'); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1 * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2 * * @return bool */ public function betweenIncluded($date1, $date2): bool { return $this->between($date1, $date2, true); } /** * Determines if the instance is between two others, bounds excluded. * * @example * ``` * Carbon::parse('2018-07-25')->betweenExcluded('2018-07-14', '2018-08-01'); // true * Carbon::parse('2018-07-25')->betweenExcluded('2018-08-01', '2018-08-20'); // false * Carbon::parse('2018-07-25')->betweenExcluded('2018-07-25', '2018-08-01'); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1 * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2 * * @return bool */ public function betweenExcluded($date1, $date2): bool { return $this->between($date1, $date2, false); } /** * Determines if the instance is between two others * * @example * ``` * Carbon::parse('2018-07-25')->isBetween('2018-07-14', '2018-08-01'); // true * Carbon::parse('2018-07-25')->isBetween('2018-08-01', '2018-08-20'); // false * Carbon::parse('2018-07-25')->isBetween('2018-07-25', '2018-08-01'); // true * Carbon::parse('2018-07-25')->isBetween('2018-07-25', '2018-08-01', false); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1 * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2 * @param bool $equal Indicates if an equal to comparison should be done * * @return bool */ public function isBetween($date1, $date2, $equal = true): bool { return $this->between($date1, $date2, $equal); } /** * Determines if the instance is a weekday. * * @example * ``` * Carbon::parse('2019-07-14')->isWeekday(); // false * Carbon::parse('2019-07-15')->isWeekday(); // true * ``` * * @return bool */ public function isWeekday() { return !$this->isWeekend(); } /** * Determines if the instance is a weekend day. * * @example * ``` * Carbon::parse('2019-07-14')->isWeekend(); // true * Carbon::parse('2019-07-15')->isWeekend(); // false * ``` * * @return bool */ public function isWeekend() { return \in_array($this->dayOfWeek, static::$weekendDays, true); } /** * Determines if the instance is yesterday. * * @example * ``` * Carbon::yesterday()->isYesterday(); // true * Carbon::tomorrow()->isYesterday(); // false * ``` * * @return bool */ public function isYesterday() { return $this->toDateString() === static::yesterday($this->getTimezone())->toDateString(); } /** * Determines if the instance is today. * * @example * ``` * Carbon::today()->isToday(); // true * Carbon::tomorrow()->isToday(); // false * ``` * * @return bool */ public function isToday() { return $this->toDateString() === $this->nowWithSameTz()->toDateString(); } /** * Determines if the instance is tomorrow. * * @example * ``` * Carbon::tomorrow()->isTomorrow(); // true * Carbon::yesterday()->isTomorrow(); // false * ``` * * @return bool */ public function isTomorrow() { return $this->toDateString() === static::tomorrow($this->getTimezone())->toDateString(); } /** * Determines if the instance is in the future, ie. greater (after) than now. * * @example * ``` * Carbon::now()->addHours(5)->isFuture(); // true * Carbon::now()->subHours(5)->isFuture(); // false * ``` * * @return bool */ public function isFuture() { return $this->greaterThan($this->nowWithSameTz()); } /** * Determines if the instance is in the past, ie. less (before) than now. * * @example * ``` * Carbon::now()->subHours(5)->isPast(); // true * Carbon::now()->addHours(5)->isPast(); // false * ``` * * @return bool */ public function isPast() { return $this->lessThan($this->nowWithSameTz()); } /** * Determines if the instance is a leap year. * * @example * ``` * Carbon::parse('2020-01-01')->isLeapYear(); // true * Carbon::parse('2019-01-01')->isLeapYear(); // false * ``` * * @return bool */ public function isLeapYear() { return $this->rawFormat('L') === '1'; } /** * Determines if the instance is a long year (using calendar year). * * ⚠️ This method completely ignores month and day to use the numeric year number, * it's not correct if the exact date matters. For instance as `2019-12-30` is already * in the first week of the 2020 year, if you want to know from this date if ISO week * year 2020 is a long year, use `isLongIsoYear` instead. * * @example * ``` * Carbon::create(2015)->isLongYear(); // true * Carbon::create(2016)->isLongYear(); // false * ``` * * @see https://en.wikipedia.org/wiki/ISO_8601#Week_dates * * @return bool */ public function isLongYear() { return static::create($this->year, 12, 28, 0, 0, 0, $this->tz)->weekOfYear === 53; } /** * Determines if the instance is a long year (using ISO 8601 year). * * @example * ``` * Carbon::parse('2015-01-01')->isLongIsoYear(); // true * Carbon::parse('2016-01-01')->isLongIsoYear(); // true * Carbon::parse('2016-01-03')->isLongIsoYear(); // false * Carbon::parse('2019-12-29')->isLongIsoYear(); // false * Carbon::parse('2019-12-30')->isLongIsoYear(); // true * ``` * * @see https://en.wikipedia.org/wiki/ISO_8601#Week_dates * * @return bool */ public function isLongIsoYear() { return static::create($this->isoWeekYear, 12, 28, 0, 0, 0, $this->tz)->weekOfYear === 53; } /** * Compares the formatted values of the two dates. * * @example * ``` * Carbon::parse('2019-06-13')->isSameAs('Y-d', Carbon::parse('2019-12-13')); // true * Carbon::parse('2019-06-13')->isSameAs('Y-d', Carbon::parse('2019-06-14')); // false * ``` * * @param string $format date formats to compare. * @param \Carbon\Carbon|\DateTimeInterface|string|null $date instance to compare with or null to use current day. * * @return bool */ public function isSameAs($format, $date = null) { return $this->rawFormat($format) === $this->resolveCarbon($date)->rawFormat($format); } /** * Determines if the instance is in the current unit given. * * @example * ``` * Carbon::parse('2019-01-13')->isSameUnit('year', Carbon::parse('2019-12-25')); // true * Carbon::parse('2018-12-13')->isSameUnit('year', Carbon::parse('2019-12-25')); // false * ``` * * @param string $unit singular unit string * @param \Carbon\Carbon|\DateTimeInterface|null $date instance to compare with or null to use current day. * * @throws BadComparisonUnitException * * @return bool */ public function isSameUnit($unit, $date = null) { $units = [ // @call isSameUnit 'year' => 'Y', // @call isSameUnit 'week' => 'o-W', // @call isSameUnit 'day' => 'Y-m-d', // @call isSameUnit 'hour' => 'Y-m-d H', // @call isSameUnit 'minute' => 'Y-m-d H:i', // @call isSameUnit 'second' => 'Y-m-d H:i:s', // @call isSameUnit 'micro' => 'Y-m-d H:i:s.u', // @call isSameUnit 'microsecond' => 'Y-m-d H:i:s.u', ]; if (isset($units[$unit])) { return $this->isSameAs($units[$unit], $date); } if (isset($this->$unit)) { return $this->resolveCarbon($date)->$unit === $this->$unit; } if ($this->localStrictModeEnabled ?? static::isStrictModeEnabled()) { throw new BadComparisonUnitException($unit); } return false; } /** * Determines if the instance is in the current unit given. * * @example * ``` * Carbon::now()->isCurrentUnit('hour'); // true * Carbon::now()->subHours(2)->isCurrentUnit('hour'); // false * ``` * * @param string $unit The unit to test. * * @throws BadMethodCallException * * @return bool */ public function isCurrentUnit($unit) { return $this->{'isSame'.ucfirst($unit)}(); } /** * Checks if the passed in date is in the same quarter as the instance quarter (and year if needed). * * @example * ``` * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2019-03-01')); // true * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2019-04-01')); // false * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2018-03-01')); // false * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2018-03-01'), false); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|string|null $date The instance to compare with or null to use current day. * @param bool $ofSameYear Check if it is the same month in the same year. * * @return bool */ public function isSameQuarter($date = null, $ofSameYear = true) { $date = $this->resolveCarbon($date); return $this->quarter === $date->quarter && (!$ofSameYear || $this->isSameYear($date)); } /** * Checks if the passed in date is in the same month as the instance´s month. * * @example * ``` * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2019-01-01')); // true * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2019-02-01')); // false * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2018-01-01')); // false * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2018-01-01'), false); // true * ``` * * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date. * @param bool $ofSameYear Check if it is the same month in the same year. * * @return bool */ public function isSameMonth($date = null, $ofSameYear = true) { return $this->isSameAs($ofSameYear ? 'Y-m' : 'm', $date); } /** * Checks if this day is a specific day of the week. * * @example * ``` * Carbon::parse('2019-07-17')->isDayOfWeek(Carbon::WEDNESDAY); // true * Carbon::parse('2019-07-17')->isDayOfWeek(Carbon::FRIDAY); // false * Carbon::parse('2019-07-17')->isDayOfWeek('Wednesday'); // true * Carbon::parse('2019-07-17')->isDayOfWeek('Friday'); // false * ``` * * @param int $dayOfWeek * * @return bool */ public function isDayOfWeek($dayOfWeek) { if (\is_string($dayOfWeek) && \defined($constant = static::class.'::'.strtoupper($dayOfWeek))) { $dayOfWeek = \constant($constant); } return $this->dayOfWeek === $dayOfWeek; } /** * Check if its the birthday. Compares the date/month values of the two dates. * * @example * ``` * Carbon::now()->subYears(5)->isBirthday(); // true * Carbon::now()->subYears(5)->subDay()->isBirthday(); // false * Carbon::parse('2019-06-05')->isBirthday(Carbon::parse('2001-06-05')); // true * Carbon::parse('2019-06-05')->isBirthday(Carbon::parse('2001-06-06')); // false * ``` * * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day. * * @return bool */ public function isBirthday($date = null) { return $this->isSameAs('md', $date); } /** * Check if today is the last day of the Month * * @example * ``` * Carbon::parse('2019-02-28')->isLastOfMonth(); // true * Carbon::parse('2019-03-28')->isLastOfMonth(); // false * Carbon::parse('2019-03-30')->isLastOfMonth(); // false * Carbon::parse('2019-03-31')->isLastOfMonth(); // true * Carbon::parse('2019-04-30')->isLastOfMonth(); // true * ``` * * @return bool */ public function isLastOfMonth() { return $this->day === $this->daysInMonth; } /** * Check if the instance is start of day / midnight. * * @example * ``` * Carbon::parse('2019-02-28 00:00:00')->isStartOfDay(); // true * Carbon::parse('2019-02-28 00:00:00.999999')->isStartOfDay(); // true * Carbon::parse('2019-02-28 00:00:01')->isStartOfDay(); // false * Carbon::parse('2019-02-28 00:00:00.000000')->isStartOfDay(true); // true * Carbon::parse('2019-02-28 00:00:00.000012')->isStartOfDay(true); // false * ``` * * @param bool $checkMicroseconds check time at microseconds precision * * @return bool */ public function isStartOfDay($checkMicroseconds = false) { /* @var CarbonInterface $this */ return $checkMicroseconds ? $this->rawFormat('H:i:s.u') === '00:00:00.000000' : $this->rawFormat('H:i:s') === '00:00:00'; } /** * Check if the instance is end of day. * * @example * ``` * Carbon::parse('2019-02-28 23:59:59.999999')->isEndOfDay(); // true * Carbon::parse('2019-02-28 23:59:59.123456')->isEndOfDay(); // true * Carbon::parse('2019-02-28 23:59:59')->isEndOfDay(); // true * Carbon::parse('2019-02-28 23:59:58.999999')->isEndOfDay(); // false * Carbon::parse('2019-02-28 23:59:59.999999')->isEndOfDay(true); // true * Carbon::parse('2019-02-28 23:59:59.123456')->isEndOfDay(true); // false * Carbon::parse('2019-02-28 23:59:59')->isEndOfDay(true); // false * ``` * * @param bool $checkMicroseconds check time at microseconds precision * * @return bool */ public function isEndOfDay($checkMicroseconds = false) { /* @var CarbonInterface $this */ return $checkMicroseconds ? $this->rawFormat('H:i:s.u') === '23:59:59.999999' : $this->rawFormat('H:i:s') === '23:59:59'; } /** * Check if the instance is start of day / midnight. * * @example * ``` * Carbon::parse('2019-02-28 00:00:00')->isMidnight(); // true * Carbon::parse('2019-02-28 00:00:00.999999')->isMidnight(); // true * Carbon::parse('2019-02-28 00:00:01')->isMidnight(); // false * ``` * * @return bool */ public function isMidnight() { return $this->isStartOfDay(); } /** * Check if the instance is midday. * * @example * ``` * Carbon::parse('2019-02-28 11:59:59.999999')->isMidday(); // false * Carbon::parse('2019-02-28 12:00:00')->isMidday(); // true * Carbon::parse('2019-02-28 12:00:00.999999')->isMidday(); // true * Carbon::parse('2019-02-28 12:00:01')->isMidday(); // false * ``` * * @return bool */ public function isMidday() { /* @var CarbonInterface $this */ return $this->rawFormat('G:i:s') === static::$midDayAt.':00:00'; } /** * Checks if the (date)time string is in a given format. * * @example * ``` * Carbon::hasFormat('11:12:45', 'h:i:s'); // true * Carbon::hasFormat('13:12:45', 'h:i:s'); // false * ``` * * @param string $date * @param string $format * * @return bool */ public static function hasFormat($date, $format) { // createFromFormat() is known to handle edge cases silently. // E.g. "1975-5-1" (Y-n-j) will still be parsed correctly when "Y-m-d" is supplied as the format. // To ensure we're really testing against our desired format, perform an additional regex validation. return self::matchFormatPattern((string) $date, preg_quote((string) $format, '/'), static::$regexFormats); } /** * Checks if the (date)time string is in a given format. * * @example * ``` * Carbon::hasFormatWithModifiers('31/08/2015', 'd#m#Y'); // true * Carbon::hasFormatWithModifiers('31/08/2015', 'm#d#Y'); // false * ``` * * @param string $date * @param string $format * * @return bool */ public static function hasFormatWithModifiers($date, $format): bool { return self::matchFormatPattern((string) $date, (string) $format, array_merge(static::$regexFormats, static::$regexFormatModifiers)); } /** * Checks if the (date)time string is in a given format and valid to create a * new instance. * * @example * ``` * Carbon::canBeCreatedFromFormat('11:12:45', 'h:i:s'); // true * Carbon::canBeCreatedFromFormat('13:12:45', 'h:i:s'); // false * ``` * * @param string $date * @param string $format * * @return bool */ public static function canBeCreatedFromFormat($date, $format) { try { // Try to create a DateTime object. Throws an InvalidArgumentException if the provided time string // doesn't match the format in any way. if (!static::rawCreateFromFormat($format, $date)) { return false; } } catch (InvalidArgumentException $e) { return false; } return static::hasFormatWithModifiers($date, $format); } /** * Returns true if the current date matches the given string. * * @example * ``` * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2019')); // true * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2018')); // false * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2019-06')); // true * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('06-02')); // true * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2019-06-02')); // true * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('Sunday')); // true * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('June')); // true * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12:23')); // true * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12:23:45')); // true * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12:23:00')); // false * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12h')); // true * var_dump(Carbon::parse('2019-06-02 15:23:45')->is('3pm')); // true * var_dump(Carbon::parse('2019-06-02 15:23:45')->is('3am')); // false * ``` * * @param string $tester day name, month name, hour, date, etc. as string * * @return bool */ public function is(string $tester) { $tester = trim($tester); if (preg_match('/^\d+$/', $tester)) { return $this->year === (int) $tester; } if (preg_match('/^(?:Jan|January|Feb|February|Mar|March|Apr|April|May|Jun|June|Jul|July|Aug|August|Sep|September|Oct|October|Nov|November|Dec|December)$/i', $tester)) { return $this->isSameMonth(static::parse($tester), false); } if (preg_match('/^\d{3,}-\d{1,2}$/', $tester)) { return $this->isSameMonth(static::parse($tester)); } if (preg_match('/^\d{1,2}-\d{1,2}$/', $tester)) { return $this->isSameDay(static::parse($this->year.'-'.$tester)); } $modifier = preg_replace('/(\d)h$/i', '$1:00', $tester); /* @var CarbonInterface $max */ $median = static::parse('5555-06-15 12:30:30.555555')->modify($modifier); $current = $this->avoidMutation(); /* @var CarbonInterface $other */ $other = $this->avoidMutation()->modify($modifier); if ($current->eq($other)) { return true; } if (preg_match('/\d:\d{1,2}:\d{1,2}$/', $tester)) { return $current->startOfSecond()->eq($other); } if (preg_match('/\d:\d{1,2}$/', $tester)) { return $current->startOfMinute()->eq($other); } if (preg_match('/\d(?:h|am|pm)$/', $tester)) { return $current->startOfHour()->eq($other); } if (preg_match( '/^(?:january|february|march|april|may|june|july|august|september|october|november|december)(?:\s+\d+)?$/i', $tester )) { return $current->startOfMonth()->eq($other->startOfMonth()); } $units = [ 'month' => [1, 'year'], 'day' => [1, 'month'], 'hour' => [0, 'day'], 'minute' => [0, 'hour'], 'second' => [0, 'minute'], 'microsecond' => [0, 'second'], ]; foreach ($units as $unit => [$minimum, $startUnit]) { if ($minimum === $median->$unit) { $current = $current->startOf($startUnit); break; } } return $current->eq($other); } /** * Checks if the (date)time string is in a given format with * given list of pattern replacements. * * @example * ``` * Carbon::hasFormat('11:12:45', 'h:i:s'); // true * Carbon::hasFormat('13:12:45', 'h:i:s'); // false * ``` * * @param string $date * @param string $format * @param array $replacements * * @return bool */ private static function matchFormatPattern(string $date, string $format, array $replacements): bool { // Preg quote, but remove escaped backslashes since we'll deal with escaped characters in the format string. $regex = str_replace('\\\\', '\\', $format); // Replace not-escaped letters $regex = preg_replace_callback( '/(?<!\\\\)((?:\\\\{2})*)(['.implode('', array_keys($replacements)).'])/', function ($match) use ($replacements) { return $match[1].strtr($match[2], $replacements); }, $regex ); // Replace escaped letters by the letter itself $regex = preg_replace('/(?<!\\\\)((?:\\\\{2})*)\\\\(\w)/', '$1$2', $regex); // Escape not escaped slashes $regex = preg_replace('#(?<!\\\\)((?:\\\\{2})*)/#', '$1\\/', $regex); return (bool) @preg_match('/^'.$regex.'$/', $date); } /** * Returns true if the date was created using CarbonImmutable::startOfTime() * * @return bool */ public function isStartOfTime(): bool { return $this->startOfTime ?? false; } /** * Returns true if the date was created using CarbonImmutable::endOfTime() * * @return bool */ public function isEndOfTime(): bool { return $this->endOfTime ?? false; } private function discourageNull($value): void { if ($value === null) { @trigger_error("Since 2.61.0, it's deprecated to compare a date to null, meaning of such comparison is ambiguous and will no longer be possible in 3.0.0, you should explicitly pass 'now' or make an other check to eliminate null values.", \E_USER_DEPRECATED); } } private function discourageBoolean($value): void { if (\is_bool($value)) { @trigger_error("Since 2.61.0, it's deprecated to compare a date to true or false, meaning of such comparison is ambiguous and will no longer be possible in 3.0.0, you should explicitly pass 'now' or make an other check to eliminate boolean values.", \E_USER_DEPRECATED); } } } PK������<1Z 5;1r��r����Carbon/Traits/Localization.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; use Carbon\CarbonInterface; use Carbon\Exceptions\InvalidTypeException; use Carbon\Exceptions\NotLocaleAwareException; use Carbon\Language; use Carbon\Translator; use Carbon\TranslatorStrongTypeInterface; use Closure; use Symfony\Component\Translation\TranslatorBagInterface; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Contracts\Translation\LocaleAwareInterface; use Symfony\Contracts\Translation\TranslatorInterface as ContractsTranslatorInterface; // @codeCoverageIgnoreStart if (interface_exists('Symfony\\Contracts\\Translation\\TranslatorInterface') && !interface_exists('Symfony\\Component\\Translation\\TranslatorInterface') ) { class_alias( 'Symfony\\Contracts\\Translation\\TranslatorInterface', 'Symfony\\Component\\Translation\\TranslatorInterface' ); } // @codeCoverageIgnoreEnd /** * Trait Localization. * * Embed default and locale translators and translation base methods. */ trait Localization { /** * Default translator. * * @var \Symfony\Component\Translation\TranslatorInterface */ protected static $translator; /** * Specific translator of the current instance. * * @var \Symfony\Component\Translation\TranslatorInterface */ protected $localTranslator; /** * Options for diffForHumans(). * * @var int */ protected static $humanDiffOptions = CarbonInterface::NO_ZERO_DIFF; /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * @see settings * * @param int $humanDiffOptions */ public static function setHumanDiffOptions($humanDiffOptions) { static::$humanDiffOptions = $humanDiffOptions; } /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * @see settings * * @param int $humanDiffOption */ public static function enableHumanDiffOption($humanDiffOption) { static::$humanDiffOptions = static::getHumanDiffOptions() | $humanDiffOption; } /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather use the ->settings() method. * @see settings * * @param int $humanDiffOption */ public static function disableHumanDiffOption($humanDiffOption) { static::$humanDiffOptions = static::getHumanDiffOptions() & ~$humanDiffOption; } /** * Return default humanDiff() options (merged flags as integer). * * @return int */ public static function getHumanDiffOptions() { return static::$humanDiffOptions; } /** * Get the default translator instance in use. * * @return \Symfony\Component\Translation\TranslatorInterface */ public static function getTranslator() { return static::translator(); } /** * Set the default translator instance to use. * * @param \Symfony\Component\Translation\TranslatorInterface $translator * * @return void */ public static function setTranslator(TranslatorInterface $translator) { static::$translator = $translator; } /** * Return true if the current instance has its own translator. * * @return bool */ public function hasLocalTranslator() { return isset($this->localTranslator); } /** * Get the translator of the current instance or the default if none set. * * @return \Symfony\Component\Translation\TranslatorInterface */ public function getLocalTranslator() { return $this->localTranslator ?: static::translator(); } /** * Set the translator for the current instance. * * @param \Symfony\Component\Translation\TranslatorInterface $translator * * @return $this */ public function setLocalTranslator(TranslatorInterface $translator) { $this->localTranslator = $translator; return $this; } /** * Returns raw translation message for a given key. * * @param \Symfony\Component\Translation\TranslatorInterface $translator the translator to use * @param string $key key to find * @param string|null $locale current locale used if null * @param string|null $default default value if translation returns the key * * @return string */ public static function getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null) { if (!($translator instanceof TranslatorBagInterface && $translator instanceof TranslatorInterface)) { throw new InvalidTypeException( 'Translator does not implement '.TranslatorInterface::class.' and '.TranslatorBagInterface::class.'. '. (\is_object($translator) ? \get_class($translator) : \gettype($translator)).' has been given.' ); } if (!$locale && $translator instanceof LocaleAwareInterface) { $locale = $translator->getLocale(); } $result = self::getFromCatalogue($translator, $translator->getCatalogue($locale), $key); return $result === $key ? $default : $result; } /** * Returns raw translation message for a given key. * * @param string $key key to find * @param string|null $locale current locale used if null * @param string|null $default default value if translation returns the key * @param \Symfony\Component\Translation\TranslatorInterface $translator an optional translator to use * * @return string */ public function getTranslationMessage(string $key, ?string $locale = null, ?string $default = null, $translator = null) { return static::getTranslationMessageWith($translator ?: $this->getLocalTranslator(), $key, $locale, $default); } /** * Translate using translation string or callback available. * * @param \Symfony\Component\Translation\TranslatorInterface $translator * @param string $key * @param array $parameters * @param null $number * * @return string */ public static function translateWith(TranslatorInterface $translator, string $key, array $parameters = [], $number = null): string { $message = static::getTranslationMessageWith($translator, $key, null, $key); if ($message instanceof Closure) { return (string) $message(...array_values($parameters)); } if ($number !== null) { $parameters['%count%'] = $number; } if (isset($parameters['%count%'])) { $parameters[':count'] = $parameters['%count%']; } // @codeCoverageIgnoreStart $choice = $translator instanceof ContractsTranslatorInterface ? $translator->trans($key, $parameters) : $translator->transChoice($key, $number, $parameters); // @codeCoverageIgnoreEnd return (string) $choice; } /** * Translate using translation string or callback available. * * @param string $key * @param array $parameters * @param string|int|float|null $number * @param \Symfony\Component\Translation\TranslatorInterface|null $translator * @param bool $altNumbers * * @return string */ public function translate(string $key, array $parameters = [], $number = null, ?TranslatorInterface $translator = null, bool $altNumbers = false): string { $translation = static::translateWith($translator ?: $this->getLocalTranslator(), $key, $parameters, $number); if ($number !== null && $altNumbers) { return str_replace($number, $this->translateNumber($number), $translation); } return $translation; } /** * Returns the alternative number for a given integer if available in the current locale. * * @param int $number * * @return string */ public function translateNumber(int $number): string { $translateKey = "alt_numbers.$number"; $symbol = $this->translate($translateKey); if ($symbol !== $translateKey) { return $symbol; } if ($number > 99 && $this->translate('alt_numbers.99') !== 'alt_numbers.99') { $start = ''; foreach ([10000, 1000, 100] as $exp) { $key = "alt_numbers_pow.$exp"; if ($number >= $exp && $number < $exp * 10 && ($pow = $this->translate($key)) !== $key) { $unit = floor($number / $exp); $number -= $unit * $exp; $start .= ($unit > 1 ? $this->translate("alt_numbers.$unit") : '').$pow; } } $result = ''; while ($number) { $chunk = $number % 100; $result = $this->translate("alt_numbers.$chunk").$result; $number = floor($number / 100); } return "$start$result"; } if ($number > 9 && $this->translate('alt_numbers.9') !== 'alt_numbers.9') { $result = ''; while ($number) { $chunk = $number % 10; $result = $this->translate("alt_numbers.$chunk").$result; $number = floor($number / 10); } return $result; } return (string) $number; } /** * Translate a time string from a locale to an other. * * @param string $timeString date/time/duration string to translate (may also contain English) * @param string|null $from input locale of the $timeString parameter (`Carbon::getLocale()` by default) * @param string|null $to output locale of the result returned (`"en"` by default) * @param int $mode specify what to translate with options: * - CarbonInterface::TRANSLATE_ALL (default) * - CarbonInterface::TRANSLATE_MONTHS * - CarbonInterface::TRANSLATE_DAYS * - CarbonInterface::TRANSLATE_UNITS * - CarbonInterface::TRANSLATE_MERIDIEM * You can use pipe to group: CarbonInterface::TRANSLATE_MONTHS | CarbonInterface::TRANSLATE_DAYS * * @return string */ public static function translateTimeString($timeString, $from = null, $to = null, $mode = CarbonInterface::TRANSLATE_ALL) { // Fallback source and destination locales $from = $from ?: static::getLocale(); $to = $to ?: 'en'; if ($from === $to) { return $timeString; } // Standardize apostrophe $timeString = strtr($timeString, ['’' => "'"]); $fromTranslations = []; $toTranslations = []; foreach (['from', 'to'] as $key) { $language = $$key; $translator = Translator::get($language); $translations = $translator->getMessages(); if (!isset($translations[$language])) { return $timeString; } $translationKey = $key.'Translations'; $messages = $translations[$language]; $months = $messages['months'] ?? []; $weekdays = $messages['weekdays'] ?? []; $meridiem = $messages['meridiem'] ?? ['AM', 'PM']; if (isset($messages['ordinal_words'])) { $timeString = self::replaceOrdinalWords( $timeString, $key === 'from' ? array_flip($messages['ordinal_words']) : $messages['ordinal_words'] ); } if ($key === 'from') { foreach (['months', 'weekdays'] as $variable) { $list = $messages[$variable.'_standalone'] ?? null; if ($list) { foreach ($$variable as $index => &$name) { $name .= '|'.$messages[$variable.'_standalone'][$index]; } } } } $$translationKey = array_merge( $mode & CarbonInterface::TRANSLATE_MONTHS ? static::getTranslationArray($months, 12, $timeString) : [], $mode & CarbonInterface::TRANSLATE_MONTHS ? static::getTranslationArray($messages['months_short'] ?? [], 12, $timeString) : [], $mode & CarbonInterface::TRANSLATE_DAYS ? static::getTranslationArray($weekdays, 7, $timeString) : [], $mode & CarbonInterface::TRANSLATE_DAYS ? static::getTranslationArray($messages['weekdays_short'] ?? [], 7, $timeString) : [], $mode & CarbonInterface::TRANSLATE_DIFF ? static::translateWordsByKeys([ 'diff_now', 'diff_today', 'diff_yesterday', 'diff_tomorrow', 'diff_before_yesterday', 'diff_after_tomorrow', ], $messages, $key) : [], $mode & CarbonInterface::TRANSLATE_UNITS ? static::translateWordsByKeys([ 'year', 'month', 'week', 'day', 'hour', 'minute', 'second', ], $messages, $key) : [], $mode & CarbonInterface::TRANSLATE_MERIDIEM ? array_map(function ($hour) use ($meridiem) { if (\is_array($meridiem)) { return $meridiem[$hour < 12 ? 0 : 1]; } return $meridiem($hour, 0, false); }, range(0, 23)) : [] ); } return substr(preg_replace_callback('/(?<=[\d\s+.\/,_-])('.implode('|', $fromTranslations).')(?=[\d\s+.\/,_-])/iu', function ($match) use ($fromTranslations, $toTranslations) { [$chunk] = $match; foreach ($fromTranslations as $index => $word) { if (preg_match("/^$word\$/iu", $chunk)) { return $toTranslations[$index] ?? ''; } } return $chunk; // @codeCoverageIgnore }, " $timeString "), 1, -1); } /** * Translate a time string from the current locale (`$date->locale()`) to an other. * * @param string $timeString time string to translate * @param string|null $to output locale of the result returned ("en" by default) * * @return string */ public function translateTimeStringTo($timeString, $to = null) { return static::translateTimeString($timeString, $this->getTranslatorLocale(), $to); } /** * Get/set the locale for the current instance. * * @param string|null $locale * @param string ...$fallbackLocales * * @return $this|string */ public function locale(?string $locale = null, ...$fallbackLocales) { if ($locale === null) { return $this->getTranslatorLocale(); } if (!$this->localTranslator || $this->getTranslatorLocale($this->localTranslator) !== $locale) { $translator = Translator::get($locale); if (!empty($fallbackLocales)) { $translator->setFallbackLocales($fallbackLocales); foreach ($fallbackLocales as $fallbackLocale) { $messages = Translator::get($fallbackLocale)->getMessages(); if (isset($messages[$fallbackLocale])) { $translator->setMessages($fallbackLocale, $messages[$fallbackLocale]); } } } $this->localTranslator = $translator; } return $this; } /** * Get the current translator locale. * * @return string */ public static function getLocale() { return static::getLocaleAwareTranslator()->getLocale(); } /** * Set the current translator locale and indicate if the source locale file exists. * Pass 'auto' as locale to use closest language from the current LC_TIME locale. * * @param string $locale locale ex. en * * @return bool */ public static function setLocale($locale) { return static::getLocaleAwareTranslator()->setLocale($locale) !== false; } /** * Set the fallback locale. * * @see https://symfony.com/doc/current/components/translation.html#fallback-locales * * @param string $locale */ public static function setFallbackLocale($locale) { $translator = static::getTranslator(); if (method_exists($translator, 'setFallbackLocales')) { $translator->setFallbackLocales([$locale]); if ($translator instanceof Translator) { $preferredLocale = $translator->getLocale(); $translator->setMessages($preferredLocale, array_replace_recursive( $translator->getMessages()[$locale] ?? [], Translator::get($locale)->getMessages()[$locale] ?? [], $translator->getMessages($preferredLocale) )); } } } /** * Get the fallback locale. * * @see https://symfony.com/doc/current/components/translation.html#fallback-locales * * @return string|null */ public static function getFallbackLocale() { $translator = static::getTranslator(); if (method_exists($translator, 'getFallbackLocales')) { return $translator->getFallbackLocales()[0] ?? null; } return null; } /** * Set the current locale to the given, execute the passed function, reset the locale to previous one, * then return the result of the closure (or null if the closure was void). * * @param string $locale locale ex. en * @param callable $func * * @return mixed */ public static function executeWithLocale($locale, $func) { $currentLocale = static::getLocale(); $result = $func(static::setLocale($locale) ? static::getLocale() : false, static::translator()); static::setLocale($currentLocale); return $result; } /** * Returns true if the given locale is internally supported and has short-units support. * Support is considered enabled if either year, day or hour has a short variant translated. * * @param string $locale locale ex. en * * @return bool */ public static function localeHasShortUnits($locale) { return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) { return ($newLocale && (($y = static::translateWith($translator, 'y')) !== 'y' && $y !== static::translateWith($translator, 'year'))) || ( ($y = static::translateWith($translator, 'd')) !== 'd' && $y !== static::translateWith($translator, 'day') ) || ( ($y = static::translateWith($translator, 'h')) !== 'h' && $y !== static::translateWith($translator, 'hour') ); }); } /** * Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after). * Support is considered enabled if the 4 sentences are translated in the given locale. * * @param string $locale locale ex. en * * @return bool */ public static function localeHasDiffSyntax($locale) { return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) { if (!$newLocale) { return false; } foreach (['ago', 'from_now', 'before', 'after'] as $key) { if ($translator instanceof TranslatorBagInterface && self::getFromCatalogue($translator, $translator->getCatalogue($newLocale), $key) instanceof Closure ) { continue; } if ($translator->trans($key) === $key) { return false; } } return true; }); } /** * Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow). * Support is considered enabled if the 3 words are translated in the given locale. * * @param string $locale locale ex. en * * @return bool */ public static function localeHasDiffOneDayWords($locale) { return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) { return $newLocale && $translator->trans('diff_now') !== 'diff_now' && $translator->trans('diff_yesterday') !== 'diff_yesterday' && $translator->trans('diff_tomorrow') !== 'diff_tomorrow'; }); } /** * Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow). * Support is considered enabled if the 2 words are translated in the given locale. * * @param string $locale locale ex. en * * @return bool */ public static function localeHasDiffTwoDayWords($locale) { return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) { return $newLocale && $translator->trans('diff_before_yesterday') !== 'diff_before_yesterday' && $translator->trans('diff_after_tomorrow') !== 'diff_after_tomorrow'; }); } /** * Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X). * Support is considered enabled if the 4 sentences are translated in the given locale. * * @param string $locale locale ex. en * * @return bool */ public static function localeHasPeriodSyntax($locale) { return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) { return $newLocale && $translator->trans('period_recurrences') !== 'period_recurrences' && $translator->trans('period_interval') !== 'period_interval' && $translator->trans('period_start_date') !== 'period_start_date' && $translator->trans('period_end_date') !== 'period_end_date'; }); } /** * Returns the list of internally available locales and already loaded custom locales. * (It will ignore custom translator dynamic loading.) * * @return array */ public static function getAvailableLocales() { $translator = static::getLocaleAwareTranslator(); return $translator instanceof Translator ? $translator->getAvailableLocales() : [$translator->getLocale()]; } /** * Returns list of Language object for each available locale. This object allow you to get the ISO name, native * name, region and variant of the locale. * * @return Language[] */ public static function getAvailableLocalesInfo() { $languages = []; foreach (static::getAvailableLocales() as $id) { $languages[$id] = new Language($id); } return $languages; } /** * Initialize the default translator instance if necessary. * * @return \Symfony\Component\Translation\TranslatorInterface */ protected static function translator() { if (static::$translator === null) { static::$translator = Translator::get(); } return static::$translator; } /** * Get the locale of a given translator. * * If null or omitted, current local translator is used. * If no local translator is in use, current global translator is used. * * @param null $translator * * @return string|null */ protected function getTranslatorLocale($translator = null): ?string { if (\func_num_args() === 0) { $translator = $this->getLocalTranslator(); } $translator = static::getLocaleAwareTranslator($translator); return $translator ? $translator->getLocale() : null; } /** * Throw an error if passed object is not LocaleAwareInterface. * * @param LocaleAwareInterface|null $translator * * @return LocaleAwareInterface|null */ protected static function getLocaleAwareTranslator($translator = null) { if (\func_num_args() === 0) { $translator = static::translator(); } if ($translator && !($translator instanceof LocaleAwareInterface || method_exists($translator, 'getLocale'))) { throw new NotLocaleAwareException($translator); // @codeCoverageIgnore } return $translator; } /** * @param mixed $translator * @param \Symfony\Component\Translation\MessageCatalogueInterface $catalogue * * @return mixed */ private static function getFromCatalogue($translator, $catalogue, string $id, string $domain = 'messages') { return $translator instanceof TranslatorStrongTypeInterface ? $translator->getFromCatalogue($catalogue, $id, $domain) // @codeCoverageIgnore : $catalogue->get($id, $domain); } /** * Return the word cleaned from its translation codes. * * @param string $word * * @return string */ private static function cleanWordFromTranslationString($word) { $word = str_replace([':count', '%count', ':time'], '', $word); $word = strtr($word, ['’' => "'"]); $word = preg_replace('/({\d+(,(\d+|Inf))?}|[\[\]]\d+(,(\d+|Inf))?[\[\]])/', '', $word); return trim($word); } /** * Translate a list of words. * * @param string[] $keys keys to translate. * @param string[] $messages messages bag handling translations. * @param string $key 'to' (to get the translation) or 'from' (to get the detection RegExp pattern). * * @return string[] */ private static function translateWordsByKeys($keys, $messages, $key): array { return array_map(function ($wordKey) use ($messages, $key) { $message = $key === 'from' && isset($messages[$wordKey.'_regexp']) ? $messages[$wordKey.'_regexp'] : ($messages[$wordKey] ?? null); if (!$message) { return '>>DO NOT REPLACE<<'; } $parts = explode('|', $message); return $key === 'to' ? self::cleanWordFromTranslationString(end($parts)) : '(?:'.implode('|', array_map([static::class, 'cleanWordFromTranslationString'], $parts)).')'; }, $keys); } /** * Get an array of translations based on the current date. * * @param callable $translation * @param int $length * @param string $timeString * * @return string[] */ private static function getTranslationArray($translation, $length, $timeString): array { $filler = '>>DO NOT REPLACE<<'; if (\is_array($translation)) { return array_pad($translation, $length, $filler); } $list = []; $date = static::now(); for ($i = 0; $i < $length; $i++) { $list[] = $translation($date, $timeString, $i) ?? $filler; } return $list; } private static function replaceOrdinalWords(string $timeString, array $ordinalWords): string { return preg_replace_callback('/(?<![a-z])[a-z]+(?![a-z])/i', function (array $match) use ($ordinalWords) { return $ordinalWords[mb_strtolower($match[0])] ?? $match[0]; }, $timeString); } } PK������<1Z * ��* ����Carbon/Traits/IntervalStep.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; use Carbon\Carbon; use Carbon\CarbonImmutable; use Carbon\CarbonInterface; use Closure; use DateTimeImmutable; use DateTimeInterface; trait IntervalStep { /** * Step to apply instead of a fixed interval to get the new date. * * @var Closure|null */ protected $step; /** * Get the dynamic step in use. * * @return Closure */ public function getStep(): ?Closure { return $this->step; } /** * Set a step to apply instead of a fixed interval to get the new date. * * Or pass null to switch to fixed interval. * * @param Closure|null $step */ public function setStep(?Closure $step): void { $this->step = $step; } /** * Take a date and apply either the step if set, or the current interval else. * * The interval/step is applied negatively (typically subtraction instead of addition) if $negated is true. * * @param DateTimeInterface $dateTime * @param bool $negated * * @return CarbonInterface */ public function convertDate(DateTimeInterface $dateTime, bool $negated = false): CarbonInterface { /** @var CarbonInterface $carbonDate */ $carbonDate = $dateTime instanceof CarbonInterface ? $dateTime : $this->resolveCarbon($dateTime); if ($this->step) { return $carbonDate->setDateTimeFrom(($this->step)($carbonDate->avoidMutation(), $negated)); } if ($negated) { return $carbonDate->rawSub($this); } return $carbonDate->rawAdd($this); } /** * Convert DateTimeImmutable instance to CarbonImmutable instance and DateTime instance to Carbon instance. * * @param DateTimeInterface $dateTime * * @return Carbon|CarbonImmutable */ private function resolveCarbon(DateTimeInterface $dateTime) { if ($dateTime instanceof DateTimeImmutable) { return CarbonImmutable::instance($dateTime); } return Carbon::instance($dateTime); } } PK������<1ZLd3��3��"��Carbon/Traits/IntervalRounding.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; use Carbon\CarbonInterval; use Carbon\Exceptions\InvalidIntervalException; use DateInterval; /** * Trait to call rounding methods to interval or the interval of a period. */ trait IntervalRounding { protected function callRoundMethod(string $method, array $parameters) { $action = substr($method, 0, 4); if ($action !== 'ceil') { $action = substr($method, 0, 5); } if (\in_array($action, ['round', 'floor', 'ceil'])) { return $this->{$action.'Unit'}(substr($method, \strlen($action)), ...$parameters); } return null; } protected function roundWith($precision, $function) { $unit = 'second'; if ($precision instanceof DateInterval) { $precision = (string) CarbonInterval::instance($precision, [], true); } if (\is_string($precision) && preg_match('/^\s*(?<precision>\d+)?\s*(?<unit>\w+)(?<other>\W.*)?$/', $precision, $match)) { if (trim($match['other'] ?? '') !== '') { throw new InvalidIntervalException('Rounding is only possible with single unit intervals.'); } $precision = (int) ($match['precision'] ?: 1); $unit = $match['unit']; } return $this->roundUnit($unit, $precision, $function); } } PK������<1Zy@��@����Carbon/Traits/Difference.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; use Carbon\Carbon; use Carbon\CarbonImmutable; use Carbon\CarbonInterface; use Carbon\CarbonInterval; use Carbon\CarbonPeriod; use Carbon\Translator; use Closure; use DateInterval; use DateTimeInterface; use ReturnTypeWillChange; /** * Trait Difference. * * Depends on the following methods: * * @method bool lessThan($date) * @method static copy() * @method static resolveCarbon($date = null) * @method static Translator translator() */ trait Difference { /** * @codeCoverageIgnore * * @param CarbonInterval $diff */ protected static function fixNegativeMicroseconds(CarbonInterval $diff) { if ($diff->s !== 0 || $diff->i !== 0 || $diff->h !== 0 || $diff->d !== 0 || $diff->m !== 0 || $diff->y !== 0) { $diff->f = (round($diff->f * 1000000) + 1000000) / 1000000; $diff->s--; if ($diff->s < 0) { $diff->s += 60; $diff->i--; if ($diff->i < 0) { $diff->i += 60; $diff->h--; if ($diff->h < 0) { $diff->h += 24; $diff->d--; if ($diff->d < 0) { $diff->d += 30; $diff->m--; if ($diff->m < 0) { $diff->m += 12; $diff->y--; } } } } } return; } $diff->f *= -1; $diff->invert(); } /** * @param DateInterval $diff * @param bool $absolute * * @return CarbonInterval */ protected static function fixDiffInterval(DateInterval $diff, $absolute, array $skip = []) { $diff = CarbonInterval::instance($diff, $skip); // Work-around for https://bugs.php.net/bug.php?id=77145 // @codeCoverageIgnoreStart if ($diff->f > 0 && $diff->y === -1 && $diff->m === 11 && $diff->d >= 27 && $diff->h === 23 && $diff->i === 59 && $diff->s === 59) { $diff->y = 0; $diff->m = 0; $diff->d = 0; $diff->h = 0; $diff->i = 0; $diff->s = 0; $diff->f = (1000000 - round($diff->f * 1000000)) / 1000000; $diff->invert(); } elseif ($diff->f < 0) { static::fixNegativeMicroseconds($diff); } // @codeCoverageIgnoreEnd if ($absolute && $diff->invert) { $diff->invert(); } return $diff; } /** * Get the difference as a DateInterval instance. * Return relative interval (negative if $absolute flag is not set to true and the given date is before * current one). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return DateInterval */ #[ReturnTypeWillChange] public function diff($date = null, $absolute = false) { $other = $this->resolveCarbon($date); // Work-around for https://bugs.php.net/bug.php?id=81458 // It was initially introduced for https://bugs.php.net/bug.php?id=80998 // The very specific case of 80998 was fixed in PHP 8.1beta3, but it introduced 81458 // So we still need to keep this for now // @codeCoverageIgnoreStart if (version_compare(PHP_VERSION, '8.1.0-dev', '>=') && $other->tz !== $this->tz) { $other = $other->avoidMutation()->tz($this->tz); } // @codeCoverageIgnoreEnd return parent::diff($other, (bool) $absolute); } /** * Get the difference as a CarbonInterval instance. * Return relative interval (negative if $absolute flag is not set to true and the given date is before * current one). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return CarbonInterval */ public function diffAsCarbonInterval($date = null, $absolute = true, array $skip = []) { return static::fixDiffInterval($this->diff($this->resolveCarbon($date), $absolute), $absolute, $skip); } /** * Get the difference in years * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInYears($date = null, $absolute = true) { return (int) $this->diff($this->resolveCarbon($date), $absolute)->format('%r%y'); } /** * Get the difference in quarters rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInQuarters($date = null, $absolute = true) { return (int) ($this->diffInMonths($date, $absolute) / static::MONTHS_PER_QUARTER); } /** * Get the difference in months rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInMonths($date = null, $absolute = true) { $date = $this->resolveCarbon($date)->avoidMutation()->tz($this->tz); [$yearStart, $monthStart, $dayStart] = explode('-', $this->format('Y-m-dHisu')); [$yearEnd, $monthEnd, $dayEnd] = explode('-', $date->format('Y-m-dHisu')); $diff = (((int) $yearEnd) - ((int) $yearStart)) * static::MONTHS_PER_YEAR + ((int) $monthEnd) - ((int) $monthStart); if ($diff > 0) { $diff -= ($dayStart > $dayEnd ? 1 : 0); } elseif ($diff < 0) { $diff += ($dayStart < $dayEnd ? 1 : 0); } return $absolute ? abs($diff) : $diff; } /** * Get the difference in weeks rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInWeeks($date = null, $absolute = true) { return (int) ($this->diffInDays($date, $absolute) / static::DAYS_PER_WEEK); } /** * Get the difference in days rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInDays($date = null, $absolute = true) { return $this->getIntervalDayDiff($this->diff($this->resolveCarbon($date), $absolute)); } /** * Get the difference in days using a filter closure rounded down. * * @param Closure $callback * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInDaysFiltered(Closure $callback, $date = null, $absolute = true) { return $this->diffFiltered(CarbonInterval::day(), $callback, $date, $absolute); } /** * Get the difference in hours using a filter closure rounded down. * * @param Closure $callback * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInHoursFiltered(Closure $callback, $date = null, $absolute = true) { return $this->diffFiltered(CarbonInterval::hour(), $callback, $date, $absolute); } /** * Get the difference by the given interval using a filter closure. * * @param CarbonInterval $ci An interval to traverse by * @param Closure $callback * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffFiltered(CarbonInterval $ci, Closure $callback, $date = null, $absolute = true) { $start = $this; $end = $this->resolveCarbon($date); $inverse = false; if ($end < $start) { $start = $end; $end = $this; $inverse = true; } $options = CarbonPeriod::EXCLUDE_END_DATE | ($this->isMutable() ? 0 : CarbonPeriod::IMMUTABLE); $diff = $ci->toPeriod($start, $end, $options)->filter($callback)->count(); return $inverse && !$absolute ? -$diff : $diff; } /** * Get the difference in weekdays rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInWeekdays($date = null, $absolute = true) { return $this->diffInDaysFiltered(static function (CarbonInterface $date) { return $date->isWeekday(); }, $this->resolveCarbon($date)->avoidMutation()->modify($this->format('H:i:s.u')), $absolute); } /** * Get the difference in weekend days using a filter rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInWeekendDays($date = null, $absolute = true) { return $this->diffInDaysFiltered(static function (CarbonInterface $date) { return $date->isWeekend(); }, $this->resolveCarbon($date)->avoidMutation()->modify($this->format('H:i:s.u')), $absolute); } /** * Get the difference in hours rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInHours($date = null, $absolute = true) { return (int) ($this->diffInSeconds($date, $absolute) / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR); } /** * Get the difference in hours rounded down using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInRealHours($date = null, $absolute = true) { return (int) ($this->diffInRealSeconds($date, $absolute) / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR); } /** * Get the difference in minutes rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInMinutes($date = null, $absolute = true) { return (int) ($this->diffInSeconds($date, $absolute) / static::SECONDS_PER_MINUTE); } /** * Get the difference in minutes rounded down using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInRealMinutes($date = null, $absolute = true) { return (int) ($this->diffInRealSeconds($date, $absolute) / static::SECONDS_PER_MINUTE); } /** * Get the difference in seconds rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInSeconds($date = null, $absolute = true) { $diff = $this->diff($date); if ($diff->days === 0) { $diff = static::fixDiffInterval($diff, $absolute); } $value = (((($diff->m || $diff->y ? $diff->days : $diff->d) * static::HOURS_PER_DAY) + $diff->h) * static::MINUTES_PER_HOUR + $diff->i) * static::SECONDS_PER_MINUTE + $diff->s; return $absolute || !$diff->invert ? $value : -$value; } /** * Get the difference in microseconds. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInMicroseconds($date = null, $absolute = true) { $diff = $this->diff($date); $value = (int) round(((((($diff->m || $diff->y ? $diff->days : $diff->d) * static::HOURS_PER_DAY) + $diff->h) * static::MINUTES_PER_HOUR + $diff->i) * static::SECONDS_PER_MINUTE + ($diff->f + $diff->s)) * static::MICROSECONDS_PER_SECOND); return $absolute || !$diff->invert ? $value : -$value; } /** * Get the difference in milliseconds rounded down. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInMilliseconds($date = null, $absolute = true) { return (int) ($this->diffInMicroseconds($date, $absolute) / static::MICROSECONDS_PER_MILLISECOND); } /** * Get the difference in seconds using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInRealSeconds($date = null, $absolute = true) { /** @var CarbonInterface $date */ $date = $this->resolveCarbon($date); $value = $date->getTimestamp() - $this->getTimestamp(); return $absolute ? abs($value) : $value; } /** * Get the difference in microseconds using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInRealMicroseconds($date = null, $absolute = true) { /** @var CarbonInterface $date */ $date = $this->resolveCarbon($date); $value = ($date->timestamp - $this->timestamp) * static::MICROSECONDS_PER_SECOND + $date->micro - $this->micro; return $absolute ? abs($value) : $value; } /** * Get the difference in milliseconds rounded down using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return int */ public function diffInRealMilliseconds($date = null, $absolute = true) { return (int) ($this->diffInRealMicroseconds($date, $absolute) / static::MICROSECONDS_PER_MILLISECOND); } /** * Get the difference in seconds as float (microsecond-precision). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInSeconds($date = null, $absolute = true) { return (float) ($this->diffInMicroseconds($date, $absolute) / static::MICROSECONDS_PER_SECOND); } /** * Get the difference in minutes as float (microsecond-precision). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInMinutes($date = null, $absolute = true) { return $this->floatDiffInSeconds($date, $absolute) / static::SECONDS_PER_MINUTE; } /** * Get the difference in hours as float (microsecond-precision). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInHours($date = null, $absolute = true) { return $this->floatDiffInMinutes($date, $absolute) / static::MINUTES_PER_HOUR; } /** * Get the difference in days as float (microsecond-precision). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInDays($date = null, $absolute = true) { $hoursDiff = $this->floatDiffInHours($date, $absolute); $interval = $this->diff($date, $absolute); if ($interval->y === 0 && $interval->m === 0 && $interval->d === 0) { return $hoursDiff / static::HOURS_PER_DAY; } $daysDiff = $this->getIntervalDayDiff($interval); return $daysDiff + fmod($hoursDiff, static::HOURS_PER_DAY) / static::HOURS_PER_DAY; } /** * Get the difference in weeks as float (microsecond-precision). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInWeeks($date = null, $absolute = true) { return $this->floatDiffInDays($date, $absolute) / static::DAYS_PER_WEEK; } /** * Get the difference in months as float (microsecond-precision). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInMonths($date = null, $absolute = true) { $start = $this; $end = $this->resolveCarbon($date); $ascending = ($start <= $end); $sign = $absolute || $ascending ? 1 : -1; if (!$ascending) { [$start, $end] = [$end, $start]; } $monthsDiff = $start->diffInMonths($end); /** @var Carbon|CarbonImmutable $floorEnd */ $floorEnd = $start->avoidMutation()->addMonths($monthsDiff); if ($floorEnd >= $end) { return $sign * $monthsDiff; } /** @var Carbon|CarbonImmutable $startOfMonthAfterFloorEnd */ $startOfMonthAfterFloorEnd = $floorEnd->avoidMutation()->addMonth()->startOfMonth(); if ($startOfMonthAfterFloorEnd > $end) { return $sign * ($monthsDiff + $floorEnd->floatDiffInDays($end) / $floorEnd->daysInMonth); } return $sign * ($monthsDiff + $floorEnd->floatDiffInDays($startOfMonthAfterFloorEnd) / $floorEnd->daysInMonth + $startOfMonthAfterFloorEnd->floatDiffInDays($end) / $end->daysInMonth); } /** * Get the difference in year as float (microsecond-precision). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInYears($date = null, $absolute = true) { $start = $this; $end = $this->resolveCarbon($date); $ascending = ($start <= $end); $sign = $absolute || $ascending ? 1 : -1; if (!$ascending) { [$start, $end] = [$end, $start]; } $yearsDiff = $start->diffInYears($end); /** @var Carbon|CarbonImmutable $floorEnd */ $floorEnd = $start->avoidMutation()->addYears($yearsDiff); if ($floorEnd >= $end) { return $sign * $yearsDiff; } /** @var Carbon|CarbonImmutable $startOfYearAfterFloorEnd */ $startOfYearAfterFloorEnd = $floorEnd->avoidMutation()->addYear()->startOfYear(); if ($startOfYearAfterFloorEnd > $end) { return $sign * ($yearsDiff + $floorEnd->floatDiffInDays($end) / $floorEnd->daysInYear); } return $sign * ($yearsDiff + $floorEnd->floatDiffInDays($startOfYearAfterFloorEnd) / $floorEnd->daysInYear + $startOfYearAfterFloorEnd->floatDiffInDays($end) / $end->daysInYear); } /** * Get the difference in seconds as float (microsecond-precision) using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInRealSeconds($date = null, $absolute = true) { return $this->diffInRealMicroseconds($date, $absolute) / static::MICROSECONDS_PER_SECOND; } /** * Get the difference in minutes as float (microsecond-precision) using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInRealMinutes($date = null, $absolute = true) { return $this->floatDiffInRealSeconds($date, $absolute) / static::SECONDS_PER_MINUTE; } /** * Get the difference in hours as float (microsecond-precision) using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInRealHours($date = null, $absolute = true) { return $this->floatDiffInRealMinutes($date, $absolute) / static::MINUTES_PER_HOUR; } /** * Get the difference in days as float (microsecond-precision). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInRealDays($date = null, $absolute = true) { $date = $this->resolveUTC($date); $utc = $this->avoidMutation()->utc(); $hoursDiff = $utc->floatDiffInRealHours($date, $absolute); return ($hoursDiff < 0 ? -1 : 1) * $utc->diffInDays($date) + fmod($hoursDiff, static::HOURS_PER_DAY) / static::HOURS_PER_DAY; } /** * Get the difference in weeks as float (microsecond-precision). * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInRealWeeks($date = null, $absolute = true) { return $this->floatDiffInRealDays($date, $absolute) / static::DAYS_PER_WEEK; } /** * Get the difference in months as float (microsecond-precision) using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInRealMonths($date = null, $absolute = true) { $start = $this; $end = $this->resolveCarbon($date); $ascending = ($start <= $end); $sign = $absolute || $ascending ? 1 : -1; if (!$ascending) { [$start, $end] = [$end, $start]; } $monthsDiff = $start->diffInMonths($end); /** @var Carbon|CarbonImmutable $floorEnd */ $floorEnd = $start->avoidMutation()->addMonths($monthsDiff); if ($floorEnd >= $end) { return $sign * $monthsDiff; } /** @var Carbon|CarbonImmutable $startOfMonthAfterFloorEnd */ $startOfMonthAfterFloorEnd = $floorEnd->avoidMutation()->addMonth()->startOfMonth(); if ($startOfMonthAfterFloorEnd > $end) { return $sign * ($monthsDiff + $floorEnd->floatDiffInRealDays($end) / $floorEnd->daysInMonth); } return $sign * ($monthsDiff + $floorEnd->floatDiffInRealDays($startOfMonthAfterFloorEnd) / $floorEnd->daysInMonth + $startOfMonthAfterFloorEnd->floatDiffInRealDays($end) / $end->daysInMonth); } /** * Get the difference in year as float (microsecond-precision) using timestamps. * * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date * @param bool $absolute Get the absolute of the difference * * @return float */ public function floatDiffInRealYears($date = null, $absolute = true) { $start = $this; $end = $this->resolveCarbon($date); $ascending = ($start <= $end); $sign = $absolute || $ascending ? 1 : -1; if (!$ascending) { [$start, $end] = [$end, $start]; } $yearsDiff = $start->diffInYears($end); /** @var Carbon|CarbonImmutable $floorEnd */ $floorEnd = $start->avoidMutation()->addYears($yearsDiff); if ($floorEnd >= $end) { return $sign * $yearsDiff; } /** @var Carbon|CarbonImmutable $startOfYearAfterFloorEnd */ $startOfYearAfterFloorEnd = $floorEnd->avoidMutation()->addYear()->startOfYear(); if ($startOfYearAfterFloorEnd > $end) { return $sign * ($yearsDiff + $floorEnd->floatDiffInRealDays($end) / $floorEnd->daysInYear); } return $sign * ($yearsDiff + $floorEnd->floatDiffInRealDays($startOfYearAfterFloorEnd) / $floorEnd->daysInYear + $startOfYearAfterFloorEnd->floatDiffInRealDays($end) / $end->daysInYear); } /** * The number of seconds since midnight. * * @return int */ public function secondsSinceMidnight() { return $this->diffInSeconds($this->avoidMutation()->startOfDay()); } /** * The number of seconds until 23:59:59. * * @return int */ public function secondsUntilEndOfDay() { return $this->diffInSeconds($this->avoidMutation()->endOfDay()); } /** * Get the difference in a human readable format in the current locale from current instance to an other * instance given (or now if null given). * * @example * ``` * echo Carbon::tomorrow()->diffForHumans() . "\n"; * echo Carbon::tomorrow()->diffForHumans(['parts' => 2]) . "\n"; * echo Carbon::tomorrow()->diffForHumans(['parts' => 3, 'join' => true]) . "\n"; * echo Carbon::tomorrow()->diffForHumans(Carbon::yesterday()) . "\n"; * echo Carbon::tomorrow()->diffForHumans(Carbon::yesterday(), ['short' => true]) . "\n"; * ``` * * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below; * if null passed, now will be used as comparison reference; * if any other type, it will be converted to date and used as reference. * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains: * - 'syntax' entry (see below) * - 'short' entry (see below) * - 'parts' entry (see below) * - 'options' entry (see below) * - 'skip' entry, list of units to skip (array of strings or a single string, * ` it can be the unit name (singular or plural) or its shortcut * ` (y, m, w, d, h, min, s, ms, µs). * - 'aUnit' entry, prefer "an hour" over "1 hour" if true * - 'join' entry determines how to join multiple parts of the string * ` - if $join is a string, it's used as a joiner glue * ` - if $join is a callable/closure, it get the list of string and should return a string * ` - if $join is an array, the first item will be the default glue, and the second item * ` will be used instead of the glue for the last item * ` - if $join is true, it will be guessed from the locale ('list' translation file entry) * ` - if $join is missing, a space will be used as glue * - 'other' entry (see above) * - 'minimumUnit' entry determines the smallest unit of time to display can be long or * ` short form of the units, e.g. 'hour' or 'h' (default value: s) * if int passed, it add modifiers: * Possible values: * - CarbonInterface::DIFF_ABSOLUTE no modifiers * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier * Default value: CarbonInterface::DIFF_ABSOLUTE * @param bool $short displays short format of time units * @param int $parts maximum number of parts to display (default value: 1: single unit) * @param int $options human diff options * * @return string */ public function diffForHumans($other = null, $syntax = null, $short = false, $parts = 1, $options = null) { /* @var CarbonInterface $this */ if (\is_array($other)) { $other['syntax'] = \array_key_exists('syntax', $other) ? $other['syntax'] : $syntax; $syntax = $other; $other = $syntax['other'] ?? null; } $intSyntax = &$syntax; if (\is_array($syntax)) { $syntax['syntax'] = $syntax['syntax'] ?? null; $intSyntax = &$syntax['syntax']; } $intSyntax = (int) ($intSyntax ?? static::DIFF_RELATIVE_AUTO); $intSyntax = $intSyntax === static::DIFF_RELATIVE_AUTO && $other === null ? static::DIFF_RELATIVE_TO_NOW : $intSyntax; $parts = min(7, max(1, (int) $parts)); $skip = \is_array($syntax) ? ($syntax['skip'] ?? []) : []; return $this->diffAsCarbonInterval($other, false, (array) $skip) ->setLocalTranslator($this->getLocalTranslator()) ->forHumans($syntax, (bool) $short, $parts, $options ?? $this->localHumanDiffOptions ?? static::getHumanDiffOptions()); } /** * @alias diffForHumans * * Get the difference in a human readable format in the current locale from current instance to an other * instance given (or now if null given). * * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below; * if null passed, now will be used as comparison reference; * if any other type, it will be converted to date and used as reference. * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains: * - 'syntax' entry (see below) * - 'short' entry (see below) * - 'parts' entry (see below) * - 'options' entry (see below) * - 'join' entry determines how to join multiple parts of the string * ` - if $join is a string, it's used as a joiner glue * ` - if $join is a callable/closure, it get the list of string and should return a string * ` - if $join is an array, the first item will be the default glue, and the second item * ` will be used instead of the glue for the last item * ` - if $join is true, it will be guessed from the locale ('list' translation file entry) * ` - if $join is missing, a space will be used as glue * - 'other' entry (see above) * if int passed, it add modifiers: * Possible values: * - CarbonInterface::DIFF_ABSOLUTE no modifiers * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier * Default value: CarbonInterface::DIFF_ABSOLUTE * @param bool $short displays short format of time units * @param int $parts maximum number of parts to display (default value: 1: single unit) * @param int $options human diff options * * @return string */ public function from($other = null, $syntax = null, $short = false, $parts = 1, $options = null) { return $this->diffForHumans($other, $syntax, $short, $parts, $options); } /** * @alias diffForHumans * * Get the difference in a human readable format in the current locale from current instance to an other * instance given (or now if null given). */ public function since($other = null, $syntax = null, $short = false, $parts = 1, $options = null) { return $this->diffForHumans($other, $syntax, $short, $parts, $options); } /** * Get the difference in a human readable format in the current locale from an other * instance given (or now if null given) to current instance. * * When comparing a value in the past to default now: * 1 hour from now * 5 months from now * * When comparing a value in the future to default now: * 1 hour ago * 5 months ago * * When comparing a value in the past to another value: * 1 hour after * 5 months after * * When comparing a value in the future to another value: * 1 hour before * 5 months before * * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below; * if null passed, now will be used as comparison reference; * if any other type, it will be converted to date and used as reference. * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains: * - 'syntax' entry (see below) * - 'short' entry (see below) * - 'parts' entry (see below) * - 'options' entry (see below) * - 'join' entry determines how to join multiple parts of the string * ` - if $join is a string, it's used as a joiner glue * ` - if $join is a callable/closure, it get the list of string and should return a string * ` - if $join is an array, the first item will be the default glue, and the second item * ` will be used instead of the glue for the last item * ` - if $join is true, it will be guessed from the locale ('list' translation file entry) * ` - if $join is missing, a space will be used as glue * - 'other' entry (see above) * if int passed, it add modifiers: * Possible values: * - CarbonInterface::DIFF_ABSOLUTE no modifiers * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier * Default value: CarbonInterface::DIFF_ABSOLUTE * @param bool $short displays short format of time units * @param int $parts maximum number of parts to display (default value: 1: single unit) * @param int $options human diff options * * @return string */ public function to($other = null, $syntax = null, $short = false, $parts = 1, $options = null) { if (!$syntax && !$other) { $syntax = CarbonInterface::DIFF_RELATIVE_TO_NOW; } return $this->resolveCarbon($other)->diffForHumans($this, $syntax, $short, $parts, $options); } /** * @alias to * * Get the difference in a human readable format in the current locale from an other * instance given (or now if null given) to current instance. * * @param Carbon|\DateTimeInterface|string|array|null $other if array passed, will be used as parameters array, see $syntax below; * if null passed, now will be used as comparison reference; * if any other type, it will be converted to date and used as reference. * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains: * - 'syntax' entry (see below) * - 'short' entry (see below) * - 'parts' entry (see below) * - 'options' entry (see below) * - 'join' entry determines how to join multiple parts of the string * ` - if $join is a string, it's used as a joiner glue * ` - if $join is a callable/closure, it get the list of string and should return a string * ` - if $join is an array, the first item will be the default glue, and the second item * ` will be used instead of the glue for the last item * ` - if $join is true, it will be guessed from the locale ('list' translation file entry) * ` - if $join is missing, a space will be used as glue * - 'other' entry (see above) * if int passed, it add modifiers: * Possible values: * - CarbonInterface::DIFF_ABSOLUTE no modifiers * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier * Default value: CarbonInterface::DIFF_ABSOLUTE * @param bool $short displays short format of time units * @param int $parts maximum number of parts to display (default value: 1: single unit) * @param int $options human diff options * * @return string */ public function until($other = null, $syntax = null, $short = false, $parts = 1, $options = null) { return $this->to($other, $syntax, $short, $parts, $options); } /** * Get the difference in a human readable format in the current locale from current * instance to now. * * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains: * - 'syntax' entry (see below) * - 'short' entry (see below) * - 'parts' entry (see below) * - 'options' entry (see below) * - 'join' entry determines how to join multiple parts of the string * ` - if $join is a string, it's used as a joiner glue * ` - if $join is a callable/closure, it get the list of string and should return a string * ` - if $join is an array, the first item will be the default glue, and the second item * ` will be used instead of the glue for the last item * ` - if $join is true, it will be guessed from the locale ('list' translation file entry) * ` - if $join is missing, a space will be used as glue * if int passed, it add modifiers: * Possible values: * - CarbonInterface::DIFF_ABSOLUTE no modifiers * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier * Default value: CarbonInterface::DIFF_ABSOLUTE * @param bool $short displays short format of time units * @param int $parts maximum number of parts to display (default value: 1: single unit) * @param int $options human diff options * * @return string */ public function fromNow($syntax = null, $short = false, $parts = 1, $options = null) { $other = null; if ($syntax instanceof DateTimeInterface) { [$other, $syntax, $short, $parts, $options] = array_pad(\func_get_args(), 5, null); } return $this->from($other, $syntax, $short, $parts, $options); } /** * Get the difference in a human readable format in the current locale from an other * instance given to now * * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains: * - 'syntax' entry (see below) * - 'short' entry (see below) * - 'parts' entry (see below) * - 'options' entry (see below) * - 'join' entry determines how to join multiple parts of the string * ` - if $join is a string, it's used as a joiner glue * ` - if $join is a callable/closure, it get the list of string and should return a string * ` - if $join is an array, the first item will be the default glue, and the second item * ` will be used instead of the glue for the last item * ` - if $join is true, it will be guessed from the locale ('list' translation file entry) * ` - if $join is missing, a space will be used as glue * if int passed, it add modifiers: * Possible values: * - CarbonInterface::DIFF_ABSOLUTE no modifiers * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier * Default value: CarbonInterface::DIFF_ABSOLUTE * @param bool $short displays short format of time units * @param int $parts maximum number of parts to display (default value: 1: single part) * @param int $options human diff options * * @return string */ public function toNow($syntax = null, $short = false, $parts = 1, $options = null) { return $this->to(null, $syntax, $short, $parts, $options); } /** * Get the difference in a human readable format in the current locale from an other * instance given to now * * @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains: * - 'syntax' entry (see below) * - 'short' entry (see below) * - 'parts' entry (see below) * - 'options' entry (see below) * - 'join' entry determines how to join multiple parts of the string * ` - if $join is a string, it's used as a joiner glue * ` - if $join is a callable/closure, it get the list of string and should return a string * ` - if $join is an array, the first item will be the default glue, and the second item * ` will be used instead of the glue for the last item * ` - if $join is true, it will be guessed from the locale ('list' translation file entry) * ` - if $join is missing, a space will be used as glue * if int passed, it add modifiers: * Possible values: * - CarbonInterface::DIFF_ABSOLUTE no modifiers * - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier * - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier * Default value: CarbonInterface::DIFF_ABSOLUTE * @param bool $short displays short format of time units * @param int $parts maximum number of parts to display (default value: 1: single part) * @param int $options human diff options * * @return string */ public function ago($syntax = null, $short = false, $parts = 1, $options = null) { $other = null; if ($syntax instanceof DateTimeInterface) { [$other, $syntax, $short, $parts, $options] = array_pad(\func_get_args(), 5, null); } return $this->from($other, $syntax, $short, $parts, $options); } /** * Get the difference in a human readable format in the current locale from current instance to an other * instance given (or now if null given). * * @return string */ public function timespan($other = null, $timezone = null) { if (!$other instanceof DateTimeInterface) { $other = static::parse($other, $timezone); } return $this->diffForHumans($other, [ 'join' => ', ', 'syntax' => CarbonInterface::DIFF_ABSOLUTE, 'options' => CarbonInterface::NO_ZERO_DIFF, 'parts' => -1, ]); } /** * Returns either day of week + time (e.g. "Last Friday at 3:30 PM") if reference time is within 7 days, * or a calendar date (e.g. "10/29/2017") otherwise. * * Language, date and time formats will change according to the current locale. * * @param Carbon|\DateTimeInterface|string|null $referenceTime * @param array $formats * * @return string */ public function calendar($referenceTime = null, array $formats = []) { /** @var CarbonInterface $current */ $current = $this->avoidMutation()->startOfDay(); /** @var CarbonInterface $other */ $other = $this->resolveCarbon($referenceTime)->avoidMutation()->setTimezone($this->getTimezone())->startOfDay(); $diff = $other->diffInDays($current, false); $format = $diff < -6 ? 'sameElse' : ( $diff < -1 ? 'lastWeek' : ( $diff < 0 ? 'lastDay' : ( $diff < 1 ? 'sameDay' : ( $diff < 2 ? 'nextDay' : ( $diff < 7 ? 'nextWeek' : 'sameElse' ) ) ) ) ); $format = array_merge($this->getCalendarFormats(), $formats)[$format]; if ($format instanceof Closure) { $format = $format($current, $other) ?? ''; } return $this->isoFormat((string) $format); } private function getIntervalDayDiff(DateInterval $interval): int { $daysDiff = (int) $interval->format('%a'); $sign = $interval->format('%r') === '-' ? -1 : 1; if (\is_int($interval->days) && $interval->y === 0 && $interval->m === 0 && version_compare(PHP_VERSION, '8.1.0-dev', '<') && abs($interval->d - $daysDiff) === 1 ) { $daysDiff = abs($interval->d); // @codeCoverageIgnore } return $daysDiff * $sign; } } PK������<1Z+������Carbon/Traits/Timestamp.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; /** * Trait Timestamp. */ trait Timestamp { /** * Create a Carbon instance from a timestamp and set the timezone (use default one if not specified). * * Timestamp input can be given as int, float or a string containing one or more numbers. * * @param float|int|string $timestamp * @param \DateTimeZone|string|null $tz * * @return static */ #[\ReturnTypeWillChange] public static function createFromTimestamp($timestamp, $tz = null) { return static::createFromTimestampUTC($timestamp)->setTimezone($tz); } /** * Create a Carbon instance from an timestamp keeping the timezone to UTC. * * Timestamp input can be given as int, float or a string containing one or more numbers. * * @param float|int|string $timestamp * * @return static */ public static function createFromTimestampUTC($timestamp) { [$integer, $decimal] = self::getIntegerAndDecimalParts($timestamp); $delta = floor($decimal / static::MICROSECONDS_PER_SECOND); $integer += $delta; $decimal -= $delta * static::MICROSECONDS_PER_SECOND; $decimal = str_pad((string) $decimal, 6, '0', STR_PAD_LEFT); return static::rawCreateFromFormat('U u', "$integer $decimal"); } /** * Create a Carbon instance from a timestamp in milliseconds. * * Timestamp input can be given as int, float or a string containing one or more numbers. * * @param float|int|string $timestamp * * @return static */ public static function createFromTimestampMsUTC($timestamp) { [$milliseconds, $microseconds] = self::getIntegerAndDecimalParts($timestamp, 3); $sign = $milliseconds < 0 || ($milliseconds === 0.0 && $microseconds < 0) ? -1 : 1; $milliseconds = abs($milliseconds); $microseconds = $sign * abs($microseconds) + static::MICROSECONDS_PER_MILLISECOND * ($milliseconds % static::MILLISECONDS_PER_SECOND); $seconds = $sign * floor($milliseconds / static::MILLISECONDS_PER_SECOND); $delta = floor($microseconds / static::MICROSECONDS_PER_SECOND); $seconds += $delta; $microseconds -= $delta * static::MICROSECONDS_PER_SECOND; $microseconds = str_pad($microseconds, 6, '0', STR_PAD_LEFT); return static::rawCreateFromFormat('U u', "$seconds $microseconds"); } /** * Create a Carbon instance from a timestamp in milliseconds. * * Timestamp input can be given as int, float or a string containing one or more numbers. * * @param float|int|string $timestamp * @param \DateTimeZone|string|null $tz * * @return static */ public static function createFromTimestampMs($timestamp, $tz = null) { return static::createFromTimestampMsUTC($timestamp) ->setTimezone($tz); } /** * Set the instance's timestamp. * * Timestamp input can be given as int, float or a string containing one or more numbers. * * @param float|int|string $unixTimestamp * * @return static */ public function timestamp($unixTimestamp) { return $this->setTimestamp($unixTimestamp); } /** * Returns a timestamp rounded with the given precision (6 by default). * * @example getPreciseTimestamp() 1532087464437474 (microsecond maximum precision) * @example getPreciseTimestamp(6) 1532087464437474 * @example getPreciseTimestamp(5) 153208746443747 (1/100000 second precision) * @example getPreciseTimestamp(4) 15320874644375 (1/10000 second precision) * @example getPreciseTimestamp(3) 1532087464437 (millisecond precision) * @example getPreciseTimestamp(2) 153208746444 (1/100 second precision) * @example getPreciseTimestamp(1) 15320874644 (1/10 second precision) * @example getPreciseTimestamp(0) 1532087464 (second precision) * @example getPreciseTimestamp(-1) 153208746 (10 second precision) * @example getPreciseTimestamp(-2) 15320875 (100 second precision) * * @param int $precision * * @return float */ public function getPreciseTimestamp($precision = 6) { return round(((float) $this->rawFormat('Uu')) / pow(10, 6 - $precision)); } /** * Returns the milliseconds timestamps used amongst other by Date javascript objects. * * @return float */ public function valueOf() { return $this->getPreciseTimestamp(3); } /** * Returns the timestamp with millisecond precision. * * @return int */ public function getTimestampMs() { return (int) $this->getPreciseTimestamp(3); } /** * @alias getTimestamp * * Returns the UNIX timestamp for the current date. * * @return int */ public function unix() { return $this->getTimestamp(); } /** * Return an array with integer part digits and decimals digits split from one or more positive numbers * (such as timestamps) as string with the given number of decimals (6 by default). * * By splitting integer and decimal, this method obtain a better precision than * number_format when the input is a string. * * @param float|int|string $numbers one or more numbers * @param int $decimals number of decimals precision (6 by default) * * @return array 0-index is integer part, 1-index is decimal part digits */ private static function getIntegerAndDecimalParts($numbers, $decimals = 6) { if (\is_int($numbers) || \is_float($numbers)) { $numbers = number_format($numbers, $decimals, '.', ''); } $sign = str_starts_with($numbers, '-') ? -1 : 1; $integer = 0; $decimal = 0; foreach (preg_split('`[^\d.]+`', $numbers) as $chunk) { [$integerPart, $decimalPart] = explode('.', "$chunk."); $integer += (int) $integerPart; $decimal += (float) ("0.$decimalPart"); } $overflow = floor($decimal); $integer += $overflow; $decimal -= $overflow; return [$sign * $integer, $decimal === 0.0 ? 0.0 : $sign * round($decimal * pow(10, $decimals))]; } } PK������<1ZB��B����Carbon/Traits/Cast.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; use Carbon\Exceptions\InvalidCastException; use DateTimeInterface; /** * Trait Cast. * * Utils to cast into an other class. */ trait Cast { /** * Cast the current instance into the given class. * * @param string $className The $className::instance() method will be called to cast the current object. * * @return DateTimeInterface */ public function cast(string $className) { if (!method_exists($className, 'instance')) { if (is_a($className, DateTimeInterface::class, true)) { return new $className($this->rawFormat('Y-m-d H:i:s.u'), $this->getTimezone()); } throw new InvalidCastException("$className has not the instance() method needed to cast the date."); } return $className::instance($this); } } PK������<1ZC!���� ��Carbon/Traits/ToStringFormat.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; use Closure; /** * Trait ToStringFormat. * * Handle global format customization for string cast of the object. */ trait ToStringFormat { /** * Format to use for __toString method when type juggling occurs. * * @var string|Closure|null */ protected static $toStringFormat; /** * Reset the format used to the default when type juggling a Carbon instance to a string * * @return void */ public static function resetToStringFormat() { static::setToStringFormat(null); } /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather let Carbon object being cast to string with DEFAULT_TO_STRING_FORMAT, and * use other method or custom format passed to format() method if you need to dump another string * format. * * Set the default format used when type juggling a Carbon instance to a string. * * @param string|Closure|null $format * * @return void */ public static function setToStringFormat($format) { static::$toStringFormat = $format; } } PK������<1Z5X7b �� ����Carbon/Traits/Macro.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; /** * Trait Macros. * * Allows users to register macros within the Carbon class. */ trait Macro { use Mixin; /** * The registered macros. * * @var array */ protected static $globalMacros = []; /** * The registered generic macros. * * @var array */ protected static $globalGenericMacros = []; /** * Register a custom macro. * * @example * ``` * $userSettings = [ * 'locale' => 'pt', * 'timezone' => 'America/Sao_Paulo', * ]; * Carbon::macro('userFormat', function () use ($userSettings) { * return $this->copy()->locale($userSettings['locale'])->tz($userSettings['timezone'])->calendar(); * }); * echo Carbon::yesterday()->hours(11)->userFormat(); * ``` * * @param string $name * @param object|callable $macro * * @return void */ public static function macro($name, $macro) { static::$globalMacros[$name] = $macro; } /** * Remove all macros and generic macros. */ public static function resetMacros() { static::$globalMacros = []; static::$globalGenericMacros = []; } /** * Register a custom macro. * * @param object|callable $macro * @param int $priority marco with higher priority is tried first * * @return void */ public static function genericMacro($macro, $priority = 0) { if (!isset(static::$globalGenericMacros[$priority])) { static::$globalGenericMacros[$priority] = []; krsort(static::$globalGenericMacros, SORT_NUMERIC); } static::$globalGenericMacros[$priority][] = $macro; } /** * Checks if macro is registered globally. * * @param string $name * * @return bool */ public static function hasMacro($name) { return isset(static::$globalMacros[$name]); } /** * Get the raw callable macro registered globally for a given name. * * @param string $name * * @return callable|null */ public static function getMacro($name) { return static::$globalMacros[$name] ?? null; } /** * Checks if macro is registered globally or locally. * * @param string $name * * @return bool */ public function hasLocalMacro($name) { return ($this->localMacros && isset($this->localMacros[$name])) || static::hasMacro($name); } /** * Get the raw callable macro registered globally or locally for a given name. * * @param string $name * * @return callable|null */ public function getLocalMacro($name) { return ($this->localMacros ?? [])[$name] ?? static::getMacro($name); } } PK������<1Z$y*0��0����Carbon/Traits/Units.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; use Carbon\CarbonConverterInterface; use Carbon\CarbonInterface; use Carbon\CarbonInterval; use Carbon\Exceptions\UnitException; use Closure; use DateInterval; use DateMalformedStringException; use ReturnTypeWillChange; /** * Trait Units. * * Add, subtract and set units. */ trait Units { /** * Add seconds to the instance using timestamp. Positive $value travels * forward while negative $value travels into the past. * * @param string $unit * @param int $value * * @return static */ public function addRealUnit($unit, $value = 1) { switch ($unit) { // @call addRealUnit case 'micro': // @call addRealUnit case 'microsecond': /* @var CarbonInterface $this */ $diff = $this->microsecond + $value; $time = $this->getTimestamp(); $seconds = (int) floor($diff / static::MICROSECONDS_PER_SECOND); $time += $seconds; $diff -= $seconds * static::MICROSECONDS_PER_SECOND; $microtime = str_pad((string) $diff, 6, '0', STR_PAD_LEFT); $tz = $this->tz; return $this->tz('UTC')->modify("@$time.$microtime")->tz($tz); // @call addRealUnit case 'milli': // @call addRealUnit case 'millisecond': return $this->addRealUnit('microsecond', $value * static::MICROSECONDS_PER_MILLISECOND); // @call addRealUnit case 'second': break; // @call addRealUnit case 'minute': $value *= static::SECONDS_PER_MINUTE; break; // @call addRealUnit case 'hour': $value *= static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE; break; // @call addRealUnit case 'day': $value *= static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE; break; // @call addRealUnit case 'week': $value *= static::DAYS_PER_WEEK * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE; break; // @call addRealUnit case 'month': $value *= 30 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE; break; // @call addRealUnit case 'quarter': $value *= static::MONTHS_PER_QUARTER * 30 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE; break; // @call addRealUnit case 'year': $value *= 365 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE; break; // @call addRealUnit case 'decade': $value *= static::YEARS_PER_DECADE * 365 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE; break; // @call addRealUnit case 'century': $value *= static::YEARS_PER_CENTURY * 365 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE; break; // @call addRealUnit case 'millennium': $value *= static::YEARS_PER_MILLENNIUM * 365 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE; break; default: if ($this->localStrictModeEnabled ?? static::isStrictModeEnabled()) { throw new UnitException("Invalid unit for real timestamp add/sub: '$unit'"); } return $this; } /* @var CarbonInterface $this */ return $this->setTimestamp((int) ($this->getTimestamp() + $value)); } public function subRealUnit($unit, $value = 1) { return $this->addRealUnit($unit, -$value); } /** * Returns true if a property can be changed via setter. * * @param string $unit * * @return bool */ public static function isModifiableUnit($unit) { static $modifiableUnits = [ // @call addUnit 'millennium', // @call addUnit 'century', // @call addUnit 'decade', // @call addUnit 'quarter', // @call addUnit 'week', // @call addUnit 'weekday', ]; return \in_array($unit, $modifiableUnits, true) || \in_array($unit, static::$units, true); } /** * Call native PHP DateTime/DateTimeImmutable add() method. * * @param DateInterval $interval * * @return static */ public function rawAdd(DateInterval $interval) { return parent::add($interval); } /** * Add given units or interval to the current instance. * * @example $date->add('hour', 3) * @example $date->add(15, 'days') * @example $date->add(CarbonInterval::days(4)) * * @param string|DateInterval|Closure|CarbonConverterInterface $unit * @param int $value * @param bool|null $overflow * * @return static */ #[ReturnTypeWillChange] public function add($unit, $value = 1, $overflow = null) { if (\is_string($unit) && \func_num_args() === 1) { $unit = CarbonInterval::make($unit, [], true); } if ($unit instanceof CarbonConverterInterface) { return $this->resolveCarbon($unit->convertDate($this, false)); } if ($unit instanceof Closure) { return $this->resolveCarbon($unit($this, false)); } if ($unit instanceof DateInterval) { return parent::add($unit); } if (is_numeric($unit)) { [$value, $unit] = [$unit, $value]; } return $this->addUnit($unit, $value, $overflow); } /** * Add given units to the current instance. * * @param string $unit * @param int $value * @param bool|null $overflow * * @return static */ public function addUnit($unit, $value = 1, $overflow = null) { $originalArgs = \func_get_args(); $date = $this; if (!is_numeric($value) || !(float) $value) { return $date->isMutable() ? $date : $date->avoidMutation(); } $unit = self::singularUnit($unit); $metaUnits = [ 'millennium' => [static::YEARS_PER_MILLENNIUM, 'year'], 'century' => [static::YEARS_PER_CENTURY, 'year'], 'decade' => [static::YEARS_PER_DECADE, 'year'], 'quarter' => [static::MONTHS_PER_QUARTER, 'month'], ]; if (isset($metaUnits[$unit])) { [$factor, $unit] = $metaUnits[$unit]; $value *= $factor; } if ($unit === 'weekday') { $weekendDays = static::getWeekendDays(); if ($weekendDays !== [static::SATURDAY, static::SUNDAY]) { $absoluteValue = abs($value); $sign = $value / max(1, $absoluteValue); $weekDaysCount = 7 - min(6, \count(array_unique($weekendDays))); $weeks = floor($absoluteValue / $weekDaysCount); for ($diff = $absoluteValue % $weekDaysCount; $diff; $diff--) { /** @var static $date */ $date = $date->addDays($sign); while (\in_array($date->dayOfWeek, $weekendDays, true)) { $date = $date->addDays($sign); } } $value = $weeks * $sign; $unit = 'week'; } $timeString = $date->toTimeString(); } elseif ($canOverflow = (\in_array($unit, [ 'month', 'year', ]) && ($overflow === false || ( $overflow === null && ($ucUnit = ucfirst($unit).'s') && !($this->{'local'.$ucUnit.'Overflow'} ?? static::{'shouldOverflow'.$ucUnit}()) )))) { $day = $date->day; } $value = (int) $value; if ($unit === 'milli' || $unit === 'millisecond') { $unit = 'microsecond'; $value *= static::MICROSECONDS_PER_MILLISECOND; } // Work-around for bug https://bugs.php.net/bug.php?id=75642 if ($unit === 'micro' || $unit === 'microsecond') { $microseconds = $this->micro + $value; $second = (int) floor($microseconds / static::MICROSECONDS_PER_SECOND); $microseconds %= static::MICROSECONDS_PER_SECOND; if ($microseconds < 0) { $microseconds += static::MICROSECONDS_PER_SECOND; } $date = $date->microseconds($microseconds); $unit = 'second'; $value = $second; } try { $date = $date->modify("$value $unit"); if (isset($timeString)) { $date = $date->setTimeFromTimeString($timeString); } elseif (isset($canOverflow, $day) && $canOverflow && $day !== $date->day) { $date = $date->modify('last day of previous month'); } } catch (DateMalformedStringException $ignoredException) { // @codeCoverageIgnore $date = null; // @codeCoverageIgnore } if (!$date) { throw new UnitException('Unable to add unit '.var_export($originalArgs, true)); } return $date; } /** * Subtract given units to the current instance. * * @param string $unit * @param int $value * @param bool|null $overflow * * @return static */ public function subUnit($unit, $value = 1, $overflow = null) { return $this->addUnit($unit, -$value, $overflow); } /** * Call native PHP DateTime/DateTimeImmutable sub() method. * * @param DateInterval $interval * * @return static */ public function rawSub(DateInterval $interval) { return parent::sub($interval); } /** * Subtract given units or interval to the current instance. * * @example $date->sub('hour', 3) * @example $date->sub(15, 'days') * @example $date->sub(CarbonInterval::days(4)) * * @param string|DateInterval|Closure|CarbonConverterInterface $unit * @param int $value * @param bool|null $overflow * * @return static */ #[ReturnTypeWillChange] public function sub($unit, $value = 1, $overflow = null) { if (\is_string($unit) && \func_num_args() === 1) { $unit = CarbonInterval::make($unit, [], true); } if ($unit instanceof CarbonConverterInterface) { return $this->resolveCarbon($unit->convertDate($this, true)); } if ($unit instanceof Closure) { return $this->resolveCarbon($unit($this, true)); } if ($unit instanceof DateInterval) { return parent::sub($unit); } if (is_numeric($unit)) { [$value, $unit] = [$unit, $value]; } return $this->addUnit($unit, -(float) $value, $overflow); } /** * Subtract given units or interval to the current instance. * * @see sub() * * @param string|DateInterval $unit * @param int $value * @param bool|null $overflow * * @return static */ public function subtract($unit, $value = 1, $overflow = null) { if (\is_string($unit) && \func_num_args() === 1) { $unit = CarbonInterval::make($unit, [], true); } return $this->sub($unit, $value, $overflow); } } PK������<1Zj[������Carbon/Traits/Week.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; /** * Trait Week. * * week and ISO week number, year and count in year. * * Depends on the following properties: * * @property int $daysInYear * @property int $dayOfWeek * @property int $dayOfYear * @property int $year * * Depends on the following methods: * * @method static addWeeks(int $weeks = 1) * @method static copy() * @method static dayOfYear(int $dayOfYear) * @method string getTranslationMessage(string $key, ?string $locale = null, ?string $default = null, $translator = null) * @method static next(int|string $day = null) * @method static startOfWeek(int $day = 1) * @method static subWeeks(int $weeks = 1) * @method static year(int $year = null) */ trait Week { /** * Set/get the week number of year using given first day of week and first * day of year included in the first week. Or use ISO format if no settings * given. * * @param int|null $year if null, act as a getter, if not null, set the year and return current instance. * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday) * @param int|null $dayOfYear first day of year included in the week #1 * * @return int|static */ public function isoWeekYear($year = null, $dayOfWeek = null, $dayOfYear = null) { return $this->weekYear( $year, $dayOfWeek ?? 1, $dayOfYear ?? 4 ); } /** * Set/get the week number of year using given first day of week and first * day of year included in the first week. Or use US format if no settings * given (Sunday / Jan 6). * * @param int|null $year if null, act as a getter, if not null, set the year and return current instance. * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday) * @param int|null $dayOfYear first day of year included in the week #1 * * @return int|static */ public function weekYear($year = null, $dayOfWeek = null, $dayOfYear = null) { $dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? 0; $dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1; if ($year !== null) { $year = (int) round($year); if ($this->weekYear(null, $dayOfWeek, $dayOfYear) === $year) { return $this->avoidMutation(); } $week = $this->week(null, $dayOfWeek, $dayOfYear); $day = $this->dayOfWeek; $date = $this->year($year); switch ($date->weekYear(null, $dayOfWeek, $dayOfYear) - $year) { case 1: $date = $date->subWeeks(26); break; case -1: $date = $date->addWeeks(26); break; } $date = $date->addWeeks($week - $date->week(null, $dayOfWeek, $dayOfYear))->startOfWeek($dayOfWeek); if ($date->dayOfWeek === $day) { return $date; } return $date->next($day); } $year = $this->year; $day = $this->dayOfYear; $date = $this->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek); if ($date->year === $year && $day < $date->dayOfYear) { return $year - 1; } $date = $this->avoidMutation()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek); if ($date->year === $year && $day >= $date->dayOfYear) { return $year + 1; } return $year; } /** * Get the number of weeks of the current week-year using given first day of week and first * day of year included in the first week. Or use ISO format if no settings * given. * * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday) * @param int|null $dayOfYear first day of year included in the week #1 * * @return int */ public function isoWeeksInYear($dayOfWeek = null, $dayOfYear = null) { return $this->weeksInYear( $dayOfWeek ?? 1, $dayOfYear ?? 4 ); } /** * Get the number of weeks of the current week-year using given first day of week and first * day of year included in the first week. Or use US format if no settings * given (Sunday / Jan 6). * * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday) * @param int|null $dayOfYear first day of year included in the week #1 * * @return int */ public function weeksInYear($dayOfWeek = null, $dayOfYear = null) { $dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? 0; $dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1; $year = $this->year; $start = $this->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek); $startDay = $start->dayOfYear; if ($start->year !== $year) { $startDay -= $start->daysInYear; } $end = $this->avoidMutation()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek); $endDay = $end->dayOfYear; if ($end->year !== $year) { $endDay += $this->daysInYear; } return (int) round(($endDay - $startDay) / 7); } /** * Get/set the week number using given first day of week and first * day of year included in the first week. Or use US format if no settings * given (Sunday / Jan 6). * * @param int|null $week * @param int|null $dayOfWeek * @param int|null $dayOfYear * * @return int|static */ public function week($week = null, $dayOfWeek = null, $dayOfYear = null) { $date = $this; $dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? 0; $dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1; if ($week !== null) { return $date->addWeeks(round($week) - $this->week(null, $dayOfWeek, $dayOfYear)); } $start = $date->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek); $end = $date->avoidMutation()->startOfWeek($dayOfWeek); if ($start > $end) { $start = $start->subWeeks(26)->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek); } $week = (int) ($start->diffInDays($end) / 7 + 1); return $week > $end->weeksInYear($dayOfWeek, $dayOfYear) ? 1 : $week; } /** * Get/set the week number using given first day of week and first * day of year included in the first week. Or use ISO format if no settings * given. * * @param int|null $week * @param int|null $dayOfWeek * @param int|null $dayOfYear * * @return int|static */ public function isoWeek($week = null, $dayOfWeek = null, $dayOfYear = null) { return $this->week( $week, $dayOfWeek ?? 1, $dayOfYear ?? 4 ); } } PK������<1ZP ]���� ��Carbon/Traits/MagicParameter.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; /** * Trait MagicParameter. * * Allows to retrieve parameter in magic calls by index or name. */ trait MagicParameter { private function getMagicParameter(array $parameters, int $index, string $key, $default) { if (\array_key_exists($index, $parameters)) { return $parameters[$index]; } if (\array_key_exists($key, $parameters)) { return $parameters[$key]; } return $default; } } PK������<1ZF 9Z;��Z;����Carbon/Traits/Converter.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; use Carbon\Carbon; use Carbon\CarbonImmutable; use Carbon\CarbonInterface; use Carbon\CarbonInterval; use Carbon\CarbonPeriod; use Carbon\CarbonPeriodImmutable; use Carbon\Exceptions\UnitException; use Closure; use DateTime; use DateTimeImmutable; use ReturnTypeWillChange; /** * Trait Converter. * * Change date into different string formats and types and * handle the string cast. * * Depends on the following methods: * * @method static copy() */ trait Converter { use ToStringFormat; /** * Returns the formatted date string on success or FALSE on failure. * * @see https://php.net/manual/en/datetime.format.php * * @param string $format * * @return string */ #[ReturnTypeWillChange] public function format($format) { $function = $this->localFormatFunction ?: static::$formatFunction; if (!$function) { return $this->rawFormat($format); } if (\is_string($function) && method_exists($this, $function)) { $function = [$this, $function]; } return $function(...\func_get_args()); } /** * @see https://php.net/manual/en/datetime.format.php * * @param string $format * * @return string */ public function rawFormat($format) { return parent::format($format); } /** * Format the instance as a string using the set format * * @example * ``` * echo Carbon::now(); // Carbon instances can be cast to string * ``` * * @return string */ public function __toString() { $format = $this->localToStringFormat ?? static::$toStringFormat; return $format instanceof Closure ? $format($this) : $this->rawFormat($format ?: ( \defined('static::DEFAULT_TO_STRING_FORMAT') ? static::DEFAULT_TO_STRING_FORMAT : CarbonInterface::DEFAULT_TO_STRING_FORMAT )); } /** * Format the instance as date * * @example * ``` * echo Carbon::now()->toDateString(); * ``` * * @return string */ public function toDateString() { return $this->rawFormat('Y-m-d'); } /** * Format the instance as a readable date * * @example * ``` * echo Carbon::now()->toFormattedDateString(); * ``` * * @return string */ public function toFormattedDateString() { return $this->rawFormat('M j, Y'); } /** * Format the instance with the day, and a readable date * * @example * ``` * echo Carbon::now()->toFormattedDayDateString(); * ``` * * @return string */ public function toFormattedDayDateString(): string { return $this->rawFormat('D, M j, Y'); } /** * Format the instance as time * * @example * ``` * echo Carbon::now()->toTimeString(); * ``` * * @param string $unitPrecision * * @return string */ public function toTimeString($unitPrecision = 'second') { return $this->rawFormat(static::getTimeFormatByPrecision($unitPrecision)); } /** * Format the instance as date and time * * @example * ``` * echo Carbon::now()->toDateTimeString(); * ``` * * @param string $unitPrecision * * @return string */ public function toDateTimeString($unitPrecision = 'second') { return $this->rawFormat('Y-m-d '.static::getTimeFormatByPrecision($unitPrecision)); } /** * Return a format from H:i to H:i:s.u according to given unit precision. * * @param string $unitPrecision "minute", "second", "millisecond" or "microsecond" * * @return string */ public static function getTimeFormatByPrecision($unitPrecision) { switch (static::singularUnit($unitPrecision)) { case 'minute': return 'H:i'; case 'second': return 'H:i:s'; case 'm': case 'millisecond': return 'H:i:s.v'; case 'µ': case 'microsecond': return 'H:i:s.u'; } throw new UnitException('Precision unit expected among: minute, second, millisecond and microsecond.'); } /** * Format the instance as date and time T-separated with no timezone * * @example * ``` * echo Carbon::now()->toDateTimeLocalString(); * echo "\n"; * echo Carbon::now()->toDateTimeLocalString('minute'); // You can specify precision among: minute, second, millisecond and microsecond * ``` * * @param string $unitPrecision * * @return string */ public function toDateTimeLocalString($unitPrecision = 'second') { return $this->rawFormat('Y-m-d\T'.static::getTimeFormatByPrecision($unitPrecision)); } /** * Format the instance with day, date and time * * @example * ``` * echo Carbon::now()->toDayDateTimeString(); * ``` * * @return string */ public function toDayDateTimeString() { return $this->rawFormat('D, M j, Y g:i A'); } /** * Format the instance as ATOM * * @example * ``` * echo Carbon::now()->toAtomString(); * ``` * * @return string */ public function toAtomString() { return $this->rawFormat(DateTime::ATOM); } /** * Format the instance as COOKIE * * @example * ``` * echo Carbon::now()->toCookieString(); * ``` * * @return string */ public function toCookieString() { return $this->rawFormat(DateTime::COOKIE); } /** * Format the instance as ISO8601 * * @example * ``` * echo Carbon::now()->toIso8601String(); * ``` * * @return string */ public function toIso8601String() { return $this->toAtomString(); } /** * Format the instance as RFC822 * * @example * ``` * echo Carbon::now()->toRfc822String(); * ``` * * @return string */ public function toRfc822String() { return $this->rawFormat(DateTime::RFC822); } /** * Convert the instance to UTC and return as Zulu ISO8601 * * @example * ``` * echo Carbon::now()->toIso8601ZuluString(); * ``` * * @param string $unitPrecision * * @return string */ public function toIso8601ZuluString($unitPrecision = 'second') { return $this->avoidMutation() ->utc() ->rawFormat('Y-m-d\T'.static::getTimeFormatByPrecision($unitPrecision).'\Z'); } /** * Format the instance as RFC850 * * @example * ``` * echo Carbon::now()->toRfc850String(); * ``` * * @return string */ public function toRfc850String() { return $this->rawFormat(DateTime::RFC850); } /** * Format the instance as RFC1036 * * @example * ``` * echo Carbon::now()->toRfc1036String(); * ``` * * @return string */ public function toRfc1036String() { return $this->rawFormat(DateTime::RFC1036); } /** * Format the instance as RFC1123 * * @example * ``` * echo Carbon::now()->toRfc1123String(); * ``` * * @return string */ public function toRfc1123String() { return $this->rawFormat(DateTime::RFC1123); } /** * Format the instance as RFC2822 * * @example * ``` * echo Carbon::now()->toRfc2822String(); * ``` * * @return string */ public function toRfc2822String() { return $this->rawFormat(DateTime::RFC2822); } /** * Format the instance as RFC3339 * * @param bool $extended * * @example * ``` * echo Carbon::now()->toRfc3339String() . "\n"; * echo Carbon::now()->toRfc3339String(true) . "\n"; * ``` * * @return string */ public function toRfc3339String($extended = false) { $format = DateTime::RFC3339; if ($extended) { $format = DateTime::RFC3339_EXTENDED; } return $this->rawFormat($format); } /** * Format the instance as RSS * * @example * ``` * echo Carbon::now()->toRssString(); * ``` * * @return string */ public function toRssString() { return $this->rawFormat(DateTime::RSS); } /** * Format the instance as W3C * * @example * ``` * echo Carbon::now()->toW3cString(); * ``` * * @return string */ public function toW3cString() { return $this->rawFormat(DateTime::W3C); } /** * Format the instance as RFC7231 * * @example * ``` * echo Carbon::now()->toRfc7231String(); * ``` * * @return string */ public function toRfc7231String() { return $this->avoidMutation() ->setTimezone('GMT') ->rawFormat(\defined('static::RFC7231_FORMAT') ? static::RFC7231_FORMAT : CarbonInterface::RFC7231_FORMAT); } /** * Get default array representation. * * @example * ``` * var_dump(Carbon::now()->toArray()); * ``` * * @return array */ public function toArray() { return [ 'year' => $this->year, 'month' => $this->month, 'day' => $this->day, 'dayOfWeek' => $this->dayOfWeek, 'dayOfYear' => $this->dayOfYear, 'hour' => $this->hour, 'minute' => $this->minute, 'second' => $this->second, 'micro' => $this->micro, 'timestamp' => $this->timestamp, 'formatted' => $this->rawFormat(\defined('static::DEFAULT_TO_STRING_FORMAT') ? static::DEFAULT_TO_STRING_FORMAT : CarbonInterface::DEFAULT_TO_STRING_FORMAT), 'timezone' => $this->timezone, ]; } /** * Get default object representation. * * @example * ``` * var_dump(Carbon::now()->toObject()); * ``` * * @return object */ public function toObject() { return (object) $this->toArray(); } /** * Returns english human readable complete date string. * * @example * ``` * echo Carbon::now()->toString(); * ``` * * @return string */ public function toString() { return $this->avoidMutation()->locale('en')->isoFormat('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); } /** * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z, if $keepOffset truthy, offset will be kept: * 1977-04-22T01:00:00-05:00). * * @example * ``` * echo Carbon::now('America/Toronto')->toISOString() . "\n"; * echo Carbon::now('America/Toronto')->toISOString(true) . "\n"; * ``` * * @param bool $keepOffset Pass true to keep the date offset. Else forced to UTC. * * @return null|string */ public function toISOString($keepOffset = false) { if (!$this->isValid()) { return null; } $yearFormat = $this->year < 0 || $this->year > 9999 ? 'YYYYYY' : 'YYYY'; $tzFormat = $keepOffset ? 'Z' : '[Z]'; $date = $keepOffset ? $this : $this->avoidMutation()->utc(); return $date->isoFormat("$yearFormat-MM-DD[T]HH:mm:ss.SSSSSS$tzFormat"); } /** * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z) with UTC timezone. * * @example * ``` * echo Carbon::now('America/Toronto')->toJSON(); * ``` * * @return null|string */ public function toJSON() { return $this->toISOString(); } /** * Return native DateTime PHP object matching the current instance. * * @example * ``` * var_dump(Carbon::now()->toDateTime()); * ``` * * @return DateTime */ public function toDateTime() { return new DateTime($this->rawFormat('Y-m-d H:i:s.u'), $this->getTimezone()); } /** * Return native toDateTimeImmutable PHP object matching the current instance. * * @example * ``` * var_dump(Carbon::now()->toDateTimeImmutable()); * ``` * * @return DateTimeImmutable */ public function toDateTimeImmutable() { return new DateTimeImmutable($this->rawFormat('Y-m-d H:i:s.u'), $this->getTimezone()); } /** * @alias toDateTime * * Return native DateTime PHP object matching the current instance. * * @example * ``` * var_dump(Carbon::now()->toDate()); * ``` * * @return DateTime */ public function toDate() { return $this->toDateTime(); } /** * Create a iterable CarbonPeriod object from current date to a given end date (and optional interval). * * @param \DateTimeInterface|Carbon|CarbonImmutable|int|null $end period end date or recurrences count if int * @param int|\DateInterval|string|null $interval period default interval or number of the given $unit * @param string|null $unit if specified, $interval must be an integer * * @return CarbonPeriod */ public function toPeriod($end = null, $interval = null, $unit = null) { if ($unit) { $interval = CarbonInterval::make("$interval ".static::pluralUnit($unit)); } $period = ($this->isMutable() ? new CarbonPeriod() : new CarbonPeriodImmutable()) ->setDateClass(static::class) ->setStartDate($this); if ($interval) { $period = $period->setDateInterval($interval); } if (\is_int($end) || (\is_string($end) && ctype_digit($end))) { $period = $period->setRecurrences($end); } elseif ($end) { $period = $period->setEndDate($end); } return $period; } /** * Create a iterable CarbonPeriod object from current date to a given end date (and optional interval). * * @param \DateTimeInterface|Carbon|CarbonImmutable|null $end period end date * @param int|\DateInterval|string|null $interval period default interval or number of the given $unit * @param string|null $unit if specified, $interval must be an integer * * @return CarbonPeriod */ public function range($end = null, $interval = null, $unit = null) { return $this->toPeriod($end, $interval, $unit); } } PK������<1ZRI!��I!����Carbon/Traits/Serialization.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; use Carbon\Exceptions\InvalidFormatException; use ReturnTypeWillChange; use Throwable; /** * Trait Serialization. * * Serialization and JSON stuff. * * Depends on the following properties: * * @property int $year * @property int $month * @property int $daysInMonth * @property int $quarter * * Depends on the following methods: * * @method string|static locale(string $locale = null, string ...$fallbackLocales) * @method string toJSON() */ trait Serialization { use ObjectInitialisation; /** * The custom Carbon JSON serializer. * * @var callable|null */ protected static $serializer; /** * List of key to use for dump/serialization. * * @var string[] */ protected $dumpProperties = ['date', 'timezone_type', 'timezone']; /** * Locale to dump comes here before serialization. * * @var string|null */ protected $dumpLocale; /** * Embed date properties to dump in a dedicated variables so it won't overlap native * DateTime ones. * * @var array|null */ protected $dumpDateProperties; /** * Return a serialized string of the instance. * * @return string */ public function serialize() { return serialize($this); } /** * Create an instance from a serialized string. * * @param string $value * * @throws InvalidFormatException * * @return static */ public static function fromSerialized($value) { $instance = @unserialize((string) $value); if (!$instance instanceof static) { throw new InvalidFormatException("Invalid serialized value: $value"); } return $instance; } /** * The __set_state handler. * * @param string|array $dump * * @return static */ #[ReturnTypeWillChange] public static function __set_state($dump) { if (\is_string($dump)) { return static::parse($dump); } /** @var \DateTimeInterface $date */ $date = get_parent_class(static::class) && method_exists(parent::class, '__set_state') ? parent::__set_state((array) $dump) : (object) $dump; return static::instance($date); } /** * Returns the list of properties to dump on serialize() called on. * * Only used by PHP < 7.4. * * @return array */ public function __sleep() { $properties = $this->getSleepProperties(); if ($this->localTranslator ?? null) { $properties[] = 'dumpLocale'; $this->dumpLocale = $this->locale ?? null; } return $properties; } /** * Returns the values to dump on serialize() called on. * * Only used by PHP >= 7.4. * * @return array */ public function __serialize(): array { // @codeCoverageIgnoreStart if (isset($this->timezone_type, $this->timezone, $this->date)) { return [ 'date' => $this->date ?? null, 'timezone_type' => $this->timezone_type, 'timezone' => $this->timezone ?? null, ]; } // @codeCoverageIgnoreEnd $timezone = $this->getTimezone(); $export = [ 'date' => $this->format('Y-m-d H:i:s.u'), 'timezone_type' => $timezone->getType(), 'timezone' => $timezone->getName(), ]; // @codeCoverageIgnoreStart if (\extension_loaded('msgpack') && isset($this->constructedObjectId)) { $export['dumpDateProperties'] = [ 'date' => $this->format('Y-m-d H:i:s.u'), 'timezone' => serialize($this->timezone ?? null), ]; } // @codeCoverageIgnoreEnd if ($this->localTranslator ?? null) { $export['dumpLocale'] = $this->locale ?? null; } return $export; } /** * Set locale if specified on unserialize() called. * * Only used by PHP < 7.4. * * @return void */ #[ReturnTypeWillChange] public function __wakeup() { if (parent::class && method_exists(parent::class, '__wakeup')) { // @codeCoverageIgnoreStart try { parent::__wakeup(); } catch (Throwable $exception) { try { // FatalError occurs when calling msgpack_unpack() in PHP 7.4 or later. ['date' => $date, 'timezone' => $timezone] = $this->dumpDateProperties; parent::__construct($date, unserialize($timezone)); } catch (Throwable $ignoredException) { throw $exception; } } // @codeCoverageIgnoreEnd } $this->constructedObjectId = spl_object_hash($this); if (isset($this->dumpLocale)) { $this->locale($this->dumpLocale); $this->dumpLocale = null; } $this->cleanupDumpProperties(); } /** * Set locale if specified on unserialize() called. * * Only used by PHP >= 7.4. * * @return void */ public function __unserialize(array $data): void { // @codeCoverageIgnoreStart try { $this->__construct($data['date'] ?? null, $data['timezone'] ?? null); } catch (Throwable $exception) { if (!isset($data['dumpDateProperties']['date'], $data['dumpDateProperties']['timezone'])) { throw $exception; } try { // FatalError occurs when calling msgpack_unpack() in PHP 7.4 or later. ['date' => $date, 'timezone' => $timezone] = $data['dumpDateProperties']; $this->__construct($date, unserialize($timezone)); } catch (Throwable $ignoredException) { throw $exception; } } // @codeCoverageIgnoreEnd if (isset($data['dumpLocale'])) { $this->locale($data['dumpLocale']); } } /** * Prepare the object for JSON serialization. * * @return array|string */ #[ReturnTypeWillChange] public function jsonSerialize() { $serializer = $this->localSerializer ?? static::$serializer; if ($serializer) { return \is_string($serializer) ? $this->rawFormat($serializer) : $serializer($this); } return $this->toJSON(); } /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather transform Carbon object before the serialization. * * JSON serialize all Carbon instances using the given callback. * * @param callable $callback * * @return void */ public static function serializeUsing($callback) { static::$serializer = $callback; } /** * Cleanup properties attached to the public scope of DateTime when a dump of the date is requested. * foreach ($date as $_) {} * serializer($date) * var_export($date) * get_object_vars($date) */ public function cleanupDumpProperties() { // @codeCoverageIgnoreStart if (PHP_VERSION < 8.2) { foreach ($this->dumpProperties as $property) { if (isset($this->$property)) { unset($this->$property); } } } // @codeCoverageIgnoreEnd return $this; } private function getSleepProperties(): array { $properties = $this->dumpProperties; // @codeCoverageIgnoreStart if (!\extension_loaded('msgpack')) { return $properties; } if (isset($this->constructedObjectId)) { $this->dumpDateProperties = [ 'date' => $this->format('Y-m-d H:i:s.u'), 'timezone' => serialize($this->timezone ?? null), ]; $properties[] = 'dumpDateProperties'; } return $properties; // @codeCoverageIgnoreEnd } } PK������<1Z-c����&��Carbon/Traits/ObjectInitialisation.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; trait ObjectInitialisation { /** * True when parent::__construct has been called. * * @var string */ protected $constructedObjectId; } PK������<1ZѭQ%,��%,����Carbon/Traits/Boundaries.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; use Carbon\Exceptions\UnknownUnitException; /** * Trait Boundaries. * * startOf, endOf and derived method for each unit. * * Depends on the following properties: * * @property int $year * @property int $month * @property int $daysInMonth * @property int $quarter * * Depends on the following methods: * * @method $this setTime(int $hour, int $minute, int $second = 0, int $microseconds = 0) * @method $this setDate(int $year, int $month, int $day) * @method $this addMonths(int $value = 1) */ trait Boundaries { /** * Resets the time to 00:00:00 start of day * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfDay(); * ``` * * @return static */ public function startOfDay() { return $this->setTime(0, 0, 0, 0); } /** * Resets the time to 23:59:59.999999 end of day * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfDay(); * ``` * * @return static */ public function endOfDay() { return $this->setTime(static::HOURS_PER_DAY - 1, static::MINUTES_PER_HOUR - 1, static::SECONDS_PER_MINUTE - 1, static::MICROSECONDS_PER_SECOND - 1); } /** * Resets the date to the first day of the month and the time to 00:00:00 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfMonth(); * ``` * * @return static */ public function startOfMonth() { return $this->setDate($this->year, $this->month, 1)->startOfDay(); } /** * Resets the date to end of the month and time to 23:59:59.999999 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfMonth(); * ``` * * @return static */ public function endOfMonth() { return $this->setDate($this->year, $this->month, $this->daysInMonth)->endOfDay(); } /** * Resets the date to the first day of the quarter and the time to 00:00:00 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfQuarter(); * ``` * * @return static */ public function startOfQuarter() { $month = ($this->quarter - 1) * static::MONTHS_PER_QUARTER + 1; return $this->setDate($this->year, $month, 1)->startOfDay(); } /** * Resets the date to end of the quarter and time to 23:59:59.999999 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfQuarter(); * ``` * * @return static */ public function endOfQuarter() { return $this->startOfQuarter()->addMonths(static::MONTHS_PER_QUARTER - 1)->endOfMonth(); } /** * Resets the date to the first day of the year and the time to 00:00:00 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfYear(); * ``` * * @return static */ public function startOfYear() { return $this->setDate($this->year, 1, 1)->startOfDay(); } /** * Resets the date to end of the year and time to 23:59:59.999999 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfYear(); * ``` * * @return static */ public function endOfYear() { return $this->setDate($this->year, 12, 31)->endOfDay(); } /** * Resets the date to the first day of the decade and the time to 00:00:00 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfDecade(); * ``` * * @return static */ public function startOfDecade() { $year = $this->year - $this->year % static::YEARS_PER_DECADE; return $this->setDate($year, 1, 1)->startOfDay(); } /** * Resets the date to end of the decade and time to 23:59:59.999999 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfDecade(); * ``` * * @return static */ public function endOfDecade() { $year = $this->year - $this->year % static::YEARS_PER_DECADE + static::YEARS_PER_DECADE - 1; return $this->setDate($year, 12, 31)->endOfDay(); } /** * Resets the date to the first day of the century and the time to 00:00:00 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfCentury(); * ``` * * @return static */ public function startOfCentury() { $year = $this->year - ($this->year - 1) % static::YEARS_PER_CENTURY; return $this->setDate($year, 1, 1)->startOfDay(); } /** * Resets the date to end of the century and time to 23:59:59.999999 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfCentury(); * ``` * * @return static */ public function endOfCentury() { $year = $this->year - 1 - ($this->year - 1) % static::YEARS_PER_CENTURY + static::YEARS_PER_CENTURY; return $this->setDate($year, 12, 31)->endOfDay(); } /** * Resets the date to the first day of the millennium and the time to 00:00:00 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfMillennium(); * ``` * * @return static */ public function startOfMillennium() { $year = $this->year - ($this->year - 1) % static::YEARS_PER_MILLENNIUM; return $this->setDate($year, 1, 1)->startOfDay(); } /** * Resets the date to end of the millennium and time to 23:59:59.999999 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfMillennium(); * ``` * * @return static */ public function endOfMillennium() { $year = $this->year - 1 - ($this->year - 1) % static::YEARS_PER_MILLENNIUM + static::YEARS_PER_MILLENNIUM; return $this->setDate($year, 12, 31)->endOfDay(); } /** * Resets the date to the first day of week (defined in $weekStartsAt) and the time to 00:00:00 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfWeek() . "\n"; * echo Carbon::parse('2018-07-25 12:45:16')->locale('ar')->startOfWeek() . "\n"; * echo Carbon::parse('2018-07-25 12:45:16')->startOfWeek(Carbon::SUNDAY) . "\n"; * ``` * * @param int $weekStartsAt optional start allow you to specify the day of week to use to start the week * * @return static */ public function startOfWeek($weekStartsAt = null) { return $this->subDays((7 + $this->dayOfWeek - ($weekStartsAt ?? $this->firstWeekDay)) % 7)->startOfDay(); } /** * Resets the date to end of week (defined in $weekEndsAt) and time to 23:59:59.999999 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfWeek() . "\n"; * echo Carbon::parse('2018-07-25 12:45:16')->locale('ar')->endOfWeek() . "\n"; * echo Carbon::parse('2018-07-25 12:45:16')->endOfWeek(Carbon::SATURDAY) . "\n"; * ``` * * @param int $weekEndsAt optional start allow you to specify the day of week to use to end the week * * @return static */ public function endOfWeek($weekEndsAt = null) { return $this->addDays((7 - $this->dayOfWeek + ($weekEndsAt ?? $this->lastWeekDay)) % 7)->endOfDay(); } /** * Modify to start of current hour, minutes and seconds become 0 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfHour(); * ``` * * @return static */ public function startOfHour() { return $this->setTime($this->hour, 0, 0, 0); } /** * Modify to end of current hour, minutes and seconds become 59 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfHour(); * ``` * * @return static */ public function endOfHour() { return $this->setTime($this->hour, static::MINUTES_PER_HOUR - 1, static::SECONDS_PER_MINUTE - 1, static::MICROSECONDS_PER_SECOND - 1); } /** * Modify to start of current minute, seconds become 0 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->startOfMinute(); * ``` * * @return static */ public function startOfMinute() { return $this->setTime($this->hour, $this->minute, 0, 0); } /** * Modify to end of current minute, seconds become 59 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16')->endOfMinute(); * ``` * * @return static */ public function endOfMinute() { return $this->setTime($this->hour, $this->minute, static::SECONDS_PER_MINUTE - 1, static::MICROSECONDS_PER_SECOND - 1); } /** * Modify to start of current second, microseconds become 0 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16.334455') * ->startOfSecond() * ->format('H:i:s.u'); * ``` * * @return static */ public function startOfSecond() { return $this->setTime($this->hour, $this->minute, $this->second, 0); } /** * Modify to end of current second, microseconds become 999999 * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16.334455') * ->endOfSecond() * ->format('H:i:s.u'); * ``` * * @return static */ public function endOfSecond() { return $this->setTime($this->hour, $this->minute, $this->second, static::MICROSECONDS_PER_SECOND - 1); } /** * Modify to start of current given unit. * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16.334455') * ->startOf('month') * ->endOf('week', Carbon::FRIDAY); * ``` * * @param string $unit * @param array<int, mixed> $params * * @return static */ public function startOf($unit, ...$params) { $ucfUnit = ucfirst(static::singularUnit($unit)); $method = "startOf$ucfUnit"; if (!method_exists($this, $method)) { throw new UnknownUnitException($unit); } return $this->$method(...$params); } /** * Modify to end of current given unit. * * @example * ``` * echo Carbon::parse('2018-07-25 12:45:16.334455') * ->startOf('month') * ->endOf('week', Carbon::FRIDAY); * ``` * * @param string $unit * @param array<int, mixed> $params * * @return static */ public function endOf($unit, ...$params) { $ucfUnit = ucfirst(static::singularUnit($unit)); $method = "endOf$ucfUnit"; if (!method_exists($this, $method)) { throw new UnknownUnitException($unit); } return $this->$method(...$params); } } PK������<1Z5��5����Carbon/Traits/Modifiers.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon\Traits; use Carbon\CarbonInterface; use ReturnTypeWillChange; /** * Trait Modifiers. * * Returns dates relative to current date using modifier short-hand. */ trait Modifiers { /** * Midday/noon hour. * * @var int */ protected static $midDayAt = 12; /** * get midday/noon hour * * @return int */ public static function getMidDayAt() { return static::$midDayAt; } /** * @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather consider mid-day is always 12pm, then if you need to test if it's an other * hour, test it explicitly: * $date->format('G') == 13 * or to set explicitly to a given hour: * $date->setTime(13, 0, 0, 0) * * Set midday/noon hour * * @param int $hour midday hour * * @return void */ public static function setMidDayAt($hour) { static::$midDayAt = $hour; } /** * Modify to midday, default to self::$midDayAt * * @return static */ public function midDay() { return $this->setTime(static::$midDayAt, 0, 0, 0); } /** * Modify to the next occurrence of a given modifier such as a day of * the week. If no modifier is provided, modify to the next occurrence * of the current day of the week. Use the supplied constants * to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param string|int|null $modifier * * @return static|false */ public function next($modifier = null) { if ($modifier === null) { $modifier = $this->dayOfWeek; } return $this->change( 'next '.(\is_string($modifier) ? $modifier : static::$days[$modifier]) ); } /** * Go forward or backward to the next week- or weekend-day. * * @param bool $weekday * @param bool $forward * * @return static */ private function nextOrPreviousDay($weekday = true, $forward = true) { /** @var CarbonInterface $date */ $date = $this; $step = $forward ? 1 : -1; do { $date = $date->addDays($step); } while ($weekday ? $date->isWeekend() : $date->isWeekday()); return $date; } /** * Go forward to the next weekday. * * @return static */ public function nextWeekday() { return $this->nextOrPreviousDay(); } /** * Go backward to the previous weekday. * * @return static */ public function previousWeekday() { return $this->nextOrPreviousDay(true, false); } /** * Go forward to the next weekend day. * * @return static */ public function nextWeekendDay() { return $this->nextOrPreviousDay(false); } /** * Go backward to the previous weekend day. * * @return static */ public function previousWeekendDay() { return $this->nextOrPreviousDay(false, false); } /** * Modify to the previous occurrence of a given modifier such as a day of * the week. If no dayOfWeek is provided, modify to the previous occurrence * of the current day of the week. Use the supplied constants * to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param string|int|null $modifier * * @return static|false */ public function previous($modifier = null) { if ($modifier === null) { $modifier = $this->dayOfWeek; } return $this->change( 'last '.(\is_string($modifier) ? $modifier : static::$days[$modifier]) ); } /** * Modify to the first occurrence of a given day of the week * in the current month. If no dayOfWeek is provided, modify to the * first day of the current month. Use the supplied constants * to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param int|null $dayOfWeek * * @return static */ public function firstOfMonth($dayOfWeek = null) { $date = $this->startOfDay(); if ($dayOfWeek === null) { return $date->day(1); } return $date->modify('first '.static::$days[$dayOfWeek].' of '.$date->rawFormat('F').' '.$date->year); } /** * Modify to the last occurrence of a given day of the week * in the current month. If no dayOfWeek is provided, modify to the * last day of the current month. Use the supplied constants * to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param int|null $dayOfWeek * * @return static */ public function lastOfMonth($dayOfWeek = null) { $date = $this->startOfDay(); if ($dayOfWeek === null) { return $date->day($date->daysInMonth); } return $date->modify('last '.static::$days[$dayOfWeek].' of '.$date->rawFormat('F').' '.$date->year); } /** * Modify to the given occurrence of a given day of the week * in the current month. If the calculated occurrence is outside the scope * of the current month, then return false and no modifications are made. * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param int $nth * @param int $dayOfWeek * * @return mixed */ public function nthOfMonth($nth, $dayOfWeek) { $date = $this->avoidMutation()->firstOfMonth(); $check = $date->rawFormat('Y-m'); $date = $date->modify('+'.$nth.' '.static::$days[$dayOfWeek]); return $date->rawFormat('Y-m') === $check ? $this->modify((string) $date) : false; } /** * Modify to the first occurrence of a given day of the week * in the current quarter. If no dayOfWeek is provided, modify to the * first day of the current quarter. Use the supplied constants * to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param int|null $dayOfWeek day of the week default null * * @return static */ public function firstOfQuarter($dayOfWeek = null) { return $this->setDate($this->year, $this->quarter * static::MONTHS_PER_QUARTER - 2, 1)->firstOfMonth($dayOfWeek); } /** * Modify to the last occurrence of a given day of the week * in the current quarter. If no dayOfWeek is provided, modify to the * last day of the current quarter. Use the supplied constants * to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param int|null $dayOfWeek day of the week default null * * @return static */ public function lastOfQuarter($dayOfWeek = null) { return $this->setDate($this->year, $this->quarter * static::MONTHS_PER_QUARTER, 1)->lastOfMonth($dayOfWeek); } /** * Modify to the given occurrence of a given day of the week * in the current quarter. If the calculated occurrence is outside the scope * of the current quarter, then return false and no modifications are made. * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param int $nth * @param int $dayOfWeek * * @return mixed */ public function nthOfQuarter($nth, $dayOfWeek) { $date = $this->avoidMutation()->day(1)->month($this->quarter * static::MONTHS_PER_QUARTER); $lastMonth = $date->month; $year = $date->year; $date = $date->firstOfQuarter()->modify('+'.$nth.' '.static::$days[$dayOfWeek]); return ($lastMonth < $date->month || $year !== $date->year) ? false : $this->modify((string) $date); } /** * Modify to the first occurrence of a given day of the week * in the current year. If no dayOfWeek is provided, modify to the * first day of the current year. Use the supplied constants * to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param int|null $dayOfWeek day of the week default null * * @return static */ public function firstOfYear($dayOfWeek = null) { return $this->month(1)->firstOfMonth($dayOfWeek); } /** * Modify to the last occurrence of a given day of the week * in the current year. If no dayOfWeek is provided, modify to the * last day of the current year. Use the supplied constants * to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param int|null $dayOfWeek day of the week default null * * @return static */ public function lastOfYear($dayOfWeek = null) { return $this->month(static::MONTHS_PER_YEAR)->lastOfMonth($dayOfWeek); } /** * Modify to the given occurrence of a given day of the week * in the current year. If the calculated occurrence is outside the scope * of the current year, then return false and no modifications are made. * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY. * * @param int $nth * @param int $dayOfWeek * * @return mixed */ public function nthOfYear($nth, $dayOfWeek) { $date = $this->avoidMutation()->firstOfYear()->modify('+'.$nth.' '.static::$days[$dayOfWeek]); return $this->year === $date->year ? $this->modify((string) $date) : false; } /** * Modify the current instance to the average of a given instance (default now) and the current instance * (second-precision). * * @param \Carbon\Carbon|\DateTimeInterface|null $date * * @return static */ public function average($date = null) { return $this->addRealMicroseconds((int) ($this->diffInRealMicroseconds($this->resolveCarbon($date), false) / 2)); } /** * Get the closest date from the instance (second-precision). * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1 * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2 * * @return static */ public function closest($date1, $date2) { return $this->diffInRealMicroseconds($date1) < $this->diffInRealMicroseconds($date2) ? $date1 : $date2; } /** * Get the farthest date from the instance (second-precision). * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1 * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2 * * @return static */ public function farthest($date1, $date2) { return $this->diffInRealMicroseconds($date1) > $this->diffInRealMicroseconds($date2) ? $date1 : $date2; } /** * Get the minimum instance between a given instance (default now) and the current instance. * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @return static */ public function min($date = null) { $date = $this->resolveCarbon($date); return $this->lt($date) ? $this : $date; } /** * Get the minimum instance between a given instance (default now) and the current instance. * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see min() * * @return static */ public function minimum($date = null) { return $this->min($date); } /** * Get the maximum instance between a given instance (default now) and the current instance. * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @return static */ public function max($date = null) { $date = $this->resolveCarbon($date); return $this->gt($date) ? $this : $date; } /** * Get the maximum instance between a given instance (default now) and the current instance. * * @param \Carbon\Carbon|\DateTimeInterface|mixed $date * * @see max() * * @return static */ public function maximum($date = null) { return $this->max($date); } /** * Calls \DateTime::modify if mutable or \DateTimeImmutable::modify else. * * @see https://php.net/manual/en/datetime.modify.php * * @return static|false */ #[ReturnTypeWillChange] public function modify($modify) { return parent::modify((string) $modify); } /** * Similar to native modify() method of DateTime but can handle more grammars. * * @example * ``` * echo Carbon::now()->change('next 2pm'); * ``` * * @link https://php.net/manual/en/datetime.modify.php * * @param string $modifier * * @return static|false */ public function change($modifier) { return $this->modify(preg_replace_callback('/^(next|previous|last)\s+(\d{1,2}(h|am|pm|:\d{1,2}(:\d{1,2})?))$/i', function ($match) { $match[2] = str_replace('h', ':00', $match[2]); $test = $this->avoidMutation()->modify($match[2]); $method = $match[1] === 'next' ? 'lt' : 'gt'; $match[1] = $test->$method($this) ? $match[1].' day' : 'today'; return $match[1].' '.$match[2]; }, strtr(trim($modifier), [ ' at ' => ' ', 'just now' => 'now', 'after tomorrow' => 'tomorrow +1 day', 'before yesterday' => 'yesterday -1 day', ]))); } } PK������<1Z.mvqK�qK���Carbon/CarbonPeriod.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon; use Carbon\Exceptions\EndLessPeriodException; use Carbon\Exceptions\InvalidCastException; use Carbon\Exceptions\InvalidIntervalException; use Carbon\Exceptions\InvalidPeriodDateException; use Carbon\Exceptions\InvalidPeriodParameterException; use Carbon\Exceptions\NotACarbonClassException; use Carbon\Exceptions\NotAPeriodException; use Carbon\Exceptions\UnknownGetterException; use Carbon\Exceptions\UnknownMethodException; use Carbon\Exceptions\UnreachableException; use Carbon\Traits\IntervalRounding; use Carbon\Traits\Mixin; use Carbon\Traits\Options; use Carbon\Traits\ToStringFormat; use Closure; use Countable; use DateInterval; use DatePeriod; use DateTime; use DateTimeImmutable; use DateTimeInterface; use DateTimeZone; use InvalidArgumentException; use Iterator; use JsonSerializable; use ReflectionException; use ReturnTypeWillChange; use RuntimeException; /** * Substitution of DatePeriod with some modifications and many more features. * * @property-read int|float $recurrences number of recurrences (if end not set). * @property-read bool $include_start_date rather the start date is included in the iteration. * @property-read bool $include_end_date rather the end date is included in the iteration (if recurrences not set). * @property-read CarbonInterface $start Period start date. * @property-read CarbonInterface $current Current date from the iteration. * @property-read CarbonInterface $end Period end date. * @property-read CarbonInterval $interval Underlying date interval instance. Always present, one day by default. * * @method static static start($date, $inclusive = null) Create instance specifying start date or modify the start date if called on an instance. * @method static static since($date, $inclusive = null) Alias for start(). * @method static static sinceNow($inclusive = null) Create instance with start date set to now or set the start date to now if called on an instance. * @method static static end($date = null, $inclusive = null) Create instance specifying end date or modify the end date if called on an instance. * @method static static until($date = null, $inclusive = null) Alias for end(). * @method static static untilNow($inclusive = null) Create instance with end date set to now or set the end date to now if called on an instance. * @method static static dates($start, $end = null) Create instance with start and end dates or modify the start and end dates if called on an instance. * @method static static between($start, $end = null) Create instance with start and end dates or modify the start and end dates if called on an instance. * @method static static recurrences($recurrences = null) Create instance with maximum number of recurrences or modify the number of recurrences if called on an instance. * @method static static times($recurrences = null) Alias for recurrences(). * @method static static options($options = null) Create instance with options or modify the options if called on an instance. * @method static static toggle($options, $state = null) Create instance with options toggled on or off, or toggle options if called on an instance. * @method static static filter($callback, $name = null) Create instance with filter added to the stack or append a filter if called on an instance. * @method static static push($callback, $name = null) Alias for filter(). * @method static static prepend($callback, $name = null) Create instance with filter prepended to the stack or prepend a filter if called on an instance. * @method static static filters(array $filters = []) Create instance with filters stack or replace the whole filters stack if called on an instance. * @method static static interval($interval) Create instance with given date interval or modify the interval if called on an instance. * @method static static each($interval) Create instance with given date interval or modify the interval if called on an instance. * @method static static every($interval) Create instance with given date interval or modify the interval if called on an instance. * @method static static step($interval) Create instance with given date interval or modify the interval if called on an instance. * @method static static stepBy($interval) Create instance with given date interval or modify the interval if called on an instance. * @method static static invert() Create instance with inverted date interval or invert the interval if called on an instance. * @method static static years($years = 1) Create instance specifying a number of years for date interval or replace the interval by the given a number of years if called on an instance. * @method static static year($years = 1) Alias for years(). * @method static static months($months = 1) Create instance specifying a number of months for date interval or replace the interval by the given a number of months if called on an instance. * @method static static month($months = 1) Alias for months(). * @method static static weeks($weeks = 1) Create instance specifying a number of weeks for date interval or replace the interval by the given a number of weeks if called on an instance. * @method static static week($weeks = 1) Alias for weeks(). * @method static static days($days = 1) Create instance specifying a number of days for date interval or replace the interval by the given a number of days if called on an instance. * @method static static dayz($days = 1) Alias for days(). * @method static static day($days = 1) Alias for days(). * @method static static hours($hours = 1) Create instance specifying a number of hours for date interval or replace the interval by the given a number of hours if called on an instance. * @method static static hour($hours = 1) Alias for hours(). * @method static static minutes($minutes = 1) Create instance specifying a number of minutes for date interval or replace the interval by the given a number of minutes if called on an instance. * @method static static minute($minutes = 1) Alias for minutes(). * @method static static seconds($seconds = 1) Create instance specifying a number of seconds for date interval or replace the interval by the given a number of seconds if called on an instance. * @method static static second($seconds = 1) Alias for seconds(). * @method static static milliseconds($milliseconds = 1) Create instance specifying a number of milliseconds for date interval or replace the interval by the given a number of milliseconds if called on an instance. * @method static static millisecond($milliseconds = 1) Alias for milliseconds(). * @method static static microseconds($microseconds = 1) Create instance specifying a number of microseconds for date interval or replace the interval by the given a number of microseconds if called on an instance. * @method static static microsecond($microseconds = 1) Alias for microseconds(). * @method $this roundYear(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function. * @method $this roundYears(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function. * @method $this floorYear(float $precision = 1) Truncate the current instance year with given precision. * @method $this floorYears(float $precision = 1) Truncate the current instance year with given precision. * @method $this ceilYear(float $precision = 1) Ceil the current instance year with given precision. * @method $this ceilYears(float $precision = 1) Ceil the current instance year with given precision. * @method $this roundMonth(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function. * @method $this roundMonths(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function. * @method $this floorMonth(float $precision = 1) Truncate the current instance month with given precision. * @method $this floorMonths(float $precision = 1) Truncate the current instance month with given precision. * @method $this ceilMonth(float $precision = 1) Ceil the current instance month with given precision. * @method $this ceilMonths(float $precision = 1) Ceil the current instance month with given precision. * @method $this roundWeek(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function. * @method $this roundWeeks(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function. * @method $this floorWeek(float $precision = 1) Truncate the current instance day with given precision. * @method $this floorWeeks(float $precision = 1) Truncate the current instance day with given precision. * @method $this ceilWeek(float $precision = 1) Ceil the current instance day with given precision. * @method $this ceilWeeks(float $precision = 1) Ceil the current instance day with given precision. * @method $this roundDay(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function. * @method $this roundDays(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function. * @method $this floorDay(float $precision = 1) Truncate the current instance day with given precision. * @method $this floorDays(float $precision = 1) Truncate the current instance day with given precision. * @method $this ceilDay(float $precision = 1) Ceil the current instance day with given precision. * @method $this ceilDays(float $precision = 1) Ceil the current instance day with given precision. * @method $this roundHour(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function. * @method $this roundHours(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function. * @method $this floorHour(float $precision = 1) Truncate the current instance hour with given precision. * @method $this floorHours(float $precision = 1) Truncate the current instance hour with given precision. * @method $this ceilHour(float $precision = 1) Ceil the current instance hour with given precision. * @method $this ceilHours(float $precision = 1) Ceil the current instance hour with given precision. * @method $this roundMinute(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function. * @method $this roundMinutes(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function. * @method $this floorMinute(float $precision = 1) Truncate the current instance minute with given precision. * @method $this floorMinutes(float $precision = 1) Truncate the current instance minute with given precision. * @method $this ceilMinute(float $precision = 1) Ceil the current instance minute with given precision. * @method $this ceilMinutes(float $precision = 1) Ceil the current instance minute with given precision. * @method $this roundSecond(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function. * @method $this roundSeconds(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function. * @method $this floorSecond(float $precision = 1) Truncate the current instance second with given precision. * @method $this floorSeconds(float $precision = 1) Truncate the current instance second with given precision. * @method $this ceilSecond(float $precision = 1) Ceil the current instance second with given precision. * @method $this ceilSeconds(float $precision = 1) Ceil the current instance second with given precision. * @method $this roundMillennium(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function. * @method $this roundMillennia(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function. * @method $this floorMillennium(float $precision = 1) Truncate the current instance millennium with given precision. * @method $this floorMillennia(float $precision = 1) Truncate the current instance millennium with given precision. * @method $this ceilMillennium(float $precision = 1) Ceil the current instance millennium with given precision. * @method $this ceilMillennia(float $precision = 1) Ceil the current instance millennium with given precision. * @method $this roundCentury(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function. * @method $this roundCenturies(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function. * @method $this floorCentury(float $precision = 1) Truncate the current instance century with given precision. * @method $this floorCenturies(float $precision = 1) Truncate the current instance century with given precision. * @method $this ceilCentury(float $precision = 1) Ceil the current instance century with given precision. * @method $this ceilCenturies(float $precision = 1) Ceil the current instance century with given precision. * @method $this roundDecade(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function. * @method $this roundDecades(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function. * @method $this floorDecade(float $precision = 1) Truncate the current instance decade with given precision. * @method $this floorDecades(float $precision = 1) Truncate the current instance decade with given precision. * @method $this ceilDecade(float $precision = 1) Ceil the current instance decade with given precision. * @method $this ceilDecades(float $precision = 1) Ceil the current instance decade with given precision. * @method $this roundQuarter(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function. * @method $this roundQuarters(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function. * @method $this floorQuarter(float $precision = 1) Truncate the current instance quarter with given precision. * @method $this floorQuarters(float $precision = 1) Truncate the current instance quarter with given precision. * @method $this ceilQuarter(float $precision = 1) Ceil the current instance quarter with given precision. * @method $this ceilQuarters(float $precision = 1) Ceil the current instance quarter with given precision. * @method $this roundMillisecond(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function. * @method $this roundMilliseconds(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function. * @method $this floorMillisecond(float $precision = 1) Truncate the current instance millisecond with given precision. * @method $this floorMilliseconds(float $precision = 1) Truncate the current instance millisecond with given precision. * @method $this ceilMillisecond(float $precision = 1) Ceil the current instance millisecond with given precision. * @method $this ceilMilliseconds(float $precision = 1) Ceil the current instance millisecond with given precision. * @method $this roundMicrosecond(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function. * @method $this roundMicroseconds(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function. * @method $this floorMicrosecond(float $precision = 1) Truncate the current instance microsecond with given precision. * @method $this floorMicroseconds(float $precision = 1) Truncate the current instance microsecond with given precision. * @method $this ceilMicrosecond(float $precision = 1) Ceil the current instance microsecond with given precision. * @method $this ceilMicroseconds(float $precision = 1) Ceil the current instance microsecond with given precision. * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CarbonPeriod implements Iterator, Countable, JsonSerializable { use IntervalRounding; use Mixin { Mixin::mixin as baseMixin; } use Options; use ToStringFormat; /** * Built-in filter for limit by recurrences. * * @var callable */ public const RECURRENCES_FILTER = [self::class, 'filterRecurrences']; /** * Built-in filter for limit to an end. * * @var callable */ public const END_DATE_FILTER = [self::class, 'filterEndDate']; /** * Special value which can be returned by filters to end iteration. Also a filter. * * @var callable */ public const END_ITERATION = [self::class, 'endIteration']; /** * Exclude start date from iteration. * * @var int */ public const EXCLUDE_START_DATE = 1; /** * Exclude end date from iteration. * * @var int */ public const EXCLUDE_END_DATE = 2; /** * Yield CarbonImmutable instances. * * @var int */ public const IMMUTABLE = 4; /** * Number of maximum attempts before giving up on finding next valid date. * * @var int */ public const NEXT_MAX_ATTEMPTS = 1000; /** * Number of maximum attempts before giving up on finding end date. * * @var int */ public const END_MAX_ATTEMPTS = 10000; /** * Default date class of iteration items. * * @var string */ protected const DEFAULT_DATE_CLASS = Carbon::class; /** * The registered macros. * * @var array */ protected static $macros = []; /** * Date class of iteration items. * * @var string */ protected $dateClass = Carbon::class; /** * Underlying date interval instance. Always present, one day by default. * * @var CarbonInterval */ protected $dateInterval; /** * True once __construct is finished. * * @var bool */ protected $constructed = false; /** * Whether current date interval was set by default. * * @var bool */ protected $isDefaultInterval; /** * The filters stack. * * @var array */ protected $filters = []; /** * Period start date. Applied on rewind. Always present, now by default. * * @var CarbonInterface */ protected $startDate; /** * Period end date. For inverted interval should be before the start date. Applied via a filter. * * @var CarbonInterface|null */ protected $endDate; /** * Limit for number of recurrences. Applied via a filter. * * @var int|null */ protected $recurrences; /** * Iteration options. * * @var int */ protected $options; /** * Index of current date. Always sequential, even if some dates are skipped by filters. * Equal to null only before the first iteration. * * @var int */ protected $key; /** * Current date. May temporarily hold unaccepted value when looking for a next valid date. * Equal to null only before the first iteration. * * @var CarbonInterface */ protected $current; /** * Timezone of current date. Taken from the start date. * * @var \DateTimeZone|null */ protected $timezone; /** * The cached validation result for current date. * * @var bool|string|null */ protected $validationResult; /** * Timezone handler for settings() method. * * @var mixed */ protected $tzName; /** * Make a CarbonPeriod instance from given variable if possible. * * @param mixed $var * * @return static|null */ public static function make($var) { try { return static::instance($var); } catch (NotAPeriodException $e) { return static::create($var); } } /** * Create a new instance from a DatePeriod or CarbonPeriod object. * * @param CarbonPeriod|DatePeriod $period * * @return static */ public static function instance($period) { if ($period instanceof static) { return $period->copy(); } if ($period instanceof self) { return new static( $period->getStartDate(), $period->getEndDate() ?: $period->getRecurrences(), $period->getDateInterval(), $period->getOptions() ); } if ($period instanceof DatePeriod) { return new static( $period->start, $period->end ?: ($period->recurrences - 1), $period->interval, $period->include_start_date ? 0 : static::EXCLUDE_START_DATE ); } $class = static::class; $type = \gettype($period); throw new NotAPeriodException( 'Argument 1 passed to '.$class.'::'.__METHOD__.'() '. 'must be an instance of DatePeriod or '.$class.', '. ($type === 'object' ? 'instance of '.\get_class($period) : $type).' given.' ); } /** * Create a new instance. * * @return static */ public static function create(...$params) { return static::createFromArray($params); } /** * Create a new instance from an array of parameters. * * @param array $params * * @return static */ public static function createFromArray(array $params) { return new static(...$params); } /** * Create CarbonPeriod from ISO 8601 string. * * @param string $iso * @param int|null $options * * @return static */ public static function createFromIso($iso, $options = null) { $params = static::parseIso8601($iso); $instance = static::createFromArray($params); if ($options !== null) { $instance->setOptions($options); } return $instance; } /** * Return whether given interval contains non zero value of any time unit. * * @param \DateInterval $interval * * @return bool */ protected static function intervalHasTime(DateInterval $interval) { return $interval->h || $interval->i || $interval->s || $interval->f; } /** * Return whether given variable is an ISO 8601 specification. * * Note: Check is very basic, as actual validation will be done later when parsing. * We just want to ensure that variable is not any other type of a valid parameter. * * @param mixed $var * * @return bool */ protected static function isIso8601($var) { if (!\is_string($var)) { return false; } // Match slash but not within a timezone name. $part = '[a-z]+(?:[_-][a-z]+)*'; preg_match("#\b$part/$part\b|(/)#i", $var, $match); return isset($match[1]); } /** * Parse given ISO 8601 string into an array of arguments. * * @SuppressWarnings(PHPMD.ElseExpression) * * @param string $iso * * @return array */ protected static function parseIso8601($iso) { $result = []; $interval = null; $start = null; $end = null; $dateClass = static::DEFAULT_DATE_CLASS; foreach (explode('/', $iso) as $key => $part) { if ($key === 0 && preg_match('/^R(\d*|INF)$/', $part, $match)) { $parsed = \strlen($match[1]) ? (($match[1] !== 'INF') ? (int) $match[1] : INF) : null; } elseif ($interval === null && $parsed = CarbonInterval::make($part)) { $interval = $part; } elseif ($start === null && $parsed = $dateClass::make($part)) { $start = $part; } elseif ($end === null && $parsed = $dateClass::make(static::addMissingParts($start ?? '', $part))) { $end = $part; } else { throw new InvalidPeriodParameterException("Invalid ISO 8601 specification: $iso."); } $result[] = $parsed; } return $result; } /** * Add missing parts of the target date from the source date. * * @param string $source * @param string $target * * @return string */ protected static function addMissingParts($source, $target) { $pattern = '/'.preg_replace('/\d+/', '[0-9]+', preg_quote($target, '/')).'$/'; $result = preg_replace($pattern, $target, $source, 1, $count); return $count ? $result : $target; } /** * Register a custom macro. * * @example * ``` * CarbonPeriod::macro('middle', function () { * return $this->getStartDate()->average($this->getEndDate()); * }); * echo CarbonPeriod::since('2011-05-12')->until('2011-06-03')->middle(); * ``` * * @param string $name * @param object|callable $macro * * @return void */ public static function macro($name, $macro) { static::$macros[$name] = $macro; } /** * Register macros from a mixin object. * * @example * ``` * CarbonPeriod::mixin(new class { * public function addDays() { * return function ($count = 1) { * return $this->setStartDate( * $this->getStartDate()->addDays($count) * )->setEndDate( * $this->getEndDate()->addDays($count) * ); * }; * } * public function subDays() { * return function ($count = 1) { * return $this->setStartDate( * $this->getStartDate()->subDays($count) * )->setEndDate( * $this->getEndDate()->subDays($count) * ); * }; * } * }); * echo CarbonPeriod::create('2000-01-01', '2000-02-01')->addDays(5)->subDays(3); * ``` * * @param object|string $mixin * * @throws ReflectionException * * @return void */ public static function mixin($mixin) { static::baseMixin($mixin); } /** * Check if macro is registered. * * @param string $name * * @return bool */ public static function hasMacro($name) { return isset(static::$macros[$name]); } /** * Provide static proxy for instance aliases. * * @param string $method * @param array $parameters * * @return mixed */ public static function __callStatic($method, $parameters) { $date = new static(); if (static::hasMacro($method)) { return static::bindMacroContext(null, function () use (&$method, &$parameters, &$date) { return $date->callMacro($method, $parameters); }); } return $date->$method(...$parameters); } /** * CarbonPeriod constructor. * * @SuppressWarnings(PHPMD.ElseExpression) * * @throws InvalidArgumentException */ public function __construct(...$arguments) { if (is_a($this->dateClass, DateTimeImmutable::class, true)) { $this->options = static::IMMUTABLE; } // Parse and assign arguments one by one. First argument may be an ISO 8601 spec, // which will be first parsed into parts and then processed the same way. $argumentsCount = \count($arguments); if ($argumentsCount && static::isIso8601($iso = $arguments[0])) { array_splice($arguments, 0, 1, static::parseIso8601($iso)); } if ($argumentsCount === 1) { if ($arguments[0] instanceof DatePeriod) { $arguments = [ $arguments[0]->start, $arguments[0]->end ?: ($arguments[0]->recurrences - 1), $arguments[0]->interval, $arguments[0]->include_start_date ? 0 : static::EXCLUDE_START_DATE, ]; } elseif ($arguments[0] instanceof self) { $arguments = [ $arguments[0]->getStartDate(), $arguments[0]->getEndDate() ?: $arguments[0]->getRecurrences(), $arguments[0]->getDateInterval(), $arguments[0]->getOptions(), ]; } } $optionsSet = false; foreach ($arguments as $argument) { $parsedDate = null; if ($argument instanceof DateTimeZone) { $this->setTimezone($argument); } elseif ($this->dateInterval === null && ( (\is_string($argument) && preg_match( '/^(-?\d(\d(?![\/-])|[^\d\/-]([\/-])?)*|P[T\d].*|(?:\h*\d+(?:\.\d+)?\h*[a-z]+)+)$/i', $argument )) || $argument instanceof DateInterval || $argument instanceof Closure ) && $parsedInterval = @CarbonInterval::make($argument) ) { $this->setDateInterval($parsedInterval); } elseif ($this->startDate === null && $parsedDate = $this->makeDateTime($argument)) { $this->setStartDate($parsedDate); } elseif ($this->endDate === null && ($parsedDate = $parsedDate ?? $this->makeDateTime($argument))) { $this->setEndDate($parsedDate); } elseif ($this->recurrences === null && $this->endDate === null && is_numeric($argument)) { $this->setRecurrences($argument); } elseif (!$optionsSet && (\is_int($argument) || $argument === null)) { $optionsSet = true; $this->setOptions(((int) $this->options) | ((int) $argument)); } else { throw new InvalidPeriodParameterException('Invalid constructor parameters.'); } } if ($this->startDate === null) { $dateClass = $this->dateClass; $this->setStartDate($dateClass::now()); } if ($this->dateInterval === null) { $this->setDateInterval(CarbonInterval::day()); $this->isDefaultInterval = true; } if ($this->options === null) { $this->setOptions(0); } $this->constructed = true; } /** * Get a copy of the instance. * * @return static */ public function copy() { return clone $this; } /** * Prepare the instance to be set (self if mutable to be mutated, * copy if immutable to generate a new instance). * * @return static */ protected function copyIfImmutable() { return $this; } /** * Get the getter for a property allowing both `DatePeriod` snakeCase and camelCase names. * * @param string $name * * @return callable|null */ protected function getGetter(string $name) { switch (strtolower(preg_replace('/[A-Z]/', '_$0', $name))) { case 'start': case 'start_date': return [$this, 'getStartDate']; case 'end': case 'end_date': return [$this, 'getEndDate']; case 'interval': case 'date_interval': return [$this, 'getDateInterval']; case 'recurrences': return [$this, 'getRecurrences']; case 'include_start_date': return [$this, 'isStartIncluded']; case 'include_end_date': return [$this, 'isEndIncluded']; case 'current': return [$this, 'current']; default: return null; } } /** * Get a property allowing both `DatePeriod` snakeCase and camelCase names. * * @param string $name * * @return bool|CarbonInterface|CarbonInterval|int|null */ public function get(string $name) { $getter = $this->getGetter($name); if ($getter) { return $getter(); } throw new UnknownGetterException($name); } /** * Get a property allowing both `DatePeriod` snakeCase and camelCase names. * * @param string $name * * @return bool|CarbonInterface|CarbonInterval|int|null */ public function __get(string $name) { return $this->get($name); } /** * Check if an attribute exists on the object * * @param string $name * * @return bool */ public function __isset(string $name): bool { return $this->getGetter($name) !== null; } /** * @alias copy * * Get a copy of the instance. * * @return static */ public function clone() { return clone $this; } /** * Set the iteration item class. * * @param string $dateClass * * @return static */ public function setDateClass(string $dateClass) { if (!is_a($dateClass, CarbonInterface::class, true)) { throw new NotACarbonClassException($dateClass); } $self = $this->copyIfImmutable(); $self->dateClass = $dateClass; if (is_a($dateClass, Carbon::class, true)) { $self->options = $self->options & ~static::IMMUTABLE; } elseif (is_a($dateClass, CarbonImmutable::class, true)) { $self->options = $self->options | static::IMMUTABLE; } return $self; } /** * Returns iteration item date class. * * @return string */ public function getDateClass(): string { return $this->dateClass; } /** * Change the period date interval. * * @param DateInterval|string $interval * * @throws InvalidIntervalException * * @return static */ public function setDateInterval($interval) { if (!$interval = CarbonInterval::make($interval)) { throw new InvalidIntervalException('Invalid interval.'); } if ($interval->spec() === 'PT0S' && !$interval->f && !$interval->getStep()) { throw new InvalidIntervalException('Empty interval is not accepted.'); } $self = $this->copyIfImmutable(); $self->dateInterval = $interval; $self->isDefaultInterval = false; $self->handleChangedParameters(); return $self; } /** * Invert the period date interval. * * @return static */ public function invertDateInterval() { return $this->setDateInterval($this->dateInterval->invert()); } /** * Set start and end date. * * @param DateTime|DateTimeInterface|string $start * @param DateTime|DateTimeInterface|string|null $end * * @return static */ public function setDates($start, $end) { return $this->setStartDate($start)->setEndDate($end); } /** * Change the period options. * * @param int|null $options * * @throws InvalidArgumentException * * @return static */ public function setOptions($options) { if (!\is_int($options) && $options !== null) { throw new InvalidPeriodParameterException('Invalid options.'); } $self = $this->copyIfImmutable(); $self->options = $options ?: 0; $self->handleChangedParameters(); return $self; } /** * Get the period options. * * @return int */ public function getOptions() { return $this->options; } /** * Toggle given options on or off. * * @param int $options * @param bool|null $state * * @throws \InvalidArgumentException * * @return static */ public function toggleOptions($options, $state = null) { if ($state === null) { $state = ($this->options & $options) !== $options; } return $this->setOptions( $state ? $this->options | $options : $this->options & ~$options ); } /** * Toggle EXCLUDE_START_DATE option. * * @param bool $state * * @return static */ public function excludeStartDate($state = true) { return $this->toggleOptions(static::EXCLUDE_START_DATE, $state); } /** * Toggle EXCLUDE_END_DATE option. * * @param bool $state * * @return static */ public function excludeEndDate($state = true) { return $this->toggleOptions(static::EXCLUDE_END_DATE, $state); } /** * Get the underlying date interval. * * @return CarbonInterval */ public function getDateInterval() { return $this->dateInterval->copy(); } /** * Get start date of the period. * * @param string|null $rounding Optional rounding 'floor', 'ceil', 'round' using the period interval. * * @return CarbonInterface */ public function getStartDate(?string $rounding = null) { $date = $this->startDate->avoidMutation(); return $rounding ? $date->round($this->getDateInterval(), $rounding) : $date; } /** * Get end date of the period. * * @param string|null $rounding Optional rounding 'floor', 'ceil', 'round' using the period interval. * * @return CarbonInterface|null */ public function getEndDate(?string $rounding = null) { if (!$this->endDate) { return null; } $date = $this->endDate->avoidMutation(); return $rounding ? $date->round($this->getDateInterval(), $rounding) : $date; } /** * Get number of recurrences. * * @return int|float|null */ public function getRecurrences() { return $this->recurrences; } /** * Returns true if the start date should be excluded. * * @return bool */ public function isStartExcluded() { return ($this->options & static::EXCLUDE_START_DATE) !== 0; } /** * Returns true if the end date should be excluded. * * @return bool */ public function isEndExcluded() { return ($this->options & static::EXCLUDE_END_DATE) !== 0; } /** * Returns true if the start date should be included. * * @return bool */ public function isStartIncluded() { return !$this->isStartExcluded(); } /** * Returns true if the end date should be included. * * @return bool */ public function isEndIncluded() { return !$this->isEndExcluded(); } /** * Return the start if it's included by option, else return the start + 1 period interval. * * @return CarbonInterface */ public function getIncludedStartDate() { $start = $this->getStartDate(); if ($this->isStartExcluded()) { return $start->add($this->getDateInterval()); } return $start; } /** * Return the end if it's included by option, else return the end - 1 period interval. * Warning: if the period has no fixed end, this method will iterate the period to calculate it. * * @return CarbonInterface */ public function getIncludedEndDate() { $end = $this->getEndDate(); if (!$end) { return $this->calculateEnd(); } if ($this->isEndExcluded()) { return $end->sub($this->getDateInterval()); } return $end; } /** * Add a filter to the stack. * * @SuppressWarnings(PHPMD.UnusedFormalParameter) * * @param callable $callback * @param string $name * * @return static */ public function addFilter($callback, $name = null) { $self = $this->copyIfImmutable(); $tuple = $self->createFilterTuple(\func_get_args()); $self->filters[] = $tuple; $self->handleChangedParameters(); return $self; } /** * Prepend a filter to the stack. * * @SuppressWarnings(PHPMD.UnusedFormalParameter) * * @param callable $callback * @param string $name * * @return static */ public function prependFilter($callback, $name = null) { $self = $this->copyIfImmutable(); $tuple = $self->createFilterTuple(\func_get_args()); array_unshift($self->filters, $tuple); $self->handleChangedParameters(); return $self; } /** * Remove a filter by instance or name. * * @param callable|string $filter * * @return static */ public function removeFilter($filter) { $self = $this->copyIfImmutable(); $key = \is_callable($filter) ? 0 : 1; $self->filters = array_values(array_filter( $this->filters, function ($tuple) use ($key, $filter) { return $tuple[$key] !== $filter; } )); $self->updateInternalState(); $self->handleChangedParameters(); return $self; } /** * Return whether given instance or name is in the filter stack. * * @param callable|string $filter * * @return bool */ public function hasFilter($filter) { $key = \is_callable($filter) ? 0 : 1; foreach ($this->filters as $tuple) { if ($tuple[$key] === $filter) { return true; } } return false; } /** * Get filters stack. * * @return array */ public function getFilters() { return $this->filters; } /** * Set filters stack. * * @param array $filters * * @return static */ public function setFilters(array $filters) { $self = $this->copyIfImmutable(); $self->filters = $filters; $self->updateInternalState(); $self->handleChangedParameters(); return $self; } /** * Reset filters stack. * * @return static */ public function resetFilters() { $self = $this->copyIfImmutable(); $self->filters = []; if ($self->endDate !== null) { $self->filters[] = [static::END_DATE_FILTER, null]; } if ($self->recurrences !== null) { $self->filters[] = [static::RECURRENCES_FILTER, null]; } $self->handleChangedParameters(); return $self; } /** * Add a recurrences filter (set maximum number of recurrences). * * @param int|float|null $recurrences * * @throws InvalidArgumentException * * @return static */ public function setRecurrences($recurrences) { if ((!is_numeric($recurrences) && $recurrences !== null) || $recurrences < 0) { throw new InvalidPeriodParameterException('Invalid number of recurrences.'); } if ($recurrences === null) { return $this->removeFilter(static::RECURRENCES_FILTER); } /** @var self $self */ $self = $this->copyIfImmutable(); $self->recurrences = $recurrences === INF ? INF : (int) $recurrences; if (!$self->hasFilter(static::RECURRENCES_FILTER)) { return $self->addFilter(static::RECURRENCES_FILTER); } $self->handleChangedParameters(); return $self; } /** * Change the period start date. * * @param DateTime|DateTimeInterface|string $date * @param bool|null $inclusive * * @throws InvalidPeriodDateException * * @return static */ public function setStartDate($date, $inclusive = null) { if (!$this->isInfiniteDate($date) && !($date = ([$this->dateClass, 'make'])($date))) { throw new InvalidPeriodDateException('Invalid start date.'); } $self = $this->copyIfImmutable(); $self->startDate = $date; if ($inclusive !== null) { $self = $self->toggleOptions(static::EXCLUDE_START_DATE, !$inclusive); } return $self; } /** * Change the period end date. * * @param DateTime|DateTimeInterface|string|null $date * @param bool|null $inclusive * * @throws \InvalidArgumentException * * @return static */ public function setEndDate($date, $inclusive = null) { if ($date !== null && !$this->isInfiniteDate($date) && !$date = ([$this->dateClass, 'make'])($date)) { throw new InvalidPeriodDateException('Invalid end date.'); } if (!$date) { return $this->removeFilter(static::END_DATE_FILTER); } $self = $this->copyIfImmutable(); $self->endDate = $date; if ($inclusive !== null) { $self = $self->toggleOptions(static::EXCLUDE_END_DATE, !$inclusive); } if (!$self->hasFilter(static::END_DATE_FILTER)) { return $self->addFilter(static::END_DATE_FILTER); } $self->handleChangedParameters(); return $self; } /** * Check if the current position is valid. * * @return bool */ #[ReturnTypeWillChange] public function valid() { return $this->validateCurrentDate() === true; } /** * Return the current key. * * @return int|null */ #[ReturnTypeWillChange] public function key() { return $this->valid() ? $this->key : null; } /** * Return the current date. * * @return CarbonInterface|null */ #[ReturnTypeWillChange] public function current() { return $this->valid() ? $this->prepareForReturn($this->current) : null; } /** * Move forward to the next date. * * @throws RuntimeException * * @return void */ #[ReturnTypeWillChange] public function next() { if ($this->current === null) { $this->rewind(); } if ($this->validationResult !== static::END_ITERATION) { $this->key++; $this->incrementCurrentDateUntilValid(); } } /** * Rewind to the start date. * * Iterating over a date in the UTC timezone avoids bug during backward DST change. * * @see https://bugs.php.net/bug.php?id=72255 * @see https://bugs.php.net/bug.php?id=74274 * @see https://wiki.php.net/rfc/datetime_and_daylight_saving_time * * @throws RuntimeException * * @return void */ #[ReturnTypeWillChange] public function rewind() { $this->key = 0; $this->current = ([$this->dateClass, 'make'])($this->startDate); $settings = $this->getSettings(); if ($this->hasLocalTranslator()) { $settings['locale'] = $this->getTranslatorLocale(); } $this->current->settings($settings); $this->timezone = static::intervalHasTime($this->dateInterval) ? $this->current->getTimezone() : null; if ($this->timezone) { $this->current = $this->current->utc(); } $this->validationResult = null; if ($this->isStartExcluded() || $this->validateCurrentDate() === false) { $this->incrementCurrentDateUntilValid(); } } /** * Skip iterations and returns iteration state (false if ended, true if still valid). * * @param int $count steps number to skip (1 by default) * * @return bool */ public function skip($count = 1) { for ($i = $count; $this->valid() && $i > 0; $i--) { $this->next(); } return $this->valid(); } /** * Format the date period as ISO 8601. * * @return string */ public function toIso8601String() { $parts = []; if ($this->recurrences !== null) { $parts[] = 'R'.$this->recurrences; } $parts[] = $this->startDate->toIso8601String(); $parts[] = $this->dateInterval->spec(); if ($this->endDate !== null) { $parts[] = $this->endDate->toIso8601String(); } return implode('/', $parts); } /** * Convert the date period into a string. * * @return string */ public function toString() { $format = $this->localToStringFormat ?? static::$toStringFormat; if ($format instanceof Closure) { return $format($this); } $translator = ([$this->dateClass, 'getTranslator'])(); $parts = []; $format = $format ?? ( !$this->startDate->isStartOfDay() || ($this->endDate && !$this->endDate->isStartOfDay()) ? 'Y-m-d H:i:s' : 'Y-m-d' ); if ($this->recurrences !== null) { $parts[] = $this->translate('period_recurrences', [], $this->recurrences, $translator); } $parts[] = $this->translate('period_interval', [':interval' => $this->dateInterval->forHumans([ 'join' => true, ])], null, $translator); $parts[] = $this->translate('period_start_date', [':date' => $this->startDate->rawFormat($format)], null, $translator); if ($this->endDate !== null) { $parts[] = $this->translate('period_end_date', [':date' => $this->endDate->rawFormat($format)], null, $translator); } $result = implode(' ', $parts); return mb_strtoupper(mb_substr($result, 0, 1)).mb_substr($result, 1); } /** * Format the date period as ISO 8601. * * @return string */ public function spec() { return $this->toIso8601String(); } /** * Cast the current instance into the given class. * * @param string $className The $className::instance() method will be called to cast the current object. * * @return DatePeriod */ public function cast(string $className) { if (!method_exists($className, 'instance')) { if (is_a($className, DatePeriod::class, true)) { return new $className( $this->rawDate($this->getStartDate()), $this->getDateInterval(), $this->getEndDate() ? $this->rawDate($this->getIncludedEndDate()) : $this->getRecurrences(), $this->isStartExcluded() ? DatePeriod::EXCLUDE_START_DATE : 0 ); } throw new InvalidCastException("$className has not the instance() method needed to cast the date."); } return $className::instance($this); } /** * Return native DatePeriod PHP object matching the current instance. * * @example * ``` * var_dump(CarbonPeriod::create('2021-01-05', '2021-02-15')->toDatePeriod()); * ``` * * @return DatePeriod */ public function toDatePeriod() { return $this->cast(DatePeriod::class); } /** * Return `true` if the period has no custom filter and is guaranteed to be endless. * * Note that we can't check if a period is endless as soon as it has custom filters * because filters can emit `CarbonPeriod::END_ITERATION` to stop the iteration in * a way we can't predict without actually iterating the period. */ public function isUnfilteredAndEndLess(): bool { foreach ($this->filters as $filter) { switch ($filter) { case [static::RECURRENCES_FILTER, null]: if ($this->recurrences !== null && is_finite($this->recurrences)) { return false; } break; case [static::END_DATE_FILTER, null]: if ($this->endDate !== null && !$this->endDate->isEndOfTime()) { return false; } break; default: return false; } } return true; } /** * Convert the date period into an array without changing current iteration state. * * @return CarbonInterface[] */ public function toArray() { if ($this->isUnfilteredAndEndLess()) { throw new EndLessPeriodException("Endless period can't be converted to array nor counted."); } $state = [ $this->key, $this->current ? $this->current->avoidMutation() : null, $this->validationResult, ]; $result = iterator_to_array($this); [$this->key, $this->current, $this->validationResult] = $state; return $result; } /** * Count dates in the date period. * * @return int */ #[ReturnTypeWillChange] public function count() { return \count($this->toArray()); } /** * Return the first date in the date period. * * @return CarbonInterface|null */ public function first() { if ($this->isUnfilteredAndEndLess()) { foreach ($this as $date) { $this->rewind(); return $date; } return null; } return ($this->toArray() ?: [])[0] ?? null; } /** * Return the last date in the date period. * * @return CarbonInterface|null */ public function last() { $array = $this->toArray(); return $array ? $array[\count($array) - 1] : null; } /** * Convert the date period into a string. * * @return string */ public function __toString() { return $this->toString(); } /** * Add aliases for setters. * * CarbonPeriod::days(3)->hours(5)->invert() * ->sinceNow()->until('2010-01-10') * ->filter(...) * ->count() * * Note: We use magic method to let static and instance aliases with the same names. * * @param string $method * @param array $parameters * * @return mixed */ public function __call($method, $parameters) { if (static::hasMacro($method)) { return static::bindMacroContext($this, function () use (&$method, &$parameters) { return $this->callMacro($method, $parameters); }); } $roundedValue = $this->callRoundMethod($method, $parameters); if ($roundedValue !== null) { return $roundedValue; } switch ($method) { case 'start': case 'since': self::setDefaultParameters($parameters, [ [0, 'date', null], ]); return $this->setStartDate(...$parameters); case 'sinceNow': return $this->setStartDate(new Carbon(), ...$parameters); case 'end': case 'until': self::setDefaultParameters($parameters, [ [0, 'date', null], ]); return $this->setEndDate(...$parameters); case 'untilNow': return $this->setEndDate(new Carbon(), ...$parameters); case 'dates': case 'between': self::setDefaultParameters($parameters, [ [0, 'start', null], [1, 'end', null], ]); return $this->setDates(...$parameters); case 'recurrences': case 'times': self::setDefaultParameters($parameters, [ [0, 'recurrences', null], ]); return $this->setRecurrences(...$parameters); case 'options': self::setDefaultParameters($parameters, [ [0, 'options', null], ]); return $this->setOptions(...$parameters); case 'toggle': self::setDefaultParameters($parameters, [ [0, 'options', null], ]); return $this->toggleOptions(...$parameters); case 'filter': case 'push': return $this->addFilter(...$parameters); case 'prepend': return $this->prependFilter(...$parameters); case 'filters': self::setDefaultParameters($parameters, [ [0, 'filters', []], ]); return $this->setFilters(...$parameters); case 'interval': case 'each': case 'every': case 'step': case 'stepBy': return $this->setDateInterval(...$parameters); case 'invert': return $this->invertDateInterval(); case 'years': case 'year': case 'months': case 'month': case 'weeks': case 'week': case 'days': case 'dayz': case 'day': case 'hours': case 'hour': case 'minutes': case 'minute': case 'seconds': case 'second': case 'milliseconds': case 'millisecond': case 'microseconds': case 'microsecond': return $this->setDateInterval(( // Override default P1D when instantiating via fluent setters. [$this->isDefaultInterval ? new CarbonInterval('PT0S') : $this->dateInterval, $method] )(...$parameters)); } $dateClass = $this->dateClass; if ($this->localStrictModeEnabled ?? $dateClass::isStrictModeEnabled()) { throw new UnknownMethodException($method); } return $this; } /** * Set the instance's timezone from a string or object and apply it to start/end. * * @param \DateTimeZone|string $timezone * * @return static */ public function setTimezone($timezone) { $self = $this->copyIfImmutable(); $self->tzName = $timezone; $self->timezone = $timezone; if ($self->startDate) { $self = $self->setStartDate($self->startDate->setTimezone($timezone)); } if ($self->endDate) { $self = $self->setEndDate($self->endDate->setTimezone($timezone)); } return $self; } /** * Set the instance's timezone from a string or object and add/subtract the offset difference to start/end. * * @param \DateTimeZone|string $timezone * * @return static */ public function shiftTimezone($timezone) { $self = $this->copyIfImmutable(); $self->tzName = $timezone; $self->timezone = $timezone; if ($self->startDate) { $self = $self->setStartDate($self->startDate->shiftTimezone($timezone)); } if ($self->endDate) { $self = $self->setEndDate($self->endDate->shiftTimezone($timezone)); } return $self; } /** * Returns the end is set, else calculated from start an recurrences. * * @param string|null $rounding Optional rounding 'floor', 'ceil', 'round' using the period interval. * * @return CarbonInterface */ public function calculateEnd(?string $rounding = null) { if ($end = $this->getEndDate($rounding)) { return $end; } if ($this->dateInterval->isEmpty()) { return $this->getStartDate($rounding); } $date = $this->getEndFromRecurrences() ?? $this->iterateUntilEnd(); if ($date && $rounding) { $date = $date->avoidMutation()->round($this->getDateInterval(), $rounding); } return $date; } /** * @return CarbonInterface|null */ private function getEndFromRecurrences() { if ($this->recurrences === null) { throw new UnreachableException( "Could not calculate period end without either explicit end or recurrences.\n". "If you're looking for a forever-period, use ->setRecurrences(INF)." ); } if ($this->recurrences === INF) { $start = $this->getStartDate(); return $start < $start->avoidMutation()->add($this->getDateInterval()) ? CarbonImmutable::endOfTime() : CarbonImmutable::startOfTime(); } if ($this->filters === [[static::RECURRENCES_FILTER, null]]) { return $this->getStartDate()->avoidMutation()->add( $this->getDateInterval()->times( $this->recurrences - ($this->isStartExcluded() ? 0 : 1) ) ); } return null; } /** * @return CarbonInterface|null */ private function iterateUntilEnd() { $attempts = 0; $date = null; foreach ($this as $date) { if (++$attempts > static::END_MAX_ATTEMPTS) { throw new UnreachableException( 'Could not calculate period end after iterating '.static::END_MAX_ATTEMPTS.' times.' ); } } return $date; } /** * Returns true if the current period overlaps the given one (if 1 parameter passed) * or the period between 2 dates (if 2 parameters passed). * * @param CarbonPeriod|\DateTimeInterface|Carbon|CarbonImmutable|string $rangeOrRangeStart * @param \DateTimeInterface|Carbon|CarbonImmutable|string|null $rangeEnd * * @return bool */ public function overlaps($rangeOrRangeStart, $rangeEnd = null) { $range = $rangeEnd ? static::create($rangeOrRangeStart, $rangeEnd) : $rangeOrRangeStart; if (!($range instanceof self)) { $range = static::create($range); } [$start, $end] = $this->orderCouple($this->getStartDate(), $this->calculateEnd()); [$rangeStart, $rangeEnd] = $this->orderCouple($range->getStartDate(), $range->calculateEnd()); return $end > $rangeStart && $rangeEnd > $start; } /** * Execute a given function on each date of the period. * * @example * ``` * Carbon::create('2020-11-29')->daysUntil('2020-12-24')->forEach(function (Carbon $date) { * echo $date->diffInDays('2020-12-25')." days before Christmas!\n"; * }); * ``` * * @param callable $callback */ public function forEach(callable $callback) { foreach ($this as $date) { $callback($date); } } /** * Execute a given function on each date of the period and yield the result of this function. * * @example * ``` * $period = Carbon::create('2020-11-29')->daysUntil('2020-12-24'); * echo implode("\n", iterator_to_array($period->map(function (Carbon $date) { * return $date->diffInDays('2020-12-25').' days before Christmas!'; * }))); * ``` * * @param callable $callback * * @return \Generator */ public function map(callable $callback) { foreach ($this as $date) { yield $callback($date); } } /** * Determines if the instance is equal to another. * Warning: if options differ, instances will never be equal. * * @param mixed $period * * @see equalTo() * * @return bool */ public function eq($period): bool { return $this->equalTo($period); } /** * Determines if the instance is equal to another. * Warning: if options differ, instances will never be equal. * * @param mixed $period * * @return bool */ public function equalTo($period): bool { if (!($period instanceof self)) { $period = self::make($period); } $end = $this->getEndDate(); return $period !== null && $this->getDateInterval()->eq($period->getDateInterval()) && $this->getStartDate()->eq($period->getStartDate()) && ($end ? $end->eq($period->getEndDate()) : $this->getRecurrences() === $period->getRecurrences()) && ($this->getOptions() & (~static::IMMUTABLE)) === ($period->getOptions() & (~static::IMMUTABLE)); } /** * Determines if the instance is not equal to another. * Warning: if options differ, instances will never be equal. * * @param mixed $period * * @see notEqualTo() * * @return bool */ public function ne($period): bool { return $this->notEqualTo($period); } /** * Determines if the instance is not equal to another. * Warning: if options differ, instances will never be equal. * * @param mixed $period * * @return bool */ public function notEqualTo($period): bool { return !$this->eq($period); } /** * Determines if the start date is before an other given date. * (Rather start/end are included by options is ignored.) * * @param mixed $date * * @return bool */ public function startsBefore($date = null): bool { return $this->getStartDate()->lessThan($this->resolveCarbon($date)); } /** * Determines if the start date is before or the same as a given date. * (Rather start/end are included by options is ignored.) * * @param mixed $date * * @return bool */ public function startsBeforeOrAt($date = null): bool { return $this->getStartDate()->lessThanOrEqualTo($this->resolveCarbon($date)); } /** * Determines if the start date is after an other given date. * (Rather start/end are included by options is ignored.) * * @param mixed $date * * @return bool */ public function startsAfter($date = null): bool { return $this->getStartDate()->greaterThan($this->resolveCarbon($date)); } /** * Determines if the start date is after or the same as a given date. * (Rather start/end are included by options is ignored.) * * @param mixed $date * * @return bool */ public function startsAfterOrAt($date = null): bool { return $this->getStartDate()->greaterThanOrEqualTo($this->resolveCarbon($date)); } /** * Determines if the start date is the same as a given date. * (Rather start/end are included by options is ignored.) * * @param mixed $date * * @return bool */ public function startsAt($date = null): bool { return $this->getStartDate()->equalTo($this->resolveCarbon($date)); } /** * Determines if the end date is before an other given date. * (Rather start/end are included by options is ignored.) * * @param mixed $date * * @return bool */ public function endsBefore($date = null): bool { return $this->calculateEnd()->lessThan($this->resolveCarbon($date)); } /** * Determines if the end date is before or the same as a given date. * (Rather start/end are included by options is ignored.) * * @param mixed $date * * @return bool */ public function endsBeforeOrAt($date = null): bool { return $this->calculateEnd()->lessThanOrEqualTo($this->resolveCarbon($date)); } /** * Determines if the end date is after an other given date. * (Rather start/end are included by options is ignored.) * * @param mixed $date * * @return bool */ public function endsAfter($date = null): bool { return $this->calculateEnd()->greaterThan($this->resolveCarbon($date)); } /** * Determines if the end date is after or the same as a given date. * (Rather start/end are included by options is ignored.) * * @param mixed $date * * @return bool */ public function endsAfterOrAt($date = null): bool { return $this->calculateEnd()->greaterThanOrEqualTo($this->resolveCarbon($date)); } /** * Determines if the end date is the same as a given date. * (Rather start/end are included by options is ignored.) * * @param mixed $date * * @return bool */ public function endsAt($date = null): bool { return $this->calculateEnd()->equalTo($this->resolveCarbon($date)); } /** * Return true if start date is now or later. * (Rather start/end are included by options is ignored.) * * @return bool */ public function isStarted(): bool { return $this->startsBeforeOrAt(); } /** * Return true if end date is now or later. * (Rather start/end are included by options is ignored.) * * @return bool */ public function isEnded(): bool { return $this->endsBeforeOrAt(); } /** * Return true if now is between start date (included) and end date (excluded). * (Rather start/end are included by options is ignored.) * * @return bool */ public function isInProgress(): bool { return $this->isStarted() && !$this->isEnded(); } /** * Round the current instance at the given unit with given precision if specified and the given function. * * @param string $unit * @param float|int|string|\DateInterval|null $precision * @param string $function * * @return static */ public function roundUnit($unit, $precision = 1, $function = 'round') { $self = $this->copyIfImmutable(); $self = $self->setStartDate($self->getStartDate()->roundUnit($unit, $precision, $function)); if ($self->endDate) { $self = $self->setEndDate($self->getEndDate()->roundUnit($unit, $precision, $function)); } return $self->setDateInterval($self->getDateInterval()->roundUnit($unit, $precision, $function)); } /** * Truncate the current instance at the given unit with given precision if specified. * * @param string $unit * @param float|int|string|\DateInterval|null $precision * * @return static */ public function floorUnit($unit, $precision = 1) { return $this->roundUnit($unit, $precision, 'floor'); } /** * Ceil the current instance at the given unit with given precision if specified. * * @param string $unit * @param float|int|string|\DateInterval|null $precision * * @return static */ public function ceilUnit($unit, $precision = 1) { return $this->roundUnit($unit, $precision, 'ceil'); } /** * Round the current instance second with given precision if specified (else period interval is used). * * @param float|int|string|\DateInterval|null $precision * @param string $function * * @return static */ public function round($precision = null, $function = 'round') { return $this->roundWith( $precision ?? $this->getDateInterval()->setLocalTranslator(TranslatorImmutable::get('en'))->forHumans(), $function ); } /** * Round the current instance second with given precision if specified (else period interval is used). * * @param float|int|string|\DateInterval|null $precision * * @return static */ public function floor($precision = null) { return $this->round($precision, 'floor'); } /** * Ceil the current instance second with given precision if specified (else period interval is used). * * @param float|int|string|\DateInterval|null $precision * * @return static */ public function ceil($precision = null) { return $this->round($precision, 'ceil'); } /** * Specify data which should be serialized to JSON. * * @link https://php.net/manual/en/jsonserializable.jsonserialize.php * * @return CarbonInterface[] */ #[ReturnTypeWillChange] public function jsonSerialize() { return $this->toArray(); } /** * Return true if the given date is between start and end. * * @param \Carbon\Carbon|\Carbon\CarbonPeriod|\Carbon\CarbonInterval|\DateInterval|\DatePeriod|\DateTimeInterface|string|null $date * * @return bool */ public function contains($date = null): bool { $startMethod = 'startsBefore'.($this->isStartIncluded() ? 'OrAt' : ''); $endMethod = 'endsAfter'.($this->isEndIncluded() ? 'OrAt' : ''); return $this->$startMethod($date) && $this->$endMethod($date); } /** * Return true if the current period follows a given other period (with no overlap). * For instance, [2019-08-01 -> 2019-08-12] follows [2019-07-29 -> 2019-07-31] * Note than in this example, follows() would be false if 2019-08-01 or 2019-07-31 was excluded by options. * * @param \Carbon\CarbonPeriod|\DatePeriod|string $period * * @return bool */ public function follows($period, ...$arguments): bool { $period = $this->resolveCarbonPeriod($period, ...$arguments); return $this->getIncludedStartDate()->equalTo($period->getIncludedEndDate()->add($period->getDateInterval())); } /** * Return true if the given other period follows the current one (with no overlap). * For instance, [2019-07-29 -> 2019-07-31] is followed by [2019-08-01 -> 2019-08-12] * Note than in this example, isFollowedBy() would be false if 2019-08-01 or 2019-07-31 was excluded by options. * * @param \Carbon\CarbonPeriod|\DatePeriod|string $period * * @return bool */ public function isFollowedBy($period, ...$arguments): bool { $period = $this->resolveCarbonPeriod($period, ...$arguments); return $period->follows($this); } /** * Return true if the given period either follows or is followed by the current one. * * @see follows() * @see isFollowedBy() * * @param \Carbon\CarbonPeriod|\DatePeriod|string $period * * @return bool */ public function isConsecutiveWith($period, ...$arguments): bool { return $this->follows($period, ...$arguments) || $this->isFollowedBy($period, ...$arguments); } /** * Update properties after removing built-in filters. * * @return void */ protected function updateInternalState() { if (!$this->hasFilter(static::END_DATE_FILTER)) { $this->endDate = null; } if (!$this->hasFilter(static::RECURRENCES_FILTER)) { $this->recurrences = null; } } /** * Create a filter tuple from raw parameters. * * Will create an automatic filter callback for one of Carbon's is* methods. * * @param array $parameters * * @return array */ protected function createFilterTuple(array $parameters) { $method = array_shift($parameters); if (!$this->isCarbonPredicateMethod($method)) { return [$method, array_shift($parameters)]; } return [function ($date) use ($method, $parameters) { return ([$date, $method])(...$parameters); }, $method]; } /** * Return whether given callable is a string pointing to one of Carbon's is* methods * and should be automatically converted to a filter callback. * * @param callable $callable * * @return bool */ protected function isCarbonPredicateMethod($callable) { return \is_string($callable) && str_starts_with($callable, 'is') && (method_exists($this->dateClass, $callable) || ([$this->dateClass, 'hasMacro'])($callable)); } /** * Recurrences filter callback (limits number of recurrences). * * @SuppressWarnings(PHPMD.UnusedFormalParameter) * * @param \Carbon\Carbon $current * @param int $key * * @return bool|string */ protected function filterRecurrences($current, $key) { if ($key < $this->recurrences) { return true; } return static::END_ITERATION; } /** * End date filter callback. * * @param \Carbon\Carbon $current * * @return bool|string */ protected function filterEndDate($current) { if (!$this->isEndExcluded() && $current == $this->endDate) { return true; } if ($this->dateInterval->invert ? $current > $this->endDate : $current < $this->endDate) { return true; } return static::END_ITERATION; } /** * End iteration filter callback. * * @return string */ protected function endIteration() { return static::END_ITERATION; } /** * Handle change of the parameters. */ protected function handleChangedParameters() { if (($this->getOptions() & static::IMMUTABLE) && $this->dateClass === Carbon::class) { $this->dateClass = CarbonImmutable::class; } elseif (!($this->getOptions() & static::IMMUTABLE) && $this->dateClass === CarbonImmutable::class) { $this->dateClass = Carbon::class; } $this->validationResult = null; } /** * Validate current date and stop iteration when necessary. * * Returns true when current date is valid, false if it is not, or static::END_ITERATION * when iteration should be stopped. * * @return bool|string */ protected function validateCurrentDate() { if ($this->current === null) { $this->rewind(); } // Check after the first rewind to avoid repeating the initial validation. return $this->validationResult ?? ($this->validationResult = $this->checkFilters()); } /** * Check whether current value and key pass all the filters. * * @return bool|string */ protected function checkFilters() { $current = $this->prepareForReturn($this->current); foreach ($this->filters as $tuple) { $result = \call_user_func( $tuple[0], $current->avoidMutation(), $this->key, $this ); if ($result === static::END_ITERATION) { return static::END_ITERATION; } if (!$result) { return false; } } return true; } /** * Prepare given date to be returned to the external logic. * * @param CarbonInterface $date * * @return CarbonInterface */ protected function prepareForReturn(CarbonInterface $date) { $date = ([$this->dateClass, 'make'])($date); if ($this->timezone) { $date = $date->setTimezone($this->timezone); } return $date; } /** * Keep incrementing the current date until a valid date is found or the iteration is ended. * * @throws RuntimeException * * @return void */ protected function incrementCurrentDateUntilValid() { $attempts = 0; do { $this->current = $this->current->add($this->dateInterval); $this->validationResult = null; if (++$attempts > static::NEXT_MAX_ATTEMPTS) { throw new UnreachableException('Could not find next valid date.'); } } while ($this->validateCurrentDate() === false); } /** * Call given macro. * * @param string $name * @param array $parameters * * @return mixed */ protected function callMacro($name, $parameters) { $macro = static::$macros[$name]; if ($macro instanceof Closure) { $boundMacro = @$macro->bindTo($this, static::class) ?: @$macro->bindTo(null, static::class); return ($boundMacro ?: $macro)(...$parameters); } return $macro(...$parameters); } /** * Return the Carbon instance passed through, a now instance in the same timezone * if null given or parse the input if string given. * * @param \Carbon\Carbon|\Carbon\CarbonPeriod|\Carbon\CarbonInterval|\DateInterval|\DatePeriod|\DateTimeInterface|string|null $date * * @return \Carbon\CarbonInterface */ protected function resolveCarbon($date = null) { return $this->getStartDate()->nowWithSameTz()->carbonize($date); } /** * Resolve passed arguments or DatePeriod to a CarbonPeriod object. * * @param mixed $period * @param mixed ...$arguments * * @return static */ protected function resolveCarbonPeriod($period, ...$arguments) { if ($period instanceof self) { return $period; } return $period instanceof DatePeriod ? static::instance($period) : static::create($period, ...$arguments); } private function orderCouple($first, $second): array { return $first > $second ? [$second, $first] : [$first, $second]; } private function makeDateTime($value): ?DateTimeInterface { if ($value instanceof DateTimeInterface) { return $value; } if (\is_string($value)) { $value = trim($value); if (!preg_match('/^P[\dT]/', $value) && !preg_match('/^R\d/', $value) && preg_match('/[a-z\d]/i', $value) ) { $dateClass = $this->dateClass; return $dateClass::parse($value, $this->tzName); } } return null; } private function isInfiniteDate($date): bool { return $date instanceof CarbonInterface && ($date->isEndOfTime() || $date->isStartOfTime()); } private function rawDate($date): ?DateTimeInterface { if ($date === false || $date === null) { return null; } if ($date instanceof CarbonInterface) { return $date->isMutable() ? $date->toDateTime() : $date->toDateTimeImmutable(); } if (\in_array(\get_class($date), [DateTime::class, DateTimeImmutable::class], true)) { return $date; } $class = $date instanceof DateTime ? DateTime::class : DateTimeImmutable::class; return new $class($date->format('Y-m-d H:i:s.u'), $date->getTimezone()); } private static function setDefaultParameters(array &$parameters, array $defaults): void { foreach ($defaults as [$index, $name, $value]) { if (!\array_key_exists($index, $parameters) && !\array_key_exists($name, $parameters)) { $parameters[$index] = $value; } } } } PK������<1ZM ������Carbon/List/regions.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /* * ISO 3166-2 */ return [ 'AD' => 'Andorra', 'AE' => 'United Arab Emirates', 'AF' => 'Afghanistan', 'AG' => 'Antigua and Barbuda', 'AI' => 'Anguilla', 'AL' => 'Albania', 'AM' => 'Armenia', 'AO' => 'Angola', 'AQ' => 'Antarctica', 'AR' => 'Argentina', 'AS' => 'American Samoa', 'AT' => 'Austria', 'AU' => 'Australia', 'AW' => 'Aruba', 'AX' => 'Åland Islands', 'AZ' => 'Azerbaijan', 'BA' => 'Bosnia and Herzegovina', 'BB' => 'Barbados', 'BD' => 'Bangladesh', 'BE' => 'Belgium', 'BF' => 'Burkina Faso', 'BG' => 'Bulgaria', 'BH' => 'Bahrain', 'BI' => 'Burundi', 'BJ' => 'Benin', 'BL' => 'Saint Barthélemy', 'BM' => 'Bermuda', 'BN' => 'Brunei Darussalam', 'BO' => 'Bolivia (Plurinational State of)', 'BQ' => 'Bonaire, Sint Eustatius and Saba', 'BR' => 'Brazil', 'BS' => 'Bahamas', 'BT' => 'Bhutan', 'BV' => 'Bouvet Island', 'BW' => 'Botswana', 'BY' => 'Belarus', 'BZ' => 'Belize', 'CA' => 'Canada', 'CC' => 'Cocos (Keeling) Islands', 'CD' => 'Congo, Democratic Republic of the', 'CF' => 'Central African Republic', 'CG' => 'Congo', 'CH' => 'Switzerland', 'CI' => 'Côte d\'Ivoire', 'CK' => 'Cook Islands', 'CL' => 'Chile', 'CM' => 'Cameroon', 'CN' => 'China', 'CO' => 'Colombia', 'CR' => 'Costa Rica', 'CU' => 'Cuba', 'CV' => 'Cabo Verde', 'CW' => 'Curaçao', 'CX' => 'Christmas Island', 'CY' => 'Cyprus', 'CZ' => 'Czechia', 'DE' => 'Germany', 'DJ' => 'Djibouti', 'DK' => 'Denmark', 'DM' => 'Dominica', 'DO' => 'Dominican Republic', 'DZ' => 'Algeria', 'EC' => 'Ecuador', 'EE' => 'Estonia', 'EG' => 'Egypt', 'EH' => 'Western Sahara', 'ER' => 'Eritrea', 'ES' => 'Spain', 'ET' => 'Ethiopia', 'FI' => 'Finland', 'FJ' => 'Fiji', 'FK' => 'Falkland Islands (Malvinas)', 'FM' => 'Micronesia (Federated States of)', 'FO' => 'Faroe Islands', 'FR' => 'France', 'GA' => 'Gabon', 'GB' => 'United Kingdom of Great Britain and Northern Ireland', 'GD' => 'Grenada', 'GE' => 'Georgia', 'GF' => 'French Guiana', 'GG' => 'Guernsey', 'GH' => 'Ghana', 'GI' => 'Gibraltar', 'GL' => 'Greenland', 'GM' => 'Gambia', 'GN' => 'Guinea', 'GP' => 'Guadeloupe', 'GQ' => 'Equatorial Guinea', 'GR' => 'Greece', 'GS' => 'South Georgia and the South Sandwich Islands', 'GT' => 'Guatemala', 'GU' => 'Guam', 'GW' => 'Guinea-Bissau', 'GY' => 'Guyana', 'HK' => 'Hong Kong', 'HM' => 'Heard Island and McDonald Islands', 'HN' => 'Honduras', 'HR' => 'Croatia', 'HT' => 'Haiti', 'HU' => 'Hungary', 'ID' => 'Indonesia', 'IE' => 'Ireland', 'IL' => 'Israel', 'IM' => 'Isle of Man', 'IN' => 'India', 'IO' => 'British Indian Ocean Territory', 'IQ' => 'Iraq', 'IR' => 'Iran (Islamic Republic of)', 'IS' => 'Iceland', 'IT' => 'Italy', 'JE' => 'Jersey', 'JM' => 'Jamaica', 'JO' => 'Jordan', 'JP' => 'Japan', 'KE' => 'Kenya', 'KG' => 'Kyrgyzstan', 'KH' => 'Cambodia', 'KI' => 'Kiribati', 'KM' => 'Comoros', 'KN' => 'Saint Kitts and Nevis', 'KP' => 'Korea (Democratic People\'s Republic of)', 'KR' => 'Korea, Republic of', 'KW' => 'Kuwait', 'KY' => 'Cayman Islands', 'KZ' => 'Kazakhstan', 'LA' => 'Lao People\'s Democratic Republic', 'LB' => 'Lebanon', 'LC' => 'Saint Lucia', 'LI' => 'Liechtenstein', 'LK' => 'Sri Lanka', 'LR' => 'Liberia', 'LS' => 'Lesotho', 'LT' => 'Lithuania', 'LU' => 'Luxembourg', 'LV' => 'Latvia', 'LY' => 'Libya', 'MA' => 'Morocco', 'MC' => 'Monaco', 'MD' => 'Moldova, Republic of', 'ME' => 'Montenegro', 'MF' => 'Saint Martin (French part)', 'MG' => 'Madagascar', 'MH' => 'Marshall Islands', 'MK' => 'Macedonia, the former Yugoslav Republic of', 'ML' => 'Mali', 'MM' => 'Myanmar', 'MN' => 'Mongolia', 'MO' => 'Macao', 'MP' => 'Northern Mariana Islands', 'MQ' => 'Martinique', 'MR' => 'Mauritania', 'MS' => 'Montserrat', 'MT' => 'Malta', 'MU' => 'Mauritius', 'MV' => 'Maldives', 'MW' => 'Malawi', 'MX' => 'Mexico', 'MY' => 'Malaysia', 'MZ' => 'Mozambique', 'NA' => 'Namibia', 'NC' => 'New Caledonia', 'NE' => 'Niger', 'NF' => 'Norfolk Island', 'NG' => 'Nigeria', 'NI' => 'Nicaragua', 'NL' => 'Netherlands', 'NO' => 'Norway', 'NP' => 'Nepal', 'NR' => 'Nauru', 'NU' => 'Niue', 'NZ' => 'New Zealand', 'OM' => 'Oman', 'PA' => 'Panama', 'PE' => 'Peru', 'PF' => 'French Polynesia', 'PG' => 'Papua New Guinea', 'PH' => 'Philippines', 'PK' => 'Pakistan', 'PL' => 'Poland', 'PM' => 'Saint Pierre and Miquelon', 'PN' => 'Pitcairn', 'PR' => 'Puerto Rico', 'PS' => 'Palestine, State of', 'PT' => 'Portugal', 'PW' => 'Palau', 'PY' => 'Paraguay', 'QA' => 'Qatar', 'RE' => 'Réunion', 'RO' => 'Romania', 'RS' => 'Serbia', 'RU' => 'Russian Federation', 'RW' => 'Rwanda', 'SA' => 'Saudi Arabia', 'SB' => 'Solomon Islands', 'SC' => 'Seychelles', 'SD' => 'Sudan', 'SE' => 'Sweden', 'SG' => 'Singapore', 'SH' => 'Saint Helena, Ascension and Tristan da Cunha', 'SI' => 'Slovenia', 'SJ' => 'Svalbard and Jan Mayen', 'SK' => 'Slovakia', 'SL' => 'Sierra Leone', 'SM' => 'San Marino', 'SN' => 'Senegal', 'SO' => 'Somalia', 'SR' => 'Suriname', 'SS' => 'South Sudan', 'ST' => 'Sao Tome and Principe', 'SV' => 'El Salvador', 'SX' => 'Sint Maarten (Dutch part)', 'SY' => 'Syrian Arab Republic', 'SZ' => 'Eswatini', 'TC' => 'Turks and Caicos Islands', 'TD' => 'Chad', 'TF' => 'French Southern Territories', 'TG' => 'Togo', 'TH' => 'Thailand', 'TJ' => 'Tajikistan', 'TK' => 'Tokelau', 'TL' => 'Timor-Leste', 'TM' => 'Turkmenistan', 'TN' => 'Tunisia', 'TO' => 'Tonga', 'TR' => 'Turkey', 'TT' => 'Trinidad and Tobago', 'TV' => 'Tuvalu', 'TW' => 'Taiwan, Province of China', 'TZ' => 'Tanzania, United Republic of', 'UA' => 'Ukraine', 'UG' => 'Uganda', 'UM' => 'United States Minor Outlying Islands', 'US' => 'United States of America', 'UY' => 'Uruguay', 'UZ' => 'Uzbekistan', 'VA' => 'Holy See', 'VC' => 'Saint Vincent and the Grenadines', 'VE' => 'Venezuela (Bolivarian Republic of)', 'VG' => 'Virgin Islands (British)', 'VI' => 'Virgin Islands (U.S.)', 'VN' => 'Viet Nam', 'VU' => 'Vanuatu', 'WF' => 'Wallis and Futuna', 'WS' => 'Samoa', 'YE' => 'Yemen', 'YT' => 'Mayotte', 'ZA' => 'South Africa', 'ZM' => 'Zambia', 'ZW' => 'Zimbabwe', ]; PK������<1Z 's��s����Carbon/List/languages.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return [ /* * ISO 639-2 */ 'ab' => [ 'isoName' => 'Abkhazian', 'nativeName' => 'аҧсуа бызшәа, аҧсшәа', ], 'aa' => [ 'isoName' => 'Afar', 'nativeName' => 'Afaraf', ], 'af' => [ 'isoName' => 'Afrikaans', 'nativeName' => 'Afrikaans', ], 'ak' => [ 'isoName' => 'Akan', 'nativeName' => 'Akan', ], 'sq' => [ 'isoName' => 'Albanian', 'nativeName' => 'Shqip', ], 'am' => [ 'isoName' => 'Amharic', 'nativeName' => 'አማርኛ', ], 'ar' => [ 'isoName' => 'Arabic', 'nativeName' => 'العربية', ], 'an' => [ 'isoName' => 'Aragonese', 'nativeName' => 'aragonés', ], 'hy' => [ 'isoName' => 'Armenian', 'nativeName' => 'Հայերեն', ], 'as' => [ 'isoName' => 'Assamese', 'nativeName' => 'অসমীয়া', ], 'av' => [ 'isoName' => 'Avaric', 'nativeName' => 'авар мацӀ, магӀарул мацӀ', ], 'ae' => [ 'isoName' => 'Avestan', 'nativeName' => 'avesta', ], 'ay' => [ 'isoName' => 'Aymara', 'nativeName' => 'aymar aru', ], 'az' => [ 'isoName' => 'Azerbaijani', 'nativeName' => 'azərbaycan dili', ], 'bm' => [ 'isoName' => 'Bambara', 'nativeName' => 'bamanankan', ], 'ba' => [ 'isoName' => 'Bashkir', 'nativeName' => 'башҡорт теле', ], 'eu' => [ 'isoName' => 'Basque', 'nativeName' => 'euskara, euskera', ], 'be' => [ 'isoName' => 'Belarusian', 'nativeName' => 'беларуская мова', ], 'bn' => [ 'isoName' => 'Bengali', 'nativeName' => 'বাংলা', ], 'bh' => [ 'isoName' => 'Bihari languages', 'nativeName' => 'भोजपुरी', ], 'bi' => [ 'isoName' => 'Bislama', 'nativeName' => 'Bislama', ], 'bs' => [ 'isoName' => 'Bosnian', 'nativeName' => 'bosanski jezik', ], 'br' => [ 'isoName' => 'Breton', 'nativeName' => 'brezhoneg', ], 'bg' => [ 'isoName' => 'Bulgarian', 'nativeName' => 'български език', ], 'my' => [ 'isoName' => 'Burmese', 'nativeName' => 'ဗမာစာ', ], 'ca' => [ 'isoName' => 'Catalan, Valencian', 'nativeName' => 'català, valencià', ], 'ch' => [ 'isoName' => 'Chamorro', 'nativeName' => 'Chamoru', ], 'ce' => [ 'isoName' => 'Chechen', 'nativeName' => 'нохчийн мотт', ], 'ny' => [ 'isoName' => 'Chichewa, Chewa, Nyanja', 'nativeName' => 'chiCheŵa, chinyanja', ], 'zh' => [ 'isoName' => 'Chinese', 'nativeName' => '中文 (Zhōngwén), 汉语, 漢語', ], 'cv' => [ 'isoName' => 'Chuvash', 'nativeName' => 'чӑваш чӗлхи', ], 'kw' => [ 'isoName' => 'Cornish', 'nativeName' => 'Kernewek', ], 'co' => [ 'isoName' => 'Corsican', 'nativeName' => 'corsu, lingua corsa', ], 'cr' => [ 'isoName' => 'Cree', 'nativeName' => 'ᓀᐦᐃᔭᐍᐏᐣ', ], 'hr' => [ 'isoName' => 'Croatian', 'nativeName' => 'hrvatski jezik', ], 'cs' => [ 'isoName' => 'Czech', 'nativeName' => 'čeština, český jazyk', ], 'da' => [ 'isoName' => 'Danish', 'nativeName' => 'dansk', ], 'dv' => [ 'isoName' => 'Divehi, Dhivehi, Maldivian', 'nativeName' => 'ދިވެހި', ], 'nl' => [ 'isoName' => 'Dutch, Flemish', 'nativeName' => 'Nederlands, Vlaams', ], 'dz' => [ 'isoName' => 'Dzongkha', 'nativeName' => 'རྫོང་ཁ', ], 'en' => [ 'isoName' => 'English', 'nativeName' => 'English', ], 'eo' => [ 'isoName' => 'Esperanto', 'nativeName' => 'Esperanto', ], 'et' => [ 'isoName' => 'Estonian', 'nativeName' => 'eesti, eesti keel', ], 'ee' => [ 'isoName' => 'Ewe', 'nativeName' => 'Eʋegbe', ], 'fo' => [ 'isoName' => 'Faroese', 'nativeName' => 'føroyskt', ], 'fj' => [ 'isoName' => 'Fijian', 'nativeName' => 'vosa Vakaviti', ], 'fi' => [ 'isoName' => 'Finnish', 'nativeName' => 'suomi, suomen kieli', ], 'fr' => [ 'isoName' => 'French', 'nativeName' => 'français', ], 'ff' => [ 'isoName' => 'Fulah', 'nativeName' => 'Fulfulde, Pulaar, Pular', ], 'gl' => [ 'isoName' => 'Galician', 'nativeName' => 'Galego', ], 'ka' => [ 'isoName' => 'Georgian', 'nativeName' => 'ქართული', ], 'de' => [ 'isoName' => 'German', 'nativeName' => 'Deutsch', ], 'el' => [ 'isoName' => 'Greek (modern)', 'nativeName' => 'ελληνικά', ], 'gn' => [ 'isoName' => 'Guaraní', 'nativeName' => 'Avañe\'ẽ', ], 'gu' => [ 'isoName' => 'Gujarati', 'nativeName' => 'ગુજરાતી', ], 'ht' => [ 'isoName' => 'Haitian, Haitian Creole', 'nativeName' => 'Kreyòl ayisyen', ], 'ha' => [ 'isoName' => 'Hausa', 'nativeName' => '(Hausa) هَوُسَ', ], 'he' => [ 'isoName' => 'Hebrew (modern)', 'nativeName' => 'עברית', ], 'hz' => [ 'isoName' => 'Herero', 'nativeName' => 'Otjiherero', ], 'hi' => [ 'isoName' => 'Hindi', 'nativeName' => 'हिन्दी, हिंदी', ], 'ho' => [ 'isoName' => 'Hiri Motu', 'nativeName' => 'Hiri Motu', ], 'hu' => [ 'isoName' => 'Hungarian', 'nativeName' => 'magyar', ], 'ia' => [ 'isoName' => 'Interlingua', 'nativeName' => 'Interlingua', ], 'id' => [ 'isoName' => 'Indonesian', 'nativeName' => 'Bahasa Indonesia', ], 'ie' => [ 'isoName' => 'Interlingue', 'nativeName' => 'Originally called Occidental; then Interlingue after WWII', ], 'ga' => [ 'isoName' => 'Irish', 'nativeName' => 'Gaeilge', ], 'ig' => [ 'isoName' => 'Igbo', 'nativeName' => 'Asụsụ Igbo', ], 'ik' => [ 'isoName' => 'Inupiaq', 'nativeName' => 'Iñupiaq, Iñupiatun', ], 'io' => [ 'isoName' => 'Ido', 'nativeName' => 'Ido', ], 'is' => [ 'isoName' => 'Icelandic', 'nativeName' => 'Íslenska', ], 'it' => [ 'isoName' => 'Italian', 'nativeName' => 'Italiano', ], 'iu' => [ 'isoName' => 'Inuktitut', 'nativeName' => 'ᐃᓄᒃᑎᑐᑦ', ], 'ja' => [ 'isoName' => 'Japanese', 'nativeName' => '日本語 (にほんご)', ], 'jv' => [ 'isoName' => 'Javanese', 'nativeName' => 'ꦧꦱꦗꦮ, Basa Jawa', ], 'kl' => [ 'isoName' => 'Kalaallisut, Greenlandic', 'nativeName' => 'kalaallisut, kalaallit oqaasii', ], 'kn' => [ 'isoName' => 'Kannada', 'nativeName' => 'ಕನ್ನಡ', ], 'kr' => [ 'isoName' => 'Kanuri', 'nativeName' => 'Kanuri', ], 'ks' => [ 'isoName' => 'Kashmiri', 'nativeName' => 'कश्मीरी, كشميري‎', ], 'kk' => [ 'isoName' => 'Kazakh', 'nativeName' => 'қазақ тілі', ], 'km' => [ 'isoName' => 'Central Khmer', 'nativeName' => 'ខ្មែរ, ខេមរភាសា, ភាសាខ្មែរ', ], 'ki' => [ 'isoName' => 'Kikuyu, Gikuyu', 'nativeName' => 'Gĩkũyũ', ], 'rw' => [ 'isoName' => 'Kinyarwanda', 'nativeName' => 'Ikinyarwanda', ], 'ky' => [ 'isoName' => 'Kirghiz, Kyrgyz', 'nativeName' => 'Кыргызча, Кыргыз тили', ], 'kv' => [ 'isoName' => 'Komi', 'nativeName' => 'коми кыв', ], 'kg' => [ 'isoName' => 'Kongo', 'nativeName' => 'Kikongo', ], 'ko' => [ 'isoName' => 'Korean', 'nativeName' => '한국어', ], 'ku' => [ 'isoName' => 'Kurdish', 'nativeName' => 'Kurdî, کوردی‎', ], 'kj' => [ 'isoName' => 'Kuanyama, Kwanyama', 'nativeName' => 'Kuanyama', ], 'la' => [ 'isoName' => 'Latin', 'nativeName' => 'latine, lingua latina', ], 'lb' => [ 'isoName' => 'Luxembourgish, Letzeburgesch', 'nativeName' => 'Lëtzebuergesch', ], 'lg' => [ 'isoName' => 'Ganda', 'nativeName' => 'Luganda', ], 'li' => [ 'isoName' => 'Limburgan, Limburger, Limburgish', 'nativeName' => 'Limburgs', ], 'ln' => [ 'isoName' => 'Lingala', 'nativeName' => 'Lingála', ], 'lo' => [ 'isoName' => 'Lao', 'nativeName' => 'ພາສາລາວ', ], 'lt' => [ 'isoName' => 'Lithuanian', 'nativeName' => 'lietuvių kalba', ], 'lu' => [ 'isoName' => 'Luba-Katanga', 'nativeName' => 'Kiluba', ], 'lv' => [ 'isoName' => 'Latvian', 'nativeName' => 'latviešu valoda', ], 'gv' => [ 'isoName' => 'Manx', 'nativeName' => 'Gaelg, Gailck', ], 'mk' => [ 'isoName' => 'Macedonian', 'nativeName' => 'македонски јазик', ], 'mg' => [ 'isoName' => 'Malagasy', 'nativeName' => 'fiteny malagasy', ], 'ms' => [ 'isoName' => 'Malay', 'nativeName' => 'Bahasa Melayu, بهاس ملايو‎', ], 'ml' => [ 'isoName' => 'Malayalam', 'nativeName' => 'മലയാളം', ], 'mt' => [ 'isoName' => 'Maltese', 'nativeName' => 'Malti', ], 'mi' => [ 'isoName' => 'Maori', 'nativeName' => 'te reo Māori', ], 'mr' => [ 'isoName' => 'Marathi', 'nativeName' => 'मराठी', ], 'mh' => [ 'isoName' => 'Marshallese', 'nativeName' => 'Kajin M̧ajeļ', ], 'mn' => [ 'isoName' => 'Mongolian', 'nativeName' => 'Монгол хэл', ], 'na' => [ 'isoName' => 'Nauru', 'nativeName' => 'Dorerin Naoero', ], 'nv' => [ 'isoName' => 'Navajo, Navaho', 'nativeName' => 'Diné bizaad', ], 'nd' => [ 'isoName' => 'North Ndebele', 'nativeName' => 'isiNdebele', ], 'ne' => [ 'isoName' => 'Nepali', 'nativeName' => 'नेपाली', ], 'ng' => [ 'isoName' => 'Ndonga', 'nativeName' => 'Owambo', ], 'nb' => [ 'isoName' => 'Norwegian Bokmål', 'nativeName' => 'Norsk Bokmål', ], 'nn' => [ 'isoName' => 'Norwegian Nynorsk', 'nativeName' => 'Norsk Nynorsk', ], 'no' => [ 'isoName' => 'Norwegian', 'nativeName' => 'Norsk', ], 'ii' => [ 'isoName' => 'Sichuan Yi, Nuosu', 'nativeName' => 'ꆈꌠ꒿ Nuosuhxop', ], 'nr' => [ 'isoName' => 'South Ndebele', 'nativeName' => 'isiNdebele', ], 'oc' => [ 'isoName' => 'Occitan', 'nativeName' => 'occitan, lenga d\'òc', ], 'oj' => [ 'isoName' => 'Ojibwa', 'nativeName' => 'ᐊᓂᔑᓈᐯᒧᐎᓐ', ], 'cu' => [ 'isoName' => 'Church Slavic, Church Slavonic, Old Church Slavonic, Old Slavonic, Old Bulgarian', 'nativeName' => 'ѩзыкъ словѣньскъ', ], 'om' => [ 'isoName' => 'Oromo', 'nativeName' => 'Afaan Oromoo', ], 'or' => [ 'isoName' => 'Oriya', 'nativeName' => 'ଓଡ଼ିଆ', ], 'os' => [ 'isoName' => 'Ossetian, Ossetic', 'nativeName' => 'ирон æвзаг', ], 'pa' => [ 'isoName' => 'Panjabi, Punjabi', 'nativeName' => 'ਪੰਜਾਬੀ', ], 'pi' => [ 'isoName' => 'Pali', 'nativeName' => 'पाऴि', ], 'fa' => [ 'isoName' => 'Persian', 'nativeName' => 'فارسی', ], 'pl' => [ 'isoName' => 'Polish', 'nativeName' => 'język polski, polszczyzna', ], 'ps' => [ 'isoName' => 'Pashto, Pushto', 'nativeName' => 'پښتو', ], 'pt' => [ 'isoName' => 'Portuguese', 'nativeName' => 'Português', ], 'qu' => [ 'isoName' => 'Quechua', 'nativeName' => 'Runa Simi, Kichwa', ], 'rm' => [ 'isoName' => 'Romansh', 'nativeName' => 'Rumantsch Grischun', ], 'rn' => [ 'isoName' => 'Rundi', 'nativeName' => 'Ikirundi', ], 'ro' => [ 'isoName' => 'Romanian, Moldavian, Moldovan', 'nativeName' => 'Română', ], 'ru' => [ 'isoName' => 'Russian', 'nativeName' => 'русский', ], 'sa' => [ 'isoName' => 'Sanskrit', 'nativeName' => 'संस्कृतम्', ], 'sc' => [ 'isoName' => 'Sardinian', 'nativeName' => 'sardu', ], 'sd' => [ 'isoName' => 'Sindhi', 'nativeName' => 'सिन्धी, سنڌي، سندھی‎', ], 'se' => [ 'isoName' => 'Northern Sami', 'nativeName' => 'Davvisámegiella', ], 'sm' => [ 'isoName' => 'Samoan', 'nativeName' => 'gagana fa\'a Samoa', ], 'sg' => [ 'isoName' => 'Sango', 'nativeName' => 'yângâ tî sängö', ], 'sr' => [ 'isoName' => 'Serbian', 'nativeName' => 'српски језик', ], 'gd' => [ 'isoName' => 'Gaelic, Scottish Gaelic', 'nativeName' => 'Gàidhlig', ], 'sn' => [ 'isoName' => 'Shona', 'nativeName' => 'chiShona', ], 'si' => [ 'isoName' => 'Sinhala, Sinhalese', 'nativeName' => 'සිංහල', ], 'sk' => [ 'isoName' => 'Slovak', 'nativeName' => 'Slovenčina, Slovenský Jazyk', ], 'sl' => [ 'isoName' => 'Slovene', 'nativeName' => 'Slovenski Jezik, Slovenščina', ], 'so' => [ 'isoName' => 'Somali', 'nativeName' => 'Soomaaliga, af Soomaali', ], 'st' => [ 'isoName' => 'Southern Sotho', 'nativeName' => 'Sesotho', ], 'es' => [ 'isoName' => 'Spanish, Castilian', 'nativeName' => 'Español', ], 'su' => [ 'isoName' => 'Sundanese', 'nativeName' => 'Basa Sunda', ], 'sw' => [ 'isoName' => 'Swahili', 'nativeName' => 'Kiswahili', ], 'ss' => [ 'isoName' => 'Swati', 'nativeName' => 'SiSwati', ], 'sv' => [ 'isoName' => 'Swedish', 'nativeName' => 'Svenska', ], 'ta' => [ 'isoName' => 'Tamil', 'nativeName' => 'தமிழ்', ], 'te' => [ 'isoName' => 'Telugu', 'nativeName' => 'తెలుగు', ], 'tg' => [ 'isoName' => 'Tajik', 'nativeName' => 'тоҷикӣ, toçikī, تاجیکی‎', ], 'th' => [ 'isoName' => 'Thai', 'nativeName' => 'ไทย', ], 'ti' => [ 'isoName' => 'Tigrinya', 'nativeName' => 'ትግርኛ', ], 'bo' => [ 'isoName' => 'Tibetan', 'nativeName' => 'བོད་ཡིག', ], 'tk' => [ 'isoName' => 'Turkmen', 'nativeName' => 'Türkmen, Түркмен', ], 'tl' => [ 'isoName' => 'Tagalog', 'nativeName' => 'Wikang Tagalog', ], 'tn' => [ 'isoName' => 'Tswana', 'nativeName' => 'Setswana', ], 'to' => [ 'isoName' => 'Tongan (Tonga Islands)', 'nativeName' => 'Faka Tonga', ], 'tr' => [ 'isoName' => 'Turkish', 'nativeName' => 'Türkçe', ], 'ts' => [ 'isoName' => 'Tsonga', 'nativeName' => 'Xitsonga', ], 'tt' => [ 'isoName' => 'Tatar', 'nativeName' => 'татар теле, tatar tele', ], 'tw' => [ 'isoName' => 'Twi', 'nativeName' => 'Twi', ], 'ty' => [ 'isoName' => 'Tahitian', 'nativeName' => 'Reo Tahiti', ], 'ug' => [ 'isoName' => 'Uighur, Uyghur', 'nativeName' => 'Uyƣurqə, ‫ئۇيغۇرچ', ], 'uk' => [ 'isoName' => 'Ukrainian', 'nativeName' => 'Українська', ], 'ur' => [ 'isoName' => 'Urdu', 'nativeName' => 'اردو', ], 'uz' => [ 'isoName' => 'Uzbek', 'nativeName' => 'Oʻzbek, Ўзбек, أۇزبېك‎', ], 've' => [ 'isoName' => 'Venda', 'nativeName' => 'Tshivenḓa', ], 'vi' => [ 'isoName' => 'Vietnamese', 'nativeName' => 'Tiếng Việt', ], 'vo' => [ 'isoName' => 'Volapük', 'nativeName' => 'Volapük', ], 'wa' => [ 'isoName' => 'Walloon', 'nativeName' => 'Walon', ], 'cy' => [ 'isoName' => 'Welsh', 'nativeName' => 'Cymraeg', ], 'wo' => [ 'isoName' => 'Wolof', 'nativeName' => 'Wollof', ], 'fy' => [ 'isoName' => 'Western Frisian', 'nativeName' => 'Frysk', ], 'xh' => [ 'isoName' => 'Xhosa', 'nativeName' => 'isiXhosa', ], 'yi' => [ 'isoName' => 'Yiddish', 'nativeName' => 'ייִדיש', ], 'yo' => [ 'isoName' => 'Yoruba', 'nativeName' => 'Yorùbá', ], 'za' => [ 'isoName' => 'Zhuang, Chuang', 'nativeName' => 'Saɯ cueŋƅ, Saw cuengh', ], 'zu' => [ 'isoName' => 'Zulu', 'nativeName' => 'isiZulu', ], /* * Add ISO 639-3 languages available in Carbon */ 'agq' => [ 'isoName' => 'Aghem', 'nativeName' => 'Aghem', ], 'agr' => [ 'isoName' => 'Aguaruna', 'nativeName' => 'Aguaruna', ], 'anp' => [ 'isoName' => 'Angika', 'nativeName' => 'Angika', ], 'asa' => [ 'isoName' => 'Asu', 'nativeName' => 'Asu', ], 'ast' => [ 'isoName' => 'Asturian', 'nativeName' => 'Asturian', ], 'ayc' => [ 'isoName' => 'Southern Aymara', 'nativeName' => 'Southern Aymara', ], 'bas' => [ 'isoName' => 'Basaa', 'nativeName' => 'Basaa', ], 'bem' => [ 'isoName' => 'Bemba', 'nativeName' => 'Bemba', ], 'bez' => [ 'isoName' => 'Bena', 'nativeName' => 'Bena', ], 'bhb' => [ 'isoName' => 'Bhili', 'nativeName' => 'Bhili', ], 'bho' => [ 'isoName' => 'Bhojpuri', 'nativeName' => 'Bhojpuri', ], 'brx' => [ 'isoName' => 'Bodo', 'nativeName' => 'Bodo', ], 'byn' => [ 'isoName' => 'Bilin', 'nativeName' => 'Bilin', ], 'ccp' => [ 'isoName' => 'Chakma', 'nativeName' => 'Chakma', ], 'cgg' => [ 'isoName' => 'Chiga', 'nativeName' => 'Chiga', ], 'chr' => [ 'isoName' => 'Cherokee', 'nativeName' => 'Cherokee', ], 'cmn' => [ 'isoName' => 'Chinese', 'nativeName' => 'Chinese', ], 'crh' => [ 'isoName' => 'Crimean Turkish', 'nativeName' => 'Crimean Turkish', ], 'csb' => [ 'isoName' => 'Kashubian', 'nativeName' => 'Kashubian', ], 'dav' => [ 'isoName' => 'Taita', 'nativeName' => 'Taita', ], 'dje' => [ 'isoName' => 'Zarma', 'nativeName' => 'Zarma', ], 'doi' => [ 'isoName' => 'Dogri (macrolanguage)', 'nativeName' => 'Dogri (macrolanguage)', ], 'dsb' => [ 'isoName' => 'Lower Sorbian', 'nativeName' => 'Lower Sorbian', ], 'dua' => [ 'isoName' => 'Duala', 'nativeName' => 'Duala', ], 'dyo' => [ 'isoName' => 'Jola-Fonyi', 'nativeName' => 'Jola-Fonyi', ], 'ebu' => [ 'isoName' => 'Embu', 'nativeName' => 'Embu', ], 'ewo' => [ 'isoName' => 'Ewondo', 'nativeName' => 'Ewondo', ], 'fil' => [ 'isoName' => 'Filipino', 'nativeName' => 'Filipino', ], 'fur' => [ 'isoName' => 'Friulian', 'nativeName' => 'Friulian', ], 'gez' => [ 'isoName' => 'Geez', 'nativeName' => 'Geez', ], 'gom' => [ 'isoName' => 'Konkani, Goan', 'nativeName' => 'ಕೊಂಕಣಿ', ], 'gsw' => [ 'isoName' => 'Swiss German', 'nativeName' => 'Swiss German', ], 'guz' => [ 'isoName' => 'Gusii', 'nativeName' => 'Gusii', ], 'hak' => [ 'isoName' => 'Hakka Chinese', 'nativeName' => 'Hakka Chinese', ], 'haw' => [ 'isoName' => 'Hawaiian', 'nativeName' => 'Hawaiian', ], 'hif' => [ 'isoName' => 'Fiji Hindi', 'nativeName' => 'Fiji Hindi', ], 'hne' => [ 'isoName' => 'Chhattisgarhi', 'nativeName' => 'Chhattisgarhi', ], 'hsb' => [ 'isoName' => 'Upper Sorbian', 'nativeName' => 'Upper Sorbian', ], 'jgo' => [ 'isoName' => 'Ngomba', 'nativeName' => 'Ngomba', ], 'jmc' => [ 'isoName' => 'Machame', 'nativeName' => 'Machame', ], 'kab' => [ 'isoName' => 'Kabyle', 'nativeName' => 'Kabyle', ], 'kam' => [ 'isoName' => 'Kamba', 'nativeName' => 'Kamba', ], 'kde' => [ 'isoName' => 'Makonde', 'nativeName' => 'Makonde', ], 'kea' => [ 'isoName' => 'Kabuverdianu', 'nativeName' => 'Kabuverdianu', ], 'khq' => [ 'isoName' => 'Koyra Chiini', 'nativeName' => 'Koyra Chiini', ], 'kkj' => [ 'isoName' => 'Kako', 'nativeName' => 'Kako', ], 'kln' => [ 'isoName' => 'Kalenjin', 'nativeName' => 'Kalenjin', ], 'kok' => [ 'isoName' => 'Konkani', 'nativeName' => 'Konkani', ], 'ksb' => [ 'isoName' => 'Shambala', 'nativeName' => 'Shambala', ], 'ksf' => [ 'isoName' => 'Bafia', 'nativeName' => 'Bafia', ], 'ksh' => [ 'isoName' => 'Colognian', 'nativeName' => 'Colognian', ], 'lag' => [ 'isoName' => 'Langi', 'nativeName' => 'Langi', ], 'lij' => [ 'isoName' => 'Ligurian', 'nativeName' => 'Ligurian', ], 'lkt' => [ 'isoName' => 'Lakota', 'nativeName' => 'Lakota', ], 'lrc' => [ 'isoName' => 'Northern Luri', 'nativeName' => 'Northern Luri', ], 'luo' => [ 'isoName' => 'Luo', 'nativeName' => 'Luo', ], 'luy' => [ 'isoName' => 'Luyia', 'nativeName' => 'Luyia', ], 'lzh' => [ 'isoName' => 'Literary Chinese', 'nativeName' => 'Literary Chinese', ], 'mag' => [ 'isoName' => 'Magahi', 'nativeName' => 'Magahi', ], 'mai' => [ 'isoName' => 'Maithili', 'nativeName' => 'Maithili', ], 'mas' => [ 'isoName' => 'Masai', 'nativeName' => 'Masai', ], 'mer' => [ 'isoName' => 'Meru', 'nativeName' => 'Meru', ], 'mfe' => [ 'isoName' => 'Morisyen', 'nativeName' => 'Morisyen', ], 'mgh' => [ 'isoName' => 'Makhuwa-Meetto', 'nativeName' => 'Makhuwa-Meetto', ], 'mgo' => [ 'isoName' => 'Metaʼ', 'nativeName' => 'Metaʼ', ], 'mhr' => [ 'isoName' => 'Eastern Mari', 'nativeName' => 'Eastern Mari', ], 'miq' => [ 'isoName' => 'Mískito', 'nativeName' => 'Mískito', ], 'mjw' => [ 'isoName' => 'Karbi', 'nativeName' => 'Karbi', ], 'mni' => [ 'isoName' => 'Manipuri', 'nativeName' => 'Manipuri', ], 'mua' => [ 'isoName' => 'Mundang', 'nativeName' => 'Mundang', ], 'mzn' => [ 'isoName' => 'Mazanderani', 'nativeName' => 'Mazanderani', ], 'nan' => [ 'isoName' => 'Min Nan Chinese', 'nativeName' => 'Min Nan Chinese', ], 'naq' => [ 'isoName' => 'Nama', 'nativeName' => 'Nama', ], 'nds' => [ 'isoName' => 'Low German', 'nativeName' => 'Low German', ], 'nhn' => [ 'isoName' => 'Central Nahuatl', 'nativeName' => 'Central Nahuatl', ], 'niu' => [ 'isoName' => 'Niuean', 'nativeName' => 'Niuean', ], 'nmg' => [ 'isoName' => 'Kwasio', 'nativeName' => 'Kwasio', ], 'nnh' => [ 'isoName' => 'Ngiemboon', 'nativeName' => 'Ngiemboon', ], 'nso' => [ 'isoName' => 'Northern Sotho', 'nativeName' => 'Northern Sotho', ], 'nus' => [ 'isoName' => 'Nuer', 'nativeName' => 'Nuer', ], 'nyn' => [ 'isoName' => 'Nyankole', 'nativeName' => 'Nyankole', ], 'pap' => [ 'isoName' => 'Papiamento', 'nativeName' => 'Papiamento', ], 'prg' => [ 'isoName' => 'Prussian', 'nativeName' => 'Prussian', ], 'quz' => [ 'isoName' => 'Cusco Quechua', 'nativeName' => 'Cusco Quechua', ], 'raj' => [ 'isoName' => 'Rajasthani', 'nativeName' => 'Rajasthani', ], 'rof' => [ 'isoName' => 'Rombo', 'nativeName' => 'Rombo', ], 'rwk' => [ 'isoName' => 'Rwa', 'nativeName' => 'Rwa', ], 'sah' => [ 'isoName' => 'Sakha', 'nativeName' => 'Sakha', ], 'saq' => [ 'isoName' => 'Samburu', 'nativeName' => 'Samburu', ], 'sat' => [ 'isoName' => 'Santali', 'nativeName' => 'Santali', ], 'sbp' => [ 'isoName' => 'Sangu', 'nativeName' => 'Sangu', ], 'scr' => [ 'isoName' => 'Serbo Croatian', 'nativeName' => 'Serbo Croatian', ], 'seh' => [ 'isoName' => 'Sena', 'nativeName' => 'Sena', ], 'ses' => [ 'isoName' => 'Koyraboro Senni', 'nativeName' => 'Koyraboro Senni', ], 'sgs' => [ 'isoName' => 'Samogitian', 'nativeName' => 'Samogitian', ], 'shi' => [ 'isoName' => 'Tachelhit', 'nativeName' => 'Tachelhit', ], 'shn' => [ 'isoName' => 'Shan', 'nativeName' => 'Shan', ], 'shs' => [ 'isoName' => 'Shuswap', 'nativeName' => 'Shuswap', ], 'sid' => [ 'isoName' => 'Sidamo', 'nativeName' => 'Sidamo', ], 'smn' => [ 'isoName' => 'Inari Sami', 'nativeName' => 'Inari Sami', ], 'szl' => [ 'isoName' => 'Silesian', 'nativeName' => 'Silesian', ], 'tcy' => [ 'isoName' => 'Tulu', 'nativeName' => 'Tulu', ], 'teo' => [ 'isoName' => 'Teso', 'nativeName' => 'Teso', ], 'tet' => [ 'isoName' => 'Tetum', 'nativeName' => 'Tetum', ], 'the' => [ 'isoName' => 'Chitwania Tharu', 'nativeName' => 'Chitwania Tharu', ], 'tig' => [ 'isoName' => 'Tigre', 'nativeName' => 'Tigre', ], 'tlh' => [ 'isoName' => 'Klingon', 'nativeName' => 'tlhIngan Hol', ], 'tpi' => [ 'isoName' => 'Tok Pisin', 'nativeName' => 'Tok Pisin', ], 'twq' => [ 'isoName' => 'Tasawaq', 'nativeName' => 'Tasawaq', ], 'tzl' => [ 'isoName' => 'Talossan', 'nativeName' => 'Talossan', ], 'tzm' => [ 'isoName' => 'Tamazight, Central Atlas', 'nativeName' => 'ⵜⵎⴰⵣⵉⵖⵜ', ], 'unm' => [ 'isoName' => 'Unami', 'nativeName' => 'Unami', ], 'vai' => [ 'isoName' => 'Vai', 'nativeName' => 'Vai', ], 'vun' => [ 'isoName' => 'Vunjo', 'nativeName' => 'Vunjo', ], 'wae' => [ 'isoName' => 'Walser', 'nativeName' => 'Walser', ], 'wal' => [ 'isoName' => 'Wolaytta', 'nativeName' => 'Wolaytta', ], 'xog' => [ 'isoName' => 'Soga', 'nativeName' => 'Soga', ], 'yav' => [ 'isoName' => 'Yangben', 'nativeName' => 'Yangben', ], 'yue' => [ 'isoName' => 'Cantonese', 'nativeName' => 'Cantonese', ], 'yuw' => [ 'isoName' => 'Yau (Morobe Province)', 'nativeName' => 'Yau (Morobe Province)', ], 'zgh' => [ 'isoName' => 'Standard Moroccan Tamazight', 'nativeName' => 'Standard Moroccan Tamazight', ], ]; PK������<1ZFe.ĉ�ĉ���Carbon/CarbonImmutable.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon; use Carbon\Traits\Date; use Carbon\Traits\DeprecatedProperties; use DateTimeImmutable; use DateTimeInterface; use DateTimeZone; /** * A simple API extension for DateTimeImmutable. * * @mixin DeprecatedProperties * * <autodoc generated by `composer phpdoc`> * * @property int $year * @property int $yearIso * @property int $month * @property int $day * @property int $hour * @property int $minute * @property int $second * @property int $micro * @property int $microsecond * @property int|float|string $timestamp seconds since the Unix Epoch * @property string $englishDayOfWeek the day of week in English * @property string $shortEnglishDayOfWeek the abbreviated day of week in English * @property string $englishMonth the month in English * @property string $shortEnglishMonth the abbreviated month in English * @property int $milliseconds * @property int $millisecond * @property int $milli * @property int $week 1 through 53 * @property int $isoWeek 1 through 53 * @property int $weekYear year according to week format * @property int $isoWeekYear year according to ISO week format * @property int $dayOfYear 1 through 366 * @property int $age does a diffInYears() with default parameters * @property int $offset the timezone offset in seconds from UTC * @property int $offsetMinutes the timezone offset in minutes from UTC * @property int $offsetHours the timezone offset in hours from UTC * @property CarbonTimeZone $timezone the current timezone * @property CarbonTimeZone $tz alias of $timezone * @property-read int $dayOfWeek 0 (for Sunday) through 6 (for Saturday) * @property-read int $dayOfWeekIso 1 (for Monday) through 7 (for Sunday) * @property-read int $weekOfYear ISO-8601 week number of year, weeks starting on Monday * @property-read int $daysInMonth number of days in the given month * @property-read string $latinMeridiem "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark) * @property-read string $latinUpperMeridiem "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark) * @property-read string $timezoneAbbreviatedName the current timezone abbreviated name * @property-read string $tzAbbrName alias of $timezoneAbbreviatedName * @property-read string $dayName long name of weekday translated according to Carbon locale, in english if no translation available for current language * @property-read string $shortDayName short name of weekday translated according to Carbon locale, in english if no translation available for current language * @property-read string $minDayName very short name of weekday translated according to Carbon locale, in english if no translation available for current language * @property-read string $monthName long name of month translated according to Carbon locale, in english if no translation available for current language * @property-read string $shortMonthName short name of month translated according to Carbon locale, in english if no translation available for current language * @property-read string $meridiem lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language * @property-read string $upperMeridiem uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language * @property-read int $noZeroHour current hour from 1 to 24 * @property-read int $weeksInYear 51 through 53 * @property-read int $isoWeeksInYear 51 through 53 * @property-read int $weekOfMonth 1 through 5 * @property-read int $weekNumberInMonth 1 through 5 * @property-read int $firstWeekDay 0 through 6 * @property-read int $lastWeekDay 0 through 6 * @property-read int $daysInYear 365 or 366 * @property-read int $quarter the quarter of this instance, 1 - 4 * @property-read int $decade the decade of this instance * @property-read int $century the century of this instance * @property-read int $millennium the millennium of this instance * @property-read bool $dst daylight savings time indicator, true if DST, false otherwise * @property-read bool $local checks if the timezone is local, true if local, false otherwise * @property-read bool $utc checks if the timezone is UTC, true if UTC, false otherwise * @property-read string $timezoneName the current timezone name * @property-read string $tzName alias of $timezoneName * @property-read string $locale locale of the current instance * * @method bool isUtc() Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.) * @method bool isLocal() Check if the current instance has non-UTC timezone. * @method bool isValid() Check if the current instance is a valid date. * @method bool isDST() Check if the current instance is in a daylight saving time. * @method bool isSunday() Checks if the instance day is sunday. * @method bool isMonday() Checks if the instance day is monday. * @method bool isTuesday() Checks if the instance day is tuesday. * @method bool isWednesday() Checks if the instance day is wednesday. * @method bool isThursday() Checks if the instance day is thursday. * @method bool isFriday() Checks if the instance day is friday. * @method bool isSaturday() Checks if the instance day is saturday. * @method bool isSameYear(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same year as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentYear() Checks if the instance is in the same year as the current moment. * @method bool isNextYear() Checks if the instance is in the same year as the current moment next year. * @method bool isLastYear() Checks if the instance is in the same year as the current moment last year. * @method bool isSameWeek(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same week as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentWeek() Checks if the instance is in the same week as the current moment. * @method bool isNextWeek() Checks if the instance is in the same week as the current moment next week. * @method bool isLastWeek() Checks if the instance is in the same week as the current moment last week. * @method bool isSameDay(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same day as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentDay() Checks if the instance is in the same day as the current moment. * @method bool isNextDay() Checks if the instance is in the same day as the current moment next day. * @method bool isLastDay() Checks if the instance is in the same day as the current moment last day. * @method bool isSameHour(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same hour as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentHour() Checks if the instance is in the same hour as the current moment. * @method bool isNextHour() Checks if the instance is in the same hour as the current moment next hour. * @method bool isLastHour() Checks if the instance is in the same hour as the current moment last hour. * @method bool isSameMinute(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same minute as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentMinute() Checks if the instance is in the same minute as the current moment. * @method bool isNextMinute() Checks if the instance is in the same minute as the current moment next minute. * @method bool isLastMinute() Checks if the instance is in the same minute as the current moment last minute. * @method bool isSameSecond(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same second as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentSecond() Checks if the instance is in the same second as the current moment. * @method bool isNextSecond() Checks if the instance is in the same second as the current moment next second. * @method bool isLastSecond() Checks if the instance is in the same second as the current moment last second. * @method bool isSameMicro(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentMicro() Checks if the instance is in the same microsecond as the current moment. * @method bool isNextMicro() Checks if the instance is in the same microsecond as the current moment next microsecond. * @method bool isLastMicro() Checks if the instance is in the same microsecond as the current moment last microsecond. * @method bool isSameMicrosecond(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentMicrosecond() Checks if the instance is in the same microsecond as the current moment. * @method bool isNextMicrosecond() Checks if the instance is in the same microsecond as the current moment next microsecond. * @method bool isLastMicrosecond() Checks if the instance is in the same microsecond as the current moment last microsecond. * @method bool isCurrentMonth() Checks if the instance is in the same month as the current moment. * @method bool isNextMonth() Checks if the instance is in the same month as the current moment next month. * @method bool isLastMonth() Checks if the instance is in the same month as the current moment last month. * @method bool isCurrentQuarter() Checks if the instance is in the same quarter as the current moment. * @method bool isNextQuarter() Checks if the instance is in the same quarter as the current moment next quarter. * @method bool isLastQuarter() Checks if the instance is in the same quarter as the current moment last quarter. * @method bool isSameDecade(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same decade as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentDecade() Checks if the instance is in the same decade as the current moment. * @method bool isNextDecade() Checks if the instance is in the same decade as the current moment next decade. * @method bool isLastDecade() Checks if the instance is in the same decade as the current moment last decade. * @method bool isSameCentury(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same century as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentCentury() Checks if the instance is in the same century as the current moment. * @method bool isNextCentury() Checks if the instance is in the same century as the current moment next century. * @method bool isLastCentury() Checks if the instance is in the same century as the current moment last century. * @method bool isSameMillennium(Carbon|DateTimeInterface|string|null $date = null) Checks if the given date is in the same millennium as the instance. If null passed, compare to now (with the same timezone). * @method bool isCurrentMillennium() Checks if the instance is in the same millennium as the current moment. * @method bool isNextMillennium() Checks if the instance is in the same millennium as the current moment next millennium. * @method bool isLastMillennium() Checks if the instance is in the same millennium as the current moment last millennium. * @method CarbonImmutable years(int $value) Set current instance year to the given value. * @method CarbonImmutable year(int $value) Set current instance year to the given value. * @method CarbonImmutable setYears(int $value) Set current instance year to the given value. * @method CarbonImmutable setYear(int $value) Set current instance year to the given value. * @method CarbonImmutable months(int $value) Set current instance month to the given value. * @method CarbonImmutable month(int $value) Set current instance month to the given value. * @method CarbonImmutable setMonths(int $value) Set current instance month to the given value. * @method CarbonImmutable setMonth(int $value) Set current instance month to the given value. * @method CarbonImmutable days(int $value) Set current instance day to the given value. * @method CarbonImmutable day(int $value) Set current instance day to the given value. * @method CarbonImmutable setDays(int $value) Set current instance day to the given value. * @method CarbonImmutable setDay(int $value) Set current instance day to the given value. * @method CarbonImmutable hours(int $value) Set current instance hour to the given value. * @method CarbonImmutable hour(int $value) Set current instance hour to the given value. * @method CarbonImmutable setHours(int $value) Set current instance hour to the given value. * @method CarbonImmutable setHour(int $value) Set current instance hour to the given value. * @method CarbonImmutable minutes(int $value) Set current instance minute to the given value. * @method CarbonImmutable minute(int $value) Set current instance minute to the given value. * @method CarbonImmutable setMinutes(int $value) Set current instance minute to the given value. * @method CarbonImmutable setMinute(int $value) Set current instance minute to the given value. * @method CarbonImmutable seconds(int $value) Set current instance second to the given value. * @method CarbonImmutable second(int $value) Set current instance second to the given value. * @method CarbonImmutable setSeconds(int $value) Set current instance second to the given value. * @method CarbonImmutable setSecond(int $value) Set current instance second to the given value. * @method CarbonImmutable millis(int $value) Set current instance millisecond to the given value. * @method CarbonImmutable milli(int $value) Set current instance millisecond to the given value. * @method CarbonImmutable setMillis(int $value) Set current instance millisecond to the given value. * @method CarbonImmutable setMilli(int $value) Set current instance millisecond to the given value. * @method CarbonImmutable milliseconds(int $value) Set current instance millisecond to the given value. * @method CarbonImmutable millisecond(int $value) Set current instance millisecond to the given value. * @method CarbonImmutable setMilliseconds(int $value) Set current instance millisecond to the given value. * @method CarbonImmutable setMillisecond(int $value) Set current instance millisecond to the given value. * @method CarbonImmutable micros(int $value) Set current instance microsecond to the given value. * @method CarbonImmutable micro(int $value) Set current instance microsecond to the given value. * @method CarbonImmutable setMicros(int $value) Set current instance microsecond to the given value. * @method CarbonImmutable setMicro(int $value) Set current instance microsecond to the given value. * @method CarbonImmutable microseconds(int $value) Set current instance microsecond to the given value. * @method CarbonImmutable microsecond(int $value) Set current instance microsecond to the given value. * @method CarbonImmutable setMicroseconds(int $value) Set current instance microsecond to the given value. * @method CarbonImmutable setMicrosecond(int $value) Set current instance microsecond to the given value. * @method CarbonImmutable addYears(int $value = 1) Add years (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable addYear() Add one year to the instance (using date interval). * @method CarbonImmutable subYears(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable subYear() Sub one year to the instance (using date interval). * @method CarbonImmutable addYearsWithOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable addYearWithOverflow() Add one year to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable subYearsWithOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable subYearWithOverflow() Sub one year to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable addYearsWithoutOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addYearWithoutOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subYearsWithoutOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subYearWithoutOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addYearsWithNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addYearWithNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subYearsWithNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subYearWithNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addYearsNoOverflow(int $value = 1) Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addYearNoOverflow() Add one year to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subYearsNoOverflow(int $value = 1) Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subYearNoOverflow() Sub one year to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addMonths(int $value = 1) Add months (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable addMonth() Add one month to the instance (using date interval). * @method CarbonImmutable subMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable subMonth() Sub one month to the instance (using date interval). * @method CarbonImmutable addMonthsWithOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable addMonthWithOverflow() Add one month to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable subMonthsWithOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable subMonthWithOverflow() Sub one month to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable addMonthsWithoutOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addMonthWithoutOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subMonthsWithoutOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subMonthWithoutOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addMonthsWithNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addMonthWithNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subMonthsWithNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subMonthWithNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addMonthsNoOverflow(int $value = 1) Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addMonthNoOverflow() Add one month to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subMonthsNoOverflow(int $value = 1) Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subMonthNoOverflow() Sub one month to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addDays(int $value = 1) Add days (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable addDay() Add one day to the instance (using date interval). * @method CarbonImmutable subDays(int $value = 1) Sub days (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable subDay() Sub one day to the instance (using date interval). * @method CarbonImmutable addHours(int $value = 1) Add hours (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable addHour() Add one hour to the instance (using date interval). * @method CarbonImmutable subHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable subHour() Sub one hour to the instance (using date interval). * @method CarbonImmutable addMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable addMinute() Add one minute to the instance (using date interval). * @method CarbonImmutable subMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable subMinute() Sub one minute to the instance (using date interval). * @method CarbonImmutable addSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable addSecond() Add one second to the instance (using date interval). * @method CarbonImmutable subSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable subSecond() Sub one second to the instance (using date interval). * @method CarbonImmutable addMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable addMilli() Add one millisecond to the instance (using date interval). * @method CarbonImmutable subMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable subMilli() Sub one millisecond to the instance (using date interval). * @method CarbonImmutable addMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable addMillisecond() Add one millisecond to the instance (using date interval). * @method CarbonImmutable subMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable subMillisecond() Sub one millisecond to the instance (using date interval). * @method CarbonImmutable addMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable addMicro() Add one microsecond to the instance (using date interval). * @method CarbonImmutable subMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable subMicro() Sub one microsecond to the instance (using date interval). * @method CarbonImmutable addMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable addMicrosecond() Add one microsecond to the instance (using date interval). * @method CarbonImmutable subMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable subMicrosecond() Sub one microsecond to the instance (using date interval). * @method CarbonImmutable addMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable addMillennium() Add one millennium to the instance (using date interval). * @method CarbonImmutable subMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable subMillennium() Sub one millennium to the instance (using date interval). * @method CarbonImmutable addMillenniaWithOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable addMillenniumWithOverflow() Add one millennium to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable subMillenniaWithOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable subMillenniumWithOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable addMillenniaWithoutOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addMillenniumWithoutOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subMillenniaWithoutOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subMillenniumWithoutOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addMillenniaWithNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addMillenniumWithNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subMillenniaWithNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subMillenniumWithNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addMillenniaNoOverflow(int $value = 1) Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addMillenniumNoOverflow() Add one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subMillenniaNoOverflow(int $value = 1) Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subMillenniumNoOverflow() Sub one millennium to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable addCentury() Add one century to the instance (using date interval). * @method CarbonImmutable subCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable subCentury() Sub one century to the instance (using date interval). * @method CarbonImmutable addCenturiesWithOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable addCenturyWithOverflow() Add one century to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable subCenturiesWithOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable subCenturyWithOverflow() Sub one century to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable addCenturiesWithoutOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addCenturyWithoutOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subCenturiesWithoutOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subCenturyWithoutOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addCenturiesWithNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addCenturyWithNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subCenturiesWithNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subCenturyWithNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addCenturiesNoOverflow(int $value = 1) Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addCenturyNoOverflow() Add one century to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subCenturiesNoOverflow(int $value = 1) Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subCenturyNoOverflow() Sub one century to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable addDecade() Add one decade to the instance (using date interval). * @method CarbonImmutable subDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable subDecade() Sub one decade to the instance (using date interval). * @method CarbonImmutable addDecadesWithOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable addDecadeWithOverflow() Add one decade to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable subDecadesWithOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable subDecadeWithOverflow() Sub one decade to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable addDecadesWithoutOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addDecadeWithoutOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subDecadesWithoutOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subDecadeWithoutOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addDecadesWithNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addDecadeWithNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subDecadesWithNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subDecadeWithNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addDecadesNoOverflow(int $value = 1) Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addDecadeNoOverflow() Add one decade to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subDecadesNoOverflow(int $value = 1) Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subDecadeNoOverflow() Sub one decade to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable addQuarter() Add one quarter to the instance (using date interval). * @method CarbonImmutable subQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable subQuarter() Sub one quarter to the instance (using date interval). * @method CarbonImmutable addQuartersWithOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable addQuarterWithOverflow() Add one quarter to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable subQuartersWithOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable subQuarterWithOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly allowed. * @method CarbonImmutable addQuartersWithoutOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addQuarterWithoutOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subQuartersWithoutOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subQuarterWithoutOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addQuartersWithNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addQuarterWithNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subQuartersWithNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subQuarterWithNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addQuartersNoOverflow(int $value = 1) Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addQuarterNoOverflow() Add one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subQuartersNoOverflow(int $value = 1) Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable subQuarterNoOverflow() Sub one quarter to the instance (using date interval) with overflow explicitly forbidden. * @method CarbonImmutable addWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable addWeek() Add one week to the instance (using date interval). * @method CarbonImmutable subWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable subWeek() Sub one week to the instance (using date interval). * @method CarbonImmutable addWeekdays(int $value = 1) Add weekdays (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable addWeekday() Add one weekday to the instance (using date interval). * @method CarbonImmutable subWeekdays(int $value = 1) Sub weekdays (the $value count passed in) to the instance (using date interval). * @method CarbonImmutable subWeekday() Sub one weekday to the instance (using date interval). * @method CarbonImmutable addRealMicros(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable addRealMicro() Add one microsecond to the instance (using timestamp). * @method CarbonImmutable subRealMicros(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable subRealMicro() Sub one microsecond to the instance (using timestamp). * @method CarbonPeriod microsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given. * @method CarbonImmutable addRealMicroseconds(int $value = 1) Add microseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable addRealMicrosecond() Add one microsecond to the instance (using timestamp). * @method CarbonImmutable subRealMicroseconds(int $value = 1) Sub microseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable subRealMicrosecond() Sub one microsecond to the instance (using timestamp). * @method CarbonPeriod microsecondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given. * @method CarbonImmutable addRealMillis(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable addRealMilli() Add one millisecond to the instance (using timestamp). * @method CarbonImmutable subRealMillis(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable subRealMilli() Sub one millisecond to the instance (using timestamp). * @method CarbonPeriod millisUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given. * @method CarbonImmutable addRealMilliseconds(int $value = 1) Add milliseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable addRealMillisecond() Add one millisecond to the instance (using timestamp). * @method CarbonImmutable subRealMilliseconds(int $value = 1) Sub milliseconds (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable subRealMillisecond() Sub one millisecond to the instance (using timestamp). * @method CarbonPeriod millisecondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given. * @method CarbonImmutable addRealSeconds(int $value = 1) Add seconds (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable addRealSecond() Add one second to the instance (using timestamp). * @method CarbonImmutable subRealSeconds(int $value = 1) Sub seconds (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable subRealSecond() Sub one second to the instance (using timestamp). * @method CarbonPeriod secondsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each second or every X seconds if a factor is given. * @method CarbonImmutable addRealMinutes(int $value = 1) Add minutes (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable addRealMinute() Add one minute to the instance (using timestamp). * @method CarbonImmutable subRealMinutes(int $value = 1) Sub minutes (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable subRealMinute() Sub one minute to the instance (using timestamp). * @method CarbonPeriod minutesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each minute or every X minutes if a factor is given. * @method CarbonImmutable addRealHours(int $value = 1) Add hours (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable addRealHour() Add one hour to the instance (using timestamp). * @method CarbonImmutable subRealHours(int $value = 1) Sub hours (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable subRealHour() Sub one hour to the instance (using timestamp). * @method CarbonPeriod hoursUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each hour or every X hours if a factor is given. * @method CarbonImmutable addRealDays(int $value = 1) Add days (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable addRealDay() Add one day to the instance (using timestamp). * @method CarbonImmutable subRealDays(int $value = 1) Sub days (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable subRealDay() Sub one day to the instance (using timestamp). * @method CarbonPeriod daysUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each day or every X days if a factor is given. * @method CarbonImmutable addRealWeeks(int $value = 1) Add weeks (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable addRealWeek() Add one week to the instance (using timestamp). * @method CarbonImmutable subRealWeeks(int $value = 1) Sub weeks (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable subRealWeek() Sub one week to the instance (using timestamp). * @method CarbonPeriod weeksUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each week or every X weeks if a factor is given. * @method CarbonImmutable addRealMonths(int $value = 1) Add months (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable addRealMonth() Add one month to the instance (using timestamp). * @method CarbonImmutable subRealMonths(int $value = 1) Sub months (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable subRealMonth() Sub one month to the instance (using timestamp). * @method CarbonPeriod monthsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each month or every X months if a factor is given. * @method CarbonImmutable addRealQuarters(int $value = 1) Add quarters (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable addRealQuarter() Add one quarter to the instance (using timestamp). * @method CarbonImmutable subRealQuarters(int $value = 1) Sub quarters (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable subRealQuarter() Sub one quarter to the instance (using timestamp). * @method CarbonPeriod quartersUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each quarter or every X quarters if a factor is given. * @method CarbonImmutable addRealYears(int $value = 1) Add years (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable addRealYear() Add one year to the instance (using timestamp). * @method CarbonImmutable subRealYears(int $value = 1) Sub years (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable subRealYear() Sub one year to the instance (using timestamp). * @method CarbonPeriod yearsUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each year or every X years if a factor is given. * @method CarbonImmutable addRealDecades(int $value = 1) Add decades (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable addRealDecade() Add one decade to the instance (using timestamp). * @method CarbonImmutable subRealDecades(int $value = 1) Sub decades (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable subRealDecade() Sub one decade to the instance (using timestamp). * @method CarbonPeriod decadesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each decade or every X decades if a factor is given. * @method CarbonImmutable addRealCenturies(int $value = 1) Add centuries (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable addRealCentury() Add one century to the instance (using timestamp). * @method CarbonImmutable subRealCenturies(int $value = 1) Sub centuries (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable subRealCentury() Sub one century to the instance (using timestamp). * @method CarbonPeriod centuriesUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each century or every X centuries if a factor is given. * @method CarbonImmutable addRealMillennia(int $value = 1) Add millennia (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable addRealMillennium() Add one millennium to the instance (using timestamp). * @method CarbonImmutable subRealMillennia(int $value = 1) Sub millennia (the $value count passed in) to the instance (using timestamp). * @method CarbonImmutable subRealMillennium() Sub one millennium to the instance (using timestamp). * @method CarbonPeriod millenniaUntil($endDate = null, int $factor = 1) Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millennium or every X millennia if a factor is given. * @method CarbonImmutable roundYear(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function. * @method CarbonImmutable roundYears(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function. * @method CarbonImmutable floorYear(float $precision = 1) Truncate the current instance year with given precision. * @method CarbonImmutable floorYears(float $precision = 1) Truncate the current instance year with given precision. * @method CarbonImmutable ceilYear(float $precision = 1) Ceil the current instance year with given precision. * @method CarbonImmutable ceilYears(float $precision = 1) Ceil the current instance year with given precision. * @method CarbonImmutable roundMonth(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function. * @method CarbonImmutable roundMonths(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function. * @method CarbonImmutable floorMonth(float $precision = 1) Truncate the current instance month with given precision. * @method CarbonImmutable floorMonths(float $precision = 1) Truncate the current instance month with given precision. * @method CarbonImmutable ceilMonth(float $precision = 1) Ceil the current instance month with given precision. * @method CarbonImmutable ceilMonths(float $precision = 1) Ceil the current instance month with given precision. * @method CarbonImmutable roundDay(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function. * @method CarbonImmutable roundDays(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function. * @method CarbonImmutable floorDay(float $precision = 1) Truncate the current instance day with given precision. * @method CarbonImmutable floorDays(float $precision = 1) Truncate the current instance day with given precision. * @method CarbonImmutable ceilDay(float $precision = 1) Ceil the current instance day with given precision. * @method CarbonImmutable ceilDays(float $precision = 1) Ceil the current instance day with given precision. * @method CarbonImmutable roundHour(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function. * @method CarbonImmutable roundHours(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function. * @method CarbonImmutable floorHour(float $precision = 1) Truncate the current instance hour with given precision. * @method CarbonImmutable floorHours(float $precision = 1) Truncate the current instance hour with given precision. * @method CarbonImmutable ceilHour(float $precision = 1) Ceil the current instance hour with given precision. * @method CarbonImmutable ceilHours(float $precision = 1) Ceil the current instance hour with given precision. * @method CarbonImmutable roundMinute(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function. * @method CarbonImmutable roundMinutes(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function. * @method CarbonImmutable floorMinute(float $precision = 1) Truncate the current instance minute with given precision. * @method CarbonImmutable floorMinutes(float $precision = 1) Truncate the current instance minute with given precision. * @method CarbonImmutable ceilMinute(float $precision = 1) Ceil the current instance minute with given precision. * @method CarbonImmutable ceilMinutes(float $precision = 1) Ceil the current instance minute with given precision. * @method CarbonImmutable roundSecond(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function. * @method CarbonImmutable roundSeconds(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function. * @method CarbonImmutable floorSecond(float $precision = 1) Truncate the current instance second with given precision. * @method CarbonImmutable floorSeconds(float $precision = 1) Truncate the current instance second with given precision. * @method CarbonImmutable ceilSecond(float $precision = 1) Ceil the current instance second with given precision. * @method CarbonImmutable ceilSeconds(float $precision = 1) Ceil the current instance second with given precision. * @method CarbonImmutable roundMillennium(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function. * @method CarbonImmutable roundMillennia(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function. * @method CarbonImmutable floorMillennium(float $precision = 1) Truncate the current instance millennium with given precision. * @method CarbonImmutable floorMillennia(float $precision = 1) Truncate the current instance millennium with given precision. * @method CarbonImmutable ceilMillennium(float $precision = 1) Ceil the current instance millennium with given precision. * @method CarbonImmutable ceilMillennia(float $precision = 1) Ceil the current instance millennium with given precision. * @method CarbonImmutable roundCentury(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function. * @method CarbonImmutable roundCenturies(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function. * @method CarbonImmutable floorCentury(float $precision = 1) Truncate the current instance century with given precision. * @method CarbonImmutable floorCenturies(float $precision = 1) Truncate the current instance century with given precision. * @method CarbonImmutable ceilCentury(float $precision = 1) Ceil the current instance century with given precision. * @method CarbonImmutable ceilCenturies(float $precision = 1) Ceil the current instance century with given precision. * @method CarbonImmutable roundDecade(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function. * @method CarbonImmutable roundDecades(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function. * @method CarbonImmutable floorDecade(float $precision = 1) Truncate the current instance decade with given precision. * @method CarbonImmutable floorDecades(float $precision = 1) Truncate the current instance decade with given precision. * @method CarbonImmutable ceilDecade(float $precision = 1) Ceil the current instance decade with given precision. * @method CarbonImmutable ceilDecades(float $precision = 1) Ceil the current instance decade with given precision. * @method CarbonImmutable roundQuarter(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function. * @method CarbonImmutable roundQuarters(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function. * @method CarbonImmutable floorQuarter(float $precision = 1) Truncate the current instance quarter with given precision. * @method CarbonImmutable floorQuarters(float $precision = 1) Truncate the current instance quarter with given precision. * @method CarbonImmutable ceilQuarter(float $precision = 1) Ceil the current instance quarter with given precision. * @method CarbonImmutable ceilQuarters(float $precision = 1) Ceil the current instance quarter with given precision. * @method CarbonImmutable roundMillisecond(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function. * @method CarbonImmutable roundMilliseconds(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function. * @method CarbonImmutable floorMillisecond(float $precision = 1) Truncate the current instance millisecond with given precision. * @method CarbonImmutable floorMilliseconds(float $precision = 1) Truncate the current instance millisecond with given precision. * @method CarbonImmutable ceilMillisecond(float $precision = 1) Ceil the current instance millisecond with given precision. * @method CarbonImmutable ceilMilliseconds(float $precision = 1) Ceil the current instance millisecond with given precision. * @method CarbonImmutable roundMicrosecond(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function. * @method CarbonImmutable roundMicroseconds(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function. * @method CarbonImmutable floorMicrosecond(float $precision = 1) Truncate the current instance microsecond with given precision. * @method CarbonImmutable floorMicroseconds(float $precision = 1) Truncate the current instance microsecond with given precision. * @method CarbonImmutable ceilMicrosecond(float $precision = 1) Ceil the current instance microsecond with given precision. * @method CarbonImmutable ceilMicroseconds(float $precision = 1) Ceil the current instance microsecond with given precision. * @method string shortAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string longAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string shortRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string longRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string shortRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string longRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string shortRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method string longRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (long format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.) * @method static static|false createFromFormat(string $format, string $time, DateTimeZone|string|false|null $timezone = null) Parse a string into a new CarbonImmutable object according to the specified format. * @method static static __set_state(array $array) https://php.net/manual/en/datetime.set-state.php * * </autodoc> */ class CarbonImmutable extends DateTimeImmutable implements CarbonInterface { use Date { __clone as dateTraitClone; } public function __clone() { $this->dateTraitClone(); $this->endOfTime = false; $this->startOfTime = false; } /** * Create a very old date representing start of time. * * @return static */ public static function startOfTime(): self { $date = static::parse('0001-01-01')->years(self::getStartOfTimeYear()); $date->startOfTime = true; return $date; } /** * Create a very far date representing end of time. * * @return static */ public static function endOfTime(): self { $date = static::parse('9999-12-31 23:59:59.999999')->years(self::getEndOfTimeYear()); $date->endOfTime = true; return $date; } /** * @codeCoverageIgnore */ private static function getEndOfTimeYear(): int { if (version_compare(PHP_VERSION, '7.3.0-dev', '<')) { return 145261681241552; } // Remove if https://bugs.php.net/bug.php?id=81107 is fixed if (version_compare(PHP_VERSION, '8.1.0-dev', '>=')) { return 1118290769066902787; } return PHP_INT_MAX; } /** * @codeCoverageIgnore */ private static function getStartOfTimeYear(): int { if (version_compare(PHP_VERSION, '7.3.0-dev', '<')) { return -135908816449551; } // Remove if https://bugs.php.net/bug.php?id=81107 is fixed if (version_compare(PHP_VERSION, '8.1.0-dev', '>=')) { return -1118290769066898816; } return max(PHP_INT_MIN, -9223372036854773760); } } PK������<1ZKJ����#��Carbon/CarbonConverterInterface.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon; use DateTimeInterface; interface CarbonConverterInterface { public function convertDate(DateTimeInterface $dateTime, bool $negated = false): CarbonInterface; } PK������<1ZS)��)����Carbon/AbstractTranslator.phpnu�W+A��������<?php /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon; use Carbon\MessageFormatter\MessageFormatterMapper; use Closure; use ReflectionException; use ReflectionFunction; use Symfony\Component\Translation; use Symfony\Component\Translation\Formatter\MessageFormatterInterface; use Symfony\Component\Translation\Loader\ArrayLoader; abstract class AbstractTranslator extends Translation\Translator { /** * Translator singletons for each language. * * @var array */ protected static $singletons = []; /** * List of custom localized messages. * * @var array */ protected $messages = []; /** * List of custom directories that contain translation files. * * @var string[] */ protected $directories = []; /** * Set to true while constructing. * * @var bool */ protected $initializing = false; /** * List of locales aliases. * * @var array<string, string> */ protected $aliases = [ 'me' => 'sr_Latn_ME', 'scr' => 'sh', ]; /** * Return a singleton instance of Translator. * * @param string|null $locale optional initial locale ("en" - english by default) * * @return static */ public static function get($locale = null) { $locale = $locale ?: 'en'; $key = static::class === Translator::class ? $locale : static::class.'|'.$locale; if (!isset(static::$singletons[$key])) { static::$singletons[$key] = new static($locale); } return static::$singletons[$key]; } public function __construct($locale, ?MessageFormatterInterface $formatter = null, $cacheDir = null, $debug = false) { parent::setLocale($locale); $this->initializing = true; $this->directories = [__DIR__.'/Lang']; $this->addLoader('array', new ArrayLoader()); parent::__construct($locale, new MessageFormatterMapper($formatter), $cacheDir, $debug); $this->initializing = false; } /** * Returns the list of directories translation files are searched in. * * @return array */ public function getDirectories(): array { return $this->directories; } /** * Set list of directories translation files are searched in. * * @param array $directories new directories list * * @return $this */ public function setDirectories(array $directories) { $this->directories = $directories; return $this; } /** * Add a directory to the list translation files are searched in. * * @param string $directory new directory * * @return $this */ public function addDirectory(string $directory) { $this->directories[] = $directory; return $this; } /** * Remove a directory from the list translation files are searched in. * * @param string $directory directory path * * @return $this */ public function removeDirectory(string $directory) { $search = rtrim(strtr($directory, '\\', '/'), '/'); return $this->setDirectories(array_filter($this->getDirectories(), function ($item) use ($search) { return rtrim(strtr($item, '\\', '/'), '/') !== $search; })); } /** * Reset messages of a locale (all locale if no locale passed). * Remove custom messages and reload initial messages from matching * file in Lang directory. * * @param string|null $locale * * @return bool */ public function resetMessages($locale = null) { if ($locale === null) { $this->messages = []; return true; } $this->assertValidLocale($locale); foreach ($this->getDirectories() as $directory) { $data = @include \sprintf('%s/%s.php', rtrim($directory, '\\/'), $locale); if ($data !== false) { $this->messages[$locale] = $data; $this->addResource('array', $this->messages[$locale], $locale); return true; } } return false; } /** * Returns the list of files matching a given locale prefix (or all if empty). * * @param string $prefix prefix required to filter result * * @return array */ public function getLocalesFiles($prefix = '') { $files = []; foreach ($this->getDirectories() as $directory) { $directory = rtrim($directory, '\\/'); foreach (glob("$directory/$prefix*.php") as $file) { $files[] = $file; } } return array_unique($files); } /** * Returns the list of internally available locales and already loaded custom locales. * (It will ignore custom translator dynamic loading.) * * @param string $prefix prefix required to filter result * * @return array */ public function getAvailableLocales($prefix = '') { $locales = []; foreach ($this->getLocalesFiles($prefix) as $file) { $locales[] = substr($file, strrpos($file, '/') + 1, -4); } return array_unique(array_merge($locales, array_keys($this->messages))); } protected function translate(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string { if ($domain === null) { $domain = 'messages'; } $catalogue = $this->getCatalogue($locale); $format = $this instanceof TranslatorStrongTypeInterface ? $this->getFromCatalogue($catalogue, (string) $id, $domain) : $this->getCatalogue($locale)->get((string) $id, $domain); // @codeCoverageIgnore if ($format instanceof Closure) { // @codeCoverageIgnoreStart try { $count = (new ReflectionFunction($format))->getNumberOfRequiredParameters(); } catch (ReflectionException $exception) { $count = 0; } // @codeCoverageIgnoreEnd return $format( ...array_values($parameters), ...array_fill(0, max(0, $count - \count($parameters)), null) ); } return parent::trans($id, $parameters, $domain, $locale); } /** * Init messages language from matching file in Lang directory. * * @param string $locale * * @return bool */ protected function loadMessagesFromFile($locale) { return isset($this->messages[$locale]) || $this->resetMessages($locale); } /** * Set messages of a locale and take file first if present. * * @param string $locale * @param array $messages * * @return $this */ public function setMessages($locale, $messages) { $this->loadMessagesFromFile($locale); $this->addResource('array', $messages, $locale); $this->messages[$locale] = array_merge( $this->messages[$locale] ?? [], $messages ); return $this; } /** * Set messages of the current locale and take file first if present. * * @param array $messages * * @return $this */ public function setTranslations($messages) { return $this->setMessages($this->getLocale(), $messages); } /** * Get messages of a locale, if none given, return all the * languages. * * @param string|null $locale * * @return array */ public function getMessages($locale = null) { return $locale === null ? $this->messages : $this->messages[$locale]; } /** * Set the current translator locale and indicate if the source locale file exists * * @param string $locale locale ex. en * * @return bool */ public function setLocale($locale) { $locale = preg_replace_callback('/[-_]([a-z]{2,}|\d{2,})/', function ($matches) { // _2-letters or YUE is a region, _3+-letters is a variant $upper = strtoupper($matches[1]); if ($upper === 'YUE' || $upper === 'ISO' || \strlen($upper) < 3) { return "_$upper"; } return '_'.ucfirst($matches[1]); }, strtolower($locale)); $previousLocale = $this->getLocale(); if ($previousLocale === $locale && isset($this->messages[$locale])) { return true; } unset(static::$singletons[$previousLocale]); if ($locale === 'auto') { $completeLocale = setlocale(LC_TIME, '0'); $locale = preg_replace('/^([^_.-]+).*$/', '$1', $completeLocale); $locales = $this->getAvailableLocales($locale); $completeLocaleChunks = preg_split('/[_.-]+/', $completeLocale); $getScore = function ($language) use ($completeLocaleChunks) { return self::compareChunkLists($completeLocaleChunks, preg_split('/[_.-]+/', $language)); }; usort($locales, function ($first, $second) use ($getScore) { return $getScore($second) <=> $getScore($first); }); $locale = $locales[0]; } if (isset($this->aliases[$locale])) { $locale = $this->aliases[$locale]; } // If subtag (ex: en_CA) first load the macro (ex: en) to have a fallback if (str_contains($locale, '_') && $this->loadMessagesFromFile($macroLocale = preg_replace('/^([^_]+).*$/', '$1', $locale)) ) { parent::setLocale($macroLocale); } if (!$this->loadMessagesFromFile($locale) && !$this->initializing) { return false; } parent::setLocale($locale); return true; } /** * Show locale on var_dump(). * * @return array */ public function __debugInfo() { return [ 'locale' => $this->getLocale(), ]; } private static function compareChunkLists($referenceChunks, $chunks) { $score = 0; foreach ($referenceChunks as $index => $chunk) { if (!isset($chunks[$index])) { $score++; continue; } if (strtolower($chunks[$index]) === strtolower($chunk)) { $score += 10; } } return $score; } } PK������1ZmaW��������ClockInterface.phpnu�W+A��������<?php namespace Psr\Clock; use DateTimeImmutable; interface ClockInterface { /** * Returns the current time as a DateTimeImmutable Object */ public function now(): DateTimeImmutable; } PK������\5ZÓCY��Y����Monolog/Logger.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog; use DateTimeZone; use Monolog\Handler\HandlerInterface; use Psr\Log\LoggerInterface; use Psr\Log\InvalidArgumentException; use Psr\Log\LogLevel; use Throwable; use Stringable; /** * Monolog log channel * * It contains a stack of Handlers and a stack of Processors, * and uses them to store records that are added to it. * * @author Jordi Boggiano <j.boggiano@seld.be> * * @phpstan-type Level Logger::DEBUG|Logger::INFO|Logger::NOTICE|Logger::WARNING|Logger::ERROR|Logger::CRITICAL|Logger::ALERT|Logger::EMERGENCY * @phpstan-type LevelName 'DEBUG'|'INFO'|'NOTICE'|'WARNING'|'ERROR'|'CRITICAL'|'ALERT'|'EMERGENCY' * @phpstan-type Record array{message: string, context: mixed[], level: Level, level_name: LevelName, channel: string, datetime: \DateTimeImmutable, extra: mixed[]} */ class Logger implements LoggerInterface, ResettableInterface { /** * Detailed debug information */ public const DEBUG = 100; /** * Interesting events * * Examples: User logs in, SQL logs. */ public const INFO = 200; /** * Uncommon events */ public const NOTICE = 250; /** * Exceptional occurrences that are not errors * * Examples: Use of deprecated APIs, poor use of an API, * undesirable things that are not necessarily wrong. */ public const WARNING = 300; /** * Runtime errors */ public const ERROR = 400; /** * Critical conditions * * Example: Application component unavailable, unexpected exception. */ public const CRITICAL = 500; /** * Action must be taken immediately * * Example: Entire website down, database unavailable, etc. * This should trigger the SMS alerts and wake you up. */ public const ALERT = 550; /** * Urgent alert. */ public const EMERGENCY = 600; /** * Monolog API version * * This is only bumped when API breaks are done and should * follow the major version of the library * * @var int */ public const API = 2; /** * This is a static variable and not a constant to serve as an extension point for custom levels * * @var array<int, string> $levels Logging levels with the levels as key * * @phpstan-var array<Level, LevelName> $levels Logging levels with the levels as key */ protected static $levels = [ self::DEBUG => 'DEBUG', self::INFO => 'INFO', self::NOTICE => 'NOTICE', self::WARNING => 'WARNING', self::ERROR => 'ERROR', self::CRITICAL => 'CRITICAL', self::ALERT => 'ALERT', self::EMERGENCY => 'EMERGENCY', ]; /** * Mapping between levels numbers defined in RFC 5424 and Monolog ones * * @phpstan-var array<int, Level> $rfc_5424_levels */ private const RFC_5424_LEVELS = [ 7 => self::DEBUG, 6 => self::INFO, 5 => self::NOTICE, 4 => self::WARNING, 3 => self::ERROR, 2 => self::CRITICAL, 1 => self::ALERT, 0 => self::EMERGENCY, ]; /** * @var string */ protected $name; /** * The handler stack * * @var HandlerInterface[] */ protected $handlers; /** * Processors that will process all log records * * To process records of a single handler instead, add the processor on that specific handler * * @var callable[] */ protected $processors; /** * @var bool */ protected $microsecondTimestamps = true; /** * @var DateTimeZone */ protected $timezone; /** * @var callable|null */ protected $exceptionHandler; /** * @var int Keeps track of depth to prevent infinite logging loops */ private $logDepth = 0; /** * @var \WeakMap<\Fiber, int>|null Keeps track of depth inside fibers to prevent infinite logging loops */ private $fiberLogDepth; /** * @var bool Whether to detect infinite logging loops * * This can be disabled via {@see useLoggingLoopDetection} if you have async handlers that do not play well with this */ private $detectCycles = true; /** * @psalm-param array<callable(array): array> $processors * * @param string $name The logging channel, a simple descriptive name that is attached to all log records * @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc. * @param callable[] $processors Optional array of processors * @param DateTimeZone|null $timezone Optional timezone, if not provided date_default_timezone_get() will be used */ public function __construct(string $name, array $handlers = [], array $processors = [], ?DateTimeZone $timezone = null) { $this->name = $name; $this->setHandlers($handlers); $this->processors = $processors; $this->timezone = $timezone ?: new DateTimeZone(date_default_timezone_get() ?: 'UTC'); if (\PHP_VERSION_ID >= 80100) { // Local variable for phpstan, see https://github.com/phpstan/phpstan/issues/6732#issuecomment-1111118412 /** @var \WeakMap<\Fiber, int> $fiberLogDepth */ $fiberLogDepth = new \WeakMap(); $this->fiberLogDepth = $fiberLogDepth; } } public function getName(): string { return $this->name; } /** * Return a new cloned instance with the name changed */ public function withName(string $name): self { $new = clone $this; $new->name = $name; return $new; } /** * Pushes a handler on to the stack. */ public function pushHandler(HandlerInterface $handler): self { array_unshift($this->handlers, $handler); return $this; } /** * Pops a handler from the stack * * @throws \LogicException If empty handler stack */ public function popHandler(): HandlerInterface { if (!$this->handlers) { throw new \LogicException('You tried to pop from an empty handler stack.'); } return array_shift($this->handlers); } /** * Set handlers, replacing all existing ones. * * If a map is passed, keys will be ignored. * * @param HandlerInterface[] $handlers */ public function setHandlers(array $handlers): self { $this->handlers = []; foreach (array_reverse($handlers) as $handler) { $this->pushHandler($handler); } return $this; } /** * @return HandlerInterface[] */ public function getHandlers(): array { return $this->handlers; } /** * Adds a processor on to the stack. */ public function pushProcessor(callable $callback): self { array_unshift($this->processors, $callback); return $this; } /** * Removes the processor on top of the stack and returns it. * * @throws \LogicException If empty processor stack * @return callable */ public function popProcessor(): callable { if (!$this->processors) { throw new \LogicException('You tried to pop from an empty processor stack.'); } return array_shift($this->processors); } /** * @return callable[] */ public function getProcessors(): array { return $this->processors; } /** * Control the use of microsecond resolution timestamps in the 'datetime' * member of new records. * * As of PHP7.1 microseconds are always included by the engine, so * there is no performance penalty and Monolog 2 enabled microseconds * by default. This function lets you disable them though in case you want * to suppress microseconds from the output. * * @param bool $micro True to use microtime() to create timestamps */ public function useMicrosecondTimestamps(bool $micro): self { $this->microsecondTimestamps = $micro; return $this; } public function useLoggingLoopDetection(bool $detectCycles): self { $this->detectCycles = $detectCycles; return $this; } /** * Adds a log record. * * @param int $level The logging level (a Monolog or RFC 5424 level) * @param string $message The log message * @param mixed[] $context The log context * @param DateTimeImmutable $datetime Optional log date to log into the past or future * @return bool Whether the record has been processed * * @phpstan-param Level $level */ public function addRecord(int $level, string $message, array $context = [], DateTimeImmutable $datetime = null): bool { if (isset(self::RFC_5424_LEVELS[$level])) { $level = self::RFC_5424_LEVELS[$level]; } if ($this->detectCycles) { if (\PHP_VERSION_ID >= 80100 && $fiber = \Fiber::getCurrent()) { $this->fiberLogDepth[$fiber] = $this->fiberLogDepth[$fiber] ?? 0; $logDepth = ++$this->fiberLogDepth[$fiber]; } else { $logDepth = ++$this->logDepth; } } else { $logDepth = 0; } if ($logDepth === 3) { $this->warning('A possible infinite logging loop was detected and aborted. It appears some of your handler code is triggering logging, see the previous log record for a hint as to what may be the cause.'); return false; } elseif ($logDepth >= 5) { // log depth 4 is let through, so we can log the warning above return false; } try { $record = null; foreach ($this->handlers as $handler) { if (null === $record) { // skip creating the record as long as no handler is going to handle it if (!$handler->isHandling(['level' => $level])) { continue; } $levelName = static::getLevelName($level); $record = [ 'message' => $message, 'context' => $context, 'level' => $level, 'level_name' => $levelName, 'channel' => $this->name, 'datetime' => $datetime ?? new DateTimeImmutable($this->microsecondTimestamps, $this->timezone), 'extra' => [], ]; try { foreach ($this->processors as $processor) { $record = $processor($record); } } catch (Throwable $e) { $this->handleException($e, $record); return true; } } // once the record exists, send it to all handlers as long as the bubbling chain is not interrupted try { if (true === $handler->handle($record)) { break; } } catch (Throwable $e) { $this->handleException($e, $record); return true; } } } finally { if ($this->detectCycles) { if (isset($fiber)) { $this->fiberLogDepth[$fiber]--; } else { $this->logDepth--; } } } return null !== $record; } /** * Ends a log cycle and frees all resources used by handlers. * * Closing a Handler means flushing all buffers and freeing any open resources/handles. * Handlers that have been closed should be able to accept log records again and re-open * themselves on demand, but this may not always be possible depending on implementation. * * This is useful at the end of a request and will be called automatically on every handler * when they get destructed. */ public function close(): void { foreach ($this->handlers as $handler) { $handler->close(); } } /** * Ends a log cycle and resets all handlers and processors to their initial state. * * Resetting a Handler or a Processor means flushing/cleaning all buffers, resetting internal * state, and getting it back to a state in which it can receive log records again. * * This is useful in case you want to avoid logs leaking between two requests or jobs when you * have a long running process like a worker or an application server serving multiple requests * in one process. */ public function reset(): void { foreach ($this->handlers as $handler) { if ($handler instanceof ResettableInterface) { $handler->reset(); } } foreach ($this->processors as $processor) { if ($processor instanceof ResettableInterface) { $processor->reset(); } } } /** * Gets all supported logging levels. * * @return array<string, int> Assoc array with human-readable level names => level codes. * @phpstan-return array<LevelName, Level> */ public static function getLevels(): array { return array_flip(static::$levels); } /** * Gets the name of the logging level. * * @throws \Psr\Log\InvalidArgumentException If level is not defined * * @phpstan-param Level $level * @phpstan-return LevelName */ public static function getLevelName(int $level): string { if (!isset(static::$levels[$level])) { throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels))); } return static::$levels[$level]; } /** * Converts PSR-3 levels to Monolog ones if necessary * * @param string|int $level Level number (monolog) or name (PSR-3) * @throws \Psr\Log\InvalidArgumentException If level is not defined * * @phpstan-param Level|LevelName|LogLevel::* $level * @phpstan-return Level */ public static function toMonologLevel($level): int { if (is_string($level)) { if (is_numeric($level)) { /** @phpstan-ignore-next-line */ return intval($level); } // Contains chars of all log levels and avoids using strtoupper() which may have // strange results depending on locale (for example, "i" will become "İ" in Turkish locale) $upper = strtr($level, 'abcdefgilmnortuwy', 'ABCDEFGILMNORTUWY'); if (defined(__CLASS__.'::'.$upper)) { return constant(__CLASS__ . '::' . $upper); } throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels) + static::$levels)); } if (!is_int($level)) { throw new InvalidArgumentException('Level "'.var_export($level, true).'" is not defined, use one of: '.implode(', ', array_keys(static::$levels) + static::$levels)); } return $level; } /** * Checks whether the Logger has a handler that listens on the given level * * @phpstan-param Level $level */ public function isHandling(int $level): bool { $record = [ 'level' => $level, ]; foreach ($this->handlers as $handler) { if ($handler->isHandling($record)) { return true; } } return false; } /** * Set a custom exception handler that will be called if adding a new record fails * * The callable will receive an exception object and the record that failed to be logged */ public function setExceptionHandler(?callable $callback): self { $this->exceptionHandler = $callback; return $this; } public function getExceptionHandler(): ?callable { return $this->exceptionHandler; } /** * Adds a log record at an arbitrary level. * * This method allows for compatibility with common interfaces. * * @param mixed $level The log level (a Monolog, PSR-3 or RFC 5424 level) * @param string|Stringable $message The log message * @param mixed[] $context The log context * * @phpstan-param Level|LevelName|LogLevel::* $level */ public function log($level, $message, array $context = []): void { if (!is_int($level) && !is_string($level)) { throw new \InvalidArgumentException('$level is expected to be a string or int'); } if (isset(self::RFC_5424_LEVELS[$level])) { $level = self::RFC_5424_LEVELS[$level]; } $level = static::toMonologLevel($level); $this->addRecord($level, (string) $message, $context); } /** * Adds a log record at the DEBUG level. * * This method allows for compatibility with common interfaces. * * @param string|Stringable $message The log message * @param mixed[] $context The log context */ public function debug($message, array $context = []): void { $this->addRecord(static::DEBUG, (string) $message, $context); } /** * Adds a log record at the INFO level. * * This method allows for compatibility with common interfaces. * * @param string|Stringable $message The log message * @param mixed[] $context The log context */ public function info($message, array $context = []): void { $this->addRecord(static::INFO, (string) $message, $context); } /** * Adds a log record at the NOTICE level. * * This method allows for compatibility with common interfaces. * * @param string|Stringable $message The log message * @param mixed[] $context The log context */ public function notice($message, array $context = []): void { $this->addRecord(static::NOTICE, (string) $message, $context); } /** * Adds a log record at the WARNING level. * * This method allows for compatibility with common interfaces. * * @param string|Stringable $message The log message * @param mixed[] $context The log context */ public function warning($message, array $context = []): void { $this->addRecord(static::WARNING, (string) $message, $context); } /** * Adds a log record at the ERROR level. * * This method allows for compatibility with common interfaces. * * @param string|Stringable $message The log message * @param mixed[] $context The log context */ public function error($message, array $context = []): void { $this->addRecord(static::ERROR, (string) $message, $context); } /** * Adds a log record at the CRITICAL level. * * This method allows for compatibility with common interfaces. * * @param string|Stringable $message The log message * @param mixed[] $context The log context */ public function critical($message, array $context = []): void { $this->addRecord(static::CRITICAL, (string) $message, $context); } /** * Adds a log record at the ALERT level. * * This method allows for compatibility with common interfaces. * * @param string|Stringable $message The log message * @param mixed[] $context The log context */ public function alert($message, array $context = []): void { $this->addRecord(static::ALERT, (string) $message, $context); } /** * Adds a log record at the EMERGENCY level. * * This method allows for compatibility with common interfaces. * * @param string|Stringable $message The log message * @param mixed[] $context The log context */ public function emergency($message, array $context = []): void { $this->addRecord(static::EMERGENCY, (string) $message, $context); } /** * Sets the timezone to be used for the timestamp of log records. */ public function setTimezone(DateTimeZone $tz): self { $this->timezone = $tz; return $this; } /** * Returns the timezone to be used for the timestamp of log records. */ public function getTimezone(): DateTimeZone { return $this->timezone; } /** * Delegates exception management to the custom exception handler, * or throws the exception if no custom handler is set. * * @param array $record * @phpstan-param Record $record */ protected function handleException(Throwable $e, array $record): void { if (!$this->exceptionHandler) { throw $e; } ($this->exceptionHandler)($e, $record); } /** * @return array<string, mixed> */ public function __serialize(): array { return [ 'name' => $this->name, 'handlers' => $this->handlers, 'processors' => $this->processors, 'microsecondTimestamps' => $this->microsecondTimestamps, 'timezone' => $this->timezone, 'exceptionHandler' => $this->exceptionHandler, 'logDepth' => $this->logDepth, 'detectCycles' => $this->detectCycles, ]; } /** * @param array<string, mixed> $data */ public function __unserialize(array $data): void { foreach (['name', 'handlers', 'processors', 'microsecondTimestamps', 'timezone', 'exceptionHandler', 'logDepth', 'detectCycles'] as $property) { if (isset($data[$property])) { $this->$property = $data[$property]; } } if (\PHP_VERSION_ID >= 80100) { // Local variable for phpstan, see https://github.com/phpstan/phpstan/issues/6732#issuecomment-1111118412 /** @var \WeakMap<\Fiber, int> $fiberLogDepth */ $fiberLogDepth = new \WeakMap(); $this->fiberLogDepth = $fiberLogDepth; } } } PK������\5Z������Monolog/SignalHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; use ReflectionExtension; /** * Monolog POSIX signal handler * * @author Robert Gust-Bardon <robert@gust-bardon.org> * * @phpstan-import-type Level from \Monolog\Logger * @phpstan-import-type LevelName from \Monolog\Logger */ class SignalHandler { /** @var LoggerInterface */ private $logger; /** @var array<int, callable|string|int> SIG_DFL, SIG_IGN or previous callable */ private $previousSignalHandler = []; /** @var array<int, int> */ private $signalLevelMap = []; /** @var array<int, bool> */ private $signalRestartSyscalls = []; public function __construct(LoggerInterface $logger) { $this->logger = $logger; } /** * @param int|string $level Level or level name * @param bool $callPrevious * @param bool $restartSyscalls * @param bool|null $async * @return $this * * @phpstan-param Level|LevelName|LogLevel::* $level */ public function registerSignalHandler(int $signo, $level = LogLevel::CRITICAL, bool $callPrevious = true, bool $restartSyscalls = true, ?bool $async = true): self { if (!extension_loaded('pcntl') || !function_exists('pcntl_signal')) { return $this; } $level = Logger::toMonologLevel($level); if ($callPrevious) { $handler = pcntl_signal_get_handler($signo); $this->previousSignalHandler[$signo] = $handler; } else { unset($this->previousSignalHandler[$signo]); } $this->signalLevelMap[$signo] = $level; $this->signalRestartSyscalls[$signo] = $restartSyscalls; if ($async !== null) { pcntl_async_signals($async); } pcntl_signal($signo, [$this, 'handleSignal'], $restartSyscalls); return $this; } /** * @param mixed $siginfo */ public function handleSignal(int $signo, $siginfo = null): void { static $signals = []; if (!$signals && extension_loaded('pcntl')) { $pcntl = new ReflectionExtension('pcntl'); // HHVM 3.24.2 returns an empty array. foreach ($pcntl->getConstants() ?: get_defined_constants(true)['Core'] as $name => $value) { if (substr($name, 0, 3) === 'SIG' && $name[3] !== '_' && is_int($value)) { $signals[$value] = $name; } } } $level = $this->signalLevelMap[$signo] ?? LogLevel::CRITICAL; $signal = $signals[$signo] ?? $signo; $context = $siginfo ?? []; $this->logger->log($level, sprintf('Program received signal %s', $signal), $context); if (!isset($this->previousSignalHandler[$signo])) { return; } if ($this->previousSignalHandler[$signo] === SIG_DFL) { if (extension_loaded('pcntl') && function_exists('pcntl_signal') && function_exists('pcntl_sigprocmask') && function_exists('pcntl_signal_dispatch') && extension_loaded('posix') && function_exists('posix_getpid') && function_exists('posix_kill') ) { $restartSyscalls = $this->signalRestartSyscalls[$signo] ?? true; pcntl_signal($signo, SIG_DFL, $restartSyscalls); pcntl_sigprocmask(SIG_UNBLOCK, [$signo], $oldset); posix_kill(posix_getpid(), $signo); pcntl_signal_dispatch(); pcntl_sigprocmask(SIG_SETMASK, $oldset); pcntl_signal($signo, [$this, 'handleSignal'], $restartSyscalls); } } elseif (is_callable($this->previousSignalHandler[$signo])) { $this->previousSignalHandler[$signo]($signo, $siginfo); } } } PK������\5ZT������Monolog/LogRecord.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog; use ArrayAccess; /** * Monolog log record interface for forward compatibility with Monolog 3.0 * * This is just present in Monolog 2.4+ to allow interoperable code to be written against * both versions by type-hinting arguments as `array|\Monolog\LogRecord $record` * * Do not rely on this interface for other purposes, and do not implement it. * * @author Jordi Boggiano <j.boggiano@seld.be> * @template-extends \ArrayAccess<'message'|'level'|'context'|'level_name'|'channel'|'datetime'|'extra'|'formatted', mixed> * @phpstan-import-type Record from Logger */ interface LogRecord extends \ArrayAccess { /** * @phpstan-return Record */ public function toArray(): array; } PK������\5Zv$=��=����Monolog/DateTimeImmutable.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog; use DateTimeZone; /** * Overrides default json encoding of date time objects * * @author Menno Holtkamp * @author Jordi Boggiano <j.boggiano@seld.be> */ class DateTimeImmutable extends \DateTimeImmutable implements \JsonSerializable { /** * @var bool */ private $useMicroseconds; public function __construct(bool $useMicroseconds, ?DateTimeZone $timezone = null) { $this->useMicroseconds = $useMicroseconds; parent::__construct('now', $timezone); } public function jsonSerialize(): string { if ($this->useMicroseconds) { return $this->format('Y-m-d\TH:i:s.uP'); } return $this->format('Y-m-d\TH:i:sP'); } public function __toString(): string { return $this->jsonSerialize(); } } PK������\5Z#G �� ��,��Monolog/Processor/PsrLogMessageProcessor.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; use Monolog\Utils; /** * Processes a record's message according to PSR-3 rules * * It replaces {foo} with the value from $context['foo'] * * @author Jordi Boggiano <j.boggiano@seld.be> */ class PsrLogMessageProcessor implements ProcessorInterface { public const SIMPLE_DATE = "Y-m-d\TH:i:s.uP"; /** @var string|null */ private $dateFormat; /** @var bool */ private $removeUsedContextFields; /** * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format * @param bool $removeUsedContextFields If set to true the fields interpolated into message gets unset */ public function __construct(?string $dateFormat = null, bool $removeUsedContextFields = false) { $this->dateFormat = $dateFormat; $this->removeUsedContextFields = $removeUsedContextFields; } /** * {@inheritDoc} */ public function __invoke(array $record): array { if (false === strpos($record['message'], '{')) { return $record; } $replacements = []; foreach ($record['context'] as $key => $val) { $placeholder = '{' . $key . '}'; if (strpos($record['message'], $placeholder) === false) { continue; } if (is_null($val) || is_scalar($val) || (is_object($val) && method_exists($val, "__toString"))) { $replacements[$placeholder] = $val; } elseif ($val instanceof \DateTimeInterface) { if (!$this->dateFormat && $val instanceof \Monolog\DateTimeImmutable) { // handle monolog dates using __toString if no specific dateFormat was asked for // so that it follows the useMicroseconds flag $replacements[$placeholder] = (string) $val; } else { $replacements[$placeholder] = $val->format($this->dateFormat ?: static::SIMPLE_DATE); } } elseif ($val instanceof \UnitEnum) { $replacements[$placeholder] = $val instanceof \BackedEnum ? $val->value : $val->name; } elseif (is_object($val)) { $replacements[$placeholder] = '[object '.Utils::getClass($val).']'; } elseif (is_array($val)) { $replacements[$placeholder] = 'array'.Utils::jsonEncode($val, null, true); } else { $replacements[$placeholder] = '['.gettype($val).']'; } if ($this->removeUsedContextFields) { unset($record['context'][$key]); } } $record['message'] = strtr($record['message'], $replacements); return $record; } } PK������\5Za����'��Monolog/Processor/HostnameProcessor.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; /** * Injects value of gethostname in all records */ class HostnameProcessor implements ProcessorInterface { /** @var string */ private static $host; public function __construct() { self::$host = (string) gethostname(); } /** * {@inheritDoc} */ public function __invoke(array $record): array { $record['extra']['hostname'] = self::$host; return $record; } } PK������\5Zx����"��Monolog/Processor/UidProcessor.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; use Monolog\ResettableInterface; /** * Adds a unique identifier into records * * @author Simon Mönch <sm@webfactory.de> */ class UidProcessor implements ProcessorInterface, ResettableInterface { /** @var string */ private $uid; public function __construct(int $length = 7) { if ($length > 32 || $length < 1) { throw new \InvalidArgumentException('The uid length must be an integer between 1 and 32'); } $this->uid = $this->generateUid($length); } /** * {@inheritDoc} */ public function __invoke(array $record): array { $record['extra']['uid'] = $this->uid; return $record; } public function getUid(): string { return $this->uid; } public function reset() { $this->uid = $this->generateUid(strlen($this->uid)); } private function generateUid(int $length): string { return substr(bin2hex(random_bytes((int) ceil($length / 2))), 0, $length); } } PK������\5Z{b��b��"��Monolog/Processor/TagProcessor.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; /** * Adds a tags array into record * * @author Martijn Riemers */ class TagProcessor implements ProcessorInterface { /** @var string[] */ private $tags; /** * @param string[] $tags */ public function __construct(array $tags = []) { $this->setTags($tags); } /** * @param string[] $tags */ public function addTags(array $tags = []): self { $this->tags = array_merge($this->tags, $tags); return $this; } /** * @param string[] $tags */ public function setTags(array $tags = []): self { $this->tags = $tags; return $this; } /** * {@inheritDoc} */ public function __invoke(array $record): array { $record['extra']['tags'] = $this->tags; return $record; } } PK������\5Za #��#��%��Monolog/Processor/MemoryProcessor.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; /** * Some methods that are common for all memory processors * * @author Rob Jensen */ abstract class MemoryProcessor implements ProcessorInterface { /** * @var bool If true, get the real size of memory allocated from system. Else, only the memory used by emalloc() is reported. */ protected $realUsage; /** * @var bool If true, then format memory size to human readable string (MB, KB, B depending on size) */ protected $useFormatting; /** * @param bool $realUsage Set this to true to get the real size of memory allocated from system. * @param bool $useFormatting If true, then format memory size to human readable string (MB, KB, B depending on size) */ public function __construct(bool $realUsage = true, bool $useFormatting = true) { $this->realUsage = $realUsage; $this->useFormatting = $useFormatting; } /** * Formats bytes into a human readable string if $this->useFormatting is true, otherwise return $bytes as is * * @param int $bytes * @return string|int Formatted string if $this->useFormatting is true, otherwise return $bytes as int */ protected function formatBytes(int $bytes) { if (!$this->useFormatting) { return $bytes; } if ($bytes > 1024 * 1024) { return round($bytes / 1024 / 1024, 2).' MB'; } elseif ($bytes > 1024) { return round($bytes / 1024, 2).' KB'; } return $bytes . ' B'; } } PK������\5Z .f����,��Monolog/Processor/IntrospectionProcessor.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; use Monolog\Logger; use Psr\Log\LogLevel; /** * Injects line/file:class/function where the log message came from * * Warning: This only works if the handler processes the logs directly. * If you put the processor on a handler that is behind a FingersCrossedHandler * for example, the processor will only be called once the trigger level is reached, * and all the log records will have the same file/line/.. data from the call that * triggered the FingersCrossedHandler. * * @author Jordi Boggiano <j.boggiano@seld.be> * * @phpstan-import-type Level from \Monolog\Logger * @phpstan-import-type LevelName from \Monolog\Logger */ class IntrospectionProcessor implements ProcessorInterface { /** @var int */ private $level; /** @var string[] */ private $skipClassesPartials; /** @var int */ private $skipStackFramesCount; /** @var string[] */ private $skipFunctions = [ 'call_user_func', 'call_user_func_array', ]; /** * @param string|int $level The minimum logging level at which this Processor will be triggered * @param string[] $skipClassesPartials * * @phpstan-param Level|LevelName|LogLevel::* $level */ public function __construct($level = Logger::DEBUG, array $skipClassesPartials = [], int $skipStackFramesCount = 0) { $this->level = Logger::toMonologLevel($level); $this->skipClassesPartials = array_merge(['Monolog\\'], $skipClassesPartials); $this->skipStackFramesCount = $skipStackFramesCount; } /** * {@inheritDoc} */ public function __invoke(array $record): array { // return if the level is not high enough if ($record['level'] < $this->level) { return $record; } $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); // skip first since it's always the current method array_shift($trace); // the call_user_func call is also skipped array_shift($trace); $i = 0; while ($this->isTraceClassOrSkippedFunction($trace, $i)) { if (isset($trace[$i]['class'])) { foreach ($this->skipClassesPartials as $part) { if (strpos($trace[$i]['class'], $part) !== false) { $i++; continue 2; } } } elseif (in_array($trace[$i]['function'], $this->skipFunctions)) { $i++; continue; } break; } $i += $this->skipStackFramesCount; // we should have the call source now $record['extra'] = array_merge( $record['extra'], [ 'file' => isset($trace[$i - 1]['file']) ? $trace[$i - 1]['file'] : null, 'line' => isset($trace[$i - 1]['line']) ? $trace[$i - 1]['line'] : null, 'class' => isset($trace[$i]['class']) ? $trace[$i]['class'] : null, 'callType' => isset($trace[$i]['type']) ? $trace[$i]['type'] : null, 'function' => isset($trace[$i]['function']) ? $trace[$i]['function'] : null, ] ); return $record; } /** * @param array[] $trace */ private function isTraceClassOrSkippedFunction(array $trace, int $index): bool { if (!isset($trace[$index])) { return false; } return isset($trace[$index]['class']) || in_array($trace[$index]['function'], $this->skipFunctions); } } PK������\5Zj: �� ��"��Monolog/Processor/WebProcessor.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; /** * Injects url/method and remote IP of the current web request in all records * * @author Jordi Boggiano <j.boggiano@seld.be> */ class WebProcessor implements ProcessorInterface { /** * @var array<string, mixed>|\ArrayAccess<string, mixed> */ protected $serverData; /** * Default fields * * Array is structured as [key in record.extra => key in $serverData] * * @var array<string, string> */ protected $extraFields = [ 'url' => 'REQUEST_URI', 'ip' => 'REMOTE_ADDR', 'http_method' => 'REQUEST_METHOD', 'server' => 'SERVER_NAME', 'referrer' => 'HTTP_REFERER', 'user_agent' => 'HTTP_USER_AGENT', ]; /** * @param array<string, mixed>|\ArrayAccess<string, mixed>|null $serverData Array or object w/ ArrayAccess that provides access to the $_SERVER data * @param array<string, string>|array<string>|null $extraFields Field names and the related key inside $serverData to be added (or just a list of field names to use the default configured $serverData mapping). If not provided it defaults to: [url, ip, http_method, server, referrer] + unique_id if present in server data */ public function __construct($serverData = null, array $extraFields = null) { if (null === $serverData) { $this->serverData = &$_SERVER; } elseif (is_array($serverData) || $serverData instanceof \ArrayAccess) { $this->serverData = $serverData; } else { throw new \UnexpectedValueException('$serverData must be an array or object implementing ArrayAccess.'); } $defaultEnabled = ['url', 'ip', 'http_method', 'server', 'referrer']; if (isset($this->serverData['UNIQUE_ID'])) { $this->extraFields['unique_id'] = 'UNIQUE_ID'; $defaultEnabled[] = 'unique_id'; } if (null === $extraFields) { $extraFields = $defaultEnabled; } if (isset($extraFields[0])) { foreach (array_keys($this->extraFields) as $fieldName) { if (!in_array($fieldName, $extraFields)) { unset($this->extraFields[$fieldName]); } } } else { $this->extraFields = $extraFields; } } /** * {@inheritDoc} */ public function __invoke(array $record): array { // skip processing if for some reason request data // is not present (CLI or wonky SAPIs) if (!isset($this->serverData['REQUEST_URI'])) { return $record; } $record['extra'] = $this->appendExtraFields($record['extra']); return $record; } public function addExtraField(string $extraName, string $serverName): self { $this->extraFields[$extraName] = $serverName; return $this; } /** * @param mixed[] $extra * @return mixed[] */ private function appendExtraFields(array $extra): array { foreach ($this->extraFields as $extraName => $serverName) { $extra[$extraName] = $this->serverData[$serverName] ?? null; } return $extra; } } PK������\5Z)1��1��*��Monolog/Processor/MemoryUsageProcessor.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; /** * Injects memory_get_usage in all records * * @see Monolog\Processor\MemoryProcessor::__construct() for options * @author Rob Jensen */ class MemoryUsageProcessor extends MemoryProcessor { /** * {@inheritDoc} */ public function __invoke(array $record): array { $usage = memory_get_usage($this->realUsage); if ($this->useFormatting) { $usage = $this->formatBytes($usage); } $record['extra']['memory_usage'] = $usage; return $record; } } PK������\5ZY^����(��Monolog/Processor/ProcessorInterface.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; /** * An optional interface to allow labelling Monolog processors. * * @author Nicolas Grekas <p@tchwork.com> * * @phpstan-import-type Record from \Monolog\Logger */ interface ProcessorInterface { /** * @return array The processed record * * @phpstan-param Record $record * @phpstan-return Record */ public function __invoke(array $record); } PK������\5Z:DCh��h��(��Monolog/Processor/MercurialProcessor.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; use Monolog\Logger; use Psr\Log\LogLevel; /** * Injects Hg branch and Hg revision number in all records * * @author Jonathan A. Schweder <jonathanschweder@gmail.com> * * @phpstan-import-type LevelName from \Monolog\Logger * @phpstan-import-type Level from \Monolog\Logger */ class MercurialProcessor implements ProcessorInterface { /** @var Level */ private $level; /** @var array{branch: string, revision: string}|array<never>|null */ private static $cache = null; /** * @param int|string $level The minimum logging level at which this Processor will be triggered * * @phpstan-param Level|LevelName|LogLevel::* $level */ public function __construct($level = Logger::DEBUG) { $this->level = Logger::toMonologLevel($level); } /** * {@inheritDoc} */ public function __invoke(array $record): array { // return if the level is not high enough if ($record['level'] < $this->level) { return $record; } $record['extra']['hg'] = self::getMercurialInfo(); return $record; } /** * @return array{branch: string, revision: string}|array<never> */ private static function getMercurialInfo(): array { if (self::$cache) { return self::$cache; } $result = explode(' ', trim(`hg id -nb`)); if (count($result) >= 3) { return self::$cache = [ 'branch' => $result[1], 'revision' => $result[2], ]; } return self::$cache = []; } } PK������\5Z_��_��(��Monolog/Processor/ProcessIdProcessor.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; /** * Adds value of getmypid into records * * @author Andreas Hörnicke */ class ProcessIdProcessor implements ProcessorInterface { /** * {@inheritDoc} */ public function __invoke(array $record): array { $record['extra']['process_id'] = getmypid(); return $record; } } PK������\5Zx\˕����"��Monolog/Processor/GitProcessor.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; use Monolog\Logger; use Psr\Log\LogLevel; /** * Injects Git branch and Git commit SHA in all records * * @author Nick Otter * @author Jordi Boggiano <j.boggiano@seld.be> * * @phpstan-import-type Level from \Monolog\Logger * @phpstan-import-type LevelName from \Monolog\Logger */ class GitProcessor implements ProcessorInterface { /** @var int */ private $level; /** @var array{branch: string, commit: string}|array<never>|null */ private static $cache = null; /** * @param string|int $level The minimum logging level at which this Processor will be triggered * * @phpstan-param Level|LevelName|LogLevel::* $level */ public function __construct($level = Logger::DEBUG) { $this->level = Logger::toMonologLevel($level); } /** * {@inheritDoc} */ public function __invoke(array $record): array { // return if the level is not high enough if ($record['level'] < $this->level) { return $record; } $record['extra']['git'] = self::getGitInfo(); return $record; } /** * @return array{branch: string, commit: string}|array<never> */ private static function getGitInfo(): array { if (self::$cache) { return self::$cache; } $branches = `git branch -v --no-abbrev`; if ($branches && preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) { return self::$cache = [ 'branch' => $matches[1], 'commit' => $matches[2], ]; } return self::$cache = []; } } PK������\5ZD��D��.��Monolog/Processor/MemoryPeakUsageProcessor.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; /** * Injects memory_get_peak_usage in all records * * @see Monolog\Processor\MemoryProcessor::__construct() for options * @author Rob Jensen */ class MemoryPeakUsageProcessor extends MemoryProcessor { /** * {@inheritDoc} */ public function __invoke(array $record): array { $usage = memory_get_peak_usage($this->realUsage); if ($this->useFormatting) { $usage = $this->formatBytes($usage); } $record['extra']['memory_peak_usage'] = $usage; return $record; } } PK������\5ZMnn ��n ����Monolog/Test/TestCase.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Test; use Monolog\Logger; use Monolog\DateTimeImmutable; use Monolog\Formatter\FormatterInterface; /** * Lets you easily generate log records and a dummy formatter for testing purposes * * @author Jordi Boggiano <j.boggiano@seld.be> * * @phpstan-import-type Record from \Monolog\Logger * @phpstan-import-type Level from \Monolog\Logger * * @internal feel free to reuse this to test your own handlers, this is marked internal to avoid issues with PHPStorm https://github.com/Seldaek/monolog/issues/1677 */ class TestCase extends \PHPUnit\Framework\TestCase { public function tearDown(): void { parent::tearDown(); if (isset($this->handler)) { unset($this->handler); } } /** * @param mixed[] $context * * @return array Record * * @phpstan-param Level $level * @phpstan-return Record */ protected function getRecord(int $level = Logger::WARNING, string $message = 'test', array $context = []): array { return [ 'message' => (string) $message, 'context' => $context, 'level' => $level, 'level_name' => Logger::getLevelName($level), 'channel' => 'test', 'datetime' => new DateTimeImmutable(true), 'extra' => [], ]; } /** * @phpstan-return Record[] */ protected function getMultipleRecords(): array { return [ $this->getRecord(Logger::DEBUG, 'debug message 1'), $this->getRecord(Logger::DEBUG, 'debug message 2'), $this->getRecord(Logger::INFO, 'information'), $this->getRecord(Logger::WARNING, 'warning'), $this->getRecord(Logger::ERROR, 'error'), ]; } protected function getIdentityFormatter(): FormatterInterface { $formatter = $this->createMock(FormatterInterface::class); $formatter->expects($this->any()) ->method('format') ->will($this->returnCallback(function ($record) { return $record['message']; })); return $formatter; } } PK������\5Z bt������Monolog/Registry.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog; use InvalidArgumentException; /** * Monolog log registry * * Allows to get `Logger` instances in the global scope * via static method calls on this class. * * <code> * $application = new Monolog\Logger('application'); * $api = new Monolog\Logger('api'); * * Monolog\Registry::addLogger($application); * Monolog\Registry::addLogger($api); * * function testLogger() * { * Monolog\Registry::api()->error('Sent to $api Logger instance'); * Monolog\Registry::application()->error('Sent to $application Logger instance'); * } * </code> * * @author Tomas Tatarko <tomas@tatarko.sk> */ class Registry { /** * List of all loggers in the registry (by named indexes) * * @var Logger[] */ private static $loggers = []; /** * Adds new logging channel to the registry * * @param Logger $logger Instance of the logging channel * @param string|null $name Name of the logging channel ($logger->getName() by default) * @param bool $overwrite Overwrite instance in the registry if the given name already exists? * @throws \InvalidArgumentException If $overwrite set to false and named Logger instance already exists * @return void */ public static function addLogger(Logger $logger, ?string $name = null, bool $overwrite = false) { $name = $name ?: $logger->getName(); if (isset(self::$loggers[$name]) && !$overwrite) { throw new InvalidArgumentException('Logger with the given name already exists'); } self::$loggers[$name] = $logger; } /** * Checks if such logging channel exists by name or instance * * @param string|Logger $logger Name or logger instance */ public static function hasLogger($logger): bool { if ($logger instanceof Logger) { $index = array_search($logger, self::$loggers, true); return false !== $index; } return isset(self::$loggers[$logger]); } /** * Removes instance from registry by name or instance * * @param string|Logger $logger Name or logger instance */ public static function removeLogger($logger): void { if ($logger instanceof Logger) { if (false !== ($idx = array_search($logger, self::$loggers, true))) { unset(self::$loggers[$idx]); } } else { unset(self::$loggers[$logger]); } } /** * Clears the registry */ public static function clear(): void { self::$loggers = []; } /** * Gets Logger instance from the registry * * @param string $name Name of the requested Logger instance * @throws \InvalidArgumentException If named Logger instance is not in the registry */ public static function getInstance($name): Logger { if (!isset(self::$loggers[$name])) { throw new InvalidArgumentException(sprintf('Requested "%s" logger instance is not in the registry', $name)); } return self::$loggers[$name]; } /** * Gets Logger instance from the registry via static method call * * @param string $name Name of the requested Logger instance * @param mixed[] $arguments Arguments passed to static method call * @throws \InvalidArgumentException If named Logger instance is not in the registry * @return Logger Requested instance of Logger */ public static function __callStatic($name, $arguments) { return self::getInstance($name); } } PK������\5Z0C����>��Monolog/Handler/FingersCrossed/ActivationStrategyInterface.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler\FingersCrossed; /** * Interface for activation strategies for the FingersCrossedHandler. * * @author Johannes M. Schmitt <schmittjoh@gmail.com> * * @phpstan-import-type Record from \Monolog\Logger */ interface ActivationStrategyInterface { /** * Returns whether the given record activates the handler. * * @phpstan-param Record $record */ public function isHandlerActivated(array $record): bool; } PK������\5ZD?N��N��?��Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler\FingersCrossed; use Monolog\Logger; use Psr\Log\LogLevel; /** * Error level based activation strategy. * * @author Johannes M. Schmitt <schmittjoh@gmail.com> * * @phpstan-import-type Level from \Monolog\Logger * @phpstan-import-type LevelName from \Monolog\Logger */ class ErrorLevelActivationStrategy implements ActivationStrategyInterface { /** * @var Level */ private $actionLevel; /** * @param int|string $actionLevel Level or name or value * * @phpstan-param Level|LevelName|LogLevel::* $actionLevel */ public function __construct($actionLevel) { $this->actionLevel = Logger::toMonologLevel($actionLevel); } public function isHandlerActivated(array $record): bool { return $record['level'] >= $this->actionLevel; } } PK������\5Zf& �� ��A��Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler\FingersCrossed; use Monolog\Logger; use Psr\Log\LogLevel; /** * Channel and Error level based monolog activation strategy. Allows to trigger activation * based on level per channel. e.g. trigger activation on level 'ERROR' by default, except * for records of the 'sql' channel; those should trigger activation on level 'WARN'. * * Example: * * <code> * $activationStrategy = new ChannelLevelActivationStrategy( * Logger::CRITICAL, * array( * 'request' => Logger::ALERT, * 'sensitive' => Logger::ERROR, * ) * ); * $handler = new FingersCrossedHandler(new StreamHandler('php://stderr'), $activationStrategy); * </code> * * @author Mike Meessen <netmikey@gmail.com> * * @phpstan-import-type Record from \Monolog\Logger * @phpstan-import-type Level from \Monolog\Logger * @phpstan-import-type LevelName from \Monolog\Logger */ class ChannelLevelActivationStrategy implements ActivationStrategyInterface { /** * @var Level */ private $defaultActionLevel; /** * @var array<string, Level> */ private $channelToActionLevel; /** * @param int|string $defaultActionLevel The default action level to be used if the record's category doesn't match any * @param array<string, int> $channelToActionLevel An array that maps channel names to action levels. * * @phpstan-param array<string, Level> $channelToActionLevel * @phpstan-param Level|LevelName|LogLevel::* $defaultActionLevel */ public function __construct($defaultActionLevel, array $channelToActionLevel = []) { $this->defaultActionLevel = Logger::toMonologLevel($defaultActionLevel); $this->channelToActionLevel = array_map('Monolog\Logger::toMonologLevel', $channelToActionLevel); } /** * @phpstan-param Record $record */ public function isHandlerActivated(array $record): bool { if (isset($this->channelToActionLevel[$record['channel']])) { return $record['level'] >= $this->channelToActionLevel[$record['channel']]; } return $record['level'] >= $this->defaultActionLevel; } } PK������\5Z!������Monolog/Handler/SqsHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Aws\Sqs\SqsClient; use Monolog\Logger; use Monolog\Utils; /** * Writes to any sqs queue. * * @author Martijn van Calker <git@amvc.nl> */ class SqsHandler extends AbstractProcessingHandler { /** 256 KB in bytes - maximum message size in SQS */ protected const MAX_MESSAGE_SIZE = 262144; /** 100 KB in bytes - head message size for new error log */ protected const HEAD_MESSAGE_SIZE = 102400; /** @var SqsClient */ private $client; /** @var string */ private $queueUrl; public function __construct(SqsClient $sqsClient, string $queueUrl, $level = Logger::DEBUG, bool $bubble = true) { parent::__construct($level, $bubble); $this->client = $sqsClient; $this->queueUrl = $queueUrl; } /** * {@inheritDoc} */ protected function write(array $record): void { if (!isset($record['formatted']) || 'string' !== gettype($record['formatted'])) { throw new \InvalidArgumentException('SqsHandler accepts only formatted records as a string' . Utils::getRecordMessageForException($record)); } $messageBody = $record['formatted']; if (strlen($messageBody) >= static::MAX_MESSAGE_SIZE) { $messageBody = Utils::substr($messageBody, 0, static::HEAD_MESSAGE_SIZE); } $this->client->sendMessage([ 'QueueUrl' => $this->queueUrl, 'MessageBody' => $messageBody, ]); } } PK������\5Z5?6 �� ��)��Monolog/Handler/AbstractSyslogHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LineFormatter; /** * Common syslog functionality * * @phpstan-import-type Level from \Monolog\Logger */ abstract class AbstractSyslogHandler extends AbstractProcessingHandler { /** @var int */ protected $facility; /** * Translates Monolog log levels to syslog log priorities. * @var array * @phpstan-var array<Level, int> */ protected $logLevels = [ Logger::DEBUG => LOG_DEBUG, Logger::INFO => LOG_INFO, Logger::NOTICE => LOG_NOTICE, Logger::WARNING => LOG_WARNING, Logger::ERROR => LOG_ERR, Logger::CRITICAL => LOG_CRIT, Logger::ALERT => LOG_ALERT, Logger::EMERGENCY => LOG_EMERG, ]; /** * List of valid log facility names. * @var array<string, int> */ protected $facilities = [ 'auth' => LOG_AUTH, 'authpriv' => LOG_AUTHPRIV, 'cron' => LOG_CRON, 'daemon' => LOG_DAEMON, 'kern' => LOG_KERN, 'lpr' => LOG_LPR, 'mail' => LOG_MAIL, 'news' => LOG_NEWS, 'syslog' => LOG_SYSLOG, 'user' => LOG_USER, 'uucp' => LOG_UUCP, ]; /** * @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant */ public function __construct($facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true) { parent::__construct($level, $bubble); if (!defined('PHP_WINDOWS_VERSION_BUILD')) { $this->facilities['local0'] = LOG_LOCAL0; $this->facilities['local1'] = LOG_LOCAL1; $this->facilities['local2'] = LOG_LOCAL2; $this->facilities['local3'] = LOG_LOCAL3; $this->facilities['local4'] = LOG_LOCAL4; $this->facilities['local5'] = LOG_LOCAL5; $this->facilities['local6'] = LOG_LOCAL6; $this->facilities['local7'] = LOG_LOCAL7; } else { $this->facilities['local0'] = 128; // LOG_LOCAL0 $this->facilities['local1'] = 136; // LOG_LOCAL1 $this->facilities['local2'] = 144; // LOG_LOCAL2 $this->facilities['local3'] = 152; // LOG_LOCAL3 $this->facilities['local4'] = 160; // LOG_LOCAL4 $this->facilities['local5'] = 168; // LOG_LOCAL5 $this->facilities['local6'] = 176; // LOG_LOCAL6 $this->facilities['local7'] = 184; // LOG_LOCAL7 } // convert textual description of facility to syslog constant if (is_string($facility) && array_key_exists(strtolower($facility), $this->facilities)) { $facility = $this->facilities[strtolower($facility)]; } elseif (!in_array($facility, array_values($this->facilities), true)) { throw new \UnexpectedValueException('Unknown facility value "'.$facility.'" given'); } $this->facility = $facility; } /** * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { return new LineFormatter('%channel%.%level_name%: %message% %context% %extra%'); } } PK������\5ZM7��7��"��Monolog/Handler/CouchDBHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\JsonFormatter; use Monolog\Logger; /** * CouchDB handler * * @author Markus Bachmann <markus.bachmann@bachi.biz> */ class CouchDBHandler extends AbstractProcessingHandler { /** @var mixed[] */ private $options; /** * @param mixed[] $options */ public function __construct(array $options = [], $level = Logger::DEBUG, bool $bubble = true) { $this->options = array_merge([ 'host' => 'localhost', 'port' => 5984, 'dbname' => 'logger', 'username' => null, 'password' => null, ], $options); parent::__construct($level, $bubble); } /** * {@inheritDoc} */ protected function write(array $record): void { $basicAuth = null; if ($this->options['username']) { $basicAuth = sprintf('%s:%s@', $this->options['username'], $this->options['password']); } $url = 'http://'.$basicAuth.$this->options['host'].':'.$this->options['port'].'/'.$this->options['dbname']; $context = stream_context_create([ 'http' => [ 'method' => 'POST', 'content' => $record['formatted'], 'ignore_errors' => true, 'max_redirects' => 0, 'header' => 'Content-type: application/json', ], ]); if (false === @file_get_contents($url, false, $context)) { throw new \RuntimeException(sprintf('Could not connect to %s', $url)); } } /** * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false); } } PK������\5Z&C����+��Monolog/Handler/WhatFailureGroupHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; /** * Forwards records to multiple handlers suppressing failures of each handler * and continuing through to give every handler a chance to succeed. * * @author Craig D'Amelio <craig@damelio.ca> * * @phpstan-import-type Record from \Monolog\Logger */ class WhatFailureGroupHandler extends GroupHandler { /** * {@inheritDoc} */ public function handle(array $record): bool { if ($this->processors) { /** @var Record $record */ $record = $this->processRecord($record); } foreach ($this->handlers as $handler) { try { $handler->handle($record); } catch (\Throwable $e) { // What failure? } } return false === $this->bubble; } /** * {@inheritDoc} */ public function handleBatch(array $records): void { if ($this->processors) { $processed = array(); foreach ($records as $record) { $processed[] = $this->processRecord($record); } /** @var Record[] $records */ $records = $processed; } foreach ($this->handlers as $handler) { try { $handler->handleBatch($records); } catch (\Throwable $e) { // What failure? } } } /** * {@inheritDoc} */ public function close(): void { foreach ($this->handlers as $handler) { try { $handler->close(); } catch (\Throwable $e) { // What failure? } } } } PK������\5Z=h��h��*��Monolog/Handler/DoctrineCouchDBHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Formatter\NormalizerFormatter; use Monolog\Formatter\FormatterInterface; use Doctrine\CouchDB\CouchDBClient; /** * CouchDB handler for Doctrine CouchDB ODM * * @author Markus Bachmann <markus.bachmann@bachi.biz> */ class DoctrineCouchDBHandler extends AbstractProcessingHandler { /** @var CouchDBClient */ private $client; public function __construct(CouchDBClient $client, $level = Logger::DEBUG, bool $bubble = true) { $this->client = $client; parent::__construct($level, $bubble); } /** * {@inheritDoc} */ protected function write(array $record): void { $this->client->postDocument($record['formatted']); } protected function getDefaultFormatter(): FormatterInterface { return new NormalizerFormatter; } } PK������\5Zy:0����/��Monolog/Handler/ProcessableHandlerInterface.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Processor\ProcessorInterface; /** * Interface to describe loggers that have processors * * @author Jordi Boggiano <j.boggiano@seld.be> * * @phpstan-import-type Record from \Monolog\Logger */ interface ProcessableHandlerInterface { /** * Adds a processor in the stack. * * @psalm-param ProcessorInterface|callable(Record): Record $callback * * @param ProcessorInterface|callable $callback * @return HandlerInterface self */ public function pushProcessor(callable $callback): HandlerInterface; /** * Removes the processor on top of the stack and returns it. * * @psalm-return ProcessorInterface|callable(Record): Record $callback * * @throws \LogicException In case the processor stack is empty * @return callable|ProcessorInterface */ public function popProcessor(): callable; } PK������\5ZV����(��Monolog/Handler/FallbackGroupHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Throwable; /** * Forwards records to at most one handler * * If a handler fails, the exception is suppressed and the record is forwarded to the next handler. * * As soon as one handler handles a record successfully, the handling stops there. * * @phpstan-import-type Record from \Monolog\Logger */ class FallbackGroupHandler extends GroupHandler { /** * {@inheritDoc} */ public function handle(array $record): bool { if ($this->processors) { /** @var Record $record */ $record = $this->processRecord($record); } foreach ($this->handlers as $handler) { try { $handler->handle($record); break; } catch (Throwable $e) { // What throwable? } } return false === $this->bubble; } /** * {@inheritDoc} */ public function handleBatch(array $records): void { if ($this->processors) { $processed = []; foreach ($records as $record) { $processed[] = $this->processRecord($record); } /** @var Record[] $records */ $records = $processed; } foreach ($this->handlers as $handler) { try { $handler->handleBatch($records); break; } catch (Throwable $e) { // What throwable? } } } } PK������\5Z �� ��#��Monolog/Handler/ErrorLogHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\LineFormatter; use Monolog\Formatter\FormatterInterface; use Monolog\Logger; use Monolog\Utils; /** * Stores to PHP error_log() handler. * * @author Elan Ruusamäe <glen@delfi.ee> */ class ErrorLogHandler extends AbstractProcessingHandler { public const OPERATING_SYSTEM = 0; public const SAPI = 4; /** @var int */ protected $messageType; /** @var bool */ protected $expandNewlines; /** * @param int $messageType Says where the error should go. * @param bool $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries */ public function __construct(int $messageType = self::OPERATING_SYSTEM, $level = Logger::DEBUG, bool $bubble = true, bool $expandNewlines = false) { parent::__construct($level, $bubble); if (false === in_array($messageType, self::getAvailableTypes(), true)) { $message = sprintf('The given message type "%s" is not supported', print_r($messageType, true)); throw new \InvalidArgumentException($message); } $this->messageType = $messageType; $this->expandNewlines = $expandNewlines; } /** * @return int[] With all available types */ public static function getAvailableTypes(): array { return [ self::OPERATING_SYSTEM, self::SAPI, ]; } /** * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { return new LineFormatter('[%datetime%] %channel%.%level_name%: %message% %context% %extra%'); } /** * {@inheritDoc} */ protected function write(array $record): void { if (!$this->expandNewlines) { error_log((string) $record['formatted'], $this->messageType); return; } $lines = preg_split('{[\r\n]+}', (string) $record['formatted']); if ($lines === false) { $pcreErrorCode = preg_last_error(); throw new \RuntimeException('Failed to preg_split formatted string: ' . $pcreErrorCode . ' / '. Utils::pcreLastErrorMessage($pcreErrorCode)); } foreach ($lines as $line) { error_log($line, $this->messageType); } } } PK������\5ZZ����&��Monolog/Handler/RedisPubSubHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\LineFormatter; use Monolog\Formatter\FormatterInterface; use Monolog\Logger; /** * Sends the message to a Redis Pub/Sub channel using PUBLISH * * usage example: * * $log = new Logger('application'); * $redis = new RedisPubSubHandler(new Predis\Client("tcp://localhost:6379"), "logs", Logger::WARNING); * $log->pushHandler($redis); * * @author Gaëtan Faugère <gaetan@fauge.re> */ class RedisPubSubHandler extends AbstractProcessingHandler { /** @var \Predis\Client<\Predis\Client>|\Redis */ private $redisClient; /** @var string */ private $channelKey; /** * @param \Predis\Client<\Predis\Client>|\Redis $redis The redis instance * @param string $key The channel key to publish records to */ public function __construct($redis, string $key, $level = Logger::DEBUG, bool $bubble = true) { if (!(($redis instanceof \Predis\Client) || ($redis instanceof \Redis))) { throw new \InvalidArgumentException('Predis\Client or Redis instance required'); } $this->redisClient = $redis; $this->channelKey = $key; parent::__construct($level, $bubble); } /** * {@inheritDoc} */ protected function write(array $record): void { $this->redisClient->publish($this->channelKey, $record["formatted"]); } /** * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { return new LineFormatter(); } } PK������\5Z^wn#k��k��'��Monolog/Handler/NativeMailerHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Formatter\LineFormatter; /** * NativeMailerHandler uses the mail() function to send the emails * * @author Christophe Coevoet <stof@notk.org> * @author Mark Garrett <mark@moderndeveloperllc.com> */ class NativeMailerHandler extends MailHandler { /** * The email addresses to which the message will be sent * @var string[] */ protected $to; /** * The subject of the email * @var string */ protected $subject; /** * Optional headers for the message * @var string[] */ protected $headers = []; /** * Optional parameters for the message * @var string[] */ protected $parameters = []; /** * The wordwrap length for the message * @var int */ protected $maxColumnWidth; /** * The Content-type for the message * @var string|null */ protected $contentType; /** * The encoding for the message * @var string */ protected $encoding = 'utf-8'; /** * @param string|string[] $to The receiver of the mail * @param string $subject The subject of the mail * @param string $from The sender of the mail * @param int $maxColumnWidth The maximum column width that the message lines will have */ public function __construct($to, string $subject, string $from, $level = Logger::ERROR, bool $bubble = true, int $maxColumnWidth = 70) { parent::__construct($level, $bubble); $this->to = (array) $to; $this->subject = $subject; $this->addHeader(sprintf('From: %s', $from)); $this->maxColumnWidth = $maxColumnWidth; } /** * Add headers to the message * * @param string|string[] $headers Custom added headers */ public function addHeader($headers): self { foreach ((array) $headers as $header) { if (strpos($header, "\n") !== false || strpos($header, "\r") !== false) { throw new \InvalidArgumentException('Headers can not contain newline characters for security reasons'); } $this->headers[] = $header; } return $this; } /** * Add parameters to the message * * @param string|string[] $parameters Custom added parameters */ public function addParameter($parameters): self { $this->parameters = array_merge($this->parameters, (array) $parameters); return $this; } /** * {@inheritDoc} */ protected function send(string $content, array $records): void { $contentType = $this->getContentType() ?: ($this->isHtmlBody($content) ? 'text/html' : 'text/plain'); if ($contentType !== 'text/html') { $content = wordwrap($content, $this->maxColumnWidth); } $headers = ltrim(implode("\r\n", $this->headers) . "\r\n", "\r\n"); $headers .= 'Content-type: ' . $contentType . '; charset=' . $this->getEncoding() . "\r\n"; if ($contentType === 'text/html' && false === strpos($headers, 'MIME-Version:')) { $headers .= 'MIME-Version: 1.0' . "\r\n"; } $subject = $this->subject; if ($records) { $subjectFormatter = new LineFormatter($this->subject); $subject = $subjectFormatter->format($this->getHighestRecord($records)); } $parameters = implode(' ', $this->parameters); foreach ($this->to as $to) { mail($to, $subject, $content, $headers, $parameters); } } public function getContentType(): ?string { return $this->contentType; } public function getEncoding(): string { return $this->encoding; } /** * @param string $contentType The content type of the email - Defaults to text/plain. Use text/html for HTML messages. */ public function setContentType(string $contentType): self { if (strpos($contentType, "\n") !== false || strpos($contentType, "\r") !== false) { throw new \InvalidArgumentException('The content type can not contain newline characters to prevent email header injection'); } $this->contentType = $contentType; return $this; } public function setEncoding(string $encoding): self { if (strpos($encoding, "\n") !== false || strpos($encoding, "\r") !== false) { throw new \InvalidArgumentException('The encoding can not contain newline characters to prevent email header injection'); } $this->encoding = $encoding; return $this; } } PK������\5Z4������Monolog/Handler/Handler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; /** * Base Handler class providing basic close() support as well as handleBatch * * @author Jordi Boggiano <j.boggiano@seld.be> */ abstract class Handler implements HandlerInterface { /** * {@inheritDoc} */ public function handleBatch(array $records): void { foreach ($records as $record) { $this->handle($record); } } /** * {@inheritDoc} */ public function close(): void { } public function __destruct() { try { $this->close(); } catch (\Throwable $e) { // do nothing } } public function __sleep() { $this->close(); $reflClass = new \ReflectionClass($this); $keys = []; foreach ($reflClass->getProperties() as $reflProp) { if (!$reflProp->isStatic()) { $keys[] = $reflProp->getName(); } } return $keys; } } PK������\5Zy �� ��-��Monolog/Handler/WebRequestRecognizerTrait.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; trait WebRequestRecognizerTrait { /** * Checks if PHP's serving a web request * @return bool */ protected function isWebRequest(): bool { return 'cli' !== \PHP_SAPI && 'phpdbg' !== \PHP_SAPI; } } PK������\5Z@v����#��Monolog/Handler/SamplingHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; /** * Sampling handler * * A sampled event stream can be useful for logging high frequency events in * a production environment where you only need an idea of what is happening * and are not concerned with capturing every occurrence. Since the decision to * handle or not handle a particular event is determined randomly, the * resulting sampled log is not guaranteed to contain 1/N of the events that * occurred in the application, but based on the Law of large numbers, it will * tend to be close to this ratio with a large number of attempts. * * @author Bryan Davis <bd808@wikimedia.org> * @author Kunal Mehta <legoktm@gmail.com> * * @phpstan-import-type Record from \Monolog\Logger * @phpstan-import-type Level from \Monolog\Logger */ class SamplingHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface { use ProcessableHandlerTrait; /** * @var HandlerInterface|callable * @phpstan-var HandlerInterface|callable(Record|array{level: Level}|null, HandlerInterface): HandlerInterface */ protected $handler; /** * @var int $factor */ protected $factor; /** * @psalm-param HandlerInterface|callable(Record|array{level: Level}|null, HandlerInterface): HandlerInterface $handler * * @param callable|HandlerInterface $handler Handler or factory callable($record|null, $samplingHandler). * @param int $factor Sample factor (e.g. 10 means every ~10th record is sampled) */ public function __construct($handler, int $factor) { parent::__construct(); $this->handler = $handler; $this->factor = $factor; if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) { throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object"); } } public function isHandling(array $record): bool { return $this->getHandler($record)->isHandling($record); } public function handle(array $record): bool { if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) { if ($this->processors) { /** @var Record $record */ $record = $this->processRecord($record); } $this->getHandler($record)->handle($record); } return false === $this->bubble; } /** * Return the nested handler * * If the handler was provided as a factory callable, this will trigger the handler's instantiation. * * @phpstan-param Record|array{level: Level}|null $record * * @return HandlerInterface */ public function getHandler(array $record = null) { if (!$this->handler instanceof HandlerInterface) { $this->handler = ($this->handler)($record, $this); if (!$this->handler instanceof HandlerInterface) { throw new \RuntimeException("The factory callable should return a HandlerInterface"); } } return $this->handler; } /** * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { $handler = $this->getHandler(); if ($handler instanceof FormattableHandlerInterface) { $handler->setFormatter($formatter); return $this; } throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.'); } /** * {@inheritDoc} */ public function getFormatter(): FormatterInterface { $handler = $this->getHandler(); if ($handler instanceof FormattableHandlerInterface) { return $handler->getFormatter(); } throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.'); } } PK������\5ZF����!��Monolog/Handler/LogglyHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LogglyFormatter; use function array_key_exists; use CurlHandle; /** * Sends errors to Loggly. * * @author Przemek Sobstel <przemek@sobstel.org> * @author Adam Pancutt <adam@pancutt.com> * @author Gregory Barchard <gregory@barchard.net> */ class LogglyHandler extends AbstractProcessingHandler { protected const HOST = 'logs-01.loggly.com'; protected const ENDPOINT_SINGLE = 'inputs'; protected const ENDPOINT_BATCH = 'bulk'; /** * Caches the curl handlers for every given endpoint. * * @var resource[]|CurlHandle[] */ protected $curlHandlers = []; /** @var string */ protected $token; /** @var string[] */ protected $tag = []; /** * @param string $token API token supplied by Loggly * * @throws MissingExtensionException If the curl extension is missing */ public function __construct(string $token, $level = Logger::DEBUG, bool $bubble = true) { if (!extension_loaded('curl')) { throw new MissingExtensionException('The curl extension is needed to use the LogglyHandler'); } $this->token = $token; parent::__construct($level, $bubble); } /** * Loads and returns the shared curl handler for the given endpoint. * * @param string $endpoint * * @return resource|CurlHandle */ protected function getCurlHandler(string $endpoint) { if (!array_key_exists($endpoint, $this->curlHandlers)) { $this->curlHandlers[$endpoint] = $this->loadCurlHandle($endpoint); } return $this->curlHandlers[$endpoint]; } /** * Starts a fresh curl session for the given endpoint and returns its handler. * * @param string $endpoint * * @return resource|CurlHandle */ private function loadCurlHandle(string $endpoint) { $url = sprintf("https://%s/%s/%s/", static::HOST, $endpoint, $this->token); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); return $ch; } /** * @param string[]|string $tag */ public function setTag($tag): self { $tag = !empty($tag) ? $tag : []; $this->tag = is_array($tag) ? $tag : [$tag]; return $this; } /** * @param string[]|string $tag */ public function addTag($tag): self { if (!empty($tag)) { $tag = is_array($tag) ? $tag : [$tag]; $this->tag = array_unique(array_merge($this->tag, $tag)); } return $this; } protected function write(array $record): void { $this->send($record["formatted"], static::ENDPOINT_SINGLE); } public function handleBatch(array $records): void { $level = $this->level; $records = array_filter($records, function ($record) use ($level) { return ($record['level'] >= $level); }); if ($records) { $this->send($this->getFormatter()->formatBatch($records), static::ENDPOINT_BATCH); } } protected function send(string $data, string $endpoint): void { $ch = $this->getCurlHandler($endpoint); $headers = ['Content-Type: application/json']; if (!empty($this->tag)) { $headers[] = 'X-LOGGLY-TAG: '.implode(',', $this->tag); } curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); Curl\Util::execute($ch, 5, false); } protected function getDefaultFormatter(): FormatterInterface { return new LogglyFormatter(); } } PK������\5Z_[ �� ��$��Monolog/Handler/FleepHookHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LineFormatter; use Monolog\Logger; /** * Sends logs to Fleep.io using Webhook integrations * * You'll need a Fleep.io account to use this handler. * * @see https://fleep.io/integrations/webhooks/ Fleep Webhooks Documentation * @author Ando Roots <ando@sqroot.eu> * * @phpstan-import-type FormattedRecord from AbstractProcessingHandler */ class FleepHookHandler extends SocketHandler { protected const FLEEP_HOST = 'fleep.io'; protected const FLEEP_HOOK_URI = '/hook/'; /** * @var string Webhook token (specifies the conversation where logs are sent) */ protected $token; /** * Construct a new Fleep.io Handler. * * For instructions on how to create a new web hook in your conversations * see https://fleep.io/integrations/webhooks/ * * @param string $token Webhook token * @throws MissingExtensionException */ public function __construct( string $token, $level = Logger::DEBUG, bool $bubble = true, bool $persistent = false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null ) { if (!extension_loaded('openssl')) { throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FleepHookHandler'); } $this->token = $token; $connectionString = 'ssl://' . static::FLEEP_HOST . ':443'; parent::__construct( $connectionString, $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize ); } /** * Returns the default formatter to use with this handler * * Overloaded to remove empty context and extra arrays from the end of the log message. * * @return LineFormatter */ protected function getDefaultFormatter(): FormatterInterface { return new LineFormatter(null, null, true, true); } /** * Handles a log record */ public function write(array $record): void { parent::write($record); $this->closeSocket(); } /** * {@inheritDoc} */ protected function generateDataStream(array $record): string { $content = $this->buildContent($record); return $this->buildHeader($content) . $content; } /** * Builds the header of the API Call */ private function buildHeader(string $content): string { $header = "POST " . static::FLEEP_HOOK_URI . $this->token . " HTTP/1.1\r\n"; $header .= "Host: " . static::FLEEP_HOST . "\r\n"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: " . strlen($content) . "\r\n"; $header .= "\r\n"; return $header; } /** * Builds the body of API call * * @phpstan-param FormattedRecord $record */ private function buildContent(array $record): string { $dataArray = [ 'message' => $record['formatted'], ]; return http_build_query($dataArray); } } PK������\5Z>$��$��!��Monolog/Handler/BufferHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\ResettableInterface; use Monolog\Formatter\FormatterInterface; /** * Buffers all records until closing the handler and then pass them as batch. * * This is useful for a MailHandler to send only one mail per request instead of * sending one per log message. * * @author Christophe Coevoet <stof@notk.org> * * @phpstan-import-type Record from \Monolog\Logger */ class BufferHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface { use ProcessableHandlerTrait; /** @var HandlerInterface */ protected $handler; /** @var int */ protected $bufferSize = 0; /** @var int */ protected $bufferLimit; /** @var bool */ protected $flushOnOverflow; /** @var Record[] */ protected $buffer = []; /** @var bool */ protected $initialized = false; /** * @param HandlerInterface $handler Handler. * @param int $bufferLimit How many entries should be buffered at most, beyond that the oldest items are removed from the buffer. * @param bool $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded */ public function __construct(HandlerInterface $handler, int $bufferLimit = 0, $level = Logger::DEBUG, bool $bubble = true, bool $flushOnOverflow = false) { parent::__construct($level, $bubble); $this->handler = $handler; $this->bufferLimit = $bufferLimit; $this->flushOnOverflow = $flushOnOverflow; } /** * {@inheritDoc} */ public function handle(array $record): bool { if ($record['level'] < $this->level) { return false; } if (!$this->initialized) { // __destructor() doesn't get called on Fatal errors register_shutdown_function([$this, 'close']); $this->initialized = true; } if ($this->bufferLimit > 0 && $this->bufferSize === $this->bufferLimit) { if ($this->flushOnOverflow) { $this->flush(); } else { array_shift($this->buffer); $this->bufferSize--; } } if ($this->processors) { /** @var Record $record */ $record = $this->processRecord($record); } $this->buffer[] = $record; $this->bufferSize++; return false === $this->bubble; } public function flush(): void { if ($this->bufferSize === 0) { return; } $this->handler->handleBatch($this->buffer); $this->clear(); } public function __destruct() { // suppress the parent behavior since we already have register_shutdown_function() // to call close(), and the reference contained there will prevent this from being // GC'd until the end of the request } /** * {@inheritDoc} */ public function close(): void { $this->flush(); $this->handler->close(); } /** * Clears the buffer without flushing any messages down to the wrapped handler. */ public function clear(): void { $this->bufferSize = 0; $this->buffer = []; } public function reset() { $this->flush(); parent::reset(); $this->resetProcessors(); if ($this->handler instanceof ResettableInterface) { $this->handler->reset(); } } /** * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { if ($this->handler instanceof FormattableHandlerInterface) { $this->handler->setFormatter($formatter); return $this; } throw new \UnexpectedValueException('The nested handler of type '.get_class($this->handler).' does not support formatters.'); } /** * {@inheritDoc} */ public function getFormatter(): FormatterInterface { if ($this->handler instanceof FormattableHandlerInterface) { return $this->handler->getFormatter(); } throw new \UnexpectedValueException('The nested handler of type '.get_class($this->handler).' does not support formatters.'); } } PK������\5ZH7 �� ��#��Monolog/Handler/MandrillHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Swift; use Swift_Message; /** * MandrillHandler uses cURL to send the emails to the Mandrill API * * @author Adam Nicholson <adamnicholson10@gmail.com> */ class MandrillHandler extends MailHandler { /** @var Swift_Message */ protected $message; /** @var string */ protected $apiKey; /** * @psalm-param Swift_Message|callable(): Swift_Message $message * * @param string $apiKey A valid Mandrill API key * @param callable|Swift_Message $message An example message for real messages, only the body will be replaced */ public function __construct(string $apiKey, $message, $level = Logger::ERROR, bool $bubble = true) { parent::__construct($level, $bubble); if (!$message instanceof Swift_Message && is_callable($message)) { $message = $message(); } if (!$message instanceof Swift_Message) { throw new \InvalidArgumentException('You must provide either a Swift_Message instance or a callable returning it'); } $this->message = $message; $this->apiKey = $apiKey; } /** * {@inheritDoc} */ protected function send(string $content, array $records): void { $mime = 'text/plain'; if ($this->isHtmlBody($content)) { $mime = 'text/html'; } $message = clone $this->message; $message->setBody($content, $mime); /** @phpstan-ignore-next-line */ if (version_compare(Swift::VERSION, '6.0.0', '>=')) { $message->setDate(new \DateTimeImmutable()); } else { /** @phpstan-ignore-next-line */ $message->setDate(time()); } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://mandrillapp.com/api/1.0/messages/send-raw.json'); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ 'key' => $this->apiKey, 'raw_message' => (string) $message, 'async' => false, ])); Curl\Util::execute($ch); } } PK������\5Zy`����+��Monolog/Handler/FormattableHandlerTrait.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LineFormatter; /** * Helper trait for implementing FormattableInterface * * @author Jordi Boggiano <j.boggiano@seld.be> */ trait FormattableHandlerTrait { /** * @var ?FormatterInterface */ protected $formatter; /** * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { $this->formatter = $formatter; return $this; } /** * {@inheritDoc} */ public function getFormatter(): FormatterInterface { if (!$this->formatter) { $this->formatter = $this->getDefaultFormatter(); } return $this->formatter; } /** * Gets the default formatter. * * Overwrite this if the LineFormatter is not a good default for your handler. */ protected function getDefaultFormatter(): FormatterInterface { return new LineFormatter(); } } PK������\5ZwӇ���� ��Monolog/Handler/IFTTTHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Utils; /** * IFTTTHandler uses cURL to trigger IFTTT Maker actions * * Register a secret key and trigger/event name at https://ifttt.com/maker * * value1 will be the channel from monolog's Logger constructor, * value2 will be the level name (ERROR, WARNING, ..) * value3 will be the log record's message * * @author Nehal Patel <nehal@nehalpatel.me> */ class IFTTTHandler extends AbstractProcessingHandler { /** @var string */ private $eventName; /** @var string */ private $secretKey; /** * @param string $eventName The name of the IFTTT Maker event that should be triggered * @param string $secretKey A valid IFTTT secret key */ public function __construct(string $eventName, string $secretKey, $level = Logger::ERROR, bool $bubble = true) { if (!extension_loaded('curl')) { throw new MissingExtensionException('The curl extension is needed to use the IFTTTHandler'); } $this->eventName = $eventName; $this->secretKey = $secretKey; parent::__construct($level, $bubble); } /** * {@inheritDoc} */ public function write(array $record): void { $postData = [ "value1" => $record["channel"], "value2" => $record["level_name"], "value3" => $record["message"], ]; $postString = Utils::jsonEncode($postData); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://maker.ifttt.com/trigger/" . $this->eventName . "/with/key/" . $this->secretKey); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $postString); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "Content-Type: application/json", ]); Curl\Util::execute($ch); } } PK������\5ZC �� ��"��Monolog/Handler/MongoDBHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use MongoDB\Driver\BulkWrite; use MongoDB\Driver\Manager; use MongoDB\Client; use Monolog\Logger; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\MongoDBFormatter; /** * Logs to a MongoDB database. * * Usage example: * * $log = new \Monolog\Logger('application'); * $client = new \MongoDB\Client('mongodb://localhost:27017'); * $mongodb = new \Monolog\Handler\MongoDBHandler($client, 'logs', 'prod'); * $log->pushHandler($mongodb); * * The above examples uses the MongoDB PHP library's client class; however, the * MongoDB\Driver\Manager class from ext-mongodb is also supported. */ class MongoDBHandler extends AbstractProcessingHandler { /** @var \MongoDB\Collection */ private $collection; /** @var Client|Manager */ private $manager; /** @var string */ private $namespace; /** * Constructor. * * @param Client|Manager $mongodb MongoDB library or driver client * @param string $database Database name * @param string $collection Collection name */ public function __construct($mongodb, string $database, string $collection, $level = Logger::DEBUG, bool $bubble = true) { if (!($mongodb instanceof Client || $mongodb instanceof Manager)) { throw new \InvalidArgumentException('MongoDB\Client or MongoDB\Driver\Manager instance required'); } if ($mongodb instanceof Client) { $this->collection = $mongodb->selectCollection($database, $collection); } else { $this->manager = $mongodb; $this->namespace = $database . '.' . $collection; } parent::__construct($level, $bubble); } protected function write(array $record): void { if (isset($this->collection)) { $this->collection->insertOne($record['formatted']); } if (isset($this->manager, $this->namespace)) { $bulk = new BulkWrite; $bulk->insert($record["formatted"]); $this->manager->executeBulkWrite($this->namespace, $bulk); } } /** * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { return new MongoDBFormatter; } } PK������\5Z_9w��w����Monolog/Handler/GelfHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Gelf\PublisherInterface; use Monolog\Logger; use Monolog\Formatter\GelfMessageFormatter; use Monolog\Formatter\FormatterInterface; /** * Handler to send messages to a Graylog2 (http://www.graylog2.org) server * * @author Matt Lehner <mlehner@gmail.com> * @author Benjamin Zikarsky <benjamin@zikarsky.de> */ class GelfHandler extends AbstractProcessingHandler { /** * @var PublisherInterface the publisher object that sends the message to the server */ protected $publisher; /** * @param PublisherInterface $publisher a gelf publisher object */ public function __construct(PublisherInterface $publisher, $level = Logger::DEBUG, bool $bubble = true) { parent::__construct($level, $bubble); $this->publisher = $publisher; } /** * {@inheritDoc} */ protected function write(array $record): void { $this->publisher->publish($record['formatted']); } /** * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { return new GelfMessageFormatter(); } } PK������\5Zl��l�� ��Monolog/Handler/SlackHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; use Monolog\Logger; use Monolog\Utils; use Monolog\Handler\Slack\SlackRecord; /** * Sends notifications through Slack API * * @author Greg Kedzierski <greg@gregkedzierski.com> * @see https://api.slack.com/ * * @phpstan-import-type FormattedRecord from AbstractProcessingHandler */ class SlackHandler extends SocketHandler { /** * Slack API token * @var string */ private $token; /** * Instance of the SlackRecord util class preparing data for Slack API. * @var SlackRecord */ private $slackRecord; /** * @param string $token Slack API token * @param string $channel Slack channel (encoded ID or name) * @param string|null $username Name of a bot * @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise) * @param string|null $iconEmoji The emoji name to use (or null) * @param bool $useShortAttachment Whether the context/extra messages added to Slack as attachments are in a short style * @param bool $includeContextAndExtra Whether the attachment should include context and extra data * @param string[] $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2'] * @throws MissingExtensionException If no OpenSSL PHP extension configured */ public function __construct( string $token, string $channel, ?string $username = null, bool $useAttachment = true, ?string $iconEmoji = null, $level = Logger::CRITICAL, bool $bubble = true, bool $useShortAttachment = false, bool $includeContextAndExtra = false, array $excludeFields = array(), bool $persistent = false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null ) { if (!extension_loaded('openssl')) { throw new MissingExtensionException('The OpenSSL PHP extension is required to use the SlackHandler'); } parent::__construct( 'ssl://slack.com:443', $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize ); $this->slackRecord = new SlackRecord( $channel, $username, $useAttachment, $iconEmoji, $useShortAttachment, $includeContextAndExtra, $excludeFields ); $this->token = $token; } public function getSlackRecord(): SlackRecord { return $this->slackRecord; } public function getToken(): string { return $this->token; } /** * {@inheritDoc} */ protected function generateDataStream(array $record): string { $content = $this->buildContent($record); return $this->buildHeader($content) . $content; } /** * Builds the body of API call * * @phpstan-param FormattedRecord $record */ private function buildContent(array $record): string { $dataArray = $this->prepareContentData($record); return http_build_query($dataArray); } /** * @phpstan-param FormattedRecord $record * @return string[] */ protected function prepareContentData(array $record): array { $dataArray = $this->slackRecord->getSlackData($record); $dataArray['token'] = $this->token; if (!empty($dataArray['attachments'])) { $dataArray['attachments'] = Utils::jsonEncode($dataArray['attachments']); } return $dataArray; } /** * Builds the header of the API Call */ private function buildHeader(string $content): string { $header = "POST /api/chat.postMessage HTTP/1.1\r\n"; $header .= "Host: slack.com\r\n"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: " . strlen($content) . "\r\n"; $header .= "\r\n"; return $header; } /** * {@inheritDoc} */ protected function write(array $record): void { parent::write($record); $this->finalizeWrite(); } /** * Finalizes the request by reading some bytes and then closing the socket * * If we do not read some but close the socket too early, slack sometimes * drops the request entirely. */ protected function finalizeWrite(): void { $res = $this->getResource(); if (is_resource($res)) { @fread($res, 2048); } $this->closeSocket(); } public function setFormatter(FormatterInterface $formatter): HandlerInterface { parent::setFormatter($formatter); $this->slackRecord->setFormatter($formatter); return $this; } public function getFormatter(): FormatterInterface { $formatter = parent::getFormatter(); $this->slackRecord->setFormatter($formatter); return $formatter; } /** * Channel used by the bot when posting */ public function setChannel(string $channel): self { $this->slackRecord->setChannel($channel); return $this; } /** * Username used by the bot when posting */ public function setUsername(string $username): self { $this->slackRecord->setUsername($username); return $this; } public function useAttachment(bool $useAttachment): self { $this->slackRecord->useAttachment($useAttachment); return $this; } public function setIconEmoji(string $iconEmoji): self { $this->slackRecord->setUserIcon($iconEmoji); return $this; } public function useShortAttachment(bool $useShortAttachment): self { $this->slackRecord->useShortAttachment($useShortAttachment); return $this; } public function includeContextAndExtra(bool $includeContextAndExtra): self { $this->slackRecord->includeContextAndExtra($includeContextAndExtra); return $this; } /** * @param string[] $excludeFields */ public function excludeFields(array $excludeFields): self { $this->slackRecord->excludeFields($excludeFields); return $this; } } PK������\5Z?p#/��/��!��Monolog/Handler/SocketHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * Stores to any socket - uses fsockopen() or pfsockopen(). * * @author Pablo de Leon Belloc <pablolb@gmail.com> * @see http://php.net/manual/en/function.fsockopen.php * * @phpstan-import-type Record from \Monolog\Logger * @phpstan-import-type FormattedRecord from AbstractProcessingHandler */ class SocketHandler extends AbstractProcessingHandler { /** @var string */ private $connectionString; /** @var float */ private $connectionTimeout; /** @var resource|null */ private $resource; /** @var float */ private $timeout; /** @var float */ private $writingTimeout; /** @var ?int */ private $lastSentBytes = null; /** @var ?int */ private $chunkSize; /** @var bool */ private $persistent; /** @var ?int */ private $errno = null; /** @var ?string */ private $errstr = null; /** @var ?float */ private $lastWritingAt = null; /** * @param string $connectionString Socket connection string * @param bool $persistent Flag to enable/disable persistent connections * @param float $timeout Socket timeout to wait until the request is being aborted * @param float $writingTimeout Socket timeout to wait until the request should've been sent/written * @param float|null $connectionTimeout Socket connect timeout to wait until the connection should've been * established * @param int|null $chunkSize Sets the chunk size. Only has effect during connection in the writing cycle * * @throws \InvalidArgumentException If an invalid timeout value (less than 0) is passed. */ public function __construct( string $connectionString, $level = Logger::DEBUG, bool $bubble = true, bool $persistent = false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null ) { parent::__construct($level, $bubble); $this->connectionString = $connectionString; if ($connectionTimeout !== null) { $this->validateTimeout($connectionTimeout); } $this->connectionTimeout = $connectionTimeout ?? (float) ini_get('default_socket_timeout'); $this->persistent = $persistent; $this->validateTimeout($timeout); $this->timeout = $timeout; $this->validateTimeout($writingTimeout); $this->writingTimeout = $writingTimeout; $this->chunkSize = $chunkSize; } /** * Connect (if necessary) and write to the socket * * {@inheritDoc} * * @throws \UnexpectedValueException * @throws \RuntimeException */ protected function write(array $record): void { $this->connectIfNotConnected(); $data = $this->generateDataStream($record); $this->writeToSocket($data); } /** * We will not close a PersistentSocket instance so it can be reused in other requests. */ public function close(): void { if (!$this->isPersistent()) { $this->closeSocket(); } } /** * Close socket, if open */ public function closeSocket(): void { if (is_resource($this->resource)) { fclose($this->resource); $this->resource = null; } } /** * Set socket connection to be persistent. It only has effect before the connection is initiated. */ public function setPersistent(bool $persistent): self { $this->persistent = $persistent; return $this; } /** * Set connection timeout. Only has effect before we connect. * * @see http://php.net/manual/en/function.fsockopen.php */ public function setConnectionTimeout(float $seconds): self { $this->validateTimeout($seconds); $this->connectionTimeout = $seconds; return $this; } /** * Set write timeout. Only has effect before we connect. * * @see http://php.net/manual/en/function.stream-set-timeout.php */ public function setTimeout(float $seconds): self { $this->validateTimeout($seconds); $this->timeout = $seconds; return $this; } /** * Set writing timeout. Only has effect during connection in the writing cycle. * * @param float $seconds 0 for no timeout */ public function setWritingTimeout(float $seconds): self { $this->validateTimeout($seconds); $this->writingTimeout = $seconds; return $this; } /** * Set chunk size. Only has effect during connection in the writing cycle. */ public function setChunkSize(int $bytes): self { $this->chunkSize = $bytes; return $this; } /** * Get current connection string */ public function getConnectionString(): string { return $this->connectionString; } /** * Get persistent setting */ public function isPersistent(): bool { return $this->persistent; } /** * Get current connection timeout setting */ public function getConnectionTimeout(): float { return $this->connectionTimeout; } /** * Get current in-transfer timeout */ public function getTimeout(): float { return $this->timeout; } /** * Get current local writing timeout * * @return float */ public function getWritingTimeout(): float { return $this->writingTimeout; } /** * Get current chunk size */ public function getChunkSize(): ?int { return $this->chunkSize; } /** * Check to see if the socket is currently available. * * UDP might appear to be connected but might fail when writing. See http://php.net/fsockopen for details. */ public function isConnected(): bool { return is_resource($this->resource) && !feof($this->resource); // on TCP - other party can close connection. } /** * Wrapper to allow mocking * * @return resource|false */ protected function pfsockopen() { return @pfsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout); } /** * Wrapper to allow mocking * * @return resource|false */ protected function fsockopen() { return @fsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout); } /** * Wrapper to allow mocking * * @see http://php.net/manual/en/function.stream-set-timeout.php * * @return bool */ protected function streamSetTimeout() { $seconds = floor($this->timeout); $microseconds = round(($this->timeout - $seconds) * 1e6); if (!is_resource($this->resource)) { throw new \LogicException('streamSetTimeout called but $this->resource is not a resource'); } return stream_set_timeout($this->resource, (int) $seconds, (int) $microseconds); } /** * Wrapper to allow mocking * * @see http://php.net/manual/en/function.stream-set-chunk-size.php * * @return int|bool */ protected function streamSetChunkSize() { if (!is_resource($this->resource)) { throw new \LogicException('streamSetChunkSize called but $this->resource is not a resource'); } if (null === $this->chunkSize) { throw new \LogicException('streamSetChunkSize called but $this->chunkSize is not set'); } return stream_set_chunk_size($this->resource, $this->chunkSize); } /** * Wrapper to allow mocking * * @return int|bool */ protected function fwrite(string $data) { if (!is_resource($this->resource)) { throw new \LogicException('fwrite called but $this->resource is not a resource'); } return @fwrite($this->resource, $data); } /** * Wrapper to allow mocking * * @return mixed[]|bool */ protected function streamGetMetadata() { if (!is_resource($this->resource)) { throw new \LogicException('streamGetMetadata called but $this->resource is not a resource'); } return stream_get_meta_data($this->resource); } private function validateTimeout(float $value): void { if ($value < 0) { throw new \InvalidArgumentException("Timeout must be 0 or a positive float (got $value)"); } } private function connectIfNotConnected(): void { if ($this->isConnected()) { return; } $this->connect(); } /** * @phpstan-param FormattedRecord $record */ protected function generateDataStream(array $record): string { return (string) $record['formatted']; } /** * @return resource|null */ protected function getResource() { return $this->resource; } private function connect(): void { $this->createSocketResource(); $this->setSocketTimeout(); $this->setStreamChunkSize(); } private function createSocketResource(): void { if ($this->isPersistent()) { $resource = $this->pfsockopen(); } else { $resource = $this->fsockopen(); } if (is_bool($resource)) { throw new \UnexpectedValueException("Failed connecting to $this->connectionString ($this->errno: $this->errstr)"); } $this->resource = $resource; } private function setSocketTimeout(): void { if (!$this->streamSetTimeout()) { throw new \UnexpectedValueException("Failed setting timeout with stream_set_timeout()"); } } private function setStreamChunkSize(): void { if ($this->chunkSize && !$this->streamSetChunkSize()) { throw new \UnexpectedValueException("Failed setting chunk size with stream_set_chunk_size()"); } } private function writeToSocket(string $data): void { $length = strlen($data); $sent = 0; $this->lastSentBytes = $sent; while ($this->isConnected() && $sent < $length) { if (0 == $sent) { $chunk = $this->fwrite($data); } else { $chunk = $this->fwrite(substr($data, $sent)); } if ($chunk === false) { throw new \RuntimeException("Could not write to socket"); } $sent += $chunk; $socketInfo = $this->streamGetMetadata(); if (is_array($socketInfo) && $socketInfo['timed_out']) { throw new \RuntimeException("Write timed-out"); } if ($this->writingIsTimedOut($sent)) { throw new \RuntimeException("Write timed-out, no data sent for `{$this->writingTimeout}` seconds, probably we got disconnected (sent $sent of $length)"); } } if (!$this->isConnected() && $sent < $length) { throw new \RuntimeException("End-of-file reached, probably we got disconnected (sent $sent of $length)"); } } private function writingIsTimedOut(int $sent): bool { // convert to ms if (0.0 == $this->writingTimeout) { return false; } if ($sent !== $this->lastSentBytes) { $this->lastWritingAt = microtime(true); $this->lastSentBytes = $sent; return false; } else { usleep(100); } if ((microtime(true) - $this->lastWritingAt) >= $this->writingTimeout) { $this->closeSocket(); return true; } return false; } } PK������\5ZY,T ��T ��"��Monolog/Handler/RollbarHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Rollbar\RollbarLogger; use Throwable; use Monolog\Logger; /** * Sends errors to Rollbar * * If the context data contains a `payload` key, that is used as an array * of payload options to RollbarLogger's log method. * * Rollbar's context info will contain the context + extra keys from the log record * merged, and then on top of that a few keys: * * - level (rollbar level name) * - monolog_level (monolog level name, raw level, as rollbar only has 5 but monolog 8) * - channel * - datetime (unix timestamp) * * @author Paul Statezny <paulstatezny@gmail.com> */ class RollbarHandler extends AbstractProcessingHandler { /** * @var RollbarLogger */ protected $rollbarLogger; /** @var string[] */ protected $levelMap = [ Logger::DEBUG => 'debug', Logger::INFO => 'info', Logger::NOTICE => 'info', Logger::WARNING => 'warning', Logger::ERROR => 'error', Logger::CRITICAL => 'critical', Logger::ALERT => 'critical', Logger::EMERGENCY => 'critical', ]; /** * Records whether any log records have been added since the last flush of the rollbar notifier * * @var bool */ private $hasRecords = false; /** @var bool */ protected $initialized = false; /** * @param RollbarLogger $rollbarLogger RollbarLogger object constructed with valid token */ public function __construct(RollbarLogger $rollbarLogger, $level = Logger::ERROR, bool $bubble = true) { $this->rollbarLogger = $rollbarLogger; parent::__construct($level, $bubble); } /** * {@inheritDoc} */ protected function write(array $record): void { if (!$this->initialized) { // __destructor() doesn't get called on Fatal errors register_shutdown_function(array($this, 'close')); $this->initialized = true; } $context = $record['context']; $context = array_merge($context, $record['extra'], [ 'level' => $this->levelMap[$record['level']], 'monolog_level' => $record['level_name'], 'channel' => $record['channel'], 'datetime' => $record['datetime']->format('U'), ]); if (isset($context['exception']) && $context['exception'] instanceof Throwable) { $exception = $context['exception']; unset($context['exception']); $toLog = $exception; } else { $toLog = $record['message']; } // @phpstan-ignore-next-line $this->rollbarLogger->log($context['level'], $toLog, $context); $this->hasRecords = true; } public function flush(): void { if ($this->hasRecords) { $this->rollbarLogger->flush(); $this->hasRecords = false; } } /** * {@inheritDoc} */ public function close(): void { $this->flush(); } /** * {@inheritDoc} */ public function reset() { $this->flush(); parent::reset(); } } PK������\5Z:��:��%��Monolog/Handler/InsightOpsHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * Inspired on LogEntriesHandler. * * @author Robert Kaufmann III <rok3@rok3.me> * @author Gabriel Machado <gabriel.ms1@hotmail.com> */ class InsightOpsHandler extends SocketHandler { /** * @var string */ protected $logToken; /** * @param string $token Log token supplied by InsightOps * @param string $region Region where InsightOps account is hosted. Could be 'us' or 'eu'. * @param bool $useSSL Whether or not SSL encryption should be used * * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing */ public function __construct( string $token, string $region = 'us', bool $useSSL = true, $level = Logger::DEBUG, bool $bubble = true, bool $persistent = false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null ) { if ($useSSL && !extension_loaded('openssl')) { throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for InsightOpsHandler'); } $endpoint = $useSSL ? 'ssl://' . $region . '.data.logs.insight.rapid7.com:443' : $region . '.data.logs.insight.rapid7.com:80'; parent::__construct( $endpoint, $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize ); $this->logToken = $token; } /** * {@inheritDoc} */ protected function generateDataStream(array $record): string { return $this->logToken . ' ' . $record['formatted']; } } PK������\5ZIL����'��Monolog/Handler/RotatingFileHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use InvalidArgumentException; use Monolog\Logger; use Monolog\Utils; /** * Stores logs to files that are rotated every day and a limited number of files are kept. * * This rotation is only intended to be used as a workaround. Using logrotate to * handle the rotation is strongly encouraged when you can use it. * * @author Christophe Coevoet <stof@notk.org> * @author Jordi Boggiano <j.boggiano@seld.be> */ class RotatingFileHandler extends StreamHandler { public const FILE_PER_DAY = 'Y-m-d'; public const FILE_PER_MONTH = 'Y-m'; public const FILE_PER_YEAR = 'Y'; /** @var string */ protected $filename; /** @var int */ protected $maxFiles; /** @var bool */ protected $mustRotate; /** @var \DateTimeImmutable */ protected $nextRotation; /** @var string */ protected $filenameFormat; /** @var string */ protected $dateFormat; /** * @param string $filename * @param int $maxFiles The maximal amount of files to keep (0 means unlimited) * @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write) * @param bool $useLocking Try to lock log file before doing any writes */ public function __construct(string $filename, int $maxFiles = 0, $level = Logger::DEBUG, bool $bubble = true, ?int $filePermission = null, bool $useLocking = false) { $this->filename = Utils::canonicalizePath($filename); $this->maxFiles = $maxFiles; $this->nextRotation = new \DateTimeImmutable('tomorrow'); $this->filenameFormat = '{filename}-{date}'; $this->dateFormat = static::FILE_PER_DAY; parent::__construct($this->getTimedFilename(), $level, $bubble, $filePermission, $useLocking); } /** * {@inheritDoc} */ public function close(): void { parent::close(); if (true === $this->mustRotate) { $this->rotate(); } } /** * {@inheritDoc} */ public function reset() { parent::reset(); if (true === $this->mustRotate) { $this->rotate(); } } public function setFilenameFormat(string $filenameFormat, string $dateFormat): self { if (!preg_match('{^[Yy](([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) { throw new InvalidArgumentException( 'Invalid date format - format must be one of '. 'RotatingFileHandler::FILE_PER_DAY ("Y-m-d"), RotatingFileHandler::FILE_PER_MONTH ("Y-m") '. 'or RotatingFileHandler::FILE_PER_YEAR ("Y"), or you can set one of the '. 'date formats using slashes, underscores and/or dots instead of dashes.' ); } if (substr_count($filenameFormat, '{date}') === 0) { throw new InvalidArgumentException( 'Invalid filename format - format must contain at least `{date}`, because otherwise rotating is impossible.' ); } $this->filenameFormat = $filenameFormat; $this->dateFormat = $dateFormat; $this->url = $this->getTimedFilename(); $this->close(); return $this; } /** * {@inheritDoc} */ protected function write(array $record): void { // on the first record written, if the log is new, we should rotate (once per day) if (null === $this->mustRotate) { $this->mustRotate = null === $this->url || !file_exists($this->url); } if ($this->nextRotation <= $record['datetime']) { $this->mustRotate = true; $this->close(); } parent::write($record); } /** * Rotates the files. */ protected function rotate(): void { // update filename $this->url = $this->getTimedFilename(); $this->nextRotation = new \DateTimeImmutable('tomorrow'); // skip GC of old logs if files are unlimited if (0 === $this->maxFiles) { return; } $logFiles = glob($this->getGlobPattern()); if (false === $logFiles) { // failed to glob return; } if ($this->maxFiles >= count($logFiles)) { // no files to remove return; } // Sorting the files by name to remove the older ones usort($logFiles, function ($a, $b) { return strcmp($b, $a); }); foreach (array_slice($logFiles, $this->maxFiles) as $file) { if (is_writable($file)) { // suppress errors here as unlink() might fail if two processes // are cleaning up/rotating at the same time set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline): bool { return false; }); unlink($file); restore_error_handler(); } } $this->mustRotate = false; } protected function getTimedFilename(): string { $fileInfo = pathinfo($this->filename); $timedFilename = str_replace( ['{filename}', '{date}'], [$fileInfo['filename'], date($this->dateFormat)], $fileInfo['dirname'] . '/' . $this->filenameFormat ); if (isset($fileInfo['extension'])) { $timedFilename .= '.'.$fileInfo['extension']; } return $timedFilename; } protected function getGlobPattern(): string { $fileInfo = pathinfo($this->filename); $glob = str_replace( ['{filename}', '{date}'], [$fileInfo['filename'], str_replace( ['Y', 'y', 'm', 'd'], ['[0-9][0-9][0-9][0-9]', '[0-9][0-9]', '[0-9][0-9]', '[0-9][0-9]'], $this->dateFormat) ], $fileInfo['dirname'] . '/' . $this->filenameFormat ); if (isset($fileInfo['extension'])) { $glob .= '.'.$fileInfo['extension']; } return $glob; } } PK������\5Zg��g����Monolog/Handler/Curl/Util.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler\Curl; use CurlHandle; /** * This class is marked as internal and it is not under the BC promise of the package. * * @internal */ final class Util { /** @var array<int> */ private static $retriableErrorCodes = [ CURLE_COULDNT_RESOLVE_HOST, CURLE_COULDNT_CONNECT, CURLE_HTTP_NOT_FOUND, CURLE_READ_ERROR, CURLE_OPERATION_TIMEOUTED, CURLE_HTTP_POST_ERROR, CURLE_SSL_CONNECT_ERROR, ]; /** * Executes a CURL request with optional retries and exception on failure * * @param resource|CurlHandle $ch curl handler * @param int $retries * @param bool $closeAfterDone * @return bool|string @see curl_exec */ public static function execute($ch, int $retries = 5, bool $closeAfterDone = true) { while ($retries--) { $curlResponse = curl_exec($ch); if ($curlResponse === false) { $curlErrno = curl_errno($ch); if (false === in_array($curlErrno, self::$retriableErrorCodes, true) || !$retries) { $curlError = curl_error($ch); if ($closeAfterDone) { curl_close($ch); } throw new \RuntimeException(sprintf('Curl error (code %d): %s', $curlErrno, $curlError)); } continue; } if ($closeAfterDone) { curl_close($ch); } return $curlResponse; } return false; } } PK������\5Z{”����#��Monolog/Handler/PushoverHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Utils; use Psr\Log\LogLevel; /** * Sends notifications through the pushover api to mobile phones * * @author Sebastian Göttschkes <sebastian.goettschkes@googlemail.com> * @see https://www.pushover.net/api * * @phpstan-import-type FormattedRecord from AbstractProcessingHandler * @phpstan-import-type Level from \Monolog\Logger * @phpstan-import-type LevelName from \Monolog\Logger */ class PushoverHandler extends SocketHandler { /** @var string */ private $token; /** @var array<int|string> */ private $users; /** @var string */ private $title; /** @var string|int|null */ private $user = null; /** @var int */ private $retry; /** @var int */ private $expire; /** @var int */ private $highPriorityLevel; /** @var int */ private $emergencyLevel; /** @var bool */ private $useFormattedMessage = false; /** * All parameters that can be sent to Pushover * @see https://pushover.net/api * @var array<string, bool> */ private $parameterNames = [ 'token' => true, 'user' => true, 'message' => true, 'device' => true, 'title' => true, 'url' => true, 'url_title' => true, 'priority' => true, 'timestamp' => true, 'sound' => true, 'retry' => true, 'expire' => true, 'callback' => true, ]; /** * Sounds the api supports by default * @see https://pushover.net/api#sounds * @var string[] */ private $sounds = [ 'pushover', 'bike', 'bugle', 'cashregister', 'classical', 'cosmic', 'falling', 'gamelan', 'incoming', 'intermission', 'magic', 'mechanical', 'pianobar', 'siren', 'spacealarm', 'tugboat', 'alien', 'climb', 'persistent', 'echo', 'updown', 'none', ]; /** * @param string $token Pushover api token * @param string|array $users Pushover user id or array of ids the message will be sent to * @param string|null $title Title sent to the Pushover API * @param bool $useSSL Whether to connect via SSL. Required when pushing messages to users that are not * the pushover.net app owner. OpenSSL is required for this option. * @param string|int $highPriorityLevel The minimum logging level at which this handler will start * sending "high priority" requests to the Pushover API * @param string|int $emergencyLevel The minimum logging level at which this handler will start * sending "emergency" requests to the Pushover API * @param int $retry The retry parameter specifies how often (in seconds) the Pushover servers will * send the same notification to the user. * @param int $expire The expire parameter specifies how many seconds your notification will continue * to be retried for (every retry seconds). * * @phpstan-param string|array<int|string> $users * @phpstan-param Level|LevelName|LogLevel::* $highPriorityLevel * @phpstan-param Level|LevelName|LogLevel::* $emergencyLevel */ public function __construct( string $token, $users, ?string $title = null, $level = Logger::CRITICAL, bool $bubble = true, bool $useSSL = true, $highPriorityLevel = Logger::CRITICAL, $emergencyLevel = Logger::EMERGENCY, int $retry = 30, int $expire = 25200, bool $persistent = false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null ) { $connectionString = $useSSL ? 'ssl://api.pushover.net:443' : 'api.pushover.net:80'; parent::__construct( $connectionString, $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize ); $this->token = $token; $this->users = (array) $users; $this->title = $title ?: (string) gethostname(); $this->highPriorityLevel = Logger::toMonologLevel($highPriorityLevel); $this->emergencyLevel = Logger::toMonologLevel($emergencyLevel); $this->retry = $retry; $this->expire = $expire; } protected function generateDataStream(array $record): string { $content = $this->buildContent($record); return $this->buildHeader($content) . $content; } /** * @phpstan-param FormattedRecord $record */ private function buildContent(array $record): string { // Pushover has a limit of 512 characters on title and message combined. $maxMessageLength = 512 - strlen($this->title); $message = ($this->useFormattedMessage) ? $record['formatted'] : $record['message']; $message = Utils::substr($message, 0, $maxMessageLength); $timestamp = $record['datetime']->getTimestamp(); $dataArray = [ 'token' => $this->token, 'user' => $this->user, 'message' => $message, 'title' => $this->title, 'timestamp' => $timestamp, ]; if (isset($record['level']) && $record['level'] >= $this->emergencyLevel) { $dataArray['priority'] = 2; $dataArray['retry'] = $this->retry; $dataArray['expire'] = $this->expire; } elseif (isset($record['level']) && $record['level'] >= $this->highPriorityLevel) { $dataArray['priority'] = 1; } // First determine the available parameters $context = array_intersect_key($record['context'], $this->parameterNames); $extra = array_intersect_key($record['extra'], $this->parameterNames); // Least important info should be merged with subsequent info $dataArray = array_merge($extra, $context, $dataArray); // Only pass sounds that are supported by the API if (isset($dataArray['sound']) && !in_array($dataArray['sound'], $this->sounds)) { unset($dataArray['sound']); } return http_build_query($dataArray); } private function buildHeader(string $content): string { $header = "POST /1/messages.json HTTP/1.1\r\n"; $header .= "Host: api.pushover.net\r\n"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: " . strlen($content) . "\r\n"; $header .= "\r\n"; return $header; } protected function write(array $record): void { foreach ($this->users as $user) { $this->user = $user; parent::write($record); $this->closeSocket(); } $this->user = null; } /** * @param int|string $value * * @phpstan-param Level|LevelName|LogLevel::* $value */ public function setHighPriorityLevel($value): self { $this->highPriorityLevel = Logger::toMonologLevel($value); return $this; } /** * @param int|string $value * * @phpstan-param Level|LevelName|LogLevel::* $value */ public function setEmergencyLevel($value): self { $this->emergencyLevel = Logger::toMonologLevel($value); return $this; } /** * Use the formatted message? */ public function useFormattedMessage(bool $value): self { $this->useFormattedMessage = $value; return $this; } } PK������\5Z����-��Monolog/Handler/MissingExtensionException.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; /** * Exception can be thrown if an extension for a handler is missing * * @author Christian Bergau <cbergau86@gmail.com> */ class MissingExtensionException extends \Exception { } PK������\5Z> �� �� ��Monolog/Handler/GroupHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; use Monolog\ResettableInterface; /** * Forwards records to multiple handlers * * @author Lenar Lõhmus <lenar@city.ee> * * @phpstan-import-type Record from \Monolog\Logger */ class GroupHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface { use ProcessableHandlerTrait; /** @var HandlerInterface[] */ protected $handlers; /** @var bool */ protected $bubble; /** * @param HandlerInterface[] $handlers Array of Handlers. * @param bool $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct(array $handlers, bool $bubble = true) { foreach ($handlers as $handler) { if (!$handler instanceof HandlerInterface) { throw new \InvalidArgumentException('The first argument of the GroupHandler must be an array of HandlerInterface instances.'); } } $this->handlers = $handlers; $this->bubble = $bubble; } /** * {@inheritDoc} */ public function isHandling(array $record): bool { foreach ($this->handlers as $handler) { if ($handler->isHandling($record)) { return true; } } return false; } /** * {@inheritDoc} */ public function handle(array $record): bool { if ($this->processors) { /** @var Record $record */ $record = $this->processRecord($record); } foreach ($this->handlers as $handler) { $handler->handle($record); } return false === $this->bubble; } /** * {@inheritDoc} */ public function handleBatch(array $records): void { if ($this->processors) { $processed = []; foreach ($records as $record) { $processed[] = $this->processRecord($record); } /** @var Record[] $records */ $records = $processed; } foreach ($this->handlers as $handler) { $handler->handleBatch($records); } } public function reset() { $this->resetProcessors(); foreach ($this->handlers as $handler) { if ($handler instanceof ResettableInterface) { $handler->reset(); } } } public function close(): void { parent::close(); foreach ($this->handlers as $handler) { $handler->close(); } } /** * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { foreach ($this->handlers as $handler) { if ($handler instanceof FormattableHandlerInterface) { $handler->setFormatter($formatter); } } return $this; } } PK������\5Z8 rU��U��&��Monolog/Handler/SwiftMailerHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Utils; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LineFormatter; use Swift_Message; use Swift; /** * SwiftMailerHandler uses Swift_Mailer to send the emails * * @author Gyula Sallai * * @phpstan-import-type Record from \Monolog\Logger * @deprecated Since Monolog 2.6. Use SymfonyMailerHandler instead. */ class SwiftMailerHandler extends MailHandler { /** @var \Swift_Mailer */ protected $mailer; /** @var Swift_Message|callable(string, Record[]): Swift_Message */ private $messageTemplate; /** * @psalm-param Swift_Message|callable(string, Record[]): Swift_Message $message * * @param \Swift_Mailer $mailer The mailer to use * @param callable|Swift_Message $message An example message for real messages, only the body will be replaced */ public function __construct(\Swift_Mailer $mailer, $message, $level = Logger::ERROR, bool $bubble = true) { parent::__construct($level, $bubble); @trigger_error('The SwiftMailerHandler is deprecated since Monolog 2.6. Use SymfonyMailerHandler instead.', E_USER_DEPRECATED); $this->mailer = $mailer; $this->messageTemplate = $message; } /** * {@inheritDoc} */ protected function send(string $content, array $records): void { $this->mailer->send($this->buildMessage($content, $records)); } /** * Gets the formatter for the Swift_Message subject. * * @param string|null $format The format of the subject */ protected function getSubjectFormatter(?string $format): FormatterInterface { return new LineFormatter($format); } /** * Creates instance of Swift_Message to be sent * * @param string $content formatted email body to be sent * @param array $records Log records that formed the content * @return Swift_Message * * @phpstan-param Record[] $records */ protected function buildMessage(string $content, array $records): Swift_Message { $message = null; if ($this->messageTemplate instanceof Swift_Message) { $message = clone $this->messageTemplate; $message->generateId(); } elseif (is_callable($this->messageTemplate)) { $message = ($this->messageTemplate)($content, $records); } if (!$message instanceof Swift_Message) { $record = reset($records); throw new \InvalidArgumentException('Could not resolve message as instance of Swift_Message or a callable returning it' . ($record ? Utils::getRecordMessageForException($record) : '')); } if ($records) { $subjectFormatter = $this->getSubjectFormatter($message->getSubject()); $message->setSubject($subjectFormatter->format($this->getHighestRecord($records))); } $mime = 'text/plain'; if ($this->isHtmlBody($content)) { $mime = 'text/html'; } $message->setBody($content, $mime); /** @phpstan-ignore-next-line */ if (version_compare(Swift::VERSION, '6.0.0', '>=')) { $message->setDate(new \DateTimeImmutable()); } else { /** @phpstan-ignore-next-line */ $message->setDate(time()); } return $message; } } PK������\5ZH����$��Monolog/Handler/SyslogUdpHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use DateTimeInterface; use Monolog\Logger; use Monolog\Handler\SyslogUdp\UdpSocket; use Monolog\Utils; /** * A Handler for logging to a remote syslogd server. * * @author Jesper Skovgaard Nielsen <nulpunkt@gmail.com> * @author Dominik Kukacka <dominik.kukacka@gmail.com> */ class SyslogUdpHandler extends AbstractSyslogHandler { const RFC3164 = 0; const RFC5424 = 1; const RFC5424e = 2; /** @var array<self::RFC*, string> */ private $dateFormats = array( self::RFC3164 => 'M d H:i:s', self::RFC5424 => \DateTime::RFC3339, self::RFC5424e => \DateTime::RFC3339_EXTENDED, ); /** @var UdpSocket */ protected $socket; /** @var string */ protected $ident; /** @var self::RFC* */ protected $rfc; /** * @param string $host Either IP/hostname or a path to a unix socket (port must be 0 then) * @param int $port Port number, or 0 if $host is a unix socket * @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant * @param bool $bubble Whether the messages that are handled can bubble up the stack or not * @param string $ident Program name or tag for each log message. * @param int $rfc RFC to format the message for. * @throws MissingExtensionException * * @phpstan-param self::RFC* $rfc */ public function __construct(string $host, int $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true, string $ident = 'php', int $rfc = self::RFC5424) { if (!extension_loaded('sockets')) { throw new MissingExtensionException('The sockets extension is required to use the SyslogUdpHandler'); } parent::__construct($facility, $level, $bubble); $this->ident = $ident; $this->rfc = $rfc; $this->socket = new UdpSocket($host, $port); } protected function write(array $record): void { $lines = $this->splitMessageIntoLines($record['formatted']); $header = $this->makeCommonSyslogHeader($this->logLevels[$record['level']], $record['datetime']); foreach ($lines as $line) { $this->socket->write($line, $header); } } public function close(): void { $this->socket->close(); } /** * @param string|string[] $message * @return string[] */ private function splitMessageIntoLines($message): array { if (is_array($message)) { $message = implode("\n", $message); } $lines = preg_split('/$\R?^/m', (string) $message, -1, PREG_SPLIT_NO_EMPTY); if (false === $lines) { $pcreErrorCode = preg_last_error(); throw new \RuntimeException('Could not preg_split: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode)); } return $lines; } /** * Make common syslog header (see rfc5424 or rfc3164) */ protected function makeCommonSyslogHeader(int $severity, DateTimeInterface $datetime): string { $priority = $severity + $this->facility; if (!$pid = getmypid()) { $pid = '-'; } if (!$hostname = gethostname()) { $hostname = '-'; } if ($this->rfc === self::RFC3164) { // see https://github.com/phpstan/phpstan/issues/5348 // @phpstan-ignore-next-line $dateNew = $datetime->setTimezone(new \DateTimeZone('UTC')); $date = $dateNew->format($this->dateFormats[$this->rfc]); return "<$priority>" . $date . " " . $hostname . " " . $this->ident . "[" . $pid . "]: "; } $date = $datetime->format($this->dateFormats[$this->rfc]); return "<$priority>1 " . $date . " " . $hostname . " " . $this->ident . " " . $pid . " - - "; } /** * Inject your own socket, mainly used for testing */ public function setSocket(UdpSocket $socket): self { $this->socket = $socket; return $this; } } PK������\5ZbT,J��J��!��Monolog/Handler/StreamHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Utils; /** * Stores to any stream resource * * Can be used to store into php://stderr, remote and local files, etc. * * @author Jordi Boggiano <j.boggiano@seld.be> * * @phpstan-import-type FormattedRecord from AbstractProcessingHandler */ class StreamHandler extends AbstractProcessingHandler { /** @const int */ protected const MAX_CHUNK_SIZE = 2147483647; /** @const int 10MB */ protected const DEFAULT_CHUNK_SIZE = 10 * 1024 * 1024; /** @var int */ protected $streamChunkSize; /** @var resource|null */ protected $stream; /** @var ?string */ protected $url = null; /** @var ?string */ private $errorMessage = null; /** @var ?int */ protected $filePermission; /** @var bool */ protected $useLocking; /** @var true|null */ private $dirCreated = null; /** * @param resource|string $stream If a missing path can't be created, an UnexpectedValueException will be thrown on first write * @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write) * @param bool $useLocking Try to lock log file before doing any writes * * @throws \InvalidArgumentException If stream is not a resource or string */ public function __construct($stream, $level = Logger::DEBUG, bool $bubble = true, ?int $filePermission = null, bool $useLocking = false) { parent::__construct($level, $bubble); if (($phpMemoryLimit = Utils::expandIniShorthandBytes(ini_get('memory_limit'))) !== false) { if ($phpMemoryLimit > 0) { // use max 10% of allowed memory for the chunk size, and at least 100KB $this->streamChunkSize = min(static::MAX_CHUNK_SIZE, max((int) ($phpMemoryLimit / 10), 100 * 1024)); } else { // memory is unlimited, set to the default 10MB $this->streamChunkSize = static::DEFAULT_CHUNK_SIZE; } } else { // no memory limit information, set to the default 10MB $this->streamChunkSize = static::DEFAULT_CHUNK_SIZE; } if (is_resource($stream)) { $this->stream = $stream; stream_set_chunk_size($this->stream, $this->streamChunkSize); } elseif (is_string($stream)) { $this->url = Utils::canonicalizePath($stream); } else { throw new \InvalidArgumentException('A stream must either be a resource or a string.'); } $this->filePermission = $filePermission; $this->useLocking = $useLocking; } /** * {@inheritDoc} */ public function close(): void { if ($this->url && is_resource($this->stream)) { fclose($this->stream); } $this->stream = null; $this->dirCreated = null; } /** * Return the currently active stream if it is open * * @return resource|null */ public function getStream() { return $this->stream; } /** * Return the stream URL if it was configured with a URL and not an active resource * * @return string|null */ public function getUrl(): ?string { return $this->url; } /** * @return int */ public function getStreamChunkSize(): int { return $this->streamChunkSize; } /** * {@inheritDoc} */ protected function write(array $record): void { if (!is_resource($this->stream)) { $url = $this->url; if (null === $url || '' === $url) { throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().' . Utils::getRecordMessageForException($record)); } $this->createDir($url); $this->errorMessage = null; set_error_handler([$this, 'customErrorHandler']); $stream = fopen($url, 'a'); if ($this->filePermission !== null) { @chmod($url, $this->filePermission); } restore_error_handler(); if (!is_resource($stream)) { $this->stream = null; throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened in append mode: '.$this->errorMessage, $url) . Utils::getRecordMessageForException($record)); } stream_set_chunk_size($stream, $this->streamChunkSize); $this->stream = $stream; } $stream = $this->stream; if (!is_resource($stream)) { throw new \LogicException('No stream was opened yet' . Utils::getRecordMessageForException($record)); } if ($this->useLocking) { // ignoring errors here, there's not much we can do about them flock($stream, LOCK_EX); } $this->streamWrite($stream, $record); if ($this->useLocking) { flock($stream, LOCK_UN); } } /** * Write to stream * @param resource $stream * @param array $record * * @phpstan-param FormattedRecord $record */ protected function streamWrite($stream, array $record): void { fwrite($stream, (string) $record['formatted']); } private function customErrorHandler(int $code, string $msg): bool { $this->errorMessage = preg_replace('{^(fopen|mkdir)\(.*?\): }', '', $msg); return true; } private function getDirFromStream(string $stream): ?string { $pos = strpos($stream, '://'); if ($pos === false) { return dirname($stream); } if ('file://' === substr($stream, 0, 7)) { return dirname(substr($stream, 7)); } return null; } private function createDir(string $url): void { // Do not try to create dir if it has already been tried. if ($this->dirCreated) { return; } $dir = $this->getDirFromStream($url); if (null !== $dir && !is_dir($dir)) { $this->errorMessage = null; set_error_handler([$this, 'customErrorHandler']); $status = mkdir($dir, 0777, true); restore_error_handler(); if (false === $status && !is_dir($dir) && strpos((string) $this->errorMessage, 'File exists') === false) { throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s" and it could not be created: '.$this->errorMessage, $dir)); } } $this->dirCreated = true; } } PK������\5ZIk9��9����Monolog/Handler/NullHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Psr\Log\LogLevel; /** * Blackhole * * Any record it can handle will be thrown away. This can be used * to put on top of an existing stack to override it temporarily. * * @author Jordi Boggiano <j.boggiano@seld.be> * * @phpstan-import-type Level from \Monolog\Logger * @phpstan-import-type LevelName from \Monolog\Logger */ class NullHandler extends Handler { /** * @var int */ private $level; /** * @param string|int $level The minimum logging level at which this handler will be triggered * * @phpstan-param Level|LevelName|LogLevel::* $level */ public function __construct($level = Logger::DEBUG) { $this->level = Logger::toMonologLevel($level); } /** * {@inheritDoc} */ public function isHandling(array $record): bool { return $record['level'] >= $this->level; } /** * {@inheritDoc} */ public function handle(array $record): bool { return $record['level'] >= $this->level; } } PK������\5Z=A ��A ��&��Monolog/Handler/ZendMonitorHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\NormalizerFormatter; use Monolog\Logger; /** * Handler sending logs to Zend Monitor * * @author Christian Bergau <cbergau86@gmail.com> * @author Jason Davis <happydude@jasondavis.net> * * @phpstan-import-type FormattedRecord from AbstractProcessingHandler */ class ZendMonitorHandler extends AbstractProcessingHandler { /** * Monolog level / ZendMonitor Custom Event priority map * * @var array<int, int> */ protected $levelMap = []; /** * @throws MissingExtensionException */ public function __construct($level = Logger::DEBUG, bool $bubble = true) { if (!function_exists('zend_monitor_custom_event')) { throw new MissingExtensionException( 'You must have Zend Server installed with Zend Monitor enabled in order to use this handler' ); } //zend monitor constants are not defined if zend monitor is not enabled. $this->levelMap = [ Logger::DEBUG => \ZEND_MONITOR_EVENT_SEVERITY_INFO, Logger::INFO => \ZEND_MONITOR_EVENT_SEVERITY_INFO, Logger::NOTICE => \ZEND_MONITOR_EVENT_SEVERITY_INFO, Logger::WARNING => \ZEND_MONITOR_EVENT_SEVERITY_WARNING, Logger::ERROR => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, Logger::CRITICAL => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, Logger::ALERT => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, Logger::EMERGENCY => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, ]; parent::__construct($level, $bubble); } /** * {@inheritDoc} */ protected function write(array $record): void { $this->writeZendMonitorCustomEvent( Logger::getLevelName($record['level']), $record['message'], $record['formatted'], $this->levelMap[$record['level']] ); } /** * Write to Zend Monitor Events * @param string $type Text displayed in "Class Name (custom)" field * @param string $message Text displayed in "Error String" * @param array $formatted Displayed in Custom Variables tab * @param int $severity Set the event severity level (-1,0,1) * * @phpstan-param FormattedRecord $formatted */ protected function writeZendMonitorCustomEvent(string $type, string $message, array $formatted, int $severity): void { zend_monitor_custom_event($type, $message, $formatted, $severity); } /** * {@inheritDoc} */ public function getDefaultFormatter(): FormatterInterface { return new NormalizerFormatter(); } /** * @return array<int, int> */ public function getLevelMap(): array { return $this->levelMap; } } PK������\5ZZ����+��Monolog/Handler/ProcessableHandlerTrait.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\ResettableInterface; use Monolog\Processor\ProcessorInterface; /** * Helper trait for implementing ProcessableInterface * * @author Jordi Boggiano <j.boggiano@seld.be> * * @phpstan-import-type Record from \Monolog\Logger */ trait ProcessableHandlerTrait { /** * @var callable[] * @phpstan-var array<ProcessorInterface|callable(Record): Record> */ protected $processors = []; /** * {@inheritDoc} */ public function pushProcessor(callable $callback): HandlerInterface { array_unshift($this->processors, $callback); return $this; } /** * {@inheritDoc} */ public function popProcessor(): callable { if (!$this->processors) { throw new \LogicException('You tried to pop from an empty processor stack.'); } return array_shift($this->processors); } /** * Processes a record. * * @phpstan-param Record $record * @phpstan-return Record */ protected function processRecord(array $record): array { foreach ($this->processors as $processor) { $record = $processor($record); } return $record; } protected function resetProcessors(): void { foreach ($this->processors as $processor) { if ($processor instanceof ResettableInterface) { $processor->reset(); } } } } PK������\5ZDi$h����(��Monolog/Handler/DeduplicationHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Psr\Log\LogLevel; /** * Simple handler wrapper that deduplicates log records across multiple requests * * It also includes the BufferHandler functionality and will buffer * all messages until the end of the request or flush() is called. * * This works by storing all log records' messages above $deduplicationLevel * to the file specified by $deduplicationStore. When further logs come in at the end of the * request (or when flush() is called), all those above $deduplicationLevel are checked * against the existing stored logs. If they match and the timestamps in the stored log is * not older than $time seconds, the new log record is discarded. If no log record is new, the * whole data set is discarded. * * This is mainly useful in combination with Mail handlers or things like Slack or HipChat handlers * that send messages to people, to avoid spamming with the same message over and over in case of * a major component failure like a database server being down which makes all requests fail in the * same way. * * @author Jordi Boggiano <j.boggiano@seld.be> * * @phpstan-import-type Record from \Monolog\Logger * @phpstan-import-type LevelName from \Monolog\Logger * @phpstan-import-type Level from \Monolog\Logger */ class DeduplicationHandler extends BufferHandler { /** * @var string */ protected $deduplicationStore; /** * @var Level */ protected $deduplicationLevel; /** * @var int */ protected $time; /** * @var bool */ private $gc = false; /** * @param HandlerInterface $handler Handler. * @param string $deduplicationStore The file/path where the deduplication log should be kept * @param string|int $deduplicationLevel The minimum logging level for log records to be looked at for deduplication purposes * @param int $time The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through * @param bool $bubble Whether the messages that are handled can bubble up the stack or not * * @phpstan-param Level|LevelName|LogLevel::* $deduplicationLevel */ public function __construct(HandlerInterface $handler, ?string $deduplicationStore = null, $deduplicationLevel = Logger::ERROR, int $time = 60, bool $bubble = true) { parent::__construct($handler, 0, Logger::DEBUG, $bubble, false); $this->deduplicationStore = $deduplicationStore === null ? sys_get_temp_dir() . '/monolog-dedup-' . substr(md5(__FILE__), 0, 20) .'.log' : $deduplicationStore; $this->deduplicationLevel = Logger::toMonologLevel($deduplicationLevel); $this->time = $time; } public function flush(): void { if ($this->bufferSize === 0) { return; } $passthru = null; foreach ($this->buffer as $record) { if ($record['level'] >= $this->deduplicationLevel) { $passthru = $passthru || !$this->isDuplicate($record); if ($passthru) { $this->appendRecord($record); } } } // default of null is valid as well as if no record matches duplicationLevel we just pass through if ($passthru === true || $passthru === null) { $this->handler->handleBatch($this->buffer); } $this->clear(); if ($this->gc) { $this->collectLogs(); } } /** * @phpstan-param Record $record */ private function isDuplicate(array $record): bool { if (!file_exists($this->deduplicationStore)) { return false; } $store = file($this->deduplicationStore, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); if (!is_array($store)) { return false; } $yesterday = time() - 86400; $timestampValidity = $record['datetime']->getTimestamp() - $this->time; $expectedMessage = preg_replace('{[\r\n].*}', '', $record['message']); for ($i = count($store) - 1; $i >= 0; $i--) { list($timestamp, $level, $message) = explode(':', $store[$i], 3); if ($level === $record['level_name'] && $message === $expectedMessage && $timestamp > $timestampValidity) { return true; } if ($timestamp < $yesterday) { $this->gc = true; } } return false; } private function collectLogs(): void { if (!file_exists($this->deduplicationStore)) { return; } $handle = fopen($this->deduplicationStore, 'rw+'); if (!$handle) { throw new \RuntimeException('Failed to open file for reading and writing: ' . $this->deduplicationStore); } flock($handle, LOCK_EX); $validLogs = []; $timestampValidity = time() - $this->time; while (!feof($handle)) { $log = fgets($handle); if ($log && substr($log, 0, 10) >= $timestampValidity) { $validLogs[] = $log; } } ftruncate($handle, 0); rewind($handle); foreach ($validLogs as $log) { fwrite($handle, $log); } flock($handle, LOCK_UN); fclose($handle); $this->gc = false; } /** * @phpstan-param Record $record */ private function appendRecord(array $record): void { file_put_contents($this->deduplicationStore, $record['datetime']->getTimestamp() . ':' . $record['level_name'] . ':' . preg_replace('{[\r\n].*}', '', $record['message']) . "\n", FILE_APPEND); } } PK������\5ZfTo��o��(��Monolog/Handler/ElasticsearchHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Elastic\Elasticsearch\Response\Elasticsearch; use Throwable; use RuntimeException; use Monolog\Logger; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\ElasticsearchFormatter; use InvalidArgumentException; use Elasticsearch\Common\Exceptions\RuntimeException as ElasticsearchRuntimeException; use Elasticsearch\Client; use Elastic\Elasticsearch\Exception\InvalidArgumentException as ElasticInvalidArgumentException; use Elastic\Elasticsearch\Client as Client8; /** * Elasticsearch handler * * @link https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/index.html * * Simple usage example: * * $client = \Elasticsearch\ClientBuilder::create() * ->setHosts($hosts) * ->build(); * * $options = array( * 'index' => 'elastic_index_name', * 'type' => 'elastic_doc_type', * ); * $handler = new ElasticsearchHandler($client, $options); * $log = new Logger('application'); * $log->pushHandler($handler); * * @author Avtandil Kikabidze <akalongman@gmail.com> */ class ElasticsearchHandler extends AbstractProcessingHandler { /** * @var Client|Client8 */ protected $client; /** * @var mixed[] Handler config options */ protected $options = []; /** * @var bool */ private $needsType; /** * @param Client|Client8 $client Elasticsearch Client object * @param mixed[] $options Handler configuration */ public function __construct($client, array $options = [], $level = Logger::DEBUG, bool $bubble = true) { if (!$client instanceof Client && !$client instanceof Client8) { throw new \TypeError('Elasticsearch\Client or Elastic\Elasticsearch\Client instance required'); } parent::__construct($level, $bubble); $this->client = $client; $this->options = array_merge( [ 'index' => 'monolog', // Elastic index name 'type' => '_doc', // Elastic document type 'ignore_error' => false, // Suppress Elasticsearch exceptions ], $options ); if ($client instanceof Client8 || $client::VERSION[0] === '7') { $this->needsType = false; // force the type to _doc for ES8/ES7 $this->options['type'] = '_doc'; } else { $this->needsType = true; } } /** * {@inheritDoc} */ protected function write(array $record): void { $this->bulkSend([$record['formatted']]); } /** * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { if ($formatter instanceof ElasticsearchFormatter) { return parent::setFormatter($formatter); } throw new InvalidArgumentException('ElasticsearchHandler is only compatible with ElasticsearchFormatter'); } /** * Getter options * * @return mixed[] */ public function getOptions(): array { return $this->options; } /** * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { return new ElasticsearchFormatter($this->options['index'], $this->options['type']); } /** * {@inheritDoc} */ public function handleBatch(array $records): void { $documents = $this->getFormatter()->formatBatch($records); $this->bulkSend($documents); } /** * Use Elasticsearch bulk API to send list of documents * * @param array[] $records Records + _index/_type keys * @throws \RuntimeException */ protected function bulkSend(array $records): void { try { $params = [ 'body' => [], ]; foreach ($records as $record) { $params['body'][] = [ 'index' => $this->needsType ? [ '_index' => $record['_index'], '_type' => $record['_type'], ] : [ '_index' => $record['_index'], ], ]; unset($record['_index'], $record['_type']); $params['body'][] = $record; } /** @var Elasticsearch */ $responses = $this->client->bulk($params); if ($responses['errors'] === true) { throw $this->createExceptionFromResponses($responses); } } catch (Throwable $e) { if (! $this->options['ignore_error']) { throw new RuntimeException('Error sending messages to Elasticsearch', 0, $e); } } } /** * Creates elasticsearch exception from responses array * * Only the first error is converted into an exception. * * @param mixed[]|Elasticsearch $responses returned by $this->client->bulk() */ protected function createExceptionFromResponses($responses): Throwable { foreach ($responses['items'] ?? [] as $item) { if (isset($item['index']['error'])) { return $this->createExceptionFromError($item['index']['error']); } } if (class_exists(ElasticInvalidArgumentException::class)) { return new ElasticInvalidArgumentException('Elasticsearch failed to index one or more records.'); } return new ElasticsearchRuntimeException('Elasticsearch failed to index one or more records.'); } /** * Creates elasticsearch exception from error array * * @param mixed[] $error */ protected function createExceptionFromError(array $error): Throwable { $previous = isset($error['caused_by']) ? $this->createExceptionFromError($error['caused_by']) : null; if (class_exists(ElasticInvalidArgumentException::class)) { return new ElasticInvalidArgumentException($error['type'] . ': ' . $error['reason'], 0, $previous); } return new ElasticsearchRuntimeException($error['type'] . ': ' . $error['reason'], 0, $previous); } } PK������\5Z������Monolog/Handler/AmqpHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\JsonFormatter; use PhpAmqpLib\Message\AMQPMessage; use PhpAmqpLib\Channel\AMQPChannel; use AMQPExchange; /** * @phpstan-import-type Record from \Monolog\Logger */ class AmqpHandler extends AbstractProcessingHandler { /** * @var AMQPExchange|AMQPChannel $exchange */ protected $exchange; /** @var array<string, mixed> */ private $extraAttributes = []; /** * @return array<string, mixed> */ public function getExtraAttributes(): array { return $this->extraAttributes; } /** * Configure extra attributes to pass to the AMQPExchange (if you are using the amqp extension) * * @param array<string, mixed> $extraAttributes One of content_type, content_encoding, * message_id, user_id, app_id, delivery_mode, * priority, timestamp, expiration, type * or reply_to, headers. * @return AmqpHandler */ public function setExtraAttributes(array $extraAttributes): self { $this->extraAttributes = $extraAttributes; return $this; } /** * @var string */ protected $exchangeName; /** * @param AMQPExchange|AMQPChannel $exchange AMQPExchange (php AMQP ext) or PHP AMQP lib channel, ready for use * @param string|null $exchangeName Optional exchange name, for AMQPChannel (PhpAmqpLib) only */ public function __construct($exchange, ?string $exchangeName = null, $level = Logger::DEBUG, bool $bubble = true) { if ($exchange instanceof AMQPChannel) { $this->exchangeName = (string) $exchangeName; } elseif (!$exchange instanceof AMQPExchange) { throw new \InvalidArgumentException('PhpAmqpLib\Channel\AMQPChannel or AMQPExchange instance required'); } elseif ($exchangeName) { @trigger_error('The $exchangeName parameter can only be passed when using PhpAmqpLib, if using an AMQPExchange instance configure it beforehand', E_USER_DEPRECATED); } $this->exchange = $exchange; parent::__construct($level, $bubble); } /** * {@inheritDoc} */ protected function write(array $record): void { $data = $record["formatted"]; $routingKey = $this->getRoutingKey($record); if ($this->exchange instanceof AMQPExchange) { $attributes = [ 'delivery_mode' => 2, 'content_type' => 'application/json', ]; if ($this->extraAttributes) { $attributes = array_merge($attributes, $this->extraAttributes); } $this->exchange->publish( $data, $routingKey, 0, $attributes ); } else { $this->exchange->basic_publish( $this->createAmqpMessage($data), $this->exchangeName, $routingKey ); } } /** * {@inheritDoc} */ public function handleBatch(array $records): void { if ($this->exchange instanceof AMQPExchange) { parent::handleBatch($records); return; } foreach ($records as $record) { if (!$this->isHandling($record)) { continue; } /** @var Record $record */ $record = $this->processRecord($record); $data = $this->getFormatter()->format($record); $this->exchange->batch_basic_publish( $this->createAmqpMessage($data), $this->exchangeName, $this->getRoutingKey($record) ); } $this->exchange->publish_batch(); } /** * Gets the routing key for the AMQP exchange * * @phpstan-param Record $record */ protected function getRoutingKey(array $record): string { $routingKey = sprintf('%s.%s', $record['level_name'], $record['channel']); return strtolower($routingKey); } private function createAmqpMessage(string $data): AMQPMessage { $attributes = [ 'delivery_mode' => 2, 'content_type' => 'application/json', ]; if ($this->extraAttributes) { $attributes = array_merge($attributes, $this->extraAttributes); } return new AMQPMessage($data, $attributes); } /** * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false); } } PK������\5Zhp��p����Monolog/Handler/NoopHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; /** * No-op * * This handler handles anything, but does nothing, and does not stop bubbling to the rest of the stack. * This can be used for testing, or to disable a handler when overriding a configuration without * influencing the rest of the stack. * * @author Roel Harbers <roelharbers@gmail.com> */ class NoopHandler extends Handler { /** * {@inheritDoc} */ public function isHandling(array $record): bool { return true; } /** * {@inheritDoc} */ public function handle(array $record): bool { return false; } } PK������\5Z+� ��� ��#��Monolog/Handler/ElasticaHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Elastica\Document; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\ElasticaFormatter; use Monolog\Logger; use Elastica\Client; use Elastica\Exception\ExceptionInterface; /** * Elastic Search handler * * Usage example: * * $client = new \Elastica\Client(); * $options = array( * 'index' => 'elastic_index_name', * 'type' => 'elastic_doc_type', Types have been removed in Elastica 7 * ); * $handler = new ElasticaHandler($client, $options); * $log = new Logger('application'); * $log->pushHandler($handler); * * @author Jelle Vink <jelle.vink@gmail.com> */ class ElasticaHandler extends AbstractProcessingHandler { /** * @var Client */ protected $client; /** * @var mixed[] Handler config options */ protected $options = []; /** * @param Client $client Elastica Client object * @param mixed[] $options Handler configuration */ public function __construct(Client $client, array $options = [], $level = Logger::DEBUG, bool $bubble = true) { parent::__construct($level, $bubble); $this->client = $client; $this->options = array_merge( [ 'index' => 'monolog', // Elastic index name 'type' => 'record', // Elastic document type 'ignore_error' => false, // Suppress Elastica exceptions ], $options ); } /** * {@inheritDoc} */ protected function write(array $record): void { $this->bulkSend([$record['formatted']]); } /** * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { if ($formatter instanceof ElasticaFormatter) { return parent::setFormatter($formatter); } throw new \InvalidArgumentException('ElasticaHandler is only compatible with ElasticaFormatter'); } /** * @return mixed[] */ public function getOptions(): array { return $this->options; } /** * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { return new ElasticaFormatter($this->options['index'], $this->options['type']); } /** * {@inheritDoc} */ public function handleBatch(array $records): void { $documents = $this->getFormatter()->formatBatch($records); $this->bulkSend($documents); } /** * Use Elasticsearch bulk API to send list of documents * * @param Document[] $documents * * @throws \RuntimeException */ protected function bulkSend(array $documents): void { try { $this->client->addDocuments($documents); } catch (ExceptionInterface $e) { if (!$this->options['ignore_error']) { throw new \RuntimeException("Error sending messages to Elasticsearch", 0, $e); } } } } PK������\5ZG� �� �� ��Monolog/Handler/RedisHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\LineFormatter; use Monolog\Formatter\FormatterInterface; use Monolog\Logger; /** * Logs to a Redis key using rpush * * usage example: * * $log = new Logger('application'); * $redis = new RedisHandler(new Predis\Client("tcp://localhost:6379"), "logs", "prod"); * $log->pushHandler($redis); * * @author Thomas Tourlourat <thomas@tourlourat.com> * * @phpstan-import-type FormattedRecord from AbstractProcessingHandler */ class RedisHandler extends AbstractProcessingHandler { /** @var \Predis\Client<\Predis\Client>|\Redis */ private $redisClient; /** @var string */ private $redisKey; /** @var int */ protected $capSize; /** * @param \Predis\Client<\Predis\Client>|\Redis $redis The redis instance * @param string $key The key name to push records to * @param int $capSize Number of entries to limit list size to, 0 = unlimited */ public function __construct($redis, string $key, $level = Logger::DEBUG, bool $bubble = true, int $capSize = 0) { if (!(($redis instanceof \Predis\Client) || ($redis instanceof \Redis))) { throw new \InvalidArgumentException('Predis\Client or Redis instance required'); } $this->redisClient = $redis; $this->redisKey = $key; $this->capSize = $capSize; parent::__construct($level, $bubble); } /** * {@inheritDoc} */ protected function write(array $record): void { if ($this->capSize) { $this->writeCapped($record); } else { $this->redisClient->rpush($this->redisKey, $record["formatted"]); } } /** * Write and cap the collection * Writes the record to the redis list and caps its * * @phpstan-param FormattedRecord $record */ protected function writeCapped(array $record): void { if ($this->redisClient instanceof \Redis) { $mode = defined('\Redis::MULTI') ? \Redis::MULTI : 1; $this->redisClient->multi($mode) ->rpush($this->redisKey, $record["formatted"]) ->ltrim($this->redisKey, -$this->capSize, -1) ->exec(); } else { $redisKey = $this->redisKey; $capSize = $this->capSize; $this->redisClient->transaction(function ($tx) use ($record, $redisKey, $capSize) { $tx->rpush($redisKey, $record["formatted"]); $tx->ltrim($redisKey, -$capSize, -1); }); } } /** * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { return new LineFormatter(); } } PK������\5Zmz��z��-��Monolog/Handler/AbstractProcessingHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; /** * Base Handler class providing the Handler structure, including processors and formatters * * Classes extending it should (in most cases) only implement write($record) * * @author Jordi Boggiano <j.boggiano@seld.be> * @author Christophe Coevoet <stof@notk.org> * * @phpstan-import-type LevelName from \Monolog\Logger * @phpstan-import-type Level from \Monolog\Logger * @phpstan-import-type Record from \Monolog\Logger * @phpstan-type FormattedRecord array{message: string, context: mixed[], level: Level, level_name: LevelName, channel: string, datetime: \DateTimeImmutable, extra: mixed[], formatted: mixed} */ abstract class AbstractProcessingHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface { use ProcessableHandlerTrait; use FormattableHandlerTrait; /** * {@inheritDoc} */ public function handle(array $record): bool { if (!$this->isHandling($record)) { return false; } if ($this->processors) { /** @var Record $record */ $record = $this->processRecord($record); } $record['formatted'] = $this->getFormatter()->format($record); $this->write($record); return false === $this->bubble; } /** * Writes the record down to the log of the implementing handler * * @phpstan-param FormattedRecord $record */ abstract protected function write(array $record): void; /** * @return void */ public function reset() { parent::reset(); $this->resetProcessors(); } } PK������\5Z$sM7 ��7 ��#��Monolog/Handler/SendGridHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * SendGridrHandler uses the SendGrid API v2 function to send Log emails, more information in https://sendgrid.com/docs/API_Reference/Web_API/mail.html * * @author Ricardo Fontanelli <ricardo.fontanelli@hotmail.com> */ class SendGridHandler extends MailHandler { /** * The SendGrid API User * @var string */ protected $apiUser; /** * The SendGrid API Key * @var string */ protected $apiKey; /** * The email addresses to which the message will be sent * @var string */ protected $from; /** * The email addresses to which the message will be sent * @var string[] */ protected $to; /** * The subject of the email * @var string */ protected $subject; /** * @param string $apiUser The SendGrid API User * @param string $apiKey The SendGrid API Key * @param string $from The sender of the email * @param string|string[] $to The recipients of the email * @param string $subject The subject of the mail */ public function __construct(string $apiUser, string $apiKey, string $from, $to, string $subject, $level = Logger::ERROR, bool $bubble = true) { if (!extension_loaded('curl')) { throw new MissingExtensionException('The curl extension is needed to use the SendGridHandler'); } parent::__construct($level, $bubble); $this->apiUser = $apiUser; $this->apiKey = $apiKey; $this->from = $from; $this->to = (array) $to; $this->subject = $subject; } /** * {@inheritDoc} */ protected function send(string $content, array $records): void { $message = []; $message['api_user'] = $this->apiUser; $message['api_key'] = $this->apiKey; $message['from'] = $this->from; foreach ($this->to as $recipient) { $message['to[]'] = $recipient; } $message['subject'] = $this->subject; $message['date'] = date('r'); if ($this->isHtmlBody($content)) { $message['html'] = $content; } else { $message['text'] = $content; } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://api.sendgrid.com/api/mail.send.json'); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($message)); Curl\Util::execute($ch, 2); } } PK������\5Z#����!��Monolog/Handler/FilterHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\ResettableInterface; use Monolog\Formatter\FormatterInterface; use Psr\Log\LogLevel; /** * Simple handler wrapper that filters records based on a list of levels * * It can be configured with an exact list of levels to allow, or a min/max level. * * @author Hennadiy Verkh * @author Jordi Boggiano <j.boggiano@seld.be> * * @phpstan-import-type Record from \Monolog\Logger * @phpstan-import-type Level from \Monolog\Logger * @phpstan-import-type LevelName from \Monolog\Logger */ class FilterHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface, FormattableHandlerInterface { use ProcessableHandlerTrait; /** * Handler or factory callable($record, $this) * * @var callable|HandlerInterface * @phpstan-var callable(?Record, HandlerInterface): HandlerInterface|HandlerInterface */ protected $handler; /** * Minimum level for logs that are passed to handler * * @var int[] * @phpstan-var array<Level, int> */ protected $acceptedLevels; /** * Whether the messages that are handled can bubble up the stack or not * * @var bool */ protected $bubble; /** * @psalm-param HandlerInterface|callable(?Record, HandlerInterface): HandlerInterface $handler * * @param callable|HandlerInterface $handler Handler or factory callable($record|null, $filterHandler). * @param int|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided * @param int|string $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array * @param bool $bubble Whether the messages that are handled can bubble up the stack or not * * @phpstan-param Level|LevelName|LogLevel::*|array<Level|LevelName|LogLevel::*> $minLevelOrList * @phpstan-param Level|LevelName|LogLevel::* $maxLevel */ public function __construct($handler, $minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY, bool $bubble = true) { $this->handler = $handler; $this->bubble = $bubble; $this->setAcceptedLevels($minLevelOrList, $maxLevel); if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) { throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object"); } } /** * @phpstan-return array<int, Level> */ public function getAcceptedLevels(): array { return array_flip($this->acceptedLevels); } /** * @param int|string|array $minLevelOrList A list of levels to accept or a minimum level or level name if maxLevel is provided * @param int|string $maxLevel Maximum level or level name to accept, only used if $minLevelOrList is not an array * * @phpstan-param Level|LevelName|LogLevel::*|array<Level|LevelName|LogLevel::*> $minLevelOrList * @phpstan-param Level|LevelName|LogLevel::* $maxLevel */ public function setAcceptedLevels($minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY): self { if (is_array($minLevelOrList)) { $acceptedLevels = array_map('Monolog\Logger::toMonologLevel', $minLevelOrList); } else { $minLevelOrList = Logger::toMonologLevel($minLevelOrList); $maxLevel = Logger::toMonologLevel($maxLevel); $acceptedLevels = array_values(array_filter(Logger::getLevels(), function ($level) use ($minLevelOrList, $maxLevel) { return $level >= $minLevelOrList && $level <= $maxLevel; })); } $this->acceptedLevels = array_flip($acceptedLevels); return $this; } /** * {@inheritDoc} */ public function isHandling(array $record): bool { return isset($this->acceptedLevels[$record['level']]); } /** * {@inheritDoc} */ public function handle(array $record): bool { if (!$this->isHandling($record)) { return false; } if ($this->processors) { /** @var Record $record */ $record = $this->processRecord($record); } $this->getHandler($record)->handle($record); return false === $this->bubble; } /** * {@inheritDoc} */ public function handleBatch(array $records): void { $filtered = []; foreach ($records as $record) { if ($this->isHandling($record)) { $filtered[] = $record; } } if (count($filtered) > 0) { $this->getHandler($filtered[count($filtered) - 1])->handleBatch($filtered); } } /** * Return the nested handler * * If the handler was provided as a factory callable, this will trigger the handler's instantiation. * * @return HandlerInterface * * @phpstan-param Record $record */ public function getHandler(array $record = null) { if (!$this->handler instanceof HandlerInterface) { $this->handler = ($this->handler)($record, $this); if (!$this->handler instanceof HandlerInterface) { throw new \RuntimeException("The factory callable should return a HandlerInterface"); } } return $this->handler; } /** * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { $handler = $this->getHandler(); if ($handler instanceof FormattableHandlerInterface) { $handler->setFormatter($formatter); return $this; } throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.'); } /** * {@inheritDoc} */ public function getFormatter(): FormatterInterface { $handler = $this->getHandler(); if ($handler instanceof FormattableHandlerInterface) { return $handler->getFormatter(); } throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.'); } public function reset() { $this->resetProcessors(); if ($this->getHandler() instanceof ResettableInterface) { $this->getHandler()->reset(); } } } PK������\5Zex������Monolog/Handler/CubeHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Utils; /** * Logs to Cube. * * @link https://github.com/square/cube/wiki * @author Wan Chen <kami@kamisama.me> * @deprecated Since 2.8.0 and 3.2.0, Cube appears abandoned and thus we will drop this handler in Monolog 4 */ class CubeHandler extends AbstractProcessingHandler { /** @var resource|\Socket|null */ private $udpConnection = null; /** @var resource|\CurlHandle|null */ private $httpConnection = null; /** @var string */ private $scheme; /** @var string */ private $host; /** @var int */ private $port; /** @var string[] */ private $acceptedSchemes = ['http', 'udp']; /** * Create a Cube handler * * @throws \UnexpectedValueException when given url is not a valid url. * A valid url must consist of three parts : protocol://host:port * Only valid protocols used by Cube are http and udp */ public function __construct(string $url, $level = Logger::DEBUG, bool $bubble = true) { $urlInfo = parse_url($url); if ($urlInfo === false || !isset($urlInfo['scheme'], $urlInfo['host'], $urlInfo['port'])) { throw new \UnexpectedValueException('URL "'.$url.'" is not valid'); } if (!in_array($urlInfo['scheme'], $this->acceptedSchemes)) { throw new \UnexpectedValueException( 'Invalid protocol (' . $urlInfo['scheme'] . ').' . ' Valid options are ' . implode(', ', $this->acceptedSchemes) ); } $this->scheme = $urlInfo['scheme']; $this->host = $urlInfo['host']; $this->port = (int) $urlInfo['port']; parent::__construct($level, $bubble); } /** * Establish a connection to an UDP socket * * @throws \LogicException when unable to connect to the socket * @throws MissingExtensionException when there is no socket extension */ protected function connectUdp(): void { if (!extension_loaded('sockets')) { throw new MissingExtensionException('The sockets extension is required to use udp URLs with the CubeHandler'); } $udpConnection = socket_create(AF_INET, SOCK_DGRAM, 0); if (false === $udpConnection) { throw new \LogicException('Unable to create a socket'); } $this->udpConnection = $udpConnection; if (!socket_connect($this->udpConnection, $this->host, $this->port)) { throw new \LogicException('Unable to connect to the socket at ' . $this->host . ':' . $this->port); } } /** * Establish a connection to an http server * * @throws \LogicException when unable to connect to the socket * @throws MissingExtensionException when no curl extension */ protected function connectHttp(): void { if (!extension_loaded('curl')) { throw new MissingExtensionException('The curl extension is required to use http URLs with the CubeHandler'); } $httpConnection = curl_init('http://'.$this->host.':'.$this->port.'/1.0/event/put'); if (false === $httpConnection) { throw new \LogicException('Unable to connect to ' . $this->host . ':' . $this->port); } $this->httpConnection = $httpConnection; curl_setopt($this->httpConnection, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($this->httpConnection, CURLOPT_RETURNTRANSFER, true); } /** * {@inheritDoc} */ protected function write(array $record): void { $date = $record['datetime']; $data = ['time' => $date->format('Y-m-d\TH:i:s.uO')]; unset($record['datetime']); if (isset($record['context']['type'])) { $data['type'] = $record['context']['type']; unset($record['context']['type']); } else { $data['type'] = $record['channel']; } $data['data'] = $record['context']; $data['data']['level'] = $record['level']; if ($this->scheme === 'http') { $this->writeHttp(Utils::jsonEncode($data)); } else { $this->writeUdp(Utils::jsonEncode($data)); } } private function writeUdp(string $data): void { if (!$this->udpConnection) { $this->connectUdp(); } socket_send($this->udpConnection, $data, strlen($data), 0); } private function writeHttp(string $data): void { if (!$this->httpConnection) { $this->connectHttp(); } if (null === $this->httpConnection) { throw new \LogicException('No connection could be established'); } curl_setopt($this->httpConnection, CURLOPT_POSTFIELDS, '['.$data.']'); curl_setopt($this->httpConnection, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', 'Content-Length: ' . strlen('['.$data.']'), ]); Curl\Util::execute($this->httpConnection, 5, false); } } PK������\5Z g����%��Monolog/Handler/LogEntriesHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * @author Robert Kaufmann III <rok3@rok3.me> */ class LogEntriesHandler extends SocketHandler { /** * @var string */ protected $logToken; /** * @param string $token Log token supplied by LogEntries * @param bool $useSSL Whether or not SSL encryption should be used. * @param string $host Custom hostname to send the data to if needed * * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing */ public function __construct( string $token, bool $useSSL = true, $level = Logger::DEBUG, bool $bubble = true, string $host = 'data.logentries.com', bool $persistent = false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null ) { if ($useSSL && !extension_loaded('openssl')) { throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for LogEntriesHandler'); } $endpoint = $useSSL ? 'ssl://' . $host . ':443' : $host . ':80'; parent::__construct( $endpoint, $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize ); $this->logToken = $token; } /** * {@inheritDoc} */ protected function generateDataStream(array $record): string { return $this->logToken . ' ' . $record['formatted']; } } PK������\5ZcR����#��Monolog/Handler/OverflowHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Formatter\FormatterInterface; /** * Handler to only pass log messages when a certain threshold of number of messages is reached. * * This can be useful in cases of processing a batch of data, but you're for example only interested * in case it fails catastrophically instead of a warning for 1 or 2 events. Worse things can happen, right? * * Usage example: * * ``` * $log = new Logger('application'); * $handler = new SomeHandler(...) * * // Pass all warnings to the handler when more than 10 & all error messages when more then 5 * $overflow = new OverflowHandler($handler, [Logger::WARNING => 10, Logger::ERROR => 5]); * * $log->pushHandler($overflow); *``` * * @author Kris Buist <krisbuist@gmail.com> */ class OverflowHandler extends AbstractHandler implements FormattableHandlerInterface { /** @var HandlerInterface */ private $handler; /** @var int[] */ private $thresholdMap = [ Logger::DEBUG => 0, Logger::INFO => 0, Logger::NOTICE => 0, Logger::WARNING => 0, Logger::ERROR => 0, Logger::CRITICAL => 0, Logger::ALERT => 0, Logger::EMERGENCY => 0, ]; /** * Buffer of all messages passed to the handler before the threshold was reached * * @var mixed[][] */ private $buffer = []; /** * @param HandlerInterface $handler * @param int[] $thresholdMap Dictionary of logger level => threshold */ public function __construct( HandlerInterface $handler, array $thresholdMap = [], $level = Logger::DEBUG, bool $bubble = true ) { $this->handler = $handler; foreach ($thresholdMap as $thresholdLevel => $threshold) { $this->thresholdMap[$thresholdLevel] = $threshold; } parent::__construct($level, $bubble); } /** * Handles a record. * * All records may be passed to this method, and the handler should discard * those that it does not want to handle. * * The return value of this function controls the bubbling process of the handler stack. * Unless the bubbling is interrupted (by returning true), the Logger class will keep on * calling further handlers in the stack with a given log record. * * {@inheritDoc} */ public function handle(array $record): bool { if ($record['level'] < $this->level) { return false; } $level = $record['level']; if (!isset($this->thresholdMap[$level])) { $this->thresholdMap[$level] = 0; } if ($this->thresholdMap[$level] > 0) { // The overflow threshold is not yet reached, so we're buffering the record and lowering the threshold by 1 $this->thresholdMap[$level]--; $this->buffer[$level][] = $record; return false === $this->bubble; } if ($this->thresholdMap[$level] == 0) { // This current message is breaking the threshold. Flush the buffer and continue handling the current record foreach ($this->buffer[$level] ?? [] as $buffered) { $this->handler->handle($buffered); } $this->thresholdMap[$level]--; unset($this->buffer[$level]); } $this->handler->handle($record); return false === $this->bubble; } /** * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { if ($this->handler instanceof FormattableHandlerInterface) { $this->handler->setFormatter($formatter); return $this; } throw new \UnexpectedValueException('The nested handler of type '.get_class($this->handler).' does not support formatters.'); } /** * {@inheritDoc} */ public function getFormatter(): FormatterInterface { if ($this->handler instanceof FormattableHandlerInterface) { return $this->handler->getFormatter(); } throw new \UnexpectedValueException('The nested handler of type '.get_class($this->handler).' does not support formatters.'); } } PK������\5ZRC��C��#��Monolog/Handler/NewRelicHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Utils; use Monolog\Formatter\NormalizerFormatter; use Monolog\Formatter\FormatterInterface; /** * Class to record a log on a NewRelic application. * Enabling New Relic High Security mode may prevent capture of useful information. * * This handler requires a NormalizerFormatter to function and expects an array in $record['formatted'] * * @see https://docs.newrelic.com/docs/agents/php-agent * @see https://docs.newrelic.com/docs/accounts-partnerships/accounts/security/high-security */ class NewRelicHandler extends AbstractProcessingHandler { /** * Name of the New Relic application that will receive logs from this handler. * * @var ?string */ protected $appName; /** * Name of the current transaction * * @var ?string */ protected $transactionName; /** * Some context and extra data is passed into the handler as arrays of values. Do we send them as is * (useful if we are using the API), or explode them for display on the NewRelic RPM website? * * @var bool */ protected $explodeArrays; /** * {@inheritDoc} * * @param string|null $appName * @param bool $explodeArrays * @param string|null $transactionName */ public function __construct( $level = Logger::ERROR, bool $bubble = true, ?string $appName = null, bool $explodeArrays = false, ?string $transactionName = null ) { parent::__construct($level, $bubble); $this->appName = $appName; $this->explodeArrays = $explodeArrays; $this->transactionName = $transactionName; } /** * {@inheritDoc} */ protected function write(array $record): void { if (!$this->isNewRelicEnabled()) { throw new MissingExtensionException('The newrelic PHP extension is required to use the NewRelicHandler'); } if ($appName = $this->getAppName($record['context'])) { $this->setNewRelicAppName($appName); } if ($transactionName = $this->getTransactionName($record['context'])) { $this->setNewRelicTransactionName($transactionName); unset($record['formatted']['context']['transaction_name']); } if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) { newrelic_notice_error($record['message'], $record['context']['exception']); unset($record['formatted']['context']['exception']); } else { newrelic_notice_error($record['message']); } if (isset($record['formatted']['context']) && is_array($record['formatted']['context'])) { foreach ($record['formatted']['context'] as $key => $parameter) { if (is_array($parameter) && $this->explodeArrays) { foreach ($parameter as $paramKey => $paramValue) { $this->setNewRelicParameter('context_' . $key . '_' . $paramKey, $paramValue); } } else { $this->setNewRelicParameter('context_' . $key, $parameter); } } } if (isset($record['formatted']['extra']) && is_array($record['formatted']['extra'])) { foreach ($record['formatted']['extra'] as $key => $parameter) { if (is_array($parameter) && $this->explodeArrays) { foreach ($parameter as $paramKey => $paramValue) { $this->setNewRelicParameter('extra_' . $key . '_' . $paramKey, $paramValue); } } else { $this->setNewRelicParameter('extra_' . $key, $parameter); } } } } /** * Checks whether the NewRelic extension is enabled in the system. * * @return bool */ protected function isNewRelicEnabled(): bool { return extension_loaded('newrelic'); } /** * Returns the appname where this log should be sent. Each log can override the default appname, set in this * handler's constructor, by providing the appname in it's context. * * @param mixed[] $context */ protected function getAppName(array $context): ?string { if (isset($context['appname'])) { return $context['appname']; } return $this->appName; } /** * Returns the name of the current transaction. Each log can override the default transaction name, set in this * handler's constructor, by providing the transaction_name in it's context * * @param mixed[] $context */ protected function getTransactionName(array $context): ?string { if (isset($context['transaction_name'])) { return $context['transaction_name']; } return $this->transactionName; } /** * Sets the NewRelic application that should receive this log. */ protected function setNewRelicAppName(string $appName): void { newrelic_set_appname($appName); } /** * Overwrites the name of the current transaction */ protected function setNewRelicTransactionName(string $transactionName): void { newrelic_name_transaction($transactionName); } /** * @param string $key * @param mixed $value */ protected function setNewRelicParameter(string $key, $value): void { if (null === $value || is_scalar($value)) { newrelic_add_custom_parameter($key, $value); } else { newrelic_add_custom_parameter($key, Utils::jsonEncode($value, null, true)); } } /** * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { return new NormalizerFormatter(); } } PK������\5Z"%��%��)��Monolog/Handler/BrowserConsoleHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LineFormatter; use Monolog\Utils; use Monolog\Logger; use function count; use function headers_list; use function stripos; use function trigger_error; use const E_USER_DEPRECATED; /** * Handler sending logs to browser's javascript console with no browser extension required * * @author Olivier Poitrey <rs@dailymotion.com> * * @phpstan-import-type FormattedRecord from AbstractProcessingHandler */ class BrowserConsoleHandler extends AbstractProcessingHandler { /** @var bool */ protected static $initialized = false; /** @var FormattedRecord[] */ protected static $records = []; protected const FORMAT_HTML = 'html'; protected const FORMAT_JS = 'js'; protected const FORMAT_UNKNOWN = 'unknown'; /** * {@inheritDoc} * * Formatted output may contain some formatting markers to be transferred to `console.log` using the %c format. * * Example of formatted string: * * You can do [[blue text]]{color: blue} or [[green background]]{background-color: green; color: white} */ protected function getDefaultFormatter(): FormatterInterface { return new LineFormatter('[[%channel%]]{macro: autolabel} [[%level_name%]]{font-weight: bold} %message%'); } /** * {@inheritDoc} */ protected function write(array $record): void { // Accumulate records static::$records[] = $record; // Register shutdown handler if not already done if (!static::$initialized) { static::$initialized = true; $this->registerShutdownFunction(); } } /** * Convert records to javascript console commands and send it to the browser. * This method is automatically called on PHP shutdown if output is HTML or Javascript. */ public static function send(): void { $format = static::getResponseFormat(); if ($format === self::FORMAT_UNKNOWN) { return; } if (count(static::$records)) { if ($format === self::FORMAT_HTML) { static::writeOutput('<script>' . static::generateScript() . '</script>'); } elseif ($format === self::FORMAT_JS) { static::writeOutput(static::generateScript()); } static::resetStatic(); } } public function close(): void { self::resetStatic(); } public function reset() { parent::reset(); self::resetStatic(); } /** * Forget all logged records */ public static function resetStatic(): void { static::$records = []; } /** * Wrapper for register_shutdown_function to allow overriding */ protected function registerShutdownFunction(): void { if (PHP_SAPI !== 'cli') { register_shutdown_function(['Monolog\Handler\BrowserConsoleHandler', 'send']); } } /** * Wrapper for echo to allow overriding */ protected static function writeOutput(string $str): void { echo $str; } /** * Checks the format of the response * * If Content-Type is set to application/javascript or text/javascript -> js * If Content-Type is set to text/html, or is unset -> html * If Content-Type is anything else -> unknown * * @return string One of 'js', 'html' or 'unknown' * @phpstan-return self::FORMAT_* */ protected static function getResponseFormat(): string { // Check content type foreach (headers_list() as $header) { if (stripos($header, 'content-type:') === 0) { return static::getResponseFormatFromContentType($header); } } return self::FORMAT_HTML; } /** * @return string One of 'js', 'html' or 'unknown' * @phpstan-return self::FORMAT_* */ protected static function getResponseFormatFromContentType(string $contentType): string { // This handler only works with HTML and javascript outputs // text/javascript is obsolete in favour of application/javascript, but still used if (stripos($contentType, 'application/javascript') !== false || stripos($contentType, 'text/javascript') !== false) { return self::FORMAT_JS; } if (stripos($contentType, 'text/html') !== false) { return self::FORMAT_HTML; } return self::FORMAT_UNKNOWN; } private static function generateScript(): string { $script = []; foreach (static::$records as $record) { $context = static::dump('Context', $record['context']); $extra = static::dump('Extra', $record['extra']); if (empty($context) && empty($extra)) { $script[] = static::call_array(static::getConsoleMethodForLevel($record['level']), static::handleStyles($record['formatted'])); } else { $script = array_merge( $script, [static::call_array('groupCollapsed', static::handleStyles($record['formatted']))], $context, $extra, [static::call('groupEnd')] ); } } return "(function (c) {if (c && c.groupCollapsed) {\n" . implode("\n", $script) . "\n}})(console);"; } private static function getConsoleMethodForLevel(int $level): string { return [ Logger::DEBUG => 'debug', Logger::INFO => 'info', Logger::NOTICE => 'info', Logger::WARNING => 'warn', Logger::ERROR => 'error', Logger::CRITICAL => 'error', Logger::ALERT => 'error', Logger::EMERGENCY => 'error', ][$level] ?? 'log'; } /** * @return string[] */ private static function handleStyles(string $formatted): array { $args = []; $format = '%c' . $formatted; preg_match_all('/\[\[(.*?)\]\]\{([^}]*)\}/s', $format, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); foreach (array_reverse($matches) as $match) { $args[] = '"font-weight: normal"'; $args[] = static::quote(static::handleCustomStyles($match[2][0], $match[1][0])); $pos = $match[0][1]; $format = Utils::substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . Utils::substr($format, $pos + strlen($match[0][0])); } $args[] = static::quote('font-weight: normal'); $args[] = static::quote($format); return array_reverse($args); } private static function handleCustomStyles(string $style, string $string): string { static $colors = ['blue', 'green', 'red', 'magenta', 'orange', 'black', 'grey']; static $labels = []; $style = preg_replace_callback('/macro\s*:(.*?)(?:;|$)/', function (array $m) use ($string, &$colors, &$labels) { if (trim($m[1]) === 'autolabel') { // Format the string as a label with consistent auto assigned background color if (!isset($labels[$string])) { $labels[$string] = $colors[count($labels) % count($colors)]; } $color = $labels[$string]; return "background-color: $color; color: white; border-radius: 3px; padding: 0 2px 0 2px"; } return $m[1]; }, $style); if (null === $style) { $pcreErrorCode = preg_last_error(); throw new \RuntimeException('Failed to run preg_replace_callback: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode)); } return $style; } /** * @param mixed[] $dict * @return mixed[] */ private static function dump(string $title, array $dict): array { $script = []; $dict = array_filter($dict); if (empty($dict)) { return $script; } $script[] = static::call('log', static::quote('%c%s'), static::quote('font-weight: bold'), static::quote($title)); foreach ($dict as $key => $value) { $value = json_encode($value); if (empty($value)) { $value = static::quote(''); } $script[] = static::call('log', static::quote('%s: %o'), static::quote((string) $key), $value); } return $script; } private static function quote(string $arg): string { return '"' . addcslashes($arg, "\"\n\\") . '"'; } /** * @param mixed $args */ private static function call(...$args): string { $method = array_shift($args); if (!is_string($method)) { throw new \UnexpectedValueException('Expected the first arg to be a string, got: '.var_export($method, true)); } return static::call_array($method, $args); } /** * @param mixed[] $args */ private static function call_array(string $method, array $args): string { return 'c.' . $method . '(' . implode(', ', $args) . ');'; } } PK������\5Z6 �� ��$��Monolog/Handler/HandlerInterface.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; /** * Interface that all Monolog Handlers must implement * * @author Jordi Boggiano <j.boggiano@seld.be> * * @phpstan-import-type Record from \Monolog\Logger * @phpstan-import-type Level from \Monolog\Logger */ interface HandlerInterface { /** * Checks whether the given record will be handled by this handler. * * This is mostly done for performance reasons, to avoid calling processors for nothing. * * Handlers should still check the record levels within handle(), returning false in isHandling() * is no guarantee that handle() will not be called, and isHandling() might not be called * for a given record. * * @param array $record Partial log record containing only a level key * * @return bool * * @phpstan-param array{level: Level} $record */ public function isHandling(array $record): bool; /** * Handles a record. * * All records may be passed to this method, and the handler should discard * those that it does not want to handle. * * The return value of this function controls the bubbling process of the handler stack. * Unless the bubbling is interrupted (by returning true), the Logger class will keep on * calling further handlers in the stack with a given log record. * * @param array $record The record to handle * @return bool true means that this handler handled the record, and that bubbling is not permitted. * false means the record was either not processed or that this handler allows bubbling. * * @phpstan-param Record $record */ public function handle(array $record): bool; /** * Handles a set of records at once. * * @param array $records The records to handle (an array of record arrays) * * @phpstan-param Record[] $records */ public function handleBatch(array $records): void; /** * Closes the handler. * * Ends a log cycle and frees all resources used by the handler. * * Closing a Handler means flushing all buffers and freeing any open resources/handles. * * Implementations have to be idempotent (i.e. it should be possible to call close several times without breakage) * and ideally handlers should be able to reopen themselves on handle() after they have been closed. * * This is useful at the end of a request and will be called automatically when the object * is destroyed if you extend Monolog\Handler\Handler. * * If you are thinking of calling this method yourself, most likely you should be * calling ResettableInterface::reset instead. Have a look. */ public function close(): void; } PK������\5ZVb_��_��"��Monolog/Handler/ProcessHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * Stores to STDIN of any process, specified by a command. * * Usage example: * <pre> * $log = new Logger('myLogger'); * $log->pushHandler(new ProcessHandler('/usr/bin/php /var/www/monolog/someScript.php')); * </pre> * * @author Kolja Zuelsdorf <koljaz@web.de> */ class ProcessHandler extends AbstractProcessingHandler { /** * Holds the process to receive data on its STDIN. * * @var resource|bool|null */ private $process; /** * @var string */ private $command; /** * @var string|null */ private $cwd; /** * @var resource[] */ private $pipes = []; /** * @var array<int, string[]> */ protected const DESCRIPTOR_SPEC = [ 0 => ['pipe', 'r'], // STDIN is a pipe that the child will read from 1 => ['pipe', 'w'], // STDOUT is a pipe that the child will write to 2 => ['pipe', 'w'], // STDERR is a pipe to catch the any errors ]; /** * @param string $command Command for the process to start. Absolute paths are recommended, * especially if you do not use the $cwd parameter. * @param string|null $cwd "Current working directory" (CWD) for the process to be executed in. * @throws \InvalidArgumentException */ public function __construct(string $command, $level = Logger::DEBUG, bool $bubble = true, ?string $cwd = null) { if ($command === '') { throw new \InvalidArgumentException('The command argument must be a non-empty string.'); } if ($cwd === '') { throw new \InvalidArgumentException('The optional CWD argument must be a non-empty string or null.'); } parent::__construct($level, $bubble); $this->command = $command; $this->cwd = $cwd; } /** * Writes the record down to the log of the implementing handler * * @throws \UnexpectedValueException */ protected function write(array $record): void { $this->ensureProcessIsStarted(); $this->writeProcessInput($record['formatted']); $errors = $this->readProcessErrors(); if (empty($errors) === false) { throw new \UnexpectedValueException(sprintf('Errors while writing to process: %s', $errors)); } } /** * Makes sure that the process is actually started, and if not, starts it, * assigns the stream pipes, and handles startup errors, if any. */ private function ensureProcessIsStarted(): void { if (is_resource($this->process) === false) { $this->startProcess(); $this->handleStartupErrors(); } } /** * Starts the actual process and sets all streams to non-blocking. */ private function startProcess(): void { $this->process = proc_open($this->command, static::DESCRIPTOR_SPEC, $this->pipes, $this->cwd); foreach ($this->pipes as $pipe) { stream_set_blocking($pipe, false); } } /** * Selects the STDERR stream, handles upcoming startup errors, and throws an exception, if any. * * @throws \UnexpectedValueException */ private function handleStartupErrors(): void { $selected = $this->selectErrorStream(); if (false === $selected) { throw new \UnexpectedValueException('Something went wrong while selecting a stream.'); } $errors = $this->readProcessErrors(); if (is_resource($this->process) === false || empty($errors) === false) { throw new \UnexpectedValueException( sprintf('The process "%s" could not be opened: ' . $errors, $this->command) ); } } /** * Selects the STDERR stream. * * @return int|bool */ protected function selectErrorStream() { $empty = []; $errorPipes = [$this->pipes[2]]; return stream_select($errorPipes, $empty, $empty, 1); } /** * Reads the errors of the process, if there are any. * * @codeCoverageIgnore * @return string Empty string if there are no errors. */ protected function readProcessErrors(): string { return (string) stream_get_contents($this->pipes[2]); } /** * Writes to the input stream of the opened process. * * @codeCoverageIgnore */ protected function writeProcessInput(string $string): void { fwrite($this->pipes[0], $string); } /** * {@inheritDoc} */ public function close(): void { if (is_resource($this->process)) { foreach ($this->pipes as $pipe) { fclose($pipe); } proc_close($this->process); $this->process = null; } } } PK������\5ZvY,)��,)��%��Monolog/Handler/PHPConsoleHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\LineFormatter; use Monolog\Formatter\FormatterInterface; use Monolog\Logger; use Monolog\Utils; use PhpConsole\Connector; use PhpConsole\Handler as VendorPhpConsoleHandler; use PhpConsole\Helper; /** * Monolog handler for Google Chrome extension "PHP Console" * * Display PHP error/debug log messages in Google Chrome console and notification popups, executes PHP code remotely * * Usage: * 1. Install Google Chrome extension [now dead and removed from the chrome store] * 2. See overview https://github.com/barbushin/php-console#overview * 3. Install PHP Console library https://github.com/barbushin/php-console#installation * 4. Example (result will looks like http://i.hizliresim.com/vg3Pz4.png) * * $logger = new \Monolog\Logger('all', array(new \Monolog\Handler\PHPConsoleHandler())); * \Monolog\ErrorHandler::register($logger); * echo $undefinedVar; * $logger->debug('SELECT * FROM users', array('db', 'time' => 0.012)); * PC::debug($_SERVER); // PHP Console debugger for any type of vars * * @author Sergey Barbushin https://www.linkedin.com/in/barbushin * * @phpstan-import-type Record from \Monolog\Logger * @deprecated Since 2.8.0 and 3.2.0, PHPConsole is abandoned and thus we will drop this handler in Monolog 4 */ class PHPConsoleHandler extends AbstractProcessingHandler { /** @var array<string, mixed> */ private $options = [ 'enabled' => true, // bool Is PHP Console server enabled 'classesPartialsTraceIgnore' => ['Monolog\\'], // array Hide calls of classes started with... 'debugTagsKeysInContext' => [0, 'tag'], // bool Is PHP Console server enabled 'useOwnErrorsHandler' => false, // bool Enable errors handling 'useOwnExceptionsHandler' => false, // bool Enable exceptions handling 'sourcesBasePath' => null, // string Base path of all project sources to strip in errors source paths 'registerHelper' => true, // bool Register PhpConsole\Helper that allows short debug calls like PC::debug($var, 'ta.g.s') 'serverEncoding' => null, // string|null Server internal encoding 'headersLimit' => null, // int|null Set headers size limit for your web-server 'password' => null, // string|null Protect PHP Console connection by password 'enableSslOnlyMode' => false, // bool Force connection by SSL for clients with PHP Console installed 'ipMasks' => [], // array Set IP masks of clients that will be allowed to connect to PHP Console: array('192.168.*.*', '127.0.0.1') 'enableEvalListener' => false, // bool Enable eval request to be handled by eval dispatcher(if enabled, 'password' option is also required) 'dumperDetectCallbacks' => false, // bool Convert callback items in dumper vars to (callback SomeClass::someMethod) strings 'dumperLevelLimit' => 5, // int Maximum dumped vars array or object nested dump level 'dumperItemsCountLimit' => 100, // int Maximum dumped var same level array items or object properties number 'dumperItemSizeLimit' => 5000, // int Maximum length of any string or dumped array item 'dumperDumpSizeLimit' => 500000, // int Maximum approximate size of dumped vars result formatted in JSON 'detectDumpTraceAndSource' => false, // bool Autodetect and append trace data to debug 'dataStorage' => null, // \PhpConsole\Storage|null Fixes problem with custom $_SESSION handler(see http://goo.gl/Ne8juJ) ]; /** @var Connector */ private $connector; /** * @param array<string, mixed> $options See \Monolog\Handler\PHPConsoleHandler::$options for more details * @param Connector|null $connector Instance of \PhpConsole\Connector class (optional) * @throws \RuntimeException */ public function __construct(array $options = [], ?Connector $connector = null, $level = Logger::DEBUG, bool $bubble = true) { if (!class_exists('PhpConsole\Connector')) { throw new \RuntimeException('PHP Console library not found. See https://github.com/barbushin/php-console#installation'); } parent::__construct($level, $bubble); $this->options = $this->initOptions($options); $this->connector = $this->initConnector($connector); } /** * @param array<string, mixed> $options * * @return array<string, mixed> */ private function initOptions(array $options): array { $wrongOptions = array_diff(array_keys($options), array_keys($this->options)); if ($wrongOptions) { throw new \RuntimeException('Unknown options: ' . implode(', ', $wrongOptions)); } return array_replace($this->options, $options); } private function initConnector(?Connector $connector = null): Connector { if (!$connector) { if ($this->options['dataStorage']) { Connector::setPostponeStorage($this->options['dataStorage']); } $connector = Connector::getInstance(); } if ($this->options['registerHelper'] && !Helper::isRegistered()) { Helper::register(); } if ($this->options['enabled'] && $connector->isActiveClient()) { if ($this->options['useOwnErrorsHandler'] || $this->options['useOwnExceptionsHandler']) { $handler = VendorPhpConsoleHandler::getInstance(); $handler->setHandleErrors($this->options['useOwnErrorsHandler']); $handler->setHandleExceptions($this->options['useOwnExceptionsHandler']); $handler->start(); } if ($this->options['sourcesBasePath']) { $connector->setSourcesBasePath($this->options['sourcesBasePath']); } if ($this->options['serverEncoding']) { $connector->setServerEncoding($this->options['serverEncoding']); } if ($this->options['password']) { $connector->setPassword($this->options['password']); } if ($this->options['enableSslOnlyMode']) { $connector->enableSslOnlyMode(); } if ($this->options['ipMasks']) { $connector->setAllowedIpMasks($this->options['ipMasks']); } if ($this->options['headersLimit']) { $connector->setHeadersLimit($this->options['headersLimit']); } if ($this->options['detectDumpTraceAndSource']) { $connector->getDebugDispatcher()->detectTraceAndSource = true; } $dumper = $connector->getDumper(); $dumper->levelLimit = $this->options['dumperLevelLimit']; $dumper->itemsCountLimit = $this->options['dumperItemsCountLimit']; $dumper->itemSizeLimit = $this->options['dumperItemSizeLimit']; $dumper->dumpSizeLimit = $this->options['dumperDumpSizeLimit']; $dumper->detectCallbacks = $this->options['dumperDetectCallbacks']; if ($this->options['enableEvalListener']) { $connector->startEvalRequestsListener(); } } return $connector; } public function getConnector(): Connector { return $this->connector; } /** * @return array<string, mixed> */ public function getOptions(): array { return $this->options; } public function handle(array $record): bool { if ($this->options['enabled'] && $this->connector->isActiveClient()) { return parent::handle($record); } return !$this->bubble; } /** * Writes the record down to the log of the implementing handler */ protected function write(array $record): void { if ($record['level'] < Logger::NOTICE) { $this->handleDebugRecord($record); } elseif (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) { $this->handleExceptionRecord($record); } else { $this->handleErrorRecord($record); } } /** * @phpstan-param Record $record */ private function handleDebugRecord(array $record): void { $tags = $this->getRecordTags($record); $message = $record['message']; if ($record['context']) { $message .= ' ' . Utils::jsonEncode($this->connector->getDumper()->dump(array_filter($record['context'])), null, true); } $this->connector->getDebugDispatcher()->dispatchDebug($message, $tags, $this->options['classesPartialsTraceIgnore']); } /** * @phpstan-param Record $record */ private function handleExceptionRecord(array $record): void { $this->connector->getErrorsDispatcher()->dispatchException($record['context']['exception']); } /** * @phpstan-param Record $record */ private function handleErrorRecord(array $record): void { $context = $record['context']; $this->connector->getErrorsDispatcher()->dispatchError( $context['code'] ?? null, $context['message'] ?? $record['message'], $context['file'] ?? null, $context['line'] ?? null, $this->options['classesPartialsTraceIgnore'] ); } /** * @phpstan-param Record $record * @return string */ private function getRecordTags(array &$record) { $tags = null; if (!empty($record['context'])) { $context = & $record['context']; foreach ($this->options['debugTagsKeysInContext'] as $key) { if (!empty($context[$key])) { $tags = $context[$key]; if ($key === 0) { array_shift($context); } else { unset($context[$key]); } break; } } } return $tags ?: strtolower($record['level_name']); } /** * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { return new LineFormatter('%message%'); } } PK������\5Z@_ �� ��#��Monolog/Handler/DynamoDbHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Aws\Sdk; use Aws\DynamoDb\DynamoDbClient; use Monolog\Formatter\FormatterInterface; use Aws\DynamoDb\Marshaler; use Monolog\Formatter\ScalarFormatter; use Monolog\Logger; /** * Amazon DynamoDB handler (http://aws.amazon.com/dynamodb/) * * @link https://github.com/aws/aws-sdk-php/ * @author Andrew Lawson <adlawson@gmail.com> */ class DynamoDbHandler extends AbstractProcessingHandler { public const DATE_FORMAT = 'Y-m-d\TH:i:s.uO'; /** * @var DynamoDbClient */ protected $client; /** * @var string */ protected $table; /** * @var int */ protected $version; /** * @var Marshaler */ protected $marshaler; public function __construct(DynamoDbClient $client, string $table, $level = Logger::DEBUG, bool $bubble = true) { /** @phpstan-ignore-next-line */ if (defined('Aws\Sdk::VERSION') && version_compare(Sdk::VERSION, '3.0', '>=')) { $this->version = 3; $this->marshaler = new Marshaler; } else { $this->version = 2; } $this->client = $client; $this->table = $table; parent::__construct($level, $bubble); } /** * {@inheritDoc} */ protected function write(array $record): void { $filtered = $this->filterEmptyFields($record['formatted']); if ($this->version === 3) { $formatted = $this->marshaler->marshalItem($filtered); } else { /** @phpstan-ignore-next-line */ $formatted = $this->client->formatAttributes($filtered); } $this->client->putItem([ 'TableName' => $this->table, 'Item' => $formatted, ]); } /** * @param mixed[] $record * @return mixed[] */ protected function filterEmptyFields(array $record): array { return array_filter($record, function ($value) { return !empty($value) || false === $value || 0 === $value; }); } /** * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { return new ScalarFormatter(self::DATE_FORMAT); } } PK������\5ZrEs��s��!��Monolog/Handler/SyslogHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Utils; /** * Logs to syslog service. * * usage example: * * $log = new Logger('application'); * $syslog = new SyslogHandler('myfacility', 'local6'); * $formatter = new LineFormatter("%channel%.%level_name%: %message% %extra%"); * $syslog->setFormatter($formatter); * $log->pushHandler($syslog); * * @author Sven Paulus <sven@karlsruhe.org> */ class SyslogHandler extends AbstractSyslogHandler { /** @var string */ protected $ident; /** @var int */ protected $logopts; /** * @param string $ident * @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant * @param int $logopts Option flags for the openlog() call, defaults to LOG_PID */ public function __construct(string $ident, $facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true, int $logopts = LOG_PID) { parent::__construct($facility, $level, $bubble); $this->ident = $ident; $this->logopts = $logopts; } /** * {@inheritDoc} */ public function close(): void { closelog(); } /** * {@inheritDoc} */ protected function write(array $record): void { if (!openlog($this->ident, $this->logopts, $this->facility)) { throw new \LogicException('Can\'t open syslog for ident "'.$this->ident.'" and facility "'.$this->facility.'"' . Utils::getRecordMessageForException($record)); } syslog($this->logLevels[$record['level']], (string) $record['formatted']); } } PK������\5Z$p)��)��%��Monolog/Handler/Slack/SlackRecord.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler\Slack; use Monolog\Logger; use Monolog\Utils; use Monolog\Formatter\NormalizerFormatter; use Monolog\Formatter\FormatterInterface; /** * Slack record utility helping to log to Slack webhooks or API. * * @author Greg Kedzierski <greg@gregkedzierski.com> * @author Haralan Dobrev <hkdobrev@gmail.com> * @see https://api.slack.com/incoming-webhooks * @see https://api.slack.com/docs/message-attachments * * @phpstan-import-type FormattedRecord from \Monolog\Handler\AbstractProcessingHandler * @phpstan-import-type Record from \Monolog\Logger */ class SlackRecord { public const COLOR_DANGER = 'danger'; public const COLOR_WARNING = 'warning'; public const COLOR_GOOD = 'good'; public const COLOR_DEFAULT = '#e3e4e6'; /** * Slack channel (encoded ID or name) * @var string|null */ private $channel; /** * Name of a bot * @var string|null */ private $username; /** * User icon e.g. 'ghost', 'http://example.com/user.png' * @var string|null */ private $userIcon; /** * Whether the message should be added to Slack as attachment (plain text otherwise) * @var bool */ private $useAttachment; /** * Whether the the context/extra messages added to Slack as attachments are in a short style * @var bool */ private $useShortAttachment; /** * Whether the attachment should include context and extra data * @var bool */ private $includeContextAndExtra; /** * Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2'] * @var string[] */ private $excludeFields; /** * @var ?FormatterInterface */ private $formatter; /** * @var NormalizerFormatter */ private $normalizerFormatter; /** * @param string[] $excludeFields */ public function __construct( ?string $channel = null, ?string $username = null, bool $useAttachment = true, ?string $userIcon = null, bool $useShortAttachment = false, bool $includeContextAndExtra = false, array $excludeFields = array(), FormatterInterface $formatter = null ) { $this ->setChannel($channel) ->setUsername($username) ->useAttachment($useAttachment) ->setUserIcon($userIcon) ->useShortAttachment($useShortAttachment) ->includeContextAndExtra($includeContextAndExtra) ->excludeFields($excludeFields) ->setFormatter($formatter); if ($this->includeContextAndExtra) { $this->normalizerFormatter = new NormalizerFormatter(); } } /** * Returns required data in format that Slack * is expecting. * * @phpstan-param FormattedRecord $record * @phpstan-return mixed[] */ public function getSlackData(array $record): array { $dataArray = array(); $record = $this->removeExcludedFields($record); if ($this->username) { $dataArray['username'] = $this->username; } if ($this->channel) { $dataArray['channel'] = $this->channel; } if ($this->formatter && !$this->useAttachment) { /** @phpstan-ignore-next-line */ $message = $this->formatter->format($record); } else { $message = $record['message']; } if ($this->useAttachment) { $attachment = array( 'fallback' => $message, 'text' => $message, 'color' => $this->getAttachmentColor($record['level']), 'fields' => array(), 'mrkdwn_in' => array('fields'), 'ts' => $record['datetime']->getTimestamp(), 'footer' => $this->username, 'footer_icon' => $this->userIcon, ); if ($this->useShortAttachment) { $attachment['title'] = $record['level_name']; } else { $attachment['title'] = 'Message'; $attachment['fields'][] = $this->generateAttachmentField('Level', $record['level_name']); } if ($this->includeContextAndExtra) { foreach (array('extra', 'context') as $key) { if (empty($record[$key])) { continue; } if ($this->useShortAttachment) { $attachment['fields'][] = $this->generateAttachmentField( (string) $key, $record[$key] ); } else { // Add all extra fields as individual fields in attachment $attachment['fields'] = array_merge( $attachment['fields'], $this->generateAttachmentFields($record[$key]) ); } } } $dataArray['attachments'] = array($attachment); } else { $dataArray['text'] = $message; } if ($this->userIcon) { if (filter_var($this->userIcon, FILTER_VALIDATE_URL)) { $dataArray['icon_url'] = $this->userIcon; } else { $dataArray['icon_emoji'] = ":{$this->userIcon}:"; } } return $dataArray; } /** * Returns a Slack message attachment color associated with * provided level. */ public function getAttachmentColor(int $level): string { switch (true) { case $level >= Logger::ERROR: return static::COLOR_DANGER; case $level >= Logger::WARNING: return static::COLOR_WARNING; case $level >= Logger::INFO: return static::COLOR_GOOD; default: return static::COLOR_DEFAULT; } } /** * Stringifies an array of key/value pairs to be used in attachment fields * * @param mixed[] $fields */ public function stringify(array $fields): string { /** @var Record $fields */ $normalized = $this->normalizerFormatter->format($fields); $hasSecondDimension = count(array_filter($normalized, 'is_array')); $hasNonNumericKeys = !count(array_filter(array_keys($normalized), 'is_numeric')); return $hasSecondDimension || $hasNonNumericKeys ? Utils::jsonEncode($normalized, JSON_PRETTY_PRINT|Utils::DEFAULT_JSON_FLAGS) : Utils::jsonEncode($normalized, Utils::DEFAULT_JSON_FLAGS); } /** * Channel used by the bot when posting * * @param ?string $channel * * @return static */ public function setChannel(?string $channel = null): self { $this->channel = $channel; return $this; } /** * Username used by the bot when posting * * @param ?string $username * * @return static */ public function setUsername(?string $username = null): self { $this->username = $username; return $this; } public function useAttachment(bool $useAttachment = true): self { $this->useAttachment = $useAttachment; return $this; } public function setUserIcon(?string $userIcon = null): self { $this->userIcon = $userIcon; if (\is_string($userIcon)) { $this->userIcon = trim($userIcon, ':'); } return $this; } public function useShortAttachment(bool $useShortAttachment = false): self { $this->useShortAttachment = $useShortAttachment; return $this; } public function includeContextAndExtra(bool $includeContextAndExtra = false): self { $this->includeContextAndExtra = $includeContextAndExtra; if ($this->includeContextAndExtra) { $this->normalizerFormatter = new NormalizerFormatter(); } return $this; } /** * @param string[] $excludeFields */ public function excludeFields(array $excludeFields = []): self { $this->excludeFields = $excludeFields; return $this; } public function setFormatter(?FormatterInterface $formatter = null): self { $this->formatter = $formatter; return $this; } /** * Generates attachment field * * @param string|mixed[] $value * * @return array{title: string, value: string, short: false} */ private function generateAttachmentField(string $title, $value): array { $value = is_array($value) ? sprintf('```%s```', substr($this->stringify($value), 0, 1990)) : $value; return array( 'title' => ucfirst($title), 'value' => $value, 'short' => false, ); } /** * Generates a collection of attachment fields from array * * @param mixed[] $data * * @return array<array{title: string, value: string, short: false}> */ private function generateAttachmentFields(array $data): array { /** @var Record $data */ $normalized = $this->normalizerFormatter->format($data); $fields = array(); foreach ($normalized as $key => $value) { $fields[] = $this->generateAttachmentField((string) $key, $value); } return $fields; } /** * Get a copy of record with fields excluded according to $this->excludeFields * * @phpstan-param FormattedRecord $record * * @return mixed[] */ private function removeExcludedFields(array $record): array { foreach ($this->excludeFields as $field) { $keys = explode('.', $field); $node = &$record; $lastKey = end($keys); foreach ($keys as $key) { if (!isset($node[$key])) { break; } if ($lastKey === $key) { unset($node[$key]); break; } $node = &$node[$key]; } } return $record; } } PK������\5Z4ƌL �� ��&��Monolog/Handler/TelegramBotHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use RuntimeException; use Monolog\Logger; use Monolog\Utils; /** * Handler send logs to Telegram using Telegram Bot API. * * How to use: * 1) Create telegram bot with https://telegram.me/BotFather * 2) Create a telegram channel where logs will be recorded. * 3) Add created bot from step 1 to the created channel from step 2. * * Use telegram bot API key from step 1 and channel name with '@' prefix from step 2 to create instance of TelegramBotHandler * * @link https://core.telegram.org/bots/api * * @author Mazur Alexandr <alexandrmazur96@gmail.com> * * @phpstan-import-type Record from \Monolog\Logger */ class TelegramBotHandler extends AbstractProcessingHandler { private const BOT_API = 'https://api.telegram.org/bot'; /** * The available values of parseMode according to the Telegram api documentation */ private const AVAILABLE_PARSE_MODES = [ 'HTML', 'MarkdownV2', 'Markdown', // legacy mode without underline and strikethrough, use MarkdownV2 instead ]; /** * The maximum number of characters allowed in a message according to the Telegram api documentation */ private const MAX_MESSAGE_LENGTH = 4096; /** * Telegram bot access token provided by BotFather. * Create telegram bot with https://telegram.me/BotFather and use access token from it. * @var string */ private $apiKey; /** * Telegram channel name. * Since to start with '@' symbol as prefix. * @var string */ private $channel; /** * The kind of formatting that is used for the message. * See available options at https://core.telegram.org/bots/api#formatting-options * or in AVAILABLE_PARSE_MODES * @var ?string */ private $parseMode; /** * Disables link previews for links in the message. * @var ?bool */ private $disableWebPagePreview; /** * Sends the message silently. Users will receive a notification with no sound. * @var ?bool */ private $disableNotification; /** * True - split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages. * False - truncates a message that is too long. * @var bool */ private $splitLongMessages; /** * Adds 1-second delay between sending a split message (according to Telegram API to avoid 429 Too Many Requests). * @var bool */ private $delayBetweenMessages; /** * @param string $apiKey Telegram bot access token provided by BotFather * @param string $channel Telegram channel name * @param bool $splitLongMessages Split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages * @param bool $delayBetweenMessages Adds delay between sending a split message according to Telegram API * @throws MissingExtensionException */ public function __construct( string $apiKey, string $channel, $level = Logger::DEBUG, bool $bubble = true, string $parseMode = null, bool $disableWebPagePreview = null, bool $disableNotification = null, bool $splitLongMessages = false, bool $delayBetweenMessages = false ) { if (!extension_loaded('curl')) { throw new MissingExtensionException('The curl extension is needed to use the TelegramBotHandler'); } parent::__construct($level, $bubble); $this->apiKey = $apiKey; $this->channel = $channel; $this->setParseMode($parseMode); $this->disableWebPagePreview($disableWebPagePreview); $this->disableNotification($disableNotification); $this->splitLongMessages($splitLongMessages); $this->delayBetweenMessages($delayBetweenMessages); } public function setParseMode(string $parseMode = null): self { if ($parseMode !== null && !in_array($parseMode, self::AVAILABLE_PARSE_MODES)) { throw new \InvalidArgumentException('Unknown parseMode, use one of these: ' . implode(', ', self::AVAILABLE_PARSE_MODES) . '.'); } $this->parseMode = $parseMode; return $this; } public function disableWebPagePreview(bool $disableWebPagePreview = null): self { $this->disableWebPagePreview = $disableWebPagePreview; return $this; } public function disableNotification(bool $disableNotification = null): self { $this->disableNotification = $disableNotification; return $this; } /** * True - split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages. * False - truncates a message that is too long. * @param bool $splitLongMessages * @return $this */ public function splitLongMessages(bool $splitLongMessages = false): self { $this->splitLongMessages = $splitLongMessages; return $this; } /** * Adds 1-second delay between sending a split message (according to Telegram API to avoid 429 Too Many Requests). * @param bool $delayBetweenMessages * @return $this */ public function delayBetweenMessages(bool $delayBetweenMessages = false): self { $this->delayBetweenMessages = $delayBetweenMessages; return $this; } /** * {@inheritDoc} */ public function handleBatch(array $records): void { /** @var Record[] $messages */ $messages = []; foreach ($records as $record) { if (!$this->isHandling($record)) { continue; } if ($this->processors) { /** @var Record $record */ $record = $this->processRecord($record); } $messages[] = $record; } if (!empty($messages)) { $this->send((string)$this->getFormatter()->formatBatch($messages)); } } /** * @inheritDoc */ protected function write(array $record): void { $this->send($record['formatted']); } /** * Send request to @link https://api.telegram.org/bot on SendMessage action. * @param string $message */ protected function send(string $message): void { $messages = $this->handleMessageLength($message); foreach ($messages as $key => $msg) { if ($this->delayBetweenMessages && $key > 0) { sleep(1); } $this->sendCurl($msg); } } protected function sendCurl(string $message): void { $ch = curl_init(); $url = self::BOT_API . $this->apiKey . '/SendMessage'; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ 'text' => $message, 'chat_id' => $this->channel, 'parse_mode' => $this->parseMode, 'disable_web_page_preview' => $this->disableWebPagePreview, 'disable_notification' => $this->disableNotification, ])); $result = Curl\Util::execute($ch); if (!is_string($result)) { throw new RuntimeException('Telegram API error. Description: No response'); } $result = json_decode($result, true); if ($result['ok'] === false) { throw new RuntimeException('Telegram API error. Description: ' . $result['description']); } } /** * Handle a message that is too long: truncates or splits into several * @param string $message * @return string[] */ private function handleMessageLength(string $message): array { $truncatedMarker = ' (...truncated)'; if (!$this->splitLongMessages && strlen($message) > self::MAX_MESSAGE_LENGTH) { return [Utils::substr($message, 0, self::MAX_MESSAGE_LENGTH - strlen($truncatedMarker)) . $truncatedMarker]; } return str_split($message, self::MAX_MESSAGE_LENGTH); } } PK������\5Zx��x��'��Monolog/Handler/SyslogUdp/UdpSocket.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler\SyslogUdp; use Monolog\Utils; use Socket; class UdpSocket { protected const DATAGRAM_MAX_LENGTH = 65023; /** @var string */ protected $ip; /** @var int */ protected $port; /** @var resource|Socket|null */ protected $socket = null; public function __construct(string $ip, int $port = 514) { $this->ip = $ip; $this->port = $port; } /** * @param string $line * @param string $header * @return void */ public function write($line, $header = "") { $this->send($this->assembleMessage($line, $header)); } public function close(): void { if (is_resource($this->socket) || $this->socket instanceof Socket) { socket_close($this->socket); $this->socket = null; } } /** * @return resource|Socket */ protected function getSocket() { if (null !== $this->socket) { return $this->socket; } $domain = AF_INET; $protocol = SOL_UDP; // Check if we are using unix sockets. if ($this->port === 0) { $domain = AF_UNIX; $protocol = IPPROTO_IP; } $this->socket = socket_create($domain, SOCK_DGRAM, $protocol) ?: null; if (null === $this->socket) { throw new \RuntimeException('The UdpSocket to '.$this->ip.':'.$this->port.' could not be opened via socket_create'); } return $this->socket; } protected function send(string $chunk): void { socket_sendto($this->getSocket(), $chunk, strlen($chunk), $flags = 0, $this->ip, $this->port); } protected function assembleMessage(string $line, string $header): string { $chunkSize = static::DATAGRAM_MAX_LENGTH - strlen($header); return $header . Utils::substr($line, 0, $chunkSize); } } PK������\5Z+!��!��)��Monolog/Handler/FingersCrossedHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy; use Monolog\Handler\FingersCrossed\ActivationStrategyInterface; use Monolog\Logger; use Monolog\ResettableInterface; use Monolog\Formatter\FormatterInterface; use Psr\Log\LogLevel; /** * Buffers all records until a certain level is reached * * The advantage of this approach is that you don't get any clutter in your log files. * Only requests which actually trigger an error (or whatever your actionLevel is) will be * in the logs, but they will contain all records, not only those above the level threshold. * * You can then have a passthruLevel as well which means that at the end of the request, * even if it did not get activated, it will still send through log records of e.g. at least a * warning level. * * You can find the various activation strategies in the * Monolog\Handler\FingersCrossed\ namespace. * * @author Jordi Boggiano <j.boggiano@seld.be> * * @phpstan-import-type Record from \Monolog\Logger * @phpstan-import-type Level from \Monolog\Logger * @phpstan-import-type LevelName from \Monolog\Logger */ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface, FormattableHandlerInterface { use ProcessableHandlerTrait; /** * @var callable|HandlerInterface * @phpstan-var callable(?Record, HandlerInterface): HandlerInterface|HandlerInterface */ protected $handler; /** @var ActivationStrategyInterface */ protected $activationStrategy; /** @var bool */ protected $buffering = true; /** @var int */ protected $bufferSize; /** @var Record[] */ protected $buffer = []; /** @var bool */ protected $stopBuffering; /** * @var ?int * @phpstan-var ?Level */ protected $passthruLevel; /** @var bool */ protected $bubble; /** * @psalm-param HandlerInterface|callable(?Record, HandlerInterface): HandlerInterface $handler * * @param callable|HandlerInterface $handler Handler or factory callable($record|null, $fingersCrossedHandler). * @param int|string|ActivationStrategyInterface $activationStrategy Strategy which determines when this handler takes action, or a level name/value at which the handler is activated * @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer. * @param bool $bubble Whether the messages that are handled can bubble up the stack or not * @param bool $stopBuffering Whether the handler should stop buffering after being triggered (default true) * @param int|string $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered * * @phpstan-param Level|LevelName|LogLevel::* $passthruLevel * @phpstan-param Level|LevelName|LogLevel::*|ActivationStrategyInterface $activationStrategy */ public function __construct($handler, $activationStrategy = null, int $bufferSize = 0, bool $bubble = true, bool $stopBuffering = true, $passthruLevel = null) { if (null === $activationStrategy) { $activationStrategy = new ErrorLevelActivationStrategy(Logger::WARNING); } // convert simple int activationStrategy to an object if (!$activationStrategy instanceof ActivationStrategyInterface) { $activationStrategy = new ErrorLevelActivationStrategy($activationStrategy); } $this->handler = $handler; $this->activationStrategy = $activationStrategy; $this->bufferSize = $bufferSize; $this->bubble = $bubble; $this->stopBuffering = $stopBuffering; if ($passthruLevel !== null) { $this->passthruLevel = Logger::toMonologLevel($passthruLevel); } if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) { throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object"); } } /** * {@inheritDoc} */ public function isHandling(array $record): bool { return true; } /** * Manually activate this logger regardless of the activation strategy */ public function activate(): void { if ($this->stopBuffering) { $this->buffering = false; } $this->getHandler(end($this->buffer) ?: null)->handleBatch($this->buffer); $this->buffer = []; } /** * {@inheritDoc} */ public function handle(array $record): bool { if ($this->processors) { /** @var Record $record */ $record = $this->processRecord($record); } if ($this->buffering) { $this->buffer[] = $record; if ($this->bufferSize > 0 && count($this->buffer) > $this->bufferSize) { array_shift($this->buffer); } if ($this->activationStrategy->isHandlerActivated($record)) { $this->activate(); } } else { $this->getHandler($record)->handle($record); } return false === $this->bubble; } /** * {@inheritDoc} */ public function close(): void { $this->flushBuffer(); $this->getHandler()->close(); } public function reset() { $this->flushBuffer(); $this->resetProcessors(); if ($this->getHandler() instanceof ResettableInterface) { $this->getHandler()->reset(); } } /** * Clears the buffer without flushing any messages down to the wrapped handler. * * It also resets the handler to its initial buffering state. */ public function clear(): void { $this->buffer = []; $this->reset(); } /** * Resets the state of the handler. Stops forwarding records to the wrapped handler. */ private function flushBuffer(): void { if (null !== $this->passthruLevel) { $level = $this->passthruLevel; $this->buffer = array_filter($this->buffer, function ($record) use ($level) { return $record['level'] >= $level; }); if (count($this->buffer) > 0) { $this->getHandler(end($this->buffer))->handleBatch($this->buffer); } } $this->buffer = []; $this->buffering = true; } /** * Return the nested handler * * If the handler was provided as a factory callable, this will trigger the handler's instantiation. * * @return HandlerInterface * * @phpstan-param Record $record */ public function getHandler(array $record = null) { if (!$this->handler instanceof HandlerInterface) { $this->handler = ($this->handler)($record, $this); if (!$this->handler instanceof HandlerInterface) { throw new \RuntimeException("The factory callable should return a HandlerInterface"); } } return $this->handler; } /** * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { $handler = $this->getHandler(); if ($handler instanceof FormattableHandlerInterface) { $handler->setFormatter($formatter); return $this; } throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.'); } /** * {@inheritDoc} */ public function getFormatter(): FormatterInterface { $handler = $this->getHandler(); if ($handler instanceof FormattableHandlerInterface) { return $handler->getFormatter(); } throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.'); } } PK������\5Z{=g&��&��#��Monolog/Handler/FlowdockHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Utils; use Monolog\Formatter\FlowdockFormatter; use Monolog\Formatter\FormatterInterface; /** * Sends notifications through the Flowdock push API * * This must be configured with a FlowdockFormatter instance via setFormatter() * * Notes: * API token - Flowdock API token * * @author Dominik Liebler <liebler.dominik@gmail.com> * @see https://www.flowdock.com/api/push * * @phpstan-import-type FormattedRecord from AbstractProcessingHandler * @deprecated Since 2.9.0 and 3.3.0, Flowdock was shutdown we will thus drop this handler in Monolog 4 */ class FlowdockHandler extends SocketHandler { /** * @var string */ protected $apiToken; /** * @throws MissingExtensionException if OpenSSL is missing */ public function __construct( string $apiToken, $level = Logger::DEBUG, bool $bubble = true, bool $persistent = false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null ) { if (!extension_loaded('openssl')) { throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FlowdockHandler'); } parent::__construct( 'ssl://api.flowdock.com:443', $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize ); $this->apiToken = $apiToken; } /** * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { if (!$formatter instanceof FlowdockFormatter) { throw new \InvalidArgumentException('The FlowdockHandler requires an instance of Monolog\Formatter\FlowdockFormatter to function correctly'); } return parent::setFormatter($formatter); } /** * Gets the default formatter. */ protected function getDefaultFormatter(): FormatterInterface { throw new \InvalidArgumentException('The FlowdockHandler must be configured (via setFormatter) with an instance of Monolog\Formatter\FlowdockFormatter to function correctly'); } /** * {@inheritDoc} */ protected function write(array $record): void { parent::write($record); $this->closeSocket(); } /** * {@inheritDoc} */ protected function generateDataStream(array $record): string { $content = $this->buildContent($record); return $this->buildHeader($content) . $content; } /** * Builds the body of API call * * @phpstan-param FormattedRecord $record */ private function buildContent(array $record): string { return Utils::jsonEncode($record['formatted']['flowdock']); } /** * Builds the header of the API Call */ private function buildHeader(string $content): string { $header = "POST /v1/messages/team_inbox/" . $this->apiToken . " HTTP/1.1\r\n"; $header .= "Host: api.flowdock.com\r\n"; $header .= "Content-Type: application/json\r\n"; $header .= "Content-Length: " . strlen($content) . "\r\n"; $header .= "\r\n"; return $header; } } PK������\5Z[ ��[ ��#��Monolog/Handler/AbstractHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\ResettableInterface; use Psr\Log\LogLevel; /** * Base Handler class providing basic level/bubble support * * @author Jordi Boggiano <j.boggiano@seld.be> * * @phpstan-import-type Level from \Monolog\Logger * @phpstan-import-type LevelName from \Monolog\Logger */ abstract class AbstractHandler extends Handler implements ResettableInterface { /** * @var int * @phpstan-var Level */ protected $level = Logger::DEBUG; /** @var bool */ protected $bubble = true; /** * @param int|string $level The minimum logging level at which this handler will be triggered * @param bool $bubble Whether the messages that are handled can bubble up the stack or not * * @phpstan-param Level|LevelName|LogLevel::* $level */ public function __construct($level = Logger::DEBUG, bool $bubble = true) { $this->setLevel($level); $this->bubble = $bubble; } /** * {@inheritDoc} */ public function isHandling(array $record): bool { return $record['level'] >= $this->level; } /** * Sets minimum logging level at which this handler will be triggered. * * @param Level|LevelName|LogLevel::* $level Level or level name * @return self */ public function setLevel($level): self { $this->level = Logger::toMonologLevel($level); return $this; } /** * Gets minimum logging level at which this handler will be triggered. * * @return int * * @phpstan-return Level */ public function getLevel(): int { return $this->level; } /** * Sets the bubbling behavior. * * @param bool $bubble true means that this handler allows bubbling. * false means that bubbling is not permitted. * @return self */ public function setBubble(bool $bubble): self { $this->bubble = $bubble; return $this; } /** * Gets the bubbling behavior. * * @return bool true means that this handler allows bubbling. * false means that bubbling is not permitted. */ public function getBubble(): bool { return $this->bubble; } /** * {@inheritDoc} */ public function reset() { } } PK������\5Zܩ �� ��#��Monolog/Handler/LogmaticHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LogmaticFormatter; /** * @author Julien Breux <julien.breux@gmail.com> */ class LogmaticHandler extends SocketHandler { /** * @var string */ private $logToken; /** * @var string */ private $hostname; /** * @var string */ private $appname; /** * @param string $token Log token supplied by Logmatic. * @param string $hostname Host name supplied by Logmatic. * @param string $appname Application name supplied by Logmatic. * @param bool $useSSL Whether or not SSL encryption should be used. * * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing */ public function __construct( string $token, string $hostname = '', string $appname = '', bool $useSSL = true, $level = Logger::DEBUG, bool $bubble = true, bool $persistent = false, float $timeout = 0.0, float $writingTimeout = 10.0, ?float $connectionTimeout = null, ?int $chunkSize = null ) { if ($useSSL && !extension_loaded('openssl')) { throw new MissingExtensionException('The OpenSSL PHP extension is required to use SSL encrypted connection for LogmaticHandler'); } $endpoint = $useSSL ? 'ssl://api.logmatic.io:10515' : 'api.logmatic.io:10514'; $endpoint .= '/v1/'; parent::__construct( $endpoint, $level, $bubble, $persistent, $timeout, $writingTimeout, $connectionTimeout, $chunkSize ); $this->logToken = $token; $this->hostname = $hostname; $this->appname = $appname; } /** * {@inheritDoc} */ protected function generateDataStream(array $record): string { return $this->logToken . ' ' . $record['formatted']; } /** * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { $formatter = new LogmaticFormatter(); if (!empty($this->hostname)) { $formatter->setHostname($this->hostname); } if (!empty($this->appname)) { $formatter->setAppname($this->appname); } return $formatter; } } PK������\5Zww% ��% ����Monolog/Handler/MailHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\HtmlFormatter; /** * Base class for all mail handlers * * @author Gyula Sallai * * @phpstan-import-type Record from \Monolog\Logger */ abstract class MailHandler extends AbstractProcessingHandler { /** * {@inheritDoc} */ public function handleBatch(array $records): void { $messages = []; foreach ($records as $record) { if ($record['level'] < $this->level) { continue; } /** @var Record $message */ $message = $this->processRecord($record); $messages[] = $message; } if (!empty($messages)) { $this->send((string) $this->getFormatter()->formatBatch($messages), $messages); } } /** * Send a mail with the given content * * @param string $content formatted email body to be sent * @param array $records the array of log records that formed this content * * @phpstan-param Record[] $records */ abstract protected function send(string $content, array $records): void; /** * {@inheritDoc} */ protected function write(array $record): void { $this->send((string) $record['formatted'], [$record]); } /** * @phpstan-param non-empty-array<Record> $records * @phpstan-return Record */ protected function getHighestRecord(array $records): array { $highestRecord = null; foreach ($records as $record) { if ($highestRecord === null || $highestRecord['level'] < $record['level']) { $highestRecord = $record; } } return $highestRecord; } protected function isHtmlBody(string $body): bool { return ($body[0] ?? null) === '<'; } /** * Gets the default formatter. * * @return FormatterInterface */ protected function getDefaultFormatter(): FormatterInterface { return new HtmlFormatter(); } } PK������\5Z����"��Monolog/Handler/FirePHPHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\WildfireFormatter; use Monolog\Formatter\FormatterInterface; /** * Simple FirePHP Handler (http://www.firephp.org/), which uses the Wildfire protocol. * * @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com> * * @phpstan-import-type FormattedRecord from AbstractProcessingHandler */ class FirePHPHandler extends AbstractProcessingHandler { use WebRequestRecognizerTrait; /** * WildFire JSON header message format */ protected const PROTOCOL_URI = 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2'; /** * FirePHP structure for parsing messages & their presentation */ protected const STRUCTURE_URI = 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1'; /** * Must reference a "known" plugin, otherwise headers won't display in FirePHP */ protected const PLUGIN_URI = 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3'; /** * Header prefix for Wildfire to recognize & parse headers */ protected const HEADER_PREFIX = 'X-Wf'; /** * Whether or not Wildfire vendor-specific headers have been generated & sent yet * @var bool */ protected static $initialized = false; /** * Shared static message index between potentially multiple handlers * @var int */ protected static $messageIndex = 1; /** @var bool */ protected static $sendHeaders = true; /** * Base header creation function used by init headers & record headers * * @param array<int|string> $meta Wildfire Plugin, Protocol & Structure Indexes * @param string $message Log message * * @return array<string, string> Complete header string ready for the client as key and message as value * * @phpstan-return non-empty-array<string, string> */ protected function createHeader(array $meta, string $message): array { $header = sprintf('%s-%s', static::HEADER_PREFIX, join('-', $meta)); return [$header => $message]; } /** * Creates message header from record * * @return array<string, string> * * @phpstan-return non-empty-array<string, string> * * @see createHeader() * * @phpstan-param FormattedRecord $record */ protected function createRecordHeader(array $record): array { // Wildfire is extensible to support multiple protocols & plugins in a single request, // but we're not taking advantage of that (yet), so we're using "1" for simplicity's sake. return $this->createHeader( [1, 1, 1, self::$messageIndex++], $record['formatted'] ); } /** * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { return new WildfireFormatter(); } /** * Wildfire initialization headers to enable message parsing * * @see createHeader() * @see sendHeader() * * @return array<string, string> */ protected function getInitHeaders(): array { // Initial payload consists of required headers for Wildfire return array_merge( $this->createHeader(['Protocol', 1], static::PROTOCOL_URI), $this->createHeader([1, 'Structure', 1], static::STRUCTURE_URI), $this->createHeader([1, 'Plugin', 1], static::PLUGIN_URI) ); } /** * Send header string to the client */ protected function sendHeader(string $header, string $content): void { if (!headers_sent() && self::$sendHeaders) { header(sprintf('%s: %s', $header, $content)); } } /** * Creates & sends header for a record, ensuring init headers have been sent prior * * @see sendHeader() * @see sendInitHeaders() */ protected function write(array $record): void { if (!self::$sendHeaders || !$this->isWebRequest()) { return; } // WildFire-specific headers must be sent prior to any messages if (!self::$initialized) { self::$initialized = true; self::$sendHeaders = $this->headersAccepted(); if (!self::$sendHeaders) { return; } foreach ($this->getInitHeaders() as $header => $content) { $this->sendHeader($header, $content); } } $header = $this->createRecordHeader($record); if (trim(current($header)) !== '') { $this->sendHeader(key($header), current($header)); } } /** * Verifies if the headers are accepted by the current user agent */ protected function headersAccepted(): bool { if (!empty($_SERVER['HTTP_USER_AGENT']) && preg_match('{\bFirePHP/\d+\.\d+\b}', $_SERVER['HTTP_USER_AGENT'])) { return true; } return isset($_SERVER['HTTP_X_FIREPHP_VERSION']); } } PK������\5Z`<S��S��'��Monolog/Handler/SlackWebhookHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; use Monolog\Logger; use Monolog\Utils; use Monolog\Handler\Slack\SlackRecord; /** * Sends notifications through Slack Webhooks * * @author Haralan Dobrev <hkdobrev@gmail.com> * @see https://api.slack.com/incoming-webhooks */ class SlackWebhookHandler extends AbstractProcessingHandler { /** * Slack Webhook token * @var string */ private $webhookUrl; /** * Instance of the SlackRecord util class preparing data for Slack API. * @var SlackRecord */ private $slackRecord; /** * @param string $webhookUrl Slack Webhook URL * @param string|null $channel Slack channel (encoded ID or name) * @param string|null $username Name of a bot * @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise) * @param string|null $iconEmoji The emoji name to use (or null) * @param bool $useShortAttachment Whether the the context/extra messages added to Slack as attachments are in a short style * @param bool $includeContextAndExtra Whether the attachment should include context and extra data * @param string[] $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2'] */ public function __construct( string $webhookUrl, ?string $channel = null, ?string $username = null, bool $useAttachment = true, ?string $iconEmoji = null, bool $useShortAttachment = false, bool $includeContextAndExtra = false, $level = Logger::CRITICAL, bool $bubble = true, array $excludeFields = array() ) { if (!extension_loaded('curl')) { throw new MissingExtensionException('The curl extension is needed to use the SlackWebhookHandler'); } parent::__construct($level, $bubble); $this->webhookUrl = $webhookUrl; $this->slackRecord = new SlackRecord( $channel, $username, $useAttachment, $iconEmoji, $useShortAttachment, $includeContextAndExtra, $excludeFields ); } public function getSlackRecord(): SlackRecord { return $this->slackRecord; } public function getWebhookUrl(): string { return $this->webhookUrl; } /** * {@inheritDoc} */ protected function write(array $record): void { $postData = $this->slackRecord->getSlackData($record); $postString = Utils::jsonEncode($postData); $ch = curl_init(); $options = array( CURLOPT_URL => $this->webhookUrl, CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => array('Content-type: application/json'), CURLOPT_POSTFIELDS => $postString, ); if (defined('CURLOPT_SAFE_UPLOAD')) { $options[CURLOPT_SAFE_UPLOAD] = true; } curl_setopt_array($ch, $options); Curl\Util::execute($ch); } public function setFormatter(FormatterInterface $formatter): HandlerInterface { parent::setFormatter($formatter); $this->slackRecord->setFormatter($formatter); return $this; } public function getFormatter(): FormatterInterface { $formatter = parent::getFormatter(); $this->slackRecord->setFormatter($formatter); return $formatter; } } PK������\5Zb^��^����Monolog/Handler/TestHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Psr\Log\LogLevel; /** * Used for testing purposes. * * It records all records and gives you access to them for verification. * * @author Jordi Boggiano <j.boggiano@seld.be> * * @method bool hasEmergency($record) * @method bool hasAlert($record) * @method bool hasCritical($record) * @method bool hasError($record) * @method bool hasWarning($record) * @method bool hasNotice($record) * @method bool hasInfo($record) * @method bool hasDebug($record) * * @method bool hasEmergencyRecords() * @method bool hasAlertRecords() * @method bool hasCriticalRecords() * @method bool hasErrorRecords() * @method bool hasWarningRecords() * @method bool hasNoticeRecords() * @method bool hasInfoRecords() * @method bool hasDebugRecords() * * @method bool hasEmergencyThatContains($message) * @method bool hasAlertThatContains($message) * @method bool hasCriticalThatContains($message) * @method bool hasErrorThatContains($message) * @method bool hasWarningThatContains($message) * @method bool hasNoticeThatContains($message) * @method bool hasInfoThatContains($message) * @method bool hasDebugThatContains($message) * * @method bool hasEmergencyThatMatches($message) * @method bool hasAlertThatMatches($message) * @method bool hasCriticalThatMatches($message) * @method bool hasErrorThatMatches($message) * @method bool hasWarningThatMatches($message) * @method bool hasNoticeThatMatches($message) * @method bool hasInfoThatMatches($message) * @method bool hasDebugThatMatches($message) * * @method bool hasEmergencyThatPasses($message) * @method bool hasAlertThatPasses($message) * @method bool hasCriticalThatPasses($message) * @method bool hasErrorThatPasses($message) * @method bool hasWarningThatPasses($message) * @method bool hasNoticeThatPasses($message) * @method bool hasInfoThatPasses($message) * @method bool hasDebugThatPasses($message) * * @phpstan-import-type Record from \Monolog\Logger * @phpstan-import-type Level from \Monolog\Logger * @phpstan-import-type LevelName from \Monolog\Logger */ class TestHandler extends AbstractProcessingHandler { /** @var Record[] */ protected $records = []; /** @var array<Level, Record[]> */ protected $recordsByLevel = []; /** @var bool */ private $skipReset = false; /** * @return array * * @phpstan-return Record[] */ public function getRecords() { return $this->records; } /** * @return void */ public function clear() { $this->records = []; $this->recordsByLevel = []; } /** * @return void */ public function reset() { if (!$this->skipReset) { $this->clear(); } } /** * @return void */ public function setSkipReset(bool $skipReset) { $this->skipReset = $skipReset; } /** * @param string|int $level Logging level value or name * * @phpstan-param Level|LevelName|LogLevel::* $level */ public function hasRecords($level): bool { return isset($this->recordsByLevel[Logger::toMonologLevel($level)]); } /** * @param string|array $record Either a message string or an array containing message and optionally context keys that will be checked against all records * @param string|int $level Logging level value or name * * @phpstan-param array{message: string, context?: mixed[]}|string $record * @phpstan-param Level|LevelName|LogLevel::* $level */ public function hasRecord($record, $level): bool { if (is_string($record)) { $record = array('message' => $record); } return $this->hasRecordThatPasses(function ($rec) use ($record) { if ($rec['message'] !== $record['message']) { return false; } if (isset($record['context']) && $rec['context'] !== $record['context']) { return false; } return true; }, $level); } /** * @param string|int $level Logging level value or name * * @phpstan-param Level|LevelName|LogLevel::* $level */ public function hasRecordThatContains(string $message, $level): bool { return $this->hasRecordThatPasses(function ($rec) use ($message) { return strpos($rec['message'], $message) !== false; }, $level); } /** * @param string|int $level Logging level value or name * * @phpstan-param Level|LevelName|LogLevel::* $level */ public function hasRecordThatMatches(string $regex, $level): bool { return $this->hasRecordThatPasses(function (array $rec) use ($regex): bool { return preg_match($regex, $rec['message']) > 0; }, $level); } /** * @param string|int $level Logging level value or name * @return bool * * @psalm-param callable(Record, int): mixed $predicate * @phpstan-param Level|LevelName|LogLevel::* $level */ public function hasRecordThatPasses(callable $predicate, $level) { $level = Logger::toMonologLevel($level); if (!isset($this->recordsByLevel[$level])) { return false; } foreach ($this->recordsByLevel[$level] as $i => $rec) { if ($predicate($rec, $i)) { return true; } } return false; } /** * {@inheritDoc} */ protected function write(array $record): void { $this->recordsByLevel[$record['level']][] = $record; $this->records[] = $record; } /** * @param string $method * @param mixed[] $args * @return bool */ public function __call($method, $args) { if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) { $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3]; $level = constant('Monolog\Logger::' . strtoupper($matches[2])); $callback = [$this, $genericMethod]; if (is_callable($callback)) { $args[] = $level; return call_user_func_array($callback, $args); } } throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()'); } } PK������\5ZaPނ����$��Monolog/Handler/ChromePHPHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\ChromePHPFormatter; use Monolog\Formatter\FormatterInterface; use Monolog\Logger; use Monolog\Utils; /** * Handler sending logs to the ChromePHP extension (http://www.chromephp.com/) * * This also works out of the box with Firefox 43+ * * @author Christophe Coevoet <stof@notk.org> * * @phpstan-import-type Record from \Monolog\Logger */ class ChromePHPHandler extends AbstractProcessingHandler { use WebRequestRecognizerTrait; /** * Version of the extension */ protected const VERSION = '4.0'; /** * Header name */ protected const HEADER_NAME = 'X-ChromeLogger-Data'; /** * Regular expression to detect supported browsers (matches any Chrome, or Firefox 43+) */ protected const USER_AGENT_REGEX = '{\b(?:Chrome/\d+(?:\.\d+)*|HeadlessChrome|Firefox/(?:4[3-9]|[5-9]\d|\d{3,})(?:\.\d)*)\b}'; /** @var bool */ protected static $initialized = false; /** * Tracks whether we sent too much data * * Chrome limits the headers to 4KB, so when we sent 3KB we stop sending * * @var bool */ protected static $overflowed = false; /** @var mixed[] */ protected static $json = [ 'version' => self::VERSION, 'columns' => ['label', 'log', 'backtrace', 'type'], 'rows' => [], ]; /** @var bool */ protected static $sendHeaders = true; public function __construct($level = Logger::DEBUG, bool $bubble = true) { parent::__construct($level, $bubble); if (!function_exists('json_encode')) { throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s ChromePHPHandler'); } } /** * {@inheritDoc} */ public function handleBatch(array $records): void { if (!$this->isWebRequest()) { return; } $messages = []; foreach ($records as $record) { if ($record['level'] < $this->level) { continue; } /** @var Record $message */ $message = $this->processRecord($record); $messages[] = $message; } if (!empty($messages)) { $messages = $this->getFormatter()->formatBatch($messages); self::$json['rows'] = array_merge(self::$json['rows'], $messages); $this->send(); } } /** * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { return new ChromePHPFormatter(); } /** * Creates & sends header for a record * * @see sendHeader() * @see send() */ protected function write(array $record): void { if (!$this->isWebRequest()) { return; } self::$json['rows'][] = $record['formatted']; $this->send(); } /** * Sends the log header * * @see sendHeader() */ protected function send(): void { if (self::$overflowed || !self::$sendHeaders) { return; } if (!self::$initialized) { self::$initialized = true; self::$sendHeaders = $this->headersAccepted(); if (!self::$sendHeaders) { return; } self::$json['request_uri'] = $_SERVER['REQUEST_URI'] ?? ''; } $json = Utils::jsonEncode(self::$json, Utils::DEFAULT_JSON_FLAGS & ~JSON_UNESCAPED_UNICODE, true); $data = base64_encode($json); if (strlen($data) > 3 * 1024) { self::$overflowed = true; $record = [ 'message' => 'Incomplete logs, chrome header size limit reached', 'context' => [], 'level' => Logger::WARNING, 'level_name' => Logger::getLevelName(Logger::WARNING), 'channel' => 'monolog', 'datetime' => new \DateTimeImmutable(), 'extra' => [], ]; self::$json['rows'][count(self::$json['rows']) - 1] = $this->getFormatter()->format($record); $json = Utils::jsonEncode(self::$json, Utils::DEFAULT_JSON_FLAGS & ~JSON_UNESCAPED_UNICODE, true); $data = base64_encode($json); } if (trim($data) !== '') { $this->sendHeader(static::HEADER_NAME, $data); } } /** * Send header string to the client */ protected function sendHeader(string $header, string $content): void { if (!headers_sent() && self::$sendHeaders) { header(sprintf('%s: %s', $header, $content)); } } /** * Verifies if the headers are accepted by the current user agent */ protected function headersAccepted(): bool { if (empty($_SERVER['HTTP_USER_AGENT'])) { return false; } return preg_match(static::USER_AGENT_REGEX, $_SERVER['HTTP_USER_AGENT']) === 1; } } PK������\5ZC �� ��"��Monolog/Handler/HandlerWrapper.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\ResettableInterface; use Monolog\Formatter\FormatterInterface; /** * This simple wrapper class can be used to extend handlers functionality. * * Example: A custom filtering that can be applied to any handler. * * Inherit from this class and override handle() like this: * * public function handle(array $record) * { * if ($record meets certain conditions) { * return false; * } * return $this->handler->handle($record); * } * * @author Alexey Karapetov <alexey@karapetov.com> */ class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, FormattableHandlerInterface, ResettableInterface { /** * @var HandlerInterface */ protected $handler; public function __construct(HandlerInterface $handler) { $this->handler = $handler; } /** * {@inheritDoc} */ public function isHandling(array $record): bool { return $this->handler->isHandling($record); } /** * {@inheritDoc} */ public function handle(array $record): bool { return $this->handler->handle($record); } /** * {@inheritDoc} */ public function handleBatch(array $records): void { $this->handler->handleBatch($records); } /** * {@inheritDoc} */ public function close(): void { $this->handler->close(); } /** * {@inheritDoc} */ public function pushProcessor(callable $callback): HandlerInterface { if ($this->handler instanceof ProcessableHandlerInterface) { $this->handler->pushProcessor($callback); return $this; } throw new \LogicException('The wrapped handler does not implement ' . ProcessableHandlerInterface::class); } /** * {@inheritDoc} */ public function popProcessor(): callable { if ($this->handler instanceof ProcessableHandlerInterface) { return $this->handler->popProcessor(); } throw new \LogicException('The wrapped handler does not implement ' . ProcessableHandlerInterface::class); } /** * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { if ($this->handler instanceof FormattableHandlerInterface) { $this->handler->setFormatter($formatter); return $this; } throw new \LogicException('The wrapped handler does not implement ' . FormattableHandlerInterface::class); } /** * {@inheritDoc} */ public function getFormatter(): FormatterInterface { if ($this->handler instanceof FormattableHandlerInterface) { return $this->handler->getFormatter(); } throw new \LogicException('The wrapped handler does not implement ' . FormattableHandlerInterface::class); } public function reset() { if ($this->handler instanceof ResettableInterface) { $this->handler->reset(); } } } PK������\5Zr!l �� ����Monolog/Handler/PsrHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Psr\Log\LoggerInterface; use Monolog\Formatter\FormatterInterface; /** * Proxies log messages to an existing PSR-3 compliant logger. * * If a formatter is configured, the formatter's output MUST be a string and the * formatted message will be fed to the wrapped PSR logger instead of the original * log record's message. * * @author Michael Moussa <michael.moussa@gmail.com> */ class PsrHandler extends AbstractHandler implements FormattableHandlerInterface { /** * PSR-3 compliant logger * * @var LoggerInterface */ protected $logger; /** * @var FormatterInterface|null */ protected $formatter; /** * @param LoggerInterface $logger The underlying PSR-3 compliant logger to which messages will be proxied */ public function __construct(LoggerInterface $logger, $level = Logger::DEBUG, bool $bubble = true) { parent::__construct($level, $bubble); $this->logger = $logger; } /** * {@inheritDoc} */ public function handle(array $record): bool { if (!$this->isHandling($record)) { return false; } if ($this->formatter) { $formatted = $this->formatter->format($record); $this->logger->log(strtolower($record['level_name']), (string) $formatted, $record['context']); } else { $this->logger->log(strtolower($record['level_name']), $record['message'], $record['context']); } return false === $this->bubble; } /** * Sets the formatter. * * @param FormatterInterface $formatter */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { $this->formatter = $formatter; return $this; } /** * Gets the formatter. * * @return FormatterInterface */ public function getFormatter(): FormatterInterface { if (!$this->formatter) { throw new \LogicException('No formatter has been set and this handler does not have a default formatter'); } return $this->formatter; } } PK������\5Z蕮 �� ��(��Monolog/Handler/SymfonyMailerHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Utils; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LineFormatter; use Symfony\Component\Mailer\MailerInterface; use Symfony\Component\Mailer\Transport\TransportInterface; use Symfony\Component\Mime\Email; /** * SymfonyMailerHandler uses Symfony's Mailer component to send the emails * * @author Jordi Boggiano <j.boggiano@seld.be> * * @phpstan-import-type Record from \Monolog\Logger */ class SymfonyMailerHandler extends MailHandler { /** @var MailerInterface|TransportInterface */ protected $mailer; /** @var Email|callable(string, Record[]): Email */ private $emailTemplate; /** * @psalm-param Email|callable(string, Record[]): Email $email * * @param MailerInterface|TransportInterface $mailer The mailer to use * @param callable|Email $email An email template, the subject/body will be replaced */ public function __construct($mailer, $email, $level = Logger::ERROR, bool $bubble = true) { parent::__construct($level, $bubble); $this->mailer = $mailer; $this->emailTemplate = $email; } /** * {@inheritDoc} */ protected function send(string $content, array $records): void { $this->mailer->send($this->buildMessage($content, $records)); } /** * Gets the formatter for the Swift_Message subject. * * @param string|null $format The format of the subject */ protected function getSubjectFormatter(?string $format): FormatterInterface { return new LineFormatter($format); } /** * Creates instance of Email to be sent * * @param string $content formatted email body to be sent * @param array $records Log records that formed the content * * @phpstan-param Record[] $records */ protected function buildMessage(string $content, array $records): Email { $message = null; if ($this->emailTemplate instanceof Email) { $message = clone $this->emailTemplate; } elseif (is_callable($this->emailTemplate)) { $message = ($this->emailTemplate)($content, $records); } if (!$message instanceof Email) { $record = reset($records); throw new \InvalidArgumentException('Could not resolve message as instance of Email or a callable returning it' . ($record ? Utils::getRecordMessageForException($record) : '')); } if ($records) { $subjectFormatter = $this->getSubjectFormatter($message->getSubject()); $message->subject($subjectFormatter->format($this->getHighestRecord($records))); } if ($this->isHtmlBody($content)) { if (null !== ($charset = $message->getHtmlCharset())) { $message->html($content, $charset); } else { $message->html($content); } } else { if (null !== ($charset = $message->getTextCharset())) { $message->text($content, $charset); } else { $message->text($content); } } return $message->date(new \DateTimeImmutable()); } } PK������\5ZBM��M��/��Monolog/Handler/FormattableHandlerInterface.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; /** * Interface to describe loggers that have a formatter * * @author Jordi Boggiano <j.boggiano@seld.be> */ interface FormattableHandlerInterface { /** * Sets the formatter. * * @param FormatterInterface $formatter * @return HandlerInterface self */ public function setFormatter(FormatterInterface $formatter): HandlerInterface; /** * Gets the formatter. * * @return FormatterInterface */ public function getFormatter(): FormatterInterface; } PK������\5Z(����(��Monolog/Attribute/AsMonologProcessor.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Attribute; /** * A reusable attribute to help configure a class or a method as a processor. * * Using it offers no guarantee: it needs to be leveraged by a Monolog third-party consumer. * * Using it with the Monolog library only has no effect at all: processors should still be turned into a callable if * needed and manually pushed to the loggers and to the processable handlers. */ #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class AsMonologProcessor { /** @var string|null */ public $channel = null; /** @var string|null */ public $handler = null; /** @var string|null */ public $method = null; /** * @param string|null $channel The logging channel the processor should be pushed to. * @param string|null $handler The handler the processor should be pushed to. * @param string|null $method The method that processes the records (if the attribute is used at the class level). */ public function __construct( ?string $channel = null, ?string $handler = null, ?string $method = null ) { $this->channel = $channel; $this->handler = $handler; $this->method = $method; } } PK������\5ZJ ��J ��'��Monolog/Formatter/LogstashFormatter.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; /** * Serializes a log message to Logstash Event Format * * @see https://www.elastic.co/products/logstash * @see https://github.com/elastic/logstash/blob/master/logstash-core/src/main/java/org/logstash/Event.java * * @author Tim Mower <timothy.mower@gmail.com> */ class LogstashFormatter extends NormalizerFormatter { /** * @var string the name of the system for the Logstash log message, used to fill the @source field */ protected $systemName; /** * @var string an application name for the Logstash log message, used to fill the @type field */ protected $applicationName; /** * @var string the key for 'extra' fields from the Monolog record */ protected $extraKey; /** * @var string the key for 'context' fields from the Monolog record */ protected $contextKey; /** * @param string $applicationName The application that sends the data, used as the "type" field of logstash * @param string|null $systemName The system/machine name, used as the "source" field of logstash, defaults to the hostname of the machine * @param string $extraKey The key for extra keys inside logstash "fields", defaults to extra * @param string $contextKey The key for context keys inside logstash "fields", defaults to context */ public function __construct(string $applicationName, ?string $systemName = null, string $extraKey = 'extra', string $contextKey = 'context') { // logstash requires a ISO 8601 format date with optional millisecond precision. parent::__construct('Y-m-d\TH:i:s.uP'); $this->systemName = $systemName === null ? (string) gethostname() : $systemName; $this->applicationName = $applicationName; $this->extraKey = $extraKey; $this->contextKey = $contextKey; } /** * {@inheritDoc} */ public function format(array $record): string { $record = parent::format($record); if (empty($record['datetime'])) { $record['datetime'] = gmdate('c'); } $message = [ '@timestamp' => $record['datetime'], '@version' => 1, 'host' => $this->systemName, ]; if (isset($record['message'])) { $message['message'] = $record['message']; } if (isset($record['channel'])) { $message['type'] = $record['channel']; $message['channel'] = $record['channel']; } if (isset($record['level_name'])) { $message['level'] = $record['level_name']; } if (isset($record['level'])) { $message['monolog_level'] = $record['level']; } if ($this->applicationName) { $message['type'] = $this->applicationName; } if (!empty($record['extra'])) { $message[$this->extraKey] = $record['extra']; } if (!empty($record['context'])) { $message[$this->contextKey] = $record['context']; } return $this->toJson($message) . "\n"; } } PK������\5ZE��E��,��Monolog/Formatter/ElasticsearchFormatter.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use DateTimeInterface; /** * Format a log message into an Elasticsearch record * * @author Avtandil Kikabidze <akalongman@gmail.com> */ class ElasticsearchFormatter extends NormalizerFormatter { /** * @var string Elasticsearch index name */ protected $index; /** * @var string Elasticsearch record type */ protected $type; /** * @param string $index Elasticsearch index name * @param string $type Elasticsearch record type */ public function __construct(string $index, string $type) { // Elasticsearch requires an ISO 8601 format date with optional millisecond precision. parent::__construct(DateTimeInterface::ISO8601); $this->index = $index; $this->type = $type; } /** * {@inheritDoc} */ public function format(array $record) { $record = parent::format($record); return $this->getDocument($record); } /** * Getter index * * @return string */ public function getIndex(): string { return $this->index; } /** * Getter type * * @return string */ public function getType(): string { return $this->type; } /** * Convert a log message into an Elasticsearch record * * @param mixed[] $record Log message * @return mixed[] */ protected function getDocument(array $record): array { $record['_index'] = $this->index; $record['_type'] = $this->type; return $record; } } PK������\5Z!te5 ��5 ��'��Monolog/Formatter/FlowdockFormatter.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; /** * formats the record to be used in the FlowdockHandler * * @author Dominik Liebler <liebler.dominik@gmail.com> * @deprecated Since 2.9.0 and 3.3.0, Flowdock was shutdown we will thus drop this handler in Monolog 4 */ class FlowdockFormatter implements FormatterInterface { /** * @var string */ private $source; /** * @var string */ private $sourceEmail; public function __construct(string $source, string $sourceEmail) { $this->source = $source; $this->sourceEmail = $sourceEmail; } /** * {@inheritDoc} * * @return mixed[] */ public function format(array $record): array { $tags = [ '#logs', '#' . strtolower($record['level_name']), '#' . $record['channel'], ]; foreach ($record['extra'] as $value) { $tags[] = '#' . $value; } $subject = sprintf( 'in %s: %s - %s', $this->source, $record['level_name'], $this->getShortMessage($record['message']) ); $record['flowdock'] = [ 'source' => $this->source, 'from_address' => $this->sourceEmail, 'subject' => $subject, 'content' => $record['message'], 'tags' => $tags, 'project' => $this->source, ]; return $record; } /** * {@inheritDoc} * * @return mixed[][] */ public function formatBatch(array $records): array { $formatted = []; foreach ($records as $record) { $formatted[] = $this->format($record); } return $formatted; } public function getShortMessage(string $message): string { static $hasMbString; if (null === $hasMbString) { $hasMbString = function_exists('mb_strlen'); } $maxLength = 45; if ($hasMbString) { if (mb_strlen($message, 'UTF-8') > $maxLength) { $message = mb_substr($message, 0, $maxLength - 4, 'UTF-8') . ' ...'; } } else { if (strlen($message) > $maxLength) { $message = substr($message, 0, $maxLength - 4) . ' ...'; } } return $message; } } PK������\5ZqR����'��Monolog/Formatter/LogmaticFormatter.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; /** * Encodes message information into JSON in a format compatible with Logmatic. * * @author Julien Breux <julien.breux@gmail.com> */ class LogmaticFormatter extends JsonFormatter { protected const MARKERS = ["sourcecode", "php"]; /** * @var string */ protected $hostname = ''; /** * @var string */ protected $appname = ''; public function setHostname(string $hostname): self { $this->hostname = $hostname; return $this; } public function setAppname(string $appname): self { $this->appname = $appname; return $this; } /** * Appends the 'hostname' and 'appname' parameter for indexing by Logmatic. * * @see http://doc.logmatic.io/docs/basics-to-send-data * @see \Monolog\Formatter\JsonFormatter::format() */ public function format(array $record): string { if (!empty($this->hostname)) { $record["hostname"] = $this->hostname; } if (!empty($this->appname)) { $record["appname"] = $this->appname; } $record["@marker"] = static::MARKERS; return parent::format($record); } } PK������\5ZX����&��Monolog/Formatter/FluentdFormatter.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\Utils; /** * Class FluentdFormatter * * Serializes a log message to Fluentd unix socket protocol * * Fluentd config: * * <source> * type unix * path /var/run/td-agent/td-agent.sock * </source> * * Monolog setup: * * $logger = new Monolog\Logger('fluent.tag'); * $fluentHandler = new Monolog\Handler\SocketHandler('unix:///var/run/td-agent/td-agent.sock'); * $fluentHandler->setFormatter(new Monolog\Formatter\FluentdFormatter()); * $logger->pushHandler($fluentHandler); * * @author Andrius Putna <fordnox@gmail.com> */ class FluentdFormatter implements FormatterInterface { /** * @var bool $levelTag should message level be a part of the fluentd tag */ protected $levelTag = false; public function __construct(bool $levelTag = false) { if (!function_exists('json_encode')) { throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s FluentdUnixFormatter'); } $this->levelTag = $levelTag; } public function isUsingLevelsInTag(): bool { return $this->levelTag; } public function format(array $record): string { $tag = $record['channel']; if ($this->levelTag) { $tag .= '.' . strtolower($record['level_name']); } $message = [ 'message' => $record['message'], 'context' => $record['context'], 'extra' => $record['extra'], ]; if (!$this->levelTag) { $message['level'] = $record['level']; $message['level_name'] = $record['level_name']; } return Utils::jsonEncode([$tag, $record['datetime']->getTimestamp(), $message]); } public function formatBatch(array $records): string { $message = ''; foreach ($records as $record) { $message .= $this->format($record); } return $message; } } PK������\5Z1e����'��Monolog/Formatter/ElasticaFormatter.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Elastica\Document; /** * Format a log message into an Elastica Document * * @author Jelle Vink <jelle.vink@gmail.com> * * @phpstan-import-type Record from \Monolog\Logger */ class ElasticaFormatter extends NormalizerFormatter { /** * @var string Elastic search index name */ protected $index; /** * @var ?string Elastic search document type */ protected $type; /** * @param string $index Elastic Search index name * @param ?string $type Elastic Search document type, deprecated as of Elastica 7 */ public function __construct(string $index, ?string $type) { // elasticsearch requires a ISO 8601 format date with optional millisecond precision. parent::__construct('Y-m-d\TH:i:s.uP'); $this->index = $index; $this->type = $type; } /** * {@inheritDoc} */ public function format(array $record) { $record = parent::format($record); return $this->getDocument($record); } public function getIndex(): string { return $this->index; } /** * @deprecated since Elastica 7 type has no effect */ public function getType(): string { /** @phpstan-ignore-next-line */ return $this->type; } /** * Convert a log message into an Elastica Document * * @phpstan-param Record $record */ protected function getDocument(array $record): Document { $document = new Document(); $document->setData($record); if (method_exists($document, 'setType')) { /** @phpstan-ignore-next-line */ $document->setType($this->type); } $document->setIndex($this->index); return $document; } } PK������\5Zj��j��1��Monolog/Formatter/GoogleCloudLoggingFormatter.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use DateTimeInterface; use Monolog\LogRecord; /** * Encodes message information into JSON in a format compatible with Cloud logging. * * @see https://cloud.google.com/logging/docs/structured-logging * @see https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry * * @author Luís Cobucci <lcobucci@gmail.com> */ final class GoogleCloudLoggingFormatter extends JsonFormatter { /** {@inheritdoc} **/ public function format(array $record): string { // Re-key level for GCP logging $record['severity'] = $record['level_name']; $record['time'] = $record['datetime']->format(DateTimeInterface::RFC3339_EXTENDED); // Remove keys that are not used by GCP unset($record['level'], $record['level_name'], $record['datetime']); return parent::format($record); } } PK������\5Z4z����(��Monolog/Formatter/FormatterInterface.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; /** * Interface for formatters * * @author Jordi Boggiano <j.boggiano@seld.be> * * @phpstan-import-type Record from \Monolog\Logger */ interface FormatterInterface { /** * Formats a log record. * * @param array $record A record to format * @return mixed The formatted record * * @phpstan-param Record $record */ public function format(array $record); /** * Formats a set of log records. * * @param array $records A set of records to format * @return mixed The formatted set of records * * @phpstan-param Record[] $records */ public function formatBatch(array $records); } PK������\5ZF����%��Monolog/Formatter/ScalarFormatter.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; /** * Formats data into an associative array of scalar values. * Objects and arrays will be JSON encoded. * * @author Andrew Lawson <adlawson@gmail.com> */ class ScalarFormatter extends NormalizerFormatter { /** * {@inheritDoc} * * @phpstan-return array<string, scalar|null> $record */ public function format(array $record): array { $result = []; foreach ($record as $key => $value) { $result[$key] = $this->normalizeValue($value); } return $result; } /** * @param mixed $value * @return scalar|null */ protected function normalizeValue($value) { $normalized = $this->normalize($value); if (is_array($normalized)) { return $this->toJson($normalized, true); } return $normalized; } } PK������\5Z ؑ����%��Monolog/Formatter/LogglyFormatter.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; /** * Encodes message information into JSON in a format compatible with Loggly. * * @author Adam Pancutt <adam@pancutt.com> */ class LogglyFormatter extends JsonFormatter { /** * Overrides the default batch mode to new lines for compatibility with the * Loggly bulk API. */ public function __construct(int $batchMode = self::BATCH_MODE_NEWLINES, bool $appendNewline = false) { parent::__construct($batchMode, $appendNewline); } /** * Appends the 'timestamp' parameter for indexing by Loggly. * * @see https://www.loggly.com/docs/automated-parsing/#json * @see \Monolog\Formatter\JsonFormatter::format() */ public function format(array $record): string { if (isset($record["datetime"]) && ($record["datetime"] instanceof \DateTimeInterface)) { $record["timestamp"] = $record["datetime"]->format("Y-m-d\TH:i:s.uO"); unset($record["datetime"]); } return parent::format($record); } } PK������\5Z& ����#��Monolog/Formatter/HtmlFormatter.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\Logger; use Monolog\Utils; /** * Formats incoming records into an HTML table * * This is especially useful for html email logging * * @author Tiago Brito <tlfbrito@gmail.com> */ class HtmlFormatter extends NormalizerFormatter { /** * Translates Monolog log levels to html color priorities. * * @var array<int, string> */ protected $logLevels = [ Logger::DEBUG => '#CCCCCC', Logger::INFO => '#28A745', Logger::NOTICE => '#17A2B8', Logger::WARNING => '#FFC107', Logger::ERROR => '#FD7E14', Logger::CRITICAL => '#DC3545', Logger::ALERT => '#821722', Logger::EMERGENCY => '#000000', ]; /** * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format */ public function __construct(?string $dateFormat = null) { parent::__construct($dateFormat); } /** * Creates an HTML table row * * @param string $th Row header content * @param string $td Row standard cell content * @param bool $escapeTd false if td content must not be html escaped */ protected function addRow(string $th, string $td = ' ', bool $escapeTd = true): string { $th = htmlspecialchars($th, ENT_NOQUOTES, 'UTF-8'); if ($escapeTd) { $td = '<pre>'.htmlspecialchars($td, ENT_NOQUOTES, 'UTF-8').'</pre>'; } return "<tr style=\"padding: 4px;text-align: left;\">\n<th style=\"vertical-align: top;background: #ccc;color: #000\" width=\"100\">$th:</th>\n<td style=\"padding: 4px;text-align: left;vertical-align: top;background: #eee;color: #000\">".$td."</td>\n</tr>"; } /** * Create a HTML h1 tag * * @param string $title Text to be in the h1 * @param int $level Error level * @return string */ protected function addTitle(string $title, int $level): string { $title = htmlspecialchars($title, ENT_NOQUOTES, 'UTF-8'); return '<h1 style="background: '.$this->logLevels[$level].';color: #ffffff;padding: 5px;" class="monolog-output">'.$title.'</h1>'; } /** * Formats a log record. * * @return string The formatted record */ public function format(array $record): string { $output = $this->addTitle($record['level_name'], $record['level']); $output .= '<table cellspacing="1" width="100%" class="monolog-output">'; $output .= $this->addRow('Message', (string) $record['message']); $output .= $this->addRow('Time', $this->formatDate($record['datetime'])); $output .= $this->addRow('Channel', $record['channel']); if ($record['context']) { $embeddedTable = '<table cellspacing="1" width="100%">'; foreach ($record['context'] as $key => $value) { $embeddedTable .= $this->addRow((string) $key, $this->convertToString($value)); } $embeddedTable .= '</table>'; $output .= $this->addRow('Context', $embeddedTable, false); } if ($record['extra']) { $embeddedTable = '<table cellspacing="1" width="100%">'; foreach ($record['extra'] as $key => $value) { $embeddedTable .= $this->addRow((string) $key, $this->convertToString($value)); } $embeddedTable .= '</table>'; $output .= $this->addRow('Extra', $embeddedTable, false); } return $output.'</table>'; } /** * Formats a set of log records. * * @return string The formatted set of records */ public function formatBatch(array $records): string { $message = ''; foreach ($records as $record) { $message .= $this->format($record); } return $message; } /** * @param mixed $data */ protected function convertToString($data): string { if (null === $data || is_scalar($data)) { return (string) $data; } $data = $this->normalize($data); return Utils::jsonEncode($data, JSON_PRETTY_PRINT | Utils::DEFAULT_JSON_FLAGS, true); } } PK������\5Z݃����*��Monolog/Formatter/GelfMessageFormatter.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\Logger; use Gelf\Message; use Monolog\Utils; /** * Serializes a log message to GELF * @see http://docs.graylog.org/en/latest/pages/gelf.html * * @author Matt Lehner <mlehner@gmail.com> * * @phpstan-import-type Level from \Monolog\Logger */ class GelfMessageFormatter extends NormalizerFormatter { protected const DEFAULT_MAX_LENGTH = 32766; /** * @var string the name of the system for the Gelf log message */ protected $systemName; /** * @var string a prefix for 'extra' fields from the Monolog record (optional) */ protected $extraPrefix; /** * @var string a prefix for 'context' fields from the Monolog record (optional) */ protected $contextPrefix; /** * @var int max length per field */ protected $maxLength; /** * @var int */ private $gelfVersion = 2; /** * Translates Monolog log levels to Graylog2 log priorities. * * @var array<int, int> * * @phpstan-var array<Level, int> */ private $logLevels = [ Logger::DEBUG => 7, Logger::INFO => 6, Logger::NOTICE => 5, Logger::WARNING => 4, Logger::ERROR => 3, Logger::CRITICAL => 2, Logger::ALERT => 1, Logger::EMERGENCY => 0, ]; public function __construct(?string $systemName = null, ?string $extraPrefix = null, string $contextPrefix = 'ctxt_', ?int $maxLength = null) { if (!class_exists(Message::class)) { throw new \RuntimeException('Composer package graylog2/gelf-php is required to use Monolog\'s GelfMessageFormatter'); } parent::__construct('U.u'); $this->systemName = (is_null($systemName) || $systemName === '') ? (string) gethostname() : $systemName; $this->extraPrefix = is_null($extraPrefix) ? '' : $extraPrefix; $this->contextPrefix = $contextPrefix; $this->maxLength = is_null($maxLength) ? self::DEFAULT_MAX_LENGTH : $maxLength; if (method_exists(Message::class, 'setFacility')) { $this->gelfVersion = 1; } } /** * {@inheritDoc} */ public function format(array $record): Message { $context = $extra = []; if (isset($record['context'])) { /** @var mixed[] $context */ $context = parent::normalize($record['context']); } if (isset($record['extra'])) { /** @var mixed[] $extra */ $extra = parent::normalize($record['extra']); } if (!isset($record['datetime'], $record['message'], $record['level'])) { throw new \InvalidArgumentException('The record should at least contain datetime, message and level keys, '.var_export($record, true).' given'); } $message = new Message(); $message ->setTimestamp($record['datetime']) ->setShortMessage((string) $record['message']) ->setHost($this->systemName) ->setLevel($this->logLevels[$record['level']]); // message length + system name length + 200 for padding / metadata $len = 200 + strlen((string) $record['message']) + strlen($this->systemName); if ($len > $this->maxLength) { $message->setShortMessage(Utils::substr($record['message'], 0, $this->maxLength)); } if ($this->gelfVersion === 1) { if (isset($record['channel'])) { $message->setFacility($record['channel']); } if (isset($extra['line'])) { $message->setLine($extra['line']); unset($extra['line']); } if (isset($extra['file'])) { $message->setFile($extra['file']); unset($extra['file']); } } else { $message->setAdditional('facility', $record['channel']); } foreach ($extra as $key => $val) { $val = is_scalar($val) || null === $val ? $val : $this->toJson($val); $len = strlen($this->extraPrefix . $key . $val); if ($len > $this->maxLength) { $message->setAdditional($this->extraPrefix . $key, Utils::substr((string) $val, 0, $this->maxLength)); continue; } $message->setAdditional($this->extraPrefix . $key, $val); } foreach ($context as $key => $val) { $val = is_scalar($val) || null === $val ? $val : $this->toJson($val); $len = strlen($this->contextPrefix . $key . $val); if ($len > $this->maxLength) { $message->setAdditional($this->contextPrefix . $key, Utils::substr((string) $val, 0, $this->maxLength)); continue; } $message->setAdditional($this->contextPrefix . $key, $val); } if ($this->gelfVersion === 1) { /** @phpstan-ignore-next-line */ if (null === $message->getFile() && isset($context['exception']['file'])) { if (preg_match("/^(.+):([0-9]+)$/", $context['exception']['file'], $matches)) { $message->setFile($matches[1]); $message->setLine($matches[2]); } } } return $message; } } PK������\5Zn����#��Monolog/Formatter/JsonFormatter.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Throwable; /** * Encodes whatever record data is passed to it as json * * This can be useful to log to databases or remote APIs * * @author Jordi Boggiano <j.boggiano@seld.be> * * @phpstan-import-type Record from \Monolog\Logger */ class JsonFormatter extends NormalizerFormatter { public const BATCH_MODE_JSON = 1; public const BATCH_MODE_NEWLINES = 2; /** @var self::BATCH_MODE_* */ protected $batchMode; /** @var bool */ protected $appendNewline; /** @var bool */ protected $ignoreEmptyContextAndExtra; /** @var bool */ protected $includeStacktraces = false; /** * @param self::BATCH_MODE_* $batchMode */ public function __construct(int $batchMode = self::BATCH_MODE_JSON, bool $appendNewline = true, bool $ignoreEmptyContextAndExtra = false, bool $includeStacktraces = false) { $this->batchMode = $batchMode; $this->appendNewline = $appendNewline; $this->ignoreEmptyContextAndExtra = $ignoreEmptyContextAndExtra; $this->includeStacktraces = $includeStacktraces; parent::__construct(); } /** * The batch mode option configures the formatting style for * multiple records. By default, multiple records will be * formatted as a JSON-encoded array. However, for * compatibility with some API endpoints, alternative styles * are available. */ public function getBatchMode(): int { return $this->batchMode; } /** * True if newlines are appended to every formatted record */ public function isAppendingNewlines(): bool { return $this->appendNewline; } /** * {@inheritDoc} */ public function format(array $record): string { $normalized = $this->normalize($record); if (isset($normalized['context']) && $normalized['context'] === []) { if ($this->ignoreEmptyContextAndExtra) { unset($normalized['context']); } else { $normalized['context'] = new \stdClass; } } if (isset($normalized['extra']) && $normalized['extra'] === []) { if ($this->ignoreEmptyContextAndExtra) { unset($normalized['extra']); } else { $normalized['extra'] = new \stdClass; } } return $this->toJson($normalized, true) . ($this->appendNewline ? "\n" : ''); } /** * {@inheritDoc} */ public function formatBatch(array $records): string { switch ($this->batchMode) { case static::BATCH_MODE_NEWLINES: return $this->formatBatchNewlines($records); case static::BATCH_MODE_JSON: default: return $this->formatBatchJson($records); } } /** * @return self */ public function includeStacktraces(bool $include = true): self { $this->includeStacktraces = $include; return $this; } /** * Return a JSON-encoded array of records. * * @phpstan-param Record[] $records */ protected function formatBatchJson(array $records): string { return $this->toJson($this->normalize($records), true); } /** * Use new lines to separate records instead of a * JSON-encoded array. * * @phpstan-param Record[] $records */ protected function formatBatchNewlines(array $records): string { $instance = $this; $oldNewline = $this->appendNewline; $this->appendNewline = false; array_walk($records, function (&$value, $key) use ($instance) { $value = $instance->format($value); }); $this->appendNewline = $oldNewline; return implode("\n", $records); } /** * Normalizes given $data. * * @param mixed $data * * @return mixed */ protected function normalize($data, int $depth = 0) { if ($depth > $this->maxNormalizeDepth) { return 'Over '.$this->maxNormalizeDepth.' levels deep, aborting normalization'; } if (is_array($data)) { $normalized = []; $count = 1; foreach ($data as $key => $value) { if ($count++ > $this->maxNormalizeItemCount) { $normalized['...'] = 'Over '.$this->maxNormalizeItemCount.' items ('.count($data).' total), aborting normalization'; break; } $normalized[$key] = $this->normalize($value, $depth + 1); } return $normalized; } if (is_object($data)) { if ($data instanceof \DateTimeInterface) { return $this->formatDate($data); } if ($data instanceof Throwable) { return $this->normalizeException($data, $depth); } // if the object has specific json serializability we want to make sure we skip the __toString treatment below if ($data instanceof \JsonSerializable) { return $data; } if (method_exists($data, '__toString')) { return $data->__toString(); } return $data; } if (is_resource($data)) { return parent::normalize($data); } return $data; } /** * Normalizes given exception with or without its own stack trace based on * `includeStacktraces` property. * * {@inheritDoc} */ protected function normalizeException(Throwable $e, int $depth = 0): array { $data = parent::normalizeException($e, $depth); if (!$this->includeStacktraces) { unset($data['trace']); } return $data; } } PK������\5Z13ca��a��'��Monolog/Formatter/WildfireFormatter.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\Logger; /** * Serializes a log message according to Wildfire's header requirements * * @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com> * @author Christophe Coevoet <stof@notk.org> * @author Kirill chEbba Chebunin <iam@chebba.org> * * @phpstan-import-type Level from \Monolog\Logger */ class WildfireFormatter extends NormalizerFormatter { /** * Translates Monolog log levels to Wildfire levels. * * @var array<Level, string> */ private $logLevels = [ Logger::DEBUG => 'LOG', Logger::INFO => 'INFO', Logger::NOTICE => 'INFO', Logger::WARNING => 'WARN', Logger::ERROR => 'ERROR', Logger::CRITICAL => 'ERROR', Logger::ALERT => 'ERROR', Logger::EMERGENCY => 'ERROR', ]; /** * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format */ public function __construct(?string $dateFormat = null) { parent::__construct($dateFormat); // http headers do not like non-ISO-8559-1 characters $this->removeJsonEncodeOption(JSON_UNESCAPED_UNICODE); } /** * {@inheritDoc} * * @return string */ public function format(array $record): string { // Retrieve the line and file if set and remove them from the formatted extra $file = $line = ''; if (isset($record['extra']['file'])) { $file = $record['extra']['file']; unset($record['extra']['file']); } if (isset($record['extra']['line'])) { $line = $record['extra']['line']; unset($record['extra']['line']); } /** @var mixed[] $record */ $record = $this->normalize($record); $message = ['message' => $record['message']]; $handleError = false; if ($record['context']) { $message['context'] = $record['context']; $handleError = true; } if ($record['extra']) { $message['extra'] = $record['extra']; $handleError = true; } if (count($message) === 1) { $message = reset($message); } if (isset($record['context']['table'])) { $type = 'TABLE'; $label = $record['channel'] .': '. $record['message']; $message = $record['context']['table']; } else { $type = $this->logLevels[$record['level']]; $label = $record['channel']; } // Create JSON object describing the appearance of the message in the console $json = $this->toJson([ [ 'Type' => $type, 'File' => $file, 'Line' => $line, 'Label' => $label, ], $message, ], $handleError); // The message itself is a serialization of the above JSON object + it's length return sprintf( '%d|%s|', strlen($json), $json ); } /** * {@inheritDoc} * * @phpstan-return never */ public function formatBatch(array $records) { throw new \BadMethodCallException('Batch formatting does not make sense for the WildfireFormatter'); } /** * {@inheritDoc} * * @return null|scalar|array<array|scalar|null>|object */ protected function normalize($data, int $depth = 0) { if (is_object($data) && !$data instanceof \DateTimeInterface) { return $data; } return parent::normalize($data, $depth); } } PK������\5Zl��l��&��Monolog/Formatter/MongoDBFormatter.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use MongoDB\BSON\Type; use MongoDB\BSON\UTCDateTime; use Monolog\Utils; /** * Formats a record for use with the MongoDBHandler. * * @author Florian Plattner <me@florianplattner.de> */ class MongoDBFormatter implements FormatterInterface { /** @var bool */ private $exceptionTraceAsString; /** @var int */ private $maxNestingLevel; /** @var bool */ private $isLegacyMongoExt; /** * @param int $maxNestingLevel 0 means infinite nesting, the $record itself is level 1, $record['context'] is 2 * @param bool $exceptionTraceAsString set to false to log exception traces as a sub documents instead of strings */ public function __construct(int $maxNestingLevel = 3, bool $exceptionTraceAsString = true) { $this->maxNestingLevel = max($maxNestingLevel, 0); $this->exceptionTraceAsString = $exceptionTraceAsString; $this->isLegacyMongoExt = extension_loaded('mongodb') && version_compare((string) phpversion('mongodb'), '1.1.9', '<='); } /** * {@inheritDoc} * * @return mixed[] */ public function format(array $record): array { /** @var mixed[] $res */ $res = $this->formatArray($record); return $res; } /** * {@inheritDoc} * * @return array<mixed[]> */ public function formatBatch(array $records): array { $formatted = []; foreach ($records as $key => $record) { $formatted[$key] = $this->format($record); } return $formatted; } /** * @param mixed[] $array * @return mixed[]|string Array except when max nesting level is reached then a string "[...]" */ protected function formatArray(array $array, int $nestingLevel = 0) { if ($this->maxNestingLevel > 0 && $nestingLevel > $this->maxNestingLevel) { return '[...]'; } foreach ($array as $name => $value) { if ($value instanceof \DateTimeInterface) { $array[$name] = $this->formatDate($value, $nestingLevel + 1); } elseif ($value instanceof \Throwable) { $array[$name] = $this->formatException($value, $nestingLevel + 1); } elseif (is_array($value)) { $array[$name] = $this->formatArray($value, $nestingLevel + 1); } elseif (is_object($value) && !$value instanceof Type) { $array[$name] = $this->formatObject($value, $nestingLevel + 1); } } return $array; } /** * @param mixed $value * @return mixed[]|string */ protected function formatObject($value, int $nestingLevel) { $objectVars = get_object_vars($value); $objectVars['class'] = Utils::getClass($value); return $this->formatArray($objectVars, $nestingLevel); } /** * @return mixed[]|string */ protected function formatException(\Throwable $exception, int $nestingLevel) { $formattedException = [ 'class' => Utils::getClass($exception), 'message' => $exception->getMessage(), 'code' => (int) $exception->getCode(), 'file' => $exception->getFile() . ':' . $exception->getLine(), ]; if ($this->exceptionTraceAsString === true) { $formattedException['trace'] = $exception->getTraceAsString(); } else { $formattedException['trace'] = $exception->getTrace(); } return $this->formatArray($formattedException, $nestingLevel); } protected function formatDate(\DateTimeInterface $value, int $nestingLevel): UTCDateTime { if ($this->isLegacyMongoExt) { return $this->legacyGetMongoDbDateTime($value); } return $this->getMongoDbDateTime($value); } private function getMongoDbDateTime(\DateTimeInterface $value): UTCDateTime { return new UTCDateTime((int) floor(((float) $value->format('U.u')) * 1000)); } /** * This is needed to support MongoDB Driver v1.19 and below * * See https://github.com/mongodb/mongo-php-driver/issues/426 * * It can probably be removed in 2.1 or later once MongoDB's 1.2 is released and widely adopted */ private function legacyGetMongoDbDateTime(\DateTimeInterface $value): UTCDateTime { $milliseconds = floor(((float) $value->format('U.u')) * 1000); $milliseconds = (PHP_INT_SIZE == 8) //64-bit OS? ? (int) $milliseconds : (string) $milliseconds; // @phpstan-ignore-next-line return new UTCDateTime($milliseconds); } } PK������\5Z](M`��`��(��Monolog/Formatter/ChromePHPFormatter.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\Logger; /** * Formats a log message according to the ChromePHP array format * * @author Christophe Coevoet <stof@notk.org> */ class ChromePHPFormatter implements FormatterInterface { /** * Translates Monolog log levels to Wildfire levels. * * @var array<int, 'log'|'info'|'warn'|'error'> */ private $logLevels = [ Logger::DEBUG => 'log', Logger::INFO => 'info', Logger::NOTICE => 'info', Logger::WARNING => 'warn', Logger::ERROR => 'error', Logger::CRITICAL => 'error', Logger::ALERT => 'error', Logger::EMERGENCY => 'error', ]; /** * {@inheritDoc} */ public function format(array $record) { // Retrieve the line and file if set and remove them from the formatted extra $backtrace = 'unknown'; if (isset($record['extra']['file'], $record['extra']['line'])) { $backtrace = $record['extra']['file'].' : '.$record['extra']['line']; unset($record['extra']['file'], $record['extra']['line']); } $message = ['message' => $record['message']]; if ($record['context']) { $message['context'] = $record['context']; } if ($record['extra']) { $message['extra'] = $record['extra']; } if (count($message) === 1) { $message = reset($message); } return [ $record['channel'], $message, $backtrace, $this->logLevels[$record['level']], ]; } /** * {@inheritDoc} */ public function formatBatch(array $records) { $formatted = []; foreach ($records as $record) { $formatted[] = $this->format($record); } return $formatted; } } PK������\5Zf��f��)��Monolog/Formatter/NormalizerFormatter.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\DateTimeImmutable; use Monolog\Utils; use Throwable; /** * Normalizes incoming records to remove objects/resources so it's easier to dump to various targets * * @author Jordi Boggiano <j.boggiano@seld.be> */ class NormalizerFormatter implements FormatterInterface { public const SIMPLE_DATE = "Y-m-d\TH:i:sP"; /** @var string */ protected $dateFormat; /** @var int */ protected $maxNormalizeDepth = 9; /** @var int */ protected $maxNormalizeItemCount = 1000; /** @var int */ private $jsonEncodeOptions = Utils::DEFAULT_JSON_FLAGS; /** * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format */ public function __construct(?string $dateFormat = null) { $this->dateFormat = null === $dateFormat ? static::SIMPLE_DATE : $dateFormat; if (!function_exists('json_encode')) { throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s NormalizerFormatter'); } } /** * {@inheritDoc} * * @param mixed[] $record */ public function format(array $record) { return $this->normalize($record); } /** * {@inheritDoc} */ public function formatBatch(array $records) { foreach ($records as $key => $record) { $records[$key] = $this->format($record); } return $records; } public function getDateFormat(): string { return $this->dateFormat; } public function setDateFormat(string $dateFormat): self { $this->dateFormat = $dateFormat; return $this; } /** * The maximum number of normalization levels to go through */ public function getMaxNormalizeDepth(): int { return $this->maxNormalizeDepth; } public function setMaxNormalizeDepth(int $maxNormalizeDepth): self { $this->maxNormalizeDepth = $maxNormalizeDepth; return $this; } /** * The maximum number of items to normalize per level */ public function getMaxNormalizeItemCount(): int { return $this->maxNormalizeItemCount; } public function setMaxNormalizeItemCount(int $maxNormalizeItemCount): self { $this->maxNormalizeItemCount = $maxNormalizeItemCount; return $this; } /** * Enables `json_encode` pretty print. */ public function setJsonPrettyPrint(bool $enable): self { if ($enable) { $this->jsonEncodeOptions |= JSON_PRETTY_PRINT; } else { $this->jsonEncodeOptions &= ~JSON_PRETTY_PRINT; } return $this; } /** * @param mixed $data * @return null|scalar|array<array|scalar|null> */ protected function normalize($data, int $depth = 0) { if ($depth > $this->maxNormalizeDepth) { return 'Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization'; } if (null === $data || is_scalar($data)) { if (is_float($data)) { if (is_infinite($data)) { return ($data > 0 ? '' : '-') . 'INF'; } if (is_nan($data)) { return 'NaN'; } } return $data; } if (is_array($data)) { $normalized = []; $count = 1; foreach ($data as $key => $value) { if ($count++ > $this->maxNormalizeItemCount) { $normalized['...'] = 'Over ' . $this->maxNormalizeItemCount . ' items ('.count($data).' total), aborting normalization'; break; } $normalized[$key] = $this->normalize($value, $depth + 1); } return $normalized; } if ($data instanceof \DateTimeInterface) { return $this->formatDate($data); } if (is_object($data)) { if ($data instanceof Throwable) { return $this->normalizeException($data, $depth); } if ($data instanceof \JsonSerializable) { /** @var null|scalar|array<array|scalar|null> $value */ $value = $data->jsonSerialize(); } elseif (method_exists($data, '__toString')) { /** @var string $value */ $value = $data->__toString(); } else { // the rest is normalized by json encoding and decoding it /** @var null|scalar|array<array|scalar|null> $value */ $value = json_decode($this->toJson($data, true), true); } return [Utils::getClass($data) => $value]; } if (is_resource($data)) { return sprintf('[resource(%s)]', get_resource_type($data)); } return '[unknown('.gettype($data).')]'; } /** * @return mixed[] */ protected function normalizeException(Throwable $e, int $depth = 0) { if ($depth > $this->maxNormalizeDepth) { return ['Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization']; } if ($e instanceof \JsonSerializable) { return (array) $e->jsonSerialize(); } $data = [ 'class' => Utils::getClass($e), 'message' => $e->getMessage(), 'code' => (int) $e->getCode(), 'file' => $e->getFile().':'.$e->getLine(), ]; if ($e instanceof \SoapFault) { if (isset($e->faultcode)) { $data['faultcode'] = $e->faultcode; } if (isset($e->faultactor)) { $data['faultactor'] = $e->faultactor; } if (isset($e->detail)) { if (is_string($e->detail)) { $data['detail'] = $e->detail; } elseif (is_object($e->detail) || is_array($e->detail)) { $data['detail'] = $this->toJson($e->detail, true); } } } $trace = $e->getTrace(); foreach ($trace as $frame) { if (isset($frame['file'])) { $data['trace'][] = $frame['file'].':'.$frame['line']; } } if ($previous = $e->getPrevious()) { $data['previous'] = $this->normalizeException($previous, $depth + 1); } return $data; } /** * Return the JSON representation of a value * * @param mixed $data * @throws \RuntimeException if encoding fails and errors are not ignored * @return string if encoding fails and ignoreErrors is true 'null' is returned */ protected function toJson($data, bool $ignoreErrors = false): string { return Utils::jsonEncode($data, $this->jsonEncodeOptions, $ignoreErrors); } /** * @return string */ protected function formatDate(\DateTimeInterface $date) { // in case the date format isn't custom then we defer to the custom DateTimeImmutable // formatting logic, which will pick the right format based on whether useMicroseconds is on if ($this->dateFormat === self::SIMPLE_DATE && $date instanceof DateTimeImmutable) { return (string) $date; } return $date->format($this->dateFormat); } public function addJsonEncodeOption(int $option): self { $this->jsonEncodeOptions |= $option; return $this; } public function removeJsonEncodeOption(int $option): self { $this->jsonEncodeOptions &= ~$option; return $this; } } PK������\5ZR; �� ��#��Monolog/Formatter/LineFormatter.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\Utils; /** * Formats incoming records into a one-line string * * This is especially useful for logging to files * * @author Jordi Boggiano <j.boggiano@seld.be> * @author Christophe Coevoet <stof@notk.org> */ class LineFormatter extends NormalizerFormatter { public const SIMPLE_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"; /** @var string */ protected $format; /** @var bool */ protected $allowInlineLineBreaks; /** @var bool */ protected $ignoreEmptyContextAndExtra; /** @var bool */ protected $includeStacktraces; /** @var ?callable */ protected $stacktracesParser; /** * @param string|null $format The format of the message * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format * @param bool $allowInlineLineBreaks Whether to allow inline line breaks in log entries * @param bool $ignoreEmptyContextAndExtra */ public function __construct(?string $format = null, ?string $dateFormat = null, bool $allowInlineLineBreaks = false, bool $ignoreEmptyContextAndExtra = false, bool $includeStacktraces = false) { $this->format = $format === null ? static::SIMPLE_FORMAT : $format; $this->allowInlineLineBreaks = $allowInlineLineBreaks; $this->ignoreEmptyContextAndExtra = $ignoreEmptyContextAndExtra; $this->includeStacktraces($includeStacktraces); parent::__construct($dateFormat); } public function includeStacktraces(bool $include = true, ?callable $parser = null): self { $this->includeStacktraces = $include; if ($this->includeStacktraces) { $this->allowInlineLineBreaks = true; $this->stacktracesParser = $parser; } return $this; } public function allowInlineLineBreaks(bool $allow = true): self { $this->allowInlineLineBreaks = $allow; return $this; } public function ignoreEmptyContextAndExtra(bool $ignore = true): self { $this->ignoreEmptyContextAndExtra = $ignore; return $this; } /** * {@inheritDoc} */ public function format(array $record): string { $vars = parent::format($record); $output = $this->format; foreach ($vars['extra'] as $var => $val) { if (false !== strpos($output, '%extra.'.$var.'%')) { $output = str_replace('%extra.'.$var.'%', $this->stringify($val), $output); unset($vars['extra'][$var]); } } foreach ($vars['context'] as $var => $val) { if (false !== strpos($output, '%context.'.$var.'%')) { $output = str_replace('%context.'.$var.'%', $this->stringify($val), $output); unset($vars['context'][$var]); } } if ($this->ignoreEmptyContextAndExtra) { if (empty($vars['context'])) { unset($vars['context']); $output = str_replace('%context%', '', $output); } if (empty($vars['extra'])) { unset($vars['extra']); $output = str_replace('%extra%', '', $output); } } foreach ($vars as $var => $val) { if (false !== strpos($output, '%'.$var.'%')) { $output = str_replace('%'.$var.'%', $this->stringify($val), $output); } } // remove leftover %extra.xxx% and %context.xxx% if any if (false !== strpos($output, '%')) { $output = preg_replace('/%(?:extra|context)\..+?%/', '', $output); if (null === $output) { $pcreErrorCode = preg_last_error(); throw new \RuntimeException('Failed to run preg_replace: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode)); } } return $output; } public function formatBatch(array $records): string { $message = ''; foreach ($records as $record) { $message .= $this->format($record); } return $message; } /** * @param mixed $value */ public function stringify($value): string { return $this->replaceNewlines($this->convertToString($value)); } protected function normalizeException(\Throwable $e, int $depth = 0): string { $str = $this->formatException($e); if ($previous = $e->getPrevious()) { do { $depth++; if ($depth > $this->maxNormalizeDepth) { $str .= '\n[previous exception] Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization'; break; } $str .= "\n[previous exception] " . $this->formatException($previous); } while ($previous = $previous->getPrevious()); } return $str; } /** * @param mixed $data */ protected function convertToString($data): string { if (null === $data || is_bool($data)) { return var_export($data, true); } if (is_scalar($data)) { return (string) $data; } return $this->toJson($data, true); } protected function replaceNewlines(string $str): string { if ($this->allowInlineLineBreaks) { if (0 === strpos($str, '{')) { $str = preg_replace('/(?<!\\\\)\\\\[rn]/', "\n", $str); if (null === $str) { $pcreErrorCode = preg_last_error(); throw new \RuntimeException('Failed to run preg_replace: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode)); } } return $str; } return str_replace(["\r\n", "\r", "\n"], ' ', $str); } private function formatException(\Throwable $e): string { $str = '[object] (' . Utils::getClass($e) . '(code: ' . $e->getCode(); if ($e instanceof \SoapFault) { if (isset($e->faultcode)) { $str .= ' faultcode: ' . $e->faultcode; } if (isset($e->faultactor)) { $str .= ' faultactor: ' . $e->faultactor; } if (isset($e->detail)) { if (is_string($e->detail)) { $str .= ' detail: ' . $e->detail; } elseif (is_object($e->detail) || is_array($e->detail)) { $str .= ' detail: ' . $this->toJson($e->detail, true); } } } $str .= '): ' . $e->getMessage() . ' at ' . $e->getFile() . ':' . $e->getLine() . ')'; if ($this->includeStacktraces) { $str .= $this->stacktracesParser($e); } return $str; } private function stacktracesParser(\Throwable $e): string { $trace = $e->getTraceAsString(); if ($this->stacktracesParser) { $trace = $this->stacktracesParserCustom($trace); } return "\n[stacktrace]\n" . $trace . "\n"; } private function stacktracesParserCustom(string $trace): string { return implode("\n", array_filter(array_map($this->stacktracesParser, explode("\n", $trace)))); } } PK������\5Z7DA%��A%����Monolog/Utils.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog; final class Utils { const DEFAULT_JSON_FLAGS = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION | JSON_INVALID_UTF8_SUBSTITUTE | JSON_PARTIAL_OUTPUT_ON_ERROR; public static function getClass(object $object): string { $class = \get_class($object); if (false === ($pos = \strpos($class, "@anonymous\0"))) { return $class; } if (false === ($parent = \get_parent_class($class))) { return \substr($class, 0, $pos + 10); } return $parent . '@anonymous'; } public static function substr(string $string, int $start, ?int $length = null): string { if (extension_loaded('mbstring')) { return mb_strcut($string, $start, $length); } return substr($string, $start, (null === $length) ? strlen($string) : $length); } /** * Makes sure if a relative path is passed in it is turned into an absolute path * * @param string $streamUrl stream URL or path without protocol */ public static function canonicalizePath(string $streamUrl): string { $prefix = ''; if ('file://' === substr($streamUrl, 0, 7)) { $streamUrl = substr($streamUrl, 7); $prefix = 'file://'; } // other type of stream, not supported if (false !== strpos($streamUrl, '://')) { return $streamUrl; } // already absolute if (substr($streamUrl, 0, 1) === '/' || substr($streamUrl, 1, 1) === ':' || substr($streamUrl, 0, 2) === '\\\\') { return $prefix.$streamUrl; } $streamUrl = getcwd() . '/' . $streamUrl; return $prefix.$streamUrl; } /** * Return the JSON representation of a value * * @param mixed $data * @param int $encodeFlags flags to pass to json encode, defaults to DEFAULT_JSON_FLAGS * @param bool $ignoreErrors whether to ignore encoding errors or to throw on error, when ignored and the encoding fails, "null" is returned which is valid json for null * @throws \RuntimeException if encoding fails and errors are not ignored * @return string when errors are ignored and the encoding fails, "null" is returned which is valid json for null */ public static function jsonEncode($data, ?int $encodeFlags = null, bool $ignoreErrors = false): string { if (null === $encodeFlags) { $encodeFlags = self::DEFAULT_JSON_FLAGS; } if ($ignoreErrors) { $json = @json_encode($data, $encodeFlags); if (false === $json) { return 'null'; } return $json; } $json = json_encode($data, $encodeFlags); if (false === $json) { $json = self::handleJsonError(json_last_error(), $data); } return $json; } /** * Handle a json_encode failure. * * If the failure is due to invalid string encoding, try to clean the * input and encode again. If the second encoding attempt fails, the * initial error is not encoding related or the input can't be cleaned then * raise a descriptive exception. * * @param int $code return code of json_last_error function * @param mixed $data data that was meant to be encoded * @param int $encodeFlags flags to pass to json encode, defaults to JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION * @throws \RuntimeException if failure can't be corrected * @return string JSON encoded data after error correction */ public static function handleJsonError(int $code, $data, ?int $encodeFlags = null): string { if ($code !== JSON_ERROR_UTF8) { self::throwEncodeError($code, $data); } if (is_string($data)) { self::detectAndCleanUtf8($data); } elseif (is_array($data)) { array_walk_recursive($data, array('Monolog\Utils', 'detectAndCleanUtf8')); } else { self::throwEncodeError($code, $data); } if (null === $encodeFlags) { $encodeFlags = self::DEFAULT_JSON_FLAGS; } $json = json_encode($data, $encodeFlags); if ($json === false) { self::throwEncodeError(json_last_error(), $data); } return $json; } /** * @internal */ public static function pcreLastErrorMessage(int $code): string { if (PHP_VERSION_ID >= 80000) { return preg_last_error_msg(); } $constants = (get_defined_constants(true))['pcre']; $constants = array_filter($constants, function ($key) { return substr($key, -6) == '_ERROR'; }, ARRAY_FILTER_USE_KEY); $constants = array_flip($constants); return $constants[$code] ?? 'UNDEFINED_ERROR'; } /** * Throws an exception according to a given code with a customized message * * @param int $code return code of json_last_error function * @param mixed $data data that was meant to be encoded * @throws \RuntimeException * * @return never */ private static function throwEncodeError(int $code, $data): void { switch ($code) { case JSON_ERROR_DEPTH: $msg = 'Maximum stack depth exceeded'; break; case JSON_ERROR_STATE_MISMATCH: $msg = 'Underflow or the modes mismatch'; break; case JSON_ERROR_CTRL_CHAR: $msg = 'Unexpected control character found'; break; case JSON_ERROR_UTF8: $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded'; break; default: $msg = 'Unknown error'; } throw new \RuntimeException('JSON encoding failed: '.$msg.'. Encoding: '.var_export($data, true)); } /** * Detect invalid UTF-8 string characters and convert to valid UTF-8. * * Valid UTF-8 input will be left unmodified, but strings containing * invalid UTF-8 codepoints will be reencoded as UTF-8 with an assumed * original encoding of ISO-8859-15. This conversion may result in * incorrect output if the actual encoding was not ISO-8859-15, but it * will be clean UTF-8 output and will not rely on expensive and fragile * detection algorithms. * * Function converts the input in place in the passed variable so that it * can be used as a callback for array_walk_recursive. * * @param mixed $data Input to check and convert if needed, passed by ref */ private static function detectAndCleanUtf8(&$data): void { if (is_string($data) && !preg_match('//u', $data)) { $data = preg_replace_callback( '/[\x80-\xFF]+/', function ($m) { return function_exists('mb_convert_encoding') ? mb_convert_encoding($m[0], 'UTF-8', 'ISO-8859-1') : utf8_encode($m[0]); }, $data ); if (!is_string($data)) { $pcreErrorCode = preg_last_error(); throw new \RuntimeException('Failed to preg_replace_callback: ' . $pcreErrorCode . ' / ' . self::pcreLastErrorMessage($pcreErrorCode)); } $data = str_replace( ['¤', '¦', '¨', '´', '¸', '¼', '½', '¾'], ['€', 'Š', 'š', 'Ž', 'ž', 'Œ', 'œ', 'Ÿ'], $data ); } } /** * Converts a string with a valid 'memory_limit' format, to bytes. * * @param string|false $val * @return int|false Returns an integer representing bytes. Returns FALSE in case of error. */ public static function expandIniShorthandBytes($val) { if (!is_string($val)) { return false; } // support -1 if ((int) $val < 0) { return (int) $val; } if (!preg_match('/^\s*(?<val>\d+)(?:\.\d+)?\s*(?<unit>[gmk]?)\s*$/i', $val, $match)) { return false; } $val = (int) $match['val']; switch (strtolower($match['unit'] ?? '')) { case 'g': $val *= 1024; case 'm': $val *= 1024; case 'k': $val *= 1024; } return $val; } /** * @param array<mixed> $record */ public static function getRecordMessageForException(array $record): string { $context = ''; $extra = ''; try { if ($record['context']) { $context = "\nContext: " . json_encode($record['context']); } if ($record['extra']) { $extra = "\nExtra: " . json_encode($record['extra']); } } catch (\Throwable $e) { // noop } return "\nThe exception occurred while attempting to log: " . $record['message'] . $context . $extra; } } PK������\5ZG������Monolog/ResettableInterface.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog; /** * Handler or Processor implementing this interface will be reset when Logger::reset() is called. * * Resetting ends a log cycle gets them back to their initial state. * * Resetting a Handler or a Processor means flushing/cleaning all buffers, resetting internal * state, and getting it back to a state in which it can receive log records again. * * This is useful in case you want to avoid logs leaking between two requests or jobs when you * have a long running process like a worker or an application server serving multiple requests * in one process. * * @author Grégoire Pineau <lyrixx@lyrixx.info> */ interface ResettableInterface { /** * @return void */ public function reset(); } PK������\5Z4**��**����Monolog/ErrorHandler.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; /** * Monolog error handler * * A facility to enable logging of runtime errors, exceptions and fatal errors. * * Quick setup: <code>ErrorHandler::register($logger);</code> * * @author Jordi Boggiano <j.boggiano@seld.be> */ class ErrorHandler { /** @var LoggerInterface */ private $logger; /** @var ?callable */ private $previousExceptionHandler = null; /** @var array<class-string, LogLevel::*> an array of class name to LogLevel::* constant mapping */ private $uncaughtExceptionLevelMap = []; /** @var callable|true|null */ private $previousErrorHandler = null; /** @var array<int, LogLevel::*> an array of E_* constant to LogLevel::* constant mapping */ private $errorLevelMap = []; /** @var bool */ private $handleOnlyReportedErrors = true; /** @var bool */ private $hasFatalErrorHandler = false; /** @var LogLevel::* */ private $fatalLevel = LogLevel::ALERT; /** @var ?string */ private $reservedMemory = null; /** @var ?array{type: int, message: string, file: string, line: int, trace: mixed} */ private $lastFatalData = null; /** @var int[] */ private static $fatalErrors = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR]; public function __construct(LoggerInterface $logger) { $this->logger = $logger; } /** * Registers a new ErrorHandler for a given Logger * * By default it will handle errors, exceptions and fatal errors * * @param LoggerInterface $logger * @param array<int, LogLevel::*>|false $errorLevelMap an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling * @param array<class-string, LogLevel::*>|false $exceptionLevelMap an array of class name to LogLevel::* constant mapping, or false to disable exception handling * @param LogLevel::*|null|false $fatalLevel a LogLevel::* constant, null to use the default LogLevel::ALERT or false to disable fatal error handling * @return ErrorHandler */ public static function register(LoggerInterface $logger, $errorLevelMap = [], $exceptionLevelMap = [], $fatalLevel = null): self { /** @phpstan-ignore-next-line */ $handler = new static($logger); if ($errorLevelMap !== false) { $handler->registerErrorHandler($errorLevelMap); } if ($exceptionLevelMap !== false) { $handler->registerExceptionHandler($exceptionLevelMap); } if ($fatalLevel !== false) { $handler->registerFatalHandler($fatalLevel); } return $handler; } /** * @param array<class-string, LogLevel::*> $levelMap an array of class name to LogLevel::* constant mapping * @return $this */ public function registerExceptionHandler(array $levelMap = [], bool $callPrevious = true): self { $prev = set_exception_handler(function (\Throwable $e): void { $this->handleException($e); }); $this->uncaughtExceptionLevelMap = $levelMap; foreach ($this->defaultExceptionLevelMap() as $class => $level) { if (!isset($this->uncaughtExceptionLevelMap[$class])) { $this->uncaughtExceptionLevelMap[$class] = $level; } } if ($callPrevious && $prev) { $this->previousExceptionHandler = $prev; } return $this; } /** * @param array<int, LogLevel::*> $levelMap an array of E_* constant to LogLevel::* constant mapping * @return $this */ public function registerErrorHandler(array $levelMap = [], bool $callPrevious = true, int $errorTypes = -1, bool $handleOnlyReportedErrors = true): self { $prev = set_error_handler([$this, 'handleError'], $errorTypes); $this->errorLevelMap = array_replace($this->defaultErrorLevelMap(), $levelMap); if ($callPrevious) { $this->previousErrorHandler = $prev ?: true; } else { $this->previousErrorHandler = null; } $this->handleOnlyReportedErrors = $handleOnlyReportedErrors; return $this; } /** * @param LogLevel::*|null $level a LogLevel::* constant, null to use the default LogLevel::ALERT * @param int $reservedMemorySize Amount of KBs to reserve in memory so that it can be freed when handling fatal errors giving Monolog some room in memory to get its job done */ public function registerFatalHandler($level = null, int $reservedMemorySize = 20): self { register_shutdown_function([$this, 'handleFatalError']); $this->reservedMemory = str_repeat(' ', 1024 * $reservedMemorySize); $this->fatalLevel = null === $level ? LogLevel::ALERT : $level; $this->hasFatalErrorHandler = true; return $this; } /** * @return array<class-string, LogLevel::*> */ protected function defaultExceptionLevelMap(): array { return [ 'ParseError' => LogLevel::CRITICAL, 'Throwable' => LogLevel::ERROR, ]; } /** * @return array<int, LogLevel::*> */ protected function defaultErrorLevelMap(): array { return [ E_ERROR => LogLevel::CRITICAL, E_WARNING => LogLevel::WARNING, E_PARSE => LogLevel::ALERT, E_NOTICE => LogLevel::NOTICE, E_CORE_ERROR => LogLevel::CRITICAL, E_CORE_WARNING => LogLevel::WARNING, E_COMPILE_ERROR => LogLevel::ALERT, E_COMPILE_WARNING => LogLevel::WARNING, E_USER_ERROR => LogLevel::ERROR, E_USER_WARNING => LogLevel::WARNING, E_USER_NOTICE => LogLevel::NOTICE, E_STRICT => LogLevel::NOTICE, E_RECOVERABLE_ERROR => LogLevel::ERROR, E_DEPRECATED => LogLevel::NOTICE, E_USER_DEPRECATED => LogLevel::NOTICE, ]; } /** * @phpstan-return never */ private function handleException(\Throwable $e): void { $level = LogLevel::ERROR; foreach ($this->uncaughtExceptionLevelMap as $class => $candidate) { if ($e instanceof $class) { $level = $candidate; break; } } $this->logger->log( $level, sprintf('Uncaught Exception %s: "%s" at %s line %s', Utils::getClass($e), $e->getMessage(), $e->getFile(), $e->getLine()), ['exception' => $e] ); if ($this->previousExceptionHandler) { ($this->previousExceptionHandler)($e); } if (!headers_sent() && !ini_get('display_errors')) { http_response_code(500); } exit(255); } /** * @private * * @param mixed[] $context */ public function handleError(int $code, string $message, string $file = '', int $line = 0, ?array $context = []): bool { if ($this->handleOnlyReportedErrors && !(error_reporting() & $code)) { return false; } // fatal error codes are ignored if a fatal error handler is present as well to avoid duplicate log entries if (!$this->hasFatalErrorHandler || !in_array($code, self::$fatalErrors, true)) { $level = $this->errorLevelMap[$code] ?? LogLevel::CRITICAL; $this->logger->log($level, self::codeToString($code).': '.$message, ['code' => $code, 'message' => $message, 'file' => $file, 'line' => $line]); } else { $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); array_shift($trace); // Exclude handleError from trace $this->lastFatalData = ['type' => $code, 'message' => $message, 'file' => $file, 'line' => $line, 'trace' => $trace]; } if ($this->previousErrorHandler === true) { return false; } elseif ($this->previousErrorHandler) { return (bool) ($this->previousErrorHandler)($code, $message, $file, $line, $context); } return true; } /** * @private */ public function handleFatalError(): void { $this->reservedMemory = ''; if (is_array($this->lastFatalData)) { $lastError = $this->lastFatalData; } else { $lastError = error_get_last(); } if ($lastError && in_array($lastError['type'], self::$fatalErrors, true)) { $trace = $lastError['trace'] ?? null; $this->logger->log( $this->fatalLevel, 'Fatal Error ('.self::codeToString($lastError['type']).'): '.$lastError['message'], ['code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'], 'trace' => $trace] ); if ($this->logger instanceof Logger) { foreach ($this->logger->getHandlers() as $handler) { $handler->close(); } } } } /** * @param int $code */ private static function codeToString($code): string { switch ($code) { case E_ERROR: return 'E_ERROR'; case E_WARNING: return 'E_WARNING'; case E_PARSE: return 'E_PARSE'; case E_NOTICE: return 'E_NOTICE'; case E_CORE_ERROR: return 'E_CORE_ERROR'; case E_CORE_WARNING: return 'E_CORE_WARNING'; case E_COMPILE_ERROR: return 'E_COMPILE_ERROR'; case E_COMPILE_WARNING: return 'E_COMPILE_WARNING'; case E_USER_ERROR: return 'E_USER_ERROR'; case E_USER_WARNING: return 'E_USER_WARNING'; case E_USER_NOTICE: return 'E_USER_NOTICE'; case E_STRICT: return 'E_STRICT'; case E_RECOVERABLE_ERROR: return 'E_RECOVERABLE_ERROR'; case E_DEPRECATED: return 'E_DEPRECATED'; case E_USER_DEPRECATED: return 'E_USER_DEPRECATED'; } return 'Unknown PHP error'; } } PK������ <ZqJ��J����Schema/Schema.phpnu�W+A��������<?php /** * This file is part of the Nette Framework (https://nette.org) * Copyright (c) 2004 David Grudl (https://davidgrudl.com) */ declare(strict_types=1); namespace Nette\Schema; interface Schema { /** * Normalization. * @return mixed */ function normalize(mixed $value, Context $context); /** * Merging. * @return mixed */ function merge(mixed $value, mixed $base); /** * Validation and finalization. * @return mixed */ function complete(mixed $value, Context $context); /** * @return mixed */ function completeDefault(Context $context); } PK������ <Zؤw������Schema/Processor.phpnu�W+A��������<?php /** * This file is part of the Nette Framework (https://nette.org) * Copyright (c) 2004 David Grudl (https://davidgrudl.com) */ declare(strict_types=1); namespace Nette\Schema; use Nette; /** * Schema validator. */ final class Processor { public array $onNewContext = []; private Context $context; private bool $skipDefaults = false; public function skipDefaults(bool $value = true): void { $this->skipDefaults = $value; } /** * Normalizes and validates data. Result is a clean completed data. * @throws ValidationException */ public function process(Schema $schema, mixed $data): mixed { $this->createContext(); $data = $schema->normalize($data, $this->context); $this->throwsErrors(); $data = $schema->complete($data, $this->context); $this->throwsErrors(); return $data; } /** * Normalizes and validates and merges multiple data. Result is a clean completed data. * @throws ValidationException */ public function processMultiple(Schema $schema, array $dataset): mixed { $this->createContext(); $flatten = null; $first = true; foreach ($dataset as $data) { $data = $schema->normalize($data, $this->context); $this->throwsErrors(); $flatten = $first ? $data : $schema->merge($data, $flatten); $first = false; } $data = $schema->complete($flatten, $this->context); $this->throwsErrors(); return $data; } /** * @return string[] */ public function getWarnings(): array { $res = []; foreach ($this->context->warnings as $message) { $res[] = $message->toString(); } return $res; } private function throwsErrors(): void { if ($this->context->errors) { throw new ValidationException(null, $this->context->errors); } } private function createContext(): void { $this->context = new Context; $this->context->skipDefaults = $this->skipDefaults; Nette\Utils\Arrays::invoke($this->onNewContext, $this->context); } } PK������ <Zm��������Schema/DynamicParameter.phpnu�W+A��������<?php /** * This file is part of the Nette Framework (https://nette.org) * Copyright (c) 2004 David Grudl (https://davidgrudl.com) */ declare(strict_types=1); namespace Nette\Schema; interface DynamicParameter { } PK������ <ZV%��%����Schema/Context.phpnu�W+A��������<?php /** * This file is part of the Nette Framework (https://nette.org) * Copyright (c) 2004 David Grudl (https://davidgrudl.com) */ declare(strict_types=1); namespace Nette\Schema; final class Context { public bool $skipDefaults = false; /** @var string[] */ public array $path = []; public bool $isKey = false; /** @var Message[] */ public array $errors = []; /** @var Message[] */ public array $warnings = []; /** @var array[] */ public array $dynamics = []; public function addError(string $message, string $code, array $variables = []): Message { $variables['isKey'] = $this->isKey; return $this->errors[] = new Message($message, $code, $this->path, $variables); } public function addWarning(string $message, string $code, array $variables = []): Message { return $this->warnings[] = new Message($message, $code, $this->path, $variables); } /** @return \Closure(): bool */ public function createChecker(): \Closure { $count = count($this->errors); return fn(): bool => $count === count($this->errors); } } PK������ <ZCg# �� ����Schema/Expect.phpnu�W+A��������<?php /** * This file is part of the Nette Framework (https://nette.org) * Copyright (c) 2004 David Grudl (https://davidgrudl.com) */ declare(strict_types=1); namespace Nette\Schema; use Nette; use Nette\Schema\Elements\AnyOf; use Nette\Schema\Elements\Structure; use Nette\Schema\Elements\Type; /** * Schema generator. * * @method static Type scalar($default = null) * @method static Type string($default = null) * @method static Type int($default = null) * @method static Type float($default = null) * @method static Type bool($default = null) * @method static Type null() * @method static Type list($default = []) * @method static Type mixed($default = null) * @method static Type email($default = null) * @method static Type unicode($default = null) */ final class Expect { public static function __callStatic(string $name, array $args): Type { $type = new Type($name); if ($args) { $type->default($args[0]); } return $type; } public static function type(string $type): Type { return new Type($type); } public static function anyOf(mixed ...$set): AnyOf { return new AnyOf(...$set); } /** * @param Schema[] $shape */ public static function structure(array $shape): Structure { return new Structure($shape); } public static function from(object $object, array $items = []): Structure { $ro = new \ReflectionObject($object); $props = $ro->hasMethod('__construct') ? $ro->getMethod('__construct')->getParameters() : $ro->getProperties(); foreach ($props as $prop) { $item = &$items[$prop->getName()]; if (!$item) { $type = Helpers::getPropertyType($prop) ?? 'mixed'; $item = new Type($type); if ($prop instanceof \ReflectionProperty ? $prop->isInitialized($object) : $prop->isOptional()) { $def = ($prop instanceof \ReflectionProperty ? $prop->getValue($object) : $prop->getDefaultValue()); if (is_object($def)) { $item = static::from($def); } elseif ($def === null && !Nette\Utils\Validators::is(null, $type)) { $item->required(); } else { $item->default($def); } } else { $item->required(); } } } return (new Structure($items))->castTo($ro->getName()); } /** * @param mixed[] $shape */ public static function array(?array $shape = []): Structure|Type { return Nette\Utils\Arrays::first($shape ?? []) instanceof Schema ? (new Structure($shape))->castTo('array') : (new Type('array'))->default($shape); } public static function arrayOf(string|Schema $valueType, string|Schema|null $keyType = null): Type { return (new Type('array'))->items($valueType, $keyType); } public static function listOf(string|Schema $type): Type { return (new Type('list'))->items($type); } } PK������ <ZЖW��W����Schema/ValidationException.phpnu�W+A��������<?php /** * This file is part of the Nette Framework (https://nette.org) * Copyright (c) 2004 David Grudl (https://davidgrudl.com) */ declare(strict_types=1); namespace Nette\Schema; use Nette; /** * Validation error. */ class ValidationException extends Nette\InvalidStateException { /** @var Message[] */ private array $messages; /** * @param Message[] $messages */ public function __construct(?string $message, array $messages = []) { parent::__construct($message ?: $messages[0]->toString()); $this->messages = $messages; } /** * @return string[] */ public function getMessages(): array { $res = []; foreach ($this->messages as $message) { $res[] = $message->toString(); } return $res; } /** * @return Message[] */ public function getMessageObjects(): array { return $this->messages; } } PK������ <Z,"o��o����Schema/Helpers.phpnu�W+A��������<?php /** * This file is part of the Nette Framework (https://nette.org) * Copyright (c) 2004 David Grudl (https://davidgrudl.com) */ declare(strict_types=1); namespace Nette\Schema; use Nette; use Nette\Utils\Reflection; /** * @internal */ final class Helpers { use Nette\StaticClass; public const PreventMerging = '_prevent_merging'; /** * Merges dataset. Left has higher priority than right one. */ public static function merge(mixed $value, mixed $base): mixed { if (is_array($value) && isset($value[self::PreventMerging])) { unset($value[self::PreventMerging]); return $value; } if (is_array($value) && is_array($base)) { $index = 0; foreach ($value as $key => $val) { if ($key === $index) { $base[] = $val; $index++; } else { $base[$key] = static::merge($val, $base[$key] ?? null); } } return $base; } elseif ($value === null && is_array($base)) { return $base; } else { return $value; } } public static function getPropertyType(\ReflectionProperty|\ReflectionParameter $prop): ?string { if ($type = Nette\Utils\Type::fromReflection($prop)) { return (string) $type; } elseif ( ($prop instanceof \ReflectionProperty) && ($type = preg_replace('#\s.*#', '', (string) self::parseAnnotation($prop, 'var'))) ) { $class = Reflection::getPropertyDeclaringClass($prop); return preg_replace_callback('#[\w\\\\]+#', fn($m) => Reflection::expandClassName($m[0], $class), $type); } return null; } /** * Returns an annotation value. * @param \ReflectionProperty $ref */ public static function parseAnnotation(\Reflector $ref, string $name): ?string { if (!Reflection::areCommentsAvailable()) { throw new Nette\InvalidStateException('You have to enable phpDoc comments in opcode cache.'); } $re = '#[\s*]@' . preg_quote($name, '#') . '(?=\s|$)(?:[ \t]+([^@\s]\S*))?#'; if ($ref->getDocComment() && preg_match($re, trim($ref->getDocComment(), '/*'), $m)) { return $m[1] ?? ''; } return null; } public static function formatValue(mixed $value): string { if ($value instanceof DynamicParameter) { return 'dynamic'; } elseif (is_object($value)) { return 'object ' . $value::class; } elseif (is_string($value)) { return "'" . Nette\Utils\Strings::truncate($value, 15, '...') . "'"; } elseif (is_scalar($value)) { return var_export($value, return: true); } else { return get_debug_type($value); } } public static function validateType(mixed $value, string $expected, Context $context): void { if (!Nette\Utils\Validators::is($value, $expected)) { $expected = str_replace(DynamicParameter::class . '|', '', $expected); $expected = str_replace(['|', ':'], [' or ', ' in range '], $expected); $context->addError( 'The %label% %path% expects to be %expected%, %value% given.', Message::TypeMismatch, ['value' => $value, 'expected' => $expected], ); } } public static function validateRange(mixed $value, array $range, Context $context, string $types = ''): void { if (is_array($value) || is_string($value)) { [$length, $label] = is_array($value) ? [count($value), 'items'] : (in_array('unicode', explode('|', $types), true) ? [Nette\Utils\Strings::length($value), 'characters'] : [strlen($value), 'bytes']); if (!self::isInRange($length, $range)) { $context->addError( "The length of %label% %path% expects to be in range %expected%, %length% $label given.", Message::LengthOutOfRange, ['value' => $value, 'length' => $length, 'expected' => implode('..', $range)], ); } } elseif ((is_int($value) || is_float($value)) && !self::isInRange($value, $range)) { $context->addError( 'The %label% %path% expects to be in range %expected%, %value% given.', Message::ValueOutOfRange, ['value' => $value, 'expected' => implode('..', $range)], ); } } public static function isInRange(mixed $value, array $range): bool { return ($range[0] === null || $value >= $range[0]) && ($range[1] === null || $value <= $range[1]); } public static function validatePattern(string $value, string $pattern, Context $context): void { if (!preg_match("\x01^(?:$pattern)$\x01Du", $value)) { $context->addError( "The %label% %path% expects to match pattern '%pattern%', %value% given.", Message::PatternMismatch, ['value' => $value, 'pattern' => $pattern], ); } } public static function getCastStrategy(string $type): \Closure { if (Nette\Utils\Reflection::isBuiltinType($type)) { return static function ($value) use ($type) { settype($value, $type); return $value; }; } elseif (method_exists($type, '__construct')) { return static fn($value) => is_array($value) || $value instanceof \stdClass ? new $type(...(array) $value) : new $type($value); } else { return static fn($value) => Nette\Utils\Arrays::toObject((array) $value, new $type); } } } PK������ <Zm<V��V����Schema/Elements/Structure.phpnu�W+A��������<?php /** * This file is part of the Nette Framework (https://nette.org) * Copyright (c) 2004 David Grudl (https://davidgrudl.com) */ declare(strict_types=1); namespace Nette\Schema\Elements; use Nette; use Nette\Schema\Context; use Nette\Schema\Helpers; use Nette\Schema\Schema; final class Structure implements Schema { use Base; /** @var Schema[] */ private array $items; /** for array|list */ private ?Schema $otherItems = null; /** @var array{?int, ?int} */ private array $range = [null, null]; private bool $skipDefaults = false; /** * @param Schema[] $shape */ public function __construct(array $shape) { (function (Schema ...$items) {})(...array_values($shape)); $this->items = $shape; $this->castTo('object'); $this->required = true; } public function default(mixed $value): self { throw new Nette\InvalidStateException('Structure cannot have default value.'); } public function min(?int $min): self { $this->range[0] = $min; return $this; } public function max(?int $max): self { $this->range[1] = $max; return $this; } public function otherItems(string|Schema $type = 'mixed'): self { $this->otherItems = $type instanceof Schema ? $type : new Type($type); return $this; } public function skipDefaults(bool $state = true): self { $this->skipDefaults = $state; return $this; } public function extend(array|self $shape): self { $shape = $shape instanceof self ? $shape->items : $shape; return new self(array_merge($this->items, $shape)); } public function getShape(): array { return $this->items; } /********************* processing ****************d*g**/ public function normalize(mixed $value, Context $context): mixed { if ($prevent = (is_array($value) && isset($value[Helpers::PreventMerging]))) { unset($value[Helpers::PreventMerging]); } $value = $this->doNormalize($value, $context); if (is_object($value)) { $value = (array) $value; } if (is_array($value)) { foreach ($value as $key => $val) { $itemSchema = $this->items[$key] ?? $this->otherItems; if ($itemSchema) { $context->path[] = $key; $value[$key] = $itemSchema->normalize($val, $context); array_pop($context->path); } } if ($prevent) { $value[Helpers::PreventMerging] = true; } } return $value; } public function merge(mixed $value, mixed $base): mixed { if (is_array($value) && isset($value[Helpers::PreventMerging])) { unset($value[Helpers::PreventMerging]); $base = null; } if (is_array($value) && is_array($base)) { $index = $this->otherItems === null ? null : 0; foreach ($value as $key => $val) { if ($key === $index) { $base[] = $val; $index++; } else { $base[$key] = array_key_exists($key, $base) && ($itemSchema = $this->items[$key] ?? $this->otherItems) ? $itemSchema->merge($val, $base[$key]) : $val; } } return $base; } return $value ?? $base; } public function complete(mixed $value, Context $context): mixed { if ($value === null) { $value = []; // is unable to distinguish null from array in NEON } $this->doDeprecation($context); $isOk = $context->createChecker(); Helpers::validateType($value, 'array', $context); $isOk() && Helpers::validateRange($value, $this->range, $context); $isOk() && $this->validateItems($value, $context); $isOk() && $value = $this->doTransform($value, $context); return $isOk() ? $value : null; } private function validateItems(array &$value, Context $context): void { $items = $this->items; if ($extraKeys = array_keys(array_diff_key($value, $items))) { if ($this->otherItems) { $items += array_fill_keys($extraKeys, $this->otherItems); } else { $keys = array_map('strval', array_keys($items)); foreach ($extraKeys as $key) { $hint = Nette\Utils\Helpers::getSuggestion($keys, (string) $key); $context->addError( 'Unexpected item %path%' . ($hint ? ", did you mean '%hint%'?" : '.'), Nette\Schema\Message::UnexpectedItem, ['hint' => $hint], )->path[] = $key; } } } foreach ($items as $itemKey => $itemVal) { $context->path[] = $itemKey; if (array_key_exists($itemKey, $value)) { $value[$itemKey] = $itemVal->complete($value[$itemKey], $context); } else { $default = $itemVal->completeDefault($context); // checks required item if (!$context->skipDefaults && !$this->skipDefaults) { $value[$itemKey] = $default; } } array_pop($context->path); } } public function completeDefault(Context $context): mixed { return $this->required ? $this->complete([], $context) : null; } } PK������ <Zԥ������Schema/Elements/Type.phpnu�W+A��������<?php /** * This file is part of the Nette Framework (https://nette.org) * Copyright (c) 2004 David Grudl (https://davidgrudl.com) */ declare(strict_types=1); namespace Nette\Schema\Elements; use Nette\Schema\Context; use Nette\Schema\DynamicParameter; use Nette\Schema\Helpers; use Nette\Schema\Schema; final class Type implements Schema { use Base; private string $type; private ?Schema $itemsValue = null; private ?Schema $itemsKey = null; /** @var array{?float, ?float} */ private array $range = [null, null]; private ?string $pattern = null; private bool $merge = true; public function __construct(string $type) { $defaults = ['list' => [], 'array' => []]; $this->type = $type; $this->default = strpos($type, '[]') ? [] : $defaults[$type] ?? null; } public function nullable(): self { $this->type = 'null|' . $this->type; return $this; } public function mergeDefaults(bool $state = true): self { $this->merge = $state; return $this; } public function dynamic(): self { $this->type = DynamicParameter::class . '|' . $this->type; return $this; } public function min(?float $min): self { $this->range[0] = $min; return $this; } public function max(?float $max): self { $this->range[1] = $max; return $this; } /** * @internal use arrayOf() or listOf() */ public function items(string|Schema $valueType = 'mixed', string|Schema|null $keyType = null): self { $this->itemsValue = $valueType instanceof Schema ? $valueType : new self($valueType); $this->itemsKey = $keyType instanceof Schema || $keyType === null ? $keyType : new self($keyType); return $this; } public function pattern(?string $pattern): self { $this->pattern = $pattern; return $this; } /********************* processing ****************d*g**/ public function normalize(mixed $value, Context $context): mixed { if ($prevent = (is_array($value) && isset($value[Helpers::PreventMerging]))) { unset($value[Helpers::PreventMerging]); } $value = $this->doNormalize($value, $context); if (is_array($value) && $this->itemsValue) { $res = []; foreach ($value as $key => $val) { $context->path[] = $key; $context->isKey = true; $key = $this->itemsKey ? $this->itemsKey->normalize($key, $context) : $key; $context->isKey = false; $res[$key] = $this->itemsValue->normalize($val, $context); array_pop($context->path); } $value = $res; } if ($prevent && is_array($value)) { $value[Helpers::PreventMerging] = true; } return $value; } public function merge(mixed $value, mixed $base): mixed { if (is_array($value) && isset($value[Helpers::PreventMerging])) { unset($value[Helpers::PreventMerging]); return $value; } if (is_array($value) && is_array($base) && $this->itemsValue) { $index = 0; foreach ($value as $key => $val) { if ($key === $index) { $base[] = $val; $index++; } else { $base[$key] = array_key_exists($key, $base) ? $this->itemsValue->merge($val, $base[$key]) : $val; } } return $base; } return Helpers::merge($value, $base); } public function complete(mixed $value, Context $context): mixed { $merge = $this->merge; if (is_array($value) && isset($value[Helpers::PreventMerging])) { unset($value[Helpers::PreventMerging]); $merge = false; } if ($value === null && is_array($this->default)) { $value = []; // is unable to distinguish null from array in NEON } $this->doDeprecation($context); $isOk = $context->createChecker(); Helpers::validateType($value, $this->type, $context); $isOk() && Helpers::validateRange($value, $this->range, $context, $this->type); $isOk() && $value !== null && $this->pattern !== null && Helpers::validatePattern($value, $this->pattern, $context); $isOk() && is_array($value) && $this->validateItems($value, $context); $isOk() && $merge && $value = Helpers::merge($value, $this->default); $isOk() && $value = $this->doTransform($value, $context); if (!$isOk()) { return null; } if ($value instanceof DynamicParameter) { $expected = $this->type . ($this->range === [null, null] ? '' : ':' . implode('..', $this->range)); $context->dynamics[] = [$value, str_replace(DynamicParameter::class . '|', '', $expected), $context->path]; } return $value; } private function validateItems(array &$value, Context $context): void { if (!$this->itemsValue) { return; } $res = []; foreach ($value as $key => $val) { $context->path[] = $key; $context->isKey = true; $key = $this->itemsKey ? $this->itemsKey->complete($key, $context) : $key; $context->isKey = false; $res[$key] = $this->itemsValue->complete($val, $context); array_pop($context->path); } $value = $res; } } PK������ <ZIl4 �� ����Schema/Elements/AnyOf.phpnu�W+A��������<?php /** * This file is part of the Nette Framework (https://nette.org) * Copyright (c) 2004 David Grudl (https://davidgrudl.com) */ declare(strict_types=1); namespace Nette\Schema\Elements; use Nette; use Nette\Schema\Context; use Nette\Schema\Helpers; use Nette\Schema\Schema; final class AnyOf implements Schema { use Base; private array $set; public function __construct(mixed ...$set) { if (!$set) { throw new Nette\InvalidStateException('The enumeration must not be empty.'); } $this->set = $set; } public function firstIsDefault(): self { $this->default = $this->set[0]; return $this; } public function nullable(): self { $this->set[] = null; return $this; } public function dynamic(): self { $this->set[] = new Type(Nette\Schema\DynamicParameter::class); return $this; } /********************* processing ****************d*g**/ public function normalize(mixed $value, Context $context): mixed { return $this->doNormalize($value, $context); } public function merge(mixed $value, mixed $base): mixed { if (is_array($value) && isset($value[Helpers::PreventMerging])) { unset($value[Helpers::PreventMerging]); return $value; } return Helpers::merge($value, $base); } public function complete(mixed $value, Context $context): mixed { $isOk = $context->createChecker(); $value = $this->findAlternative($value, $context); $isOk() && $value = $this->doTransform($value, $context); return $isOk() ? $value : null; } private function findAlternative(mixed $value, Context $context): mixed { $expecteds = $innerErrors = []; foreach ($this->set as $item) { if ($item instanceof Schema) { $dolly = new Context; $dolly->path = $context->path; $res = $item->complete($item->normalize($value, $dolly), $dolly); if (!$dolly->errors) { $context->warnings = array_merge($context->warnings, $dolly->warnings); return $res; } foreach ($dolly->errors as $error) { if ($error->path !== $context->path || empty($error->variables['expected'])) { $innerErrors[] = $error; } else { $expecteds[] = $error->variables['expected']; } } } else { if ($item === $value) { return $value; } $expecteds[] = Nette\Schema\Helpers::formatValue($item); } } if ($innerErrors) { $context->errors = array_merge($context->errors, $innerErrors); } else { $context->addError( 'The %label% %path% expects to be %expected%, %value% given.', Nette\Schema\Message::TypeMismatch, [ 'value' => $value, 'expected' => implode('|', array_unique($expecteds)), ], ); } return null; } public function completeDefault(Context $context): mixed { if ($this->required) { $context->addError( 'The mandatory item %path% is missing.', Nette\Schema\Message::MissingItem, ); return null; } if ($this->default instanceof Schema) { return $this->default->completeDefault($context); } return $this->default; } } PK������ <ZW⇕2 ��2 ����Schema/Elements/Base.phpnu�W+A��������<?php /** * This file is part of the Nette Framework (https://nette.org) * Copyright (c) 2004 David Grudl (https://davidgrudl.com) */ declare(strict_types=1); namespace Nette\Schema\Elements; use Nette; use Nette\Schema\Context; use Nette\Schema\Helpers; /** * @internal */ trait Base { private bool $required = false; private mixed $default = null; /** @var ?callable */ private $before; /** @var callable[] */ private array $transforms = []; private ?string $deprecated = null; public function default(mixed $value): self { $this->default = $value; return $this; } public function required(bool $state = true): self { $this->required = $state; return $this; } public function before(callable $handler): self { $this->before = $handler; return $this; } public function castTo(string $type): self { return $this->transform(Helpers::getCastStrategy($type)); } public function transform(callable $handler): self { $this->transforms[] = $handler; return $this; } public function assert(callable $handler, ?string $description = null): self { $expected = $description ?: (is_string($handler) ? "$handler()" : '#' . count($this->transforms)); return $this->transform(function ($value, Context $context) use ($handler, $description, $expected) { if ($handler($value)) { return $value; } $context->addError( 'Failed assertion ' . ($description ? "'%assertion%'" : '%assertion%') . ' for %label% %path% with value %value%.', Nette\Schema\Message::FailedAssertion, ['value' => $value, 'assertion' => $expected], ); }); } /** Marks as deprecated */ public function deprecated(string $message = 'The item %path% is deprecated.'): self { $this->deprecated = $message; return $this; } public function completeDefault(Context $context): mixed { if ($this->required) { $context->addError( 'The mandatory item %path% is missing.', Nette\Schema\Message::MissingItem, ); return null; } return $this->default; } public function doNormalize(mixed $value, Context $context): mixed { if ($this->before) { $value = ($this->before)($value); } return $value; } private function doDeprecation(Context $context): void { if ($this->deprecated !== null) { $context->addWarning( $this->deprecated, Nette\Schema\Message::Deprecated, ); } } private function doTransform(mixed $value, Context $context): mixed { $isOk = $context->createChecker(); foreach ($this->transforms as $handler) { $value = $handler($value, $context); if (!$isOk()) { return null; } } return $value; } /** @deprecated use Nette\Schema\Validators::validateType() */ private function doValidate(mixed $value, string $expected, Context $context): bool { $isOk = $context->createChecker(); Helpers::validateType($value, $expected, $context); return $isOk(); } /** @deprecated use Nette\Schema\Validators::validateRange() */ private static function doValidateRange(mixed $value, array $range, Context $context, string $types = ''): bool { $isOk = $context->createChecker(); Helpers::validateRange($value, $range, $context, $types); return $isOk(); } /** @deprecated use doTransform() */ private function doFinalize(mixed $value, Context $context): mixed { return $this->doTransform($value, $context); } } PK������ <ZΓ0 �� ����Schema/Message.phpnu�W+A��������<?php /** * This file is part of the Nette Framework (https://nette.org) * Copyright (c) 2004 David Grudl (https://davidgrudl.com) */ declare(strict_types=1); namespace Nette\Schema; use Nette; final class Message { /** variables: {value: mixed, expected: string} */ public const TypeMismatch = 'schema.typeMismatch'; /** variables: {value: mixed, expected: string} */ public const ValueOutOfRange = 'schema.valueOutOfRange'; /** variables: {value: mixed, length: int, expected: string} */ public const LengthOutOfRange = 'schema.lengthOutOfRange'; /** variables: {value: string, pattern: string} */ public const PatternMismatch = 'schema.patternMismatch'; /** variables: {value: mixed, assertion: string} */ public const FailedAssertion = 'schema.failedAssertion'; /** no variables */ public const MissingItem = 'schema.missingItem'; /** variables: {hint: string} */ public const UnexpectedItem = 'schema.unexpectedItem'; /** no variables */ public const Deprecated = 'schema.deprecated'; /** @deprecated use Message::TypeMismatch */ public const TYPE_MISMATCH = self::TypeMismatch; /** @deprecated use Message::ValueOutOfRange */ public const VALUE_OUT_OF_RANGE = self::ValueOutOfRange; /** @deprecated use Message::LengthOutOfRange */ public const LENGTH_OUT_OF_RANGE = self::LengthOutOfRange; /** @deprecated use Message::PatternMismatch */ public const PATTERN_MISMATCH = self::PatternMismatch; /** @deprecated use Message::FailedAssertion */ public const FAILED_ASSERTION = self::FailedAssertion; /** @deprecated use Message::MissingItem */ public const MISSING_ITEM = self::MissingItem; /** @deprecated use Message::UnexpectedItem */ public const UNEXPECTED_ITEM = self::UnexpectedItem; /** @deprecated use Message::Deprecated */ public const DEPRECATED = self::Deprecated; public string $message; public string $code; /** @var string[] */ public array $path; /** @var string[] */ public array $variables; public function __construct(string $message, string $code, array $path, array $variables = []) { $this->message = $message; $this->code = $code; $this->path = $path; $this->variables = $variables; } public function toString(): string { $vars = $this->variables; $vars['label'] = empty($vars['isKey']) ? 'item' : 'key of item'; $vars['path'] = $this->path ? "'" . implode("\u{a0}›\u{a0}", $this->path) . "'" : null; $vars['value'] = Helpers::formatValue($vars['value'] ?? null); return preg_replace_callback('~( ?)%(\w+)%~', function ($m) use ($vars) { [, $space, $key] = $m; return $vars[$key] === null ? '' : $space . $vars[$key]; }, $this->message) ?? throw new Nette\InvalidStateException(preg_last_error_msg()); } } PK������@ZZ ��Z �� ��Repository/AdapterRepository.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Repository; use Dotenv\Repository\Adapter\ReaderInterface; use Dotenv\Repository\Adapter\WriterInterface; use InvalidArgumentException; final class AdapterRepository implements RepositoryInterface { /** * The reader to use. * * @var \Dotenv\Repository\Adapter\ReaderInterface */ private $reader; /** * The writer to use. * * @var \Dotenv\Repository\Adapter\WriterInterface */ private $writer; /** * Create a new adapter repository instance. * * @param \Dotenv\Repository\Adapter\ReaderInterface $reader * @param \Dotenv\Repository\Adapter\WriterInterface $writer * * @return void */ public function __construct(ReaderInterface $reader, WriterInterface $writer) { $this->reader = $reader; $this->writer = $writer; } /** * Determine if the given environment variable is defined. * * @param string $name * * @return bool */ public function has(string $name) { return '' !== $name && $this->reader->read($name)->isDefined(); } /** * Get an environment variable. * * @param string $name * * @throws \InvalidArgumentException * * @return string|null */ public function get(string $name) { if ('' === $name) { throw new InvalidArgumentException('Expected name to be a non-empty string.'); } return $this->reader->read($name)->getOrElse(null); } /** * Set an environment variable. * * @param string $name * @param string $value * * @throws \InvalidArgumentException * * @return bool */ public function set(string $name, string $value) { if ('' === $name) { throw new InvalidArgumentException('Expected name to be a non-empty string.'); } return $this->writer->write($name, $value); } /** * Clear an environment variable. * * @param string $name * * @throws \InvalidArgumentException * * @return bool */ public function clear(string $name) { if ('' === $name) { throw new InvalidArgumentException('Expected name to be a non-empty string.'); } return $this->writer->delete($name); } } PK������@Z@l[� �� �� ��Repository/RepositoryBuilder.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Repository; use Dotenv\Repository\Adapter\AdapterInterface; use Dotenv\Repository\Adapter\EnvConstAdapter; use Dotenv\Repository\Adapter\GuardedWriter; use Dotenv\Repository\Adapter\ImmutableWriter; use Dotenv\Repository\Adapter\MultiReader; use Dotenv\Repository\Adapter\MultiWriter; use Dotenv\Repository\Adapter\ReaderInterface; use Dotenv\Repository\Adapter\ServerConstAdapter; use Dotenv\Repository\Adapter\WriterInterface; use InvalidArgumentException; use PhpOption\Some; use ReflectionClass; final class RepositoryBuilder { /** * The set of default adapters. */ private const DEFAULT_ADAPTERS = [ ServerConstAdapter::class, EnvConstAdapter::class, ]; /** * The set of readers to use. * * @var \Dotenv\Repository\Adapter\ReaderInterface[] */ private $readers; /** * The set of writers to use. * * @var \Dotenv\Repository\Adapter\WriterInterface[] */ private $writers; /** * Are we immutable? * * @var bool */ private $immutable; /** * The variable name allow list. * * @var string[]|null */ private $allowList; /** * Create a new repository builder instance. * * @param \Dotenv\Repository\Adapter\ReaderInterface[] $readers * @param \Dotenv\Repository\Adapter\WriterInterface[] $writers * @param bool $immutable * @param string[]|null $allowList * * @return void */ private function __construct(array $readers = [], array $writers = [], bool $immutable = false, ?array $allowList = null) { $this->readers = $readers; $this->writers = $writers; $this->immutable = $immutable; $this->allowList = $allowList; } /** * Create a new repository builder instance with no adapters added. * * @return \Dotenv\Repository\RepositoryBuilder */ public static function createWithNoAdapters() { return new self(); } /** * Create a new repository builder instance with the default adapters added. * * @return \Dotenv\Repository\RepositoryBuilder */ public static function createWithDefaultAdapters() { $adapters = \iterator_to_array(self::defaultAdapters()); return new self($adapters, $adapters); } /** * Return the array of default adapters. * * @return \Generator<\Dotenv\Repository\Adapter\AdapterInterface> */ private static function defaultAdapters() { foreach (self::DEFAULT_ADAPTERS as $adapter) { $instance = $adapter::create(); if ($instance->isDefined()) { yield $instance->get(); } } } /** * Determine if the given name if of an adapterclass. * * @param string $name * * @return bool */ private static function isAnAdapterClass(string $name) { if (!\class_exists($name)) { return false; } return (new ReflectionClass($name))->implementsInterface(AdapterInterface::class); } /** * Creates a repository builder with the given reader added. * * Accepts either a reader instance, or a class-string for an adapter. If * the adapter is not supported, then we silently skip adding it. * * @param \Dotenv\Repository\Adapter\ReaderInterface|string $reader * * @throws \InvalidArgumentException * * @return \Dotenv\Repository\RepositoryBuilder */ public function addReader($reader) { if (!(\is_string($reader) && self::isAnAdapterClass($reader)) && !($reader instanceof ReaderInterface)) { throw new InvalidArgumentException( \sprintf( 'Expected either an instance of %s or a class-string implementing %s', ReaderInterface::class, AdapterInterface::class ) ); } $optional = Some::create($reader)->flatMap(static function ($reader) { return \is_string($reader) ? $reader::create() : Some::create($reader); }); $readers = \array_merge($this->readers, \iterator_to_array($optional)); return new self($readers, $this->writers, $this->immutable, $this->allowList); } /** * Creates a repository builder with the given writer added. * * Accepts either a writer instance, or a class-string for an adapter. If * the adapter is not supported, then we silently skip adding it. * * @param \Dotenv\Repository\Adapter\WriterInterface|string $writer * * @throws \InvalidArgumentException * * @return \Dotenv\Repository\RepositoryBuilder */ public function addWriter($writer) { if (!(\is_string($writer) && self::isAnAdapterClass($writer)) && !($writer instanceof WriterInterface)) { throw new InvalidArgumentException( \sprintf( 'Expected either an instance of %s or a class-string implementing %s', WriterInterface::class, AdapterInterface::class ) ); } $optional = Some::create($writer)->flatMap(static function ($writer) { return \is_string($writer) ? $writer::create() : Some::create($writer); }); $writers = \array_merge($this->writers, \iterator_to_array($optional)); return new self($this->readers, $writers, $this->immutable, $this->allowList); } /** * Creates a repository builder with the given adapter added. * * Accepts either an adapter instance, or a class-string for an adapter. If * the adapter is not supported, then we silently skip adding it. We will * add the adapter as both a reader and a writer. * * @param \Dotenv\Repository\Adapter\WriterInterface|string $adapter * * @throws \InvalidArgumentException * * @return \Dotenv\Repository\RepositoryBuilder */ public function addAdapter($adapter) { if (!(\is_string($adapter) && self::isAnAdapterClass($adapter)) && !($adapter instanceof AdapterInterface)) { throw new InvalidArgumentException( \sprintf( 'Expected either an instance of %s or a class-string implementing %s', WriterInterface::class, AdapterInterface::class ) ); } $optional = Some::create($adapter)->flatMap(static function ($adapter) { return \is_string($adapter) ? $adapter::create() : Some::create($adapter); }); $readers = \array_merge($this->readers, \iterator_to_array($optional)); $writers = \array_merge($this->writers, \iterator_to_array($optional)); return new self($readers, $writers, $this->immutable, $this->allowList); } /** * Creates a repository builder with mutability enabled. * * @return \Dotenv\Repository\RepositoryBuilder */ public function immutable() { return new self($this->readers, $this->writers, true, $this->allowList); } /** * Creates a repository builder with the given allow list. * * @param string[]|null $allowList * * @return \Dotenv\Repository\RepositoryBuilder */ public function allowList(?array $allowList = null) { return new self($this->readers, $this->writers, $this->immutable, $allowList); } /** * Creates a new repository instance. * * @return \Dotenv\Repository\RepositoryInterface */ public function make() { $reader = new MultiReader($this->readers); $writer = new MultiWriter($this->writers); if ($this->immutable) { $writer = new ImmutableWriter($writer, $reader); } if ($this->allowList !== null) { $writer = new GuardedWriter($writer, $this->allowList); } return new AdapterRepository($reader, $writer); } } PK������@Z=BS��S��$��Repository/Adapter/GuardedWriter.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Repository\Adapter; final class GuardedWriter implements WriterInterface { /** * The inner writer to use. * * @var \Dotenv\Repository\Adapter\WriterInterface */ private $writer; /** * The variable name allow list. * * @var string[] */ private $allowList; /** * Create a new guarded writer instance. * * @param \Dotenv\Repository\Adapter\WriterInterface $writer * @param string[] $allowList * * @return void */ public function __construct(WriterInterface $writer, array $allowList) { $this->writer = $writer; $this->allowList = $allowList; } /** * Write to an environment variable, if possible. * * @param non-empty-string $name * @param string $value * * @return bool */ public function write(string $name, string $value) { // Don't set non-allowed variables if (!$this->isAllowed($name)) { return false; } // Set the value on the inner writer return $this->writer->write($name, $value); } /** * Delete an environment variable, if possible. * * @param non-empty-string $name * * @return bool */ public function delete(string $name) { // Don't clear non-allowed variables if (!$this->isAllowed($name)) { return false; } // Set the value on the inner writer return $this->writer->delete($name); } /** * Determine if the given variable is allowed. * * @param non-empty-string $name * * @return bool */ private function isAllowed(string $name) { return \in_array($name, $this->allowList, true); } } PK������@Z˅Z��Z��'��Repository/Adapter/AdapterInterface.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Repository\Adapter; interface AdapterInterface extends ReaderInterface, WriterInterface { /** * Create a new instance of the adapter, if it is available. * * @return \PhpOption\Option<\Dotenv\Repository\Adapter\AdapterInterface> */ public static function create(); } PK������@ZK>J��J��#��Repository/Adapter/ArrayAdapter.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Repository\Adapter; use PhpOption\Option; use PhpOption\Some; final class ArrayAdapter implements AdapterInterface { /** * The variables and their values. * * @var array<string,string> */ private $variables; /** * Create a new array adapter instance. * * @return void */ private function __construct() { $this->variables = []; } /** * Create a new instance of the adapter, if it is available. * * @return \PhpOption\Option<\Dotenv\Repository\Adapter\AdapterInterface> */ public static function create() { /** @var \PhpOption\Option<AdapterInterface> */ return Some::create(new self()); } /** * Read an environment variable, if it exists. * * @param non-empty-string $name * * @return \PhpOption\Option<string> */ public function read(string $name) { return Option::fromArraysValue($this->variables, $name); } /** * Write to an environment variable, if possible. * * @param non-empty-string $name * @param string $value * * @return bool */ public function write(string $name, string $value) { $this->variables[$name] = $value; return true; } /** * Delete an environment variable, if possible. * * @param non-empty-string $name * * @return bool */ public function delete(string $name) { unset($this->variables[$name]); return true; } } PK������@Z_.5����&��Repository/Adapter/WriterInterface.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Repository\Adapter; interface WriterInterface { /** * Write to an environment variable, if possible. * * @param non-empty-string $name * @param string $value * * @return bool */ public function write(string $name, string $value); /** * Delete an environment variable, if possible. * * @param non-empty-string $name * * @return bool */ public function delete(string $name); } PK������@Zj>Up����)��Repository/Adapter/ServerConstAdapter.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Repository\Adapter; use PhpOption\Option; use PhpOption\Some; final class ServerConstAdapter implements AdapterInterface { /** * Create a new server const adapter instance. * * @return void */ private function __construct() { // } /** * Create a new instance of the adapter, if it is available. * * @return \PhpOption\Option<\Dotenv\Repository\Adapter\AdapterInterface> */ public static function create() { /** @var \PhpOption\Option<AdapterInterface> */ return Some::create(new self()); } /** * Read an environment variable, if it exists. * * @param non-empty-string $name * * @return \PhpOption\Option<string> */ public function read(string $name) { /** @var \PhpOption\Option<string> */ return Option::fromArraysValue($_SERVER, $name) ->filter(static function ($value) { return \is_scalar($value); }) ->map(static function ($value) { if ($value === false) { return 'false'; } if ($value === true) { return 'true'; } /** @psalm-suppress PossiblyInvalidCast */ return (string) $value; }); } /** * Write to an environment variable, if possible. * * @param non-empty-string $name * @param string $value * * @return bool */ public function write(string $name, string $value) { $_SERVER[$name] = $value; return true; } /** * Delete an environment variable, if possible. * * @param non-empty-string $name * * @return bool */ public function delete(string $name) { unset($_SERVER[$name]); return true; } } PK������@Z޶����$��Repository/Adapter/ApacheAdapter.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Repository\Adapter; use PhpOption\None; use PhpOption\Option; use PhpOption\Some; final class ApacheAdapter implements AdapterInterface { /** * Create a new apache adapter instance. * * @return void */ private function __construct() { // } /** * Create a new instance of the adapter, if it is available. * * @return \PhpOption\Option<\Dotenv\Repository\Adapter\AdapterInterface> */ public static function create() { if (self::isSupported()) { /** @var \PhpOption\Option<AdapterInterface> */ return Some::create(new self()); } return None::create(); } /** * Determines if the adapter is supported. * * This happens if PHP is running as an Apache module. * * @return bool */ private static function isSupported() { return \function_exists('apache_getenv') && \function_exists('apache_setenv'); } /** * Read an environment variable, if it exists. * * @param non-empty-string $name * * @return \PhpOption\Option<string> */ public function read(string $name) { /** @var \PhpOption\Option<string> */ return Option::fromValue(apache_getenv($name))->filter(static function ($value) { return \is_string($value) && $value !== ''; }); } /** * Write to an environment variable, if possible. * * @param non-empty-string $name * @param string $value * * @return bool */ public function write(string $name, string $value) { return apache_setenv($name, $value); } /** * Delete an environment variable, if possible. * * @param non-empty-string $name * * @return bool */ public function delete(string $name) { return apache_setenv($name, ''); } } PK������@Z׷b����&��Repository/Adapter/ReplacingWriter.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Repository\Adapter; final class ReplacingWriter implements WriterInterface { /** * The inner writer to use. * * @var \Dotenv\Repository\Adapter\WriterInterface */ private $writer; /** * The inner reader to use. * * @var \Dotenv\Repository\Adapter\ReaderInterface */ private $reader; /** * The record of seen variables. * * @var array<string,string> */ private $seen; /** * Create a new replacement writer instance. * * @param \Dotenv\Repository\Adapter\WriterInterface $writer * @param \Dotenv\Repository\Adapter\ReaderInterface $reader * * @return void */ public function __construct(WriterInterface $writer, ReaderInterface $reader) { $this->writer = $writer; $this->reader = $reader; $this->seen = []; } /** * Write to an environment variable, if possible. * * @param non-empty-string $name * @param string $value * * @return bool */ public function write(string $name, string $value) { if ($this->exists($name)) { return $this->writer->write($name, $value); } // succeed if nothing to do return true; } /** * Delete an environment variable, if possible. * * @param non-empty-string $name * * @return bool */ public function delete(string $name) { if ($this->exists($name)) { return $this->writer->delete($name); } // succeed if nothing to do return true; } /** * Does the given environment variable exist. * * Returns true if it currently exists, or existed at any point in the past * that we are aware of. * * @param non-empty-string $name * * @return bool */ private function exists(string $name) { if (isset($this->seen[$name])) { return true; } if ($this->reader->read($name)->isDefined()) { $this->seen[$name] = ''; return true; } return false; } } PK������@Z����"��Repository/Adapter/MultiWriter.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Repository\Adapter; final class MultiWriter implements WriterInterface { /** * The set of writers to use. * * @var \Dotenv\Repository\Adapter\WriterInterface[] */ private $writers; /** * Create a new multi-writer instance. * * @param \Dotenv\Repository\Adapter\WriterInterface[] $writers * * @return void */ public function __construct(array $writers) { $this->writers = $writers; } /** * Write to an environment variable, if possible. * * @param non-empty-string $name * @param string $value * * @return bool */ public function write(string $name, string $value) { foreach ($this->writers as $writers) { if (!$writers->write($name, $value)) { return false; } } return true; } /** * Delete an environment variable, if possible. * * @param non-empty-string $name * * @return bool */ public function delete(string $name) { foreach ($this->writers as $writers) { if (!$writers->delete($name)) { return false; } } return true; } } PK������@ZЊs �� ��&��Repository/Adapter/ImmutableWriter.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Repository\Adapter; final class ImmutableWriter implements WriterInterface { /** * The inner writer to use. * * @var \Dotenv\Repository\Adapter\WriterInterface */ private $writer; /** * The inner reader to use. * * @var \Dotenv\Repository\Adapter\ReaderInterface */ private $reader; /** * The record of loaded variables. * * @var array<string,string> */ private $loaded; /** * Create a new immutable writer instance. * * @param \Dotenv\Repository\Adapter\WriterInterface $writer * @param \Dotenv\Repository\Adapter\ReaderInterface $reader * * @return void */ public function __construct(WriterInterface $writer, ReaderInterface $reader) { $this->writer = $writer; $this->reader = $reader; $this->loaded = []; } /** * Write to an environment variable, if possible. * * @param non-empty-string $name * @param string $value * * @return bool */ public function write(string $name, string $value) { // Don't overwrite existing environment variables // Ruby's dotenv does this with `ENV[key] ||= value` if ($this->isExternallyDefined($name)) { return false; } // Set the value on the inner writer if (!$this->writer->write($name, $value)) { return false; } // Record that we have loaded the variable $this->loaded[$name] = ''; return true; } /** * Delete an environment variable, if possible. * * @param non-empty-string $name * * @return bool */ public function delete(string $name) { // Don't clear existing environment variables if ($this->isExternallyDefined($name)) { return false; } // Clear the value on the inner writer if (!$this->writer->delete($name)) { return false; } // Leave the variable as fair game unset($this->loaded[$name]); return true; } /** * Determine if the given variable is externally defined. * * That is, is it an "existing" variable. * * @param non-empty-string $name * * @return bool */ private function isExternallyDefined(string $name) { return $this->reader->read($name)->isDefined() && !isset($this->loaded[$name]); } } PK������@ZTߗ����&��Repository/Adapter/EnvConstAdapter.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Repository\Adapter; use PhpOption\Option; use PhpOption\Some; final class EnvConstAdapter implements AdapterInterface { /** * Create a new env const adapter instance. * * @return void */ private function __construct() { // } /** * Create a new instance of the adapter, if it is available. * * @return \PhpOption\Option<\Dotenv\Repository\Adapter\AdapterInterface> */ public static function create() { /** @var \PhpOption\Option<AdapterInterface> */ return Some::create(new self()); } /** * Read an environment variable, if it exists. * * @param non-empty-string $name * * @return \PhpOption\Option<string> */ public function read(string $name) { /** @var \PhpOption\Option<string> */ return Option::fromArraysValue($_ENV, $name) ->filter(static function ($value) { return \is_scalar($value); }) ->map(static function ($value) { if ($value === false) { return 'false'; } if ($value === true) { return 'true'; } /** @psalm-suppress PossiblyInvalidCast */ return (string) $value; }); } /** * Write to an environment variable, if possible. * * @param non-empty-string $name * @param string $value * * @return bool */ public function write(string $name, string $value) { $_ENV[$name] = $value; return true; } /** * Delete an environment variable, if possible. * * @param non-empty-string $name * * @return bool */ public function delete(string $name) { unset($_ENV[$name]); return true; } } PK������@ZyO����"��Repository/Adapter/MultiReader.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Repository\Adapter; use PhpOption\None; final class MultiReader implements ReaderInterface { /** * The set of readers to use. * * @var \Dotenv\Repository\Adapter\ReaderInterface[] */ private $readers; /** * Create a new multi-reader instance. * * @param \Dotenv\Repository\Adapter\ReaderInterface[] $readers * * @return void */ public function __construct(array $readers) { $this->readers = $readers; } /** * Read an environment variable, if it exists. * * @param non-empty-string $name * * @return \PhpOption\Option<string> */ public function read(string $name) { foreach ($this->readers as $reader) { $result = $reader->read($name); if ($result->isDefined()) { return $result; } } return None::create(); } } PK������@Ze��e��$��Repository/Adapter/PutenvAdapter.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Repository\Adapter; use PhpOption\None; use PhpOption\Option; use PhpOption\Some; final class PutenvAdapter implements AdapterInterface { /** * Create a new putenv adapter instance. * * @return void */ private function __construct() { // } /** * Create a new instance of the adapter, if it is available. * * @return \PhpOption\Option<\Dotenv\Repository\Adapter\AdapterInterface> */ public static function create() { if (self::isSupported()) { /** @var \PhpOption\Option<AdapterInterface> */ return Some::create(new self()); } return None::create(); } /** * Determines if the adapter is supported. * * @return bool */ private static function isSupported() { return \function_exists('getenv') && \function_exists('putenv'); } /** * Read an environment variable, if it exists. * * @param non-empty-string $name * * @return \PhpOption\Option<string> */ public function read(string $name) { /** @var \PhpOption\Option<string> */ return Option::fromValue(\getenv($name), false)->filter(static function ($value) { return \is_string($value); }); } /** * Write to an environment variable, if possible. * * @param non-empty-string $name * @param string $value * * @return bool */ public function write(string $name, string $value) { \putenv("$name=$value"); return true; } /** * Delete an environment variable, if possible. * * @param non-empty-string $name * * @return bool */ public function delete(string $name) { \putenv($name); return true; } } PK������@Z0),��,��&��Repository/Adapter/ReaderInterface.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Repository\Adapter; interface ReaderInterface { /** * Read an environment variable, if it exists. * * @param non-empty-string $name * * @return \PhpOption\Option<string> */ public function read(string $name); } PK������@Zuȡ����"��Repository/RepositoryInterface.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Repository; interface RepositoryInterface { /** * Determine if the given environment variable is defined. * * @param string $name * * @return bool */ public function has(string $name); /** * Get an environment variable. * * @param string $name * * @throws \InvalidArgumentException * * @return string|null */ public function get(string $name); /** * Set an environment variable. * * @param string $name * @param string $value * * @throws \InvalidArgumentException * * @return bool */ public function set(string $name, string $value); /** * Clear an environment variable. * * @param string $name * * @throws \InvalidArgumentException * * @return bool */ public function clear(string $name); } PK������@Z}Y���� ��Validator.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv; use Dotenv\Exception\ValidationException; use Dotenv\Repository\RepositoryInterface; use Dotenv\Util\Regex; use Dotenv\Util\Str; class Validator { /** * The environment repository instance. * * @var \Dotenv\Repository\RepositoryInterface */ private $repository; /** * The variables to validate. * * @var string[] */ private $variables; /** * Create a new validator instance. * * @param \Dotenv\Repository\RepositoryInterface $repository * @param string[] $variables * * @throws \Dotenv\Exception\ValidationException * * @return void */ public function __construct(RepositoryInterface $repository, array $variables) { $this->repository = $repository; $this->variables = $variables; } /** * Assert that each variable is present. * * @throws \Dotenv\Exception\ValidationException * * @return \Dotenv\Validator */ public function required() { return $this->assert( static function (?string $value) { return $value !== null; }, 'is missing' ); } /** * Assert that each variable is not empty. * * @throws \Dotenv\Exception\ValidationException * * @return \Dotenv\Validator */ public function notEmpty() { return $this->assertNullable( static function (string $value) { return Str::len(\trim($value)) > 0; }, 'is empty' ); } /** * Assert that each specified variable is an integer. * * @throws \Dotenv\Exception\ValidationException * * @return \Dotenv\Validator */ public function isInteger() { return $this->assertNullable( static function (string $value) { return \ctype_digit($value); }, 'is not an integer' ); } /** * Assert that each specified variable is a boolean. * * @throws \Dotenv\Exception\ValidationException * * @return \Dotenv\Validator */ public function isBoolean() { return $this->assertNullable( static function (string $value) { if ($value === '') { return false; } return \filter_var($value, \FILTER_VALIDATE_BOOLEAN, \FILTER_NULL_ON_FAILURE) !== null; }, 'is not a boolean' ); } /** * Assert that each variable is amongst the given choices. * * @param string[] $choices * * @throws \Dotenv\Exception\ValidationException * * @return \Dotenv\Validator */ public function allowedValues(array $choices) { return $this->assertNullable( static function (string $value) use ($choices) { return \in_array($value, $choices, true); }, \sprintf('is not one of [%s]', \implode(', ', $choices)) ); } /** * Assert that each variable matches the given regular expression. * * @param string $regex * * @throws \Dotenv\Exception\ValidationException * * @return \Dotenv\Validator */ public function allowedRegexValues(string $regex) { return $this->assertNullable( static function (string $value) use ($regex) { return Regex::matches($regex, $value)->success()->getOrElse(false); }, \sprintf('does not match "%s"', $regex) ); } /** * Assert that the callback returns true for each variable. * * @param callable(?string):bool $callback * @param string $message * * @throws \Dotenv\Exception\ValidationException * * @return \Dotenv\Validator */ public function assert(callable $callback, string $message) { $failing = []; foreach ($this->variables as $variable) { if ($callback($this->repository->get($variable)) === false) { $failing[] = \sprintf('%s %s', $variable, $message); } } if (\count($failing) > 0) { throw new ValidationException(\sprintf( 'One or more environment variables failed assertions: %s.', \implode(', ', $failing) )); } return $this; } /** * Assert that the callback returns true for each variable. * * Skip checking null variable values. * * @param callable(string):bool $callback * @param string $message * * @throws \Dotenv\Exception\ValidationException * * @return \Dotenv\Validator */ public function assertNullable(callable $callback, string $message) { return $this->assert( static function (?string $value) use ($callback) { if ($value === null) { return true; } return $callback($value); }, $message ); } } PK������@Z~ΐ������Store/FileStore.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Store; use Dotenv\Exception\InvalidPathException; use Dotenv\Store\File\Reader; final class FileStore implements StoreInterface { /** * The file paths. * * @var string[] */ private $filePaths; /** * Should file loading short circuit? * * @var bool */ private $shortCircuit; /** * The file encoding. * * @var string|null */ private $fileEncoding; /** * Create a new file store instance. * * @param string[] $filePaths * @param bool $shortCircuit * @param string|null $fileEncoding * * @return void */ public function __construct(array $filePaths, bool $shortCircuit, ?string $fileEncoding = null) { $this->filePaths = $filePaths; $this->shortCircuit = $shortCircuit; $this->fileEncoding = $fileEncoding; } /** * Read the content of the environment file(s). * * @throws \Dotenv\Exception\InvalidEncodingException|\Dotenv\Exception\InvalidPathException * * @return string */ public function read() { if ($this->filePaths === []) { throw new InvalidPathException('At least one environment file path must be provided.'); } $contents = Reader::read($this->filePaths, $this->shortCircuit, $this->fileEncoding); if (\count($contents) > 0) { return \implode("\n", $contents); } throw new InvalidPathException( \sprintf('Unable to read any of the environment file(s) at [%s].', \implode(', ', $this->filePaths)) ); } } PK������@Zbx5������Store/File/Paths.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Store\File; /** * @internal */ final class Paths { /** * This class is a singleton. * * @codeCoverageIgnore * * @return void */ private function __construct() { // } /** * Returns the full paths to the files. * * @param string[] $paths * @param string[] $names * * @return string[] */ public static function filePaths(array $paths, array $names) { $files = []; foreach ($paths as $path) { foreach ($names as $name) { $files[] = \rtrim($path, \DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR.$name; } } return $files; } } PK������@Z^7��7����Store/File/Reader.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Store\File; use Dotenv\Exception\InvalidEncodingException; use Dotenv\Util\Str; use PhpOption\Option; /** * @internal */ final class Reader { /** * This class is a singleton. * * @codeCoverageIgnore * * @return void */ private function __construct() { // } /** * Read the file(s), and return their raw content. * * We provide the file path as the key, and its content as the value. If * short circuit mode is enabled, then the returned array with have length * at most one. File paths that couldn't be read are omitted entirely. * * @param string[] $filePaths * @param bool $shortCircuit * @param string|null $fileEncoding * * @throws \Dotenv\Exception\InvalidEncodingException * * @return array<string,string> */ public static function read(array $filePaths, bool $shortCircuit = true, ?string $fileEncoding = null) { $output = []; foreach ($filePaths as $filePath) { $content = self::readFromFile($filePath, $fileEncoding); if ($content->isDefined()) { $output[$filePath] = $content->get(); if ($shortCircuit) { break; } } } return $output; } /** * Read the given file. * * @param string $path * @param string|null $encoding * * @throws \Dotenv\Exception\InvalidEncodingException * * @return \PhpOption\Option<string> */ private static function readFromFile(string $path, ?string $encoding = null) { /** @var Option<string> */ $content = Option::fromValue(@\file_get_contents($path), false); return $content->flatMap(static function (string $content) use ($encoding) { return Str::utf8($content, $encoding)->mapError(static function (string $error) { throw new InvalidEncodingException($error); })->success(); }); } } PK������@Z5d ��d ����Store/StoreBuilder.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Store; use Dotenv\Store\File\Paths; final class StoreBuilder { /** * The of default name. */ private const DEFAULT_NAME = '.env'; /** * The paths to search within. * * @var string[] */ private $paths; /** * The file names to search for. * * @var string[] */ private $names; /** * Should file loading short circuit? * * @var bool */ private $shortCircuit; /** * The file encoding. * * @var string|null */ private $fileEncoding; /** * Create a new store builder instance. * * @param string[] $paths * @param string[] $names * @param bool $shortCircuit * @param string|null $fileEncoding * * @return void */ private function __construct(array $paths = [], array $names = [], bool $shortCircuit = false, ?string $fileEncoding = null) { $this->paths = $paths; $this->names = $names; $this->shortCircuit = $shortCircuit; $this->fileEncoding = $fileEncoding; } /** * Create a new store builder instance with no names. * * @return \Dotenv\Store\StoreBuilder */ public static function createWithNoNames() { return new self(); } /** * Create a new store builder instance with the default name. * * @return \Dotenv\Store\StoreBuilder */ public static function createWithDefaultName() { return new self([], [self::DEFAULT_NAME]); } /** * Creates a store builder with the given path added. * * @param string $path * * @return \Dotenv\Store\StoreBuilder */ public function addPath(string $path) { return new self(\array_merge($this->paths, [$path]), $this->names, $this->shortCircuit, $this->fileEncoding); } /** * Creates a store builder with the given name added. * * @param string $name * * @return \Dotenv\Store\StoreBuilder */ public function addName(string $name) { return new self($this->paths, \array_merge($this->names, [$name]), $this->shortCircuit, $this->fileEncoding); } /** * Creates a store builder with short circuit mode enabled. * * @return \Dotenv\Store\StoreBuilder */ public function shortCircuit() { return new self($this->paths, $this->names, true, $this->fileEncoding); } /** * Creates a store builder with the specified file encoding. * * @param string|null $fileEncoding * * @return \Dotenv\Store\StoreBuilder */ public function fileEncoding(?string $fileEncoding = null) { return new self($this->paths, $this->names, $this->shortCircuit, $fileEncoding); } /** * Creates a new store instance. * * @return \Dotenv\Store\StoreInterface */ public function make() { return new FileStore( Paths::filePaths($this->paths, $this->names), $this->shortCircuit, $this->fileEncoding ); } } PK������@Z.M��M����Store/StringStore.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Store; final class StringStore implements StoreInterface { /** * The file content. * * @var string */ private $content; /** * Create a new string store instance. * * @param string $content * * @return void */ public function __construct(string $content) { $this->content = $content; } /** * Read the content of the environment file(s). * * @return string */ public function read() { return $this->content; } } PK������@ZI<��<����Store/StoreInterface.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Store; interface StoreInterface { /** * Read the content of the environment file(s). * * @throws \Dotenv\Exception\InvalidEncodingException|\Dotenv\Exception\InvalidPathException * * @return string */ public function read(); } PK������@ZFz������&��Exception/InvalidEncodingException.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Exception; use InvalidArgumentException; final class InvalidEncodingException extends InvalidArgumentException implements ExceptionInterface { // } PK������@Z������"��Exception/InvalidFileException.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Exception; use InvalidArgumentException; final class InvalidFileException extends InvalidArgumentException implements ExceptionInterface { // } PK������@Zָč������"��Exception/InvalidPathException.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Exception; use InvalidArgumentException; final class InvalidPathException extends InvalidArgumentException implements ExceptionInterface { // } PK������@Z=������ ��Exception/ExceptionInterface.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Exception; use Throwable; interface ExceptionInterface extends Throwable { // } PK������@Z=m������Loader/LoaderInterface.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Loader; use Dotenv\Repository\RepositoryInterface; interface LoaderInterface { /** * Load the given entries into the repository. * * @param \Dotenv\Repository\RepositoryInterface $repository * @param \Dotenv\Parser\Entry[] $entries * * @return array<string,string|null> */ public function load(RepositoryInterface $repository, array $entries); } PK������@Z͐1������Loader/Resolver.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Loader; use Dotenv\Parser\Value; use Dotenv\Repository\RepositoryInterface; use Dotenv\Util\Regex; use Dotenv\Util\Str; use PhpOption\Option; final class Resolver { /** * This class is a singleton. * * @codeCoverageIgnore * * @return void */ private function __construct() { // } /** * Resolve the nested variables in the given value. * * Replaces ${varname} patterns in the allowed positions in the variable * value by an existing environment variable. * * @param \Dotenv\Repository\RepositoryInterface $repository * @param \Dotenv\Parser\Value $value * * @return string */ public static function resolve(RepositoryInterface $repository, Value $value) { return \array_reduce($value->getVars(), static function (string $s, int $i) use ($repository) { return Str::substr($s, 0, $i).self::resolveVariable($repository, Str::substr($s, $i)); }, $value->getChars()); } /** * Resolve a single nested variable. * * @param \Dotenv\Repository\RepositoryInterface $repository * @param string $str * * @return string */ private static function resolveVariable(RepositoryInterface $repository, string $str) { return Regex::replaceCallback( '/\A\${([a-zA-Z0-9_.]+)}/', static function (array $matches) use ($repository) { return Option::fromValue($repository->get($matches[1])) ->getOrElse($matches[0]); }, $str, 1 )->success()->getOrElse($str); } } PK������@Zj������Loader/Loader.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Loader; use Dotenv\Parser\Entry; use Dotenv\Parser\Value; use Dotenv\Repository\RepositoryInterface; final class Loader implements LoaderInterface { /** * Load the given entries into the repository. * * We'll substitute any nested variables, and send each variable to the * repository, with the effect of actually mutating the environment. * * @param \Dotenv\Repository\RepositoryInterface $repository * @param \Dotenv\Parser\Entry[] $entries * * @return array<string,string|null> */ public function load(RepositoryInterface $repository, array $entries) { return \array_reduce($entries, static function (array $vars, Entry $entry) use ($repository) { $name = $entry->getName(); $value = $entry->getValue()->map(static function (Value $value) use ($repository) { return Resolver::resolve($repository, $value); }); if ($value->isDefined()) { $inner = $value->get(); if ($repository->set($name, $inner)) { return \array_merge($vars, [$name => $inner]); } } else { if ($repository->clear($name)) { return \array_merge($vars, [$name => null]); } } return $vars; }, []); } } PK������@ZW' �� ����Util/Regex.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Util; use GrahamCampbell\ResultType\Error; use GrahamCampbell\ResultType\Success; /** * @internal */ final class Regex { /** * This class is a singleton. * * @codeCoverageIgnore * * @return void */ private function __construct() { // } /** * Perform a preg match, wrapping up the result. * * @param string $pattern * @param string $subject * * @return \GrahamCampbell\ResultType\Result<bool,string> */ public static function matches(string $pattern, string $subject) { return self::pregAndWrap(static function (string $subject) use ($pattern) { return @\preg_match($pattern, $subject) === 1; }, $subject); } /** * Perform a preg match all, wrapping up the result. * * @param string $pattern * @param string $subject * * @return \GrahamCampbell\ResultType\Result<int,string> */ public static function occurrences(string $pattern, string $subject) { return self::pregAndWrap(static function (string $subject) use ($pattern) { return (int) @\preg_match_all($pattern, $subject); }, $subject); } /** * Perform a preg replace callback, wrapping up the result. * * @param string $pattern * @param callable $callback * @param string $subject * @param int|null $limit * * @return \GrahamCampbell\ResultType\Result<string,string> */ public static function replaceCallback(string $pattern, callable $callback, string $subject, ?int $limit = null) { return self::pregAndWrap(static function (string $subject) use ($pattern, $callback, $limit) { return (string) @\preg_replace_callback($pattern, $callback, $subject, $limit ?? -1); }, $subject); } /** * Perform a preg split, wrapping up the result. * * @param string $pattern * @param string $subject * * @return \GrahamCampbell\ResultType\Result<string[],string> */ public static function split(string $pattern, string $subject) { return self::pregAndWrap(static function (string $subject) use ($pattern) { /** @var string[] */ return (array) @\preg_split($pattern, $subject); }, $subject); } /** * Perform a preg operation, wrapping up the result. * * @template V * * @param callable(string):V $operation * @param string $subject * * @return \GrahamCampbell\ResultType\Result<V,string> */ private static function pregAndWrap(callable $operation, string $subject) { $result = $operation($subject); if (\preg_last_error() !== \PREG_NO_ERROR) { /** @var \GrahamCampbell\ResultType\Result<V,string> */ return Error::create(\preg_last_error_msg()); } /** @var \GrahamCampbell\ResultType\Result<V,string> */ return Success::create($result); } } PK������@ZkH ��H �� ��Dotenv.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv; use Dotenv\Exception\InvalidPathException; use Dotenv\Loader\Loader; use Dotenv\Loader\LoaderInterface; use Dotenv\Parser\Parser; use Dotenv\Parser\ParserInterface; use Dotenv\Repository\Adapter\ArrayAdapter; use Dotenv\Repository\Adapter\PutenvAdapter; use Dotenv\Repository\RepositoryBuilder; use Dotenv\Repository\RepositoryInterface; use Dotenv\Store\StoreBuilder; use Dotenv\Store\StoreInterface; use Dotenv\Store\StringStore; class Dotenv { /** * The store instance. * * @var \Dotenv\Store\StoreInterface */ private $store; /** * The parser instance. * * @var \Dotenv\Parser\ParserInterface */ private $parser; /** * The loader instance. * * @var \Dotenv\Loader\LoaderInterface */ private $loader; /** * The repository instance. * * @var \Dotenv\Repository\RepositoryInterface */ private $repository; /** * Create a new dotenv instance. * * @param \Dotenv\Store\StoreInterface $store * @param \Dotenv\Parser\ParserInterface $parser * @param \Dotenv\Loader\LoaderInterface $loader * @param \Dotenv\Repository\RepositoryInterface $repository * * @return void */ public function __construct( StoreInterface $store, ParserInterface $parser, LoaderInterface $loader, RepositoryInterface $repository ) { $this->store = $store; $this->parser = $parser; $this->loader = $loader; $this->repository = $repository; } /** * Create a new dotenv instance. * * @param \Dotenv\Repository\RepositoryInterface $repository * @param string|string[] $paths * @param string|string[]|null $names * @param bool $shortCircuit * @param string|null $fileEncoding * * @return \Dotenv\Dotenv */ public static function create(RepositoryInterface $repository, $paths, $names = null, bool $shortCircuit = true, ?string $fileEncoding = null) { $builder = $names === null ? StoreBuilder::createWithDefaultName() : StoreBuilder::createWithNoNames(); foreach ((array) $paths as $path) { $builder = $builder->addPath($path); } foreach ((array) $names as $name) { $builder = $builder->addName($name); } if ($shortCircuit) { $builder = $builder->shortCircuit(); } return new self($builder->fileEncoding($fileEncoding)->make(), new Parser(), new Loader(), $repository); } /** * Create a new mutable dotenv instance with default repository. * * @param string|string[] $paths * @param string|string[]|null $names * @param bool $shortCircuit * @param string|null $fileEncoding * * @return \Dotenv\Dotenv */ public static function createMutable($paths, $names = null, bool $shortCircuit = true, ?string $fileEncoding = null) { $repository = RepositoryBuilder::createWithDefaultAdapters()->make(); return self::create($repository, $paths, $names, $shortCircuit, $fileEncoding); } /** * Create a new mutable dotenv instance with default repository with the putenv adapter. * * @param string|string[] $paths * @param string|string[]|null $names * @param bool $shortCircuit * @param string|null $fileEncoding * * @return \Dotenv\Dotenv */ public static function createUnsafeMutable($paths, $names = null, bool $shortCircuit = true, ?string $fileEncoding = null) { $repository = RepositoryBuilder::createWithDefaultAdapters() ->addAdapter(PutenvAdapter::class) ->make(); return self::create($repository, $paths, $names, $shortCircuit, $fileEncoding); } /** * Create a new immutable dotenv instance with default repository. * * @param string|string[] $paths * @param string|string[]|null $names * @param bool $shortCircuit * @param string|null $fileEncoding * * @return \Dotenv\Dotenv */ public static function createImmutable($paths, $names = null, bool $shortCircuit = true, ?string $fileEncoding = null) { $repository = RepositoryBuilder::createWithDefaultAdapters()->immutable()->make(); return self::create($repository, $paths, $names, $shortCircuit, $fileEncoding); } /** * Create a new immutable dotenv instance with default repository with the putenv adapter. * * @param string|string[] $paths * @param string|string[]|null $names * @param bool $shortCircuit * @param string|null $fileEncoding * * @return \Dotenv\Dotenv */ public static function createUnsafeImmutable($paths, $names = null, bool $shortCircuit = true, ?string $fileEncoding = null) { $repository = RepositoryBuilder::createWithDefaultAdapters() ->addAdapter(PutenvAdapter::class) ->immutable() ->make(); return self::create($repository, $paths, $names, $shortCircuit, $fileEncoding); } /** * Create a new dotenv instance with an array backed repository. * * @param string|string[] $paths * @param string|string[]|null $names * @param bool $shortCircuit * @param string|null $fileEncoding * * @return \Dotenv\Dotenv */ public static function createArrayBacked($paths, $names = null, bool $shortCircuit = true, ?string $fileEncoding = null) { $repository = RepositoryBuilder::createWithNoAdapters()->addAdapter(ArrayAdapter::class)->make(); return self::create($repository, $paths, $names, $shortCircuit, $fileEncoding); } /** * Parse the given content and resolve nested variables. * * This method behaves just like load(), only without mutating your actual * environment. We do this by using an array backed repository. * * @param string $content * * @throws \Dotenv\Exception\InvalidFileException * * @return array<string,string|null> */ public static function parse(string $content) { $repository = RepositoryBuilder::createWithNoAdapters()->addAdapter(ArrayAdapter::class)->make(); $phpdotenv = new self(new StringStore($content), new Parser(), new Loader(), $repository); return $phpdotenv->load(); } /** * Read and load environment file(s). * * @throws \Dotenv\Exception\InvalidPathException|\Dotenv\Exception\InvalidEncodingException|\Dotenv\Exception\InvalidFileException * * @return array<string,string|null> */ public function load() { $entries = $this->parser->parse($this->store->read()); return $this->loader->load($this->repository, $entries); } /** * Read and load environment file(s), silently failing if no files can be read. * * @throws \Dotenv\Exception\InvalidEncodingException|\Dotenv\Exception\InvalidFileException * * @return array<string,string|null> */ public function safeLoad() { try { return $this->load(); } catch (InvalidPathException $e) { // suppressing exception return []; } } /** * Required ensures that the specified variables exist, and returns a new validator object. * * @param string|string[] $variables * * @return \Dotenv\Validator */ public function required($variables) { return (new Validator($this->repository, (array) $variables))->required(); } /** * Returns a new validator object that won't check if the specified variables exist. * * @param string|string[] $variables * * @return \Dotenv\Validator */ public function ifPresent($variables) { return new Validator($this->repository, (array) $variables); } } PK������@ZR:������Parser/Lexer.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Parser; final class Lexer { /** * The regex for each type of token. */ private const PATTERNS = [ '[\r\n]{1,1000}', '[^\S\r\n]{1,1000}', '\\\\', '\'', '"', '\\#', '\\$', '([^(\s\\\\\'"\\#\\$)]|\\(|\\)){1,1000}', ]; /** * This class is a singleton. * * @codeCoverageIgnore * * @return void */ private function __construct() { // } /** * Convert content into a token stream. * * Multibyte string processing is not needed here, and nether is error * handling, for performance reasons. * * @param string $content * * @return \Generator<string> */ public static function lex(string $content) { static $regex; if ($regex === null) { $regex = '(('.\implode(')|(', self::PATTERNS).'))A'; } $offset = 0; while (isset($content[$offset])) { if (!\preg_match($regex, $content, $matches, 0, $offset)) { throw new \Error(\sprintf('Lexer encountered unexpected character [%s].', $content[$offset])); } $offset += \strlen($matches[0]); yield $matches[0]; } } } PK������@Z*/N��N����Parser/ParserInterface.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Parser; interface ParserInterface { /** * Parse content into an entry array. * * @param string $content * * @throws \Dotenv\Exception\InvalidFileException * * @return \Dotenv\Parser\Entry[] */ public function parse(string $content); } PK������@Z+������Parser/Parser.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Parser; use Dotenv\Exception\InvalidFileException; use Dotenv\Util\Regex; use GrahamCampbell\ResultType\Result; use GrahamCampbell\ResultType\Success; final class Parser implements ParserInterface { /** * Parse content into an entry array. * * @param string $content * * @throws \Dotenv\Exception\InvalidFileException * * @return \Dotenv\Parser\Entry[] */ public function parse(string $content) { return Regex::split("/(\r\n|\n|\r)/", $content)->mapError(static function () { return 'Could not split into separate lines.'; })->flatMap(static function (array $lines) { return self::process(Lines::process($lines)); })->mapError(static function (string $error) { throw new InvalidFileException(\sprintf('Failed to parse dotenv file. %s', $error)); })->success()->get(); } /** * Convert the raw entries into proper entries. * * @param string[] $entries * * @return \GrahamCampbell\ResultType\Result<\Dotenv\Parser\Entry[],string> */ private static function process(array $entries) { /** @var \GrahamCampbell\ResultType\Result<\Dotenv\Parser\Entry[],string> */ return \array_reduce($entries, static function (Result $result, string $raw) { return $result->flatMap(static function (array $entries) use ($raw) { return EntryParser::parse($raw)->map(static function (Entry $entry) use ($entries) { /** @var \Dotenv\Parser\Entry[] */ return \array_merge($entries, [$entry]); }); }); }, Success::create([])); } } PK������@Z[pK ��K ����Parser/Lines.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Parser; use Dotenv\Util\Regex; use Dotenv\Util\Str; final class Lines { /** * This class is a singleton. * * @codeCoverageIgnore * * @return void */ private function __construct() { // } /** * Process the array of lines of environment variables. * * This will produce an array of raw entries, one per variable. * * @param string[] $lines * * @return string[] */ public static function process(array $lines) { $output = []; $multiline = false; $multilineBuffer = []; foreach ($lines as $line) { [$multiline, $line, $multilineBuffer] = self::multilineProcess($multiline, $line, $multilineBuffer); if (!$multiline && !self::isCommentOrWhitespace($line)) { $output[] = $line; } } return $output; } /** * Used to make all multiline variable process. * * @param bool $multiline * @param string $line * @param string[] $buffer * * @return array{bool,string,string[]} */ private static function multilineProcess(bool $multiline, string $line, array $buffer) { $startsOnCurrentLine = $multiline ? false : self::looksLikeMultilineStart($line); // check if $line can be multiline variable if ($startsOnCurrentLine) { $multiline = true; } if ($multiline) { \array_push($buffer, $line); if (self::looksLikeMultilineStop($line, $startsOnCurrentLine)) { $multiline = false; $line = \implode("\n", $buffer); $buffer = []; } } return [$multiline, $line, $buffer]; } /** * Determine if the given line can be the start of a multiline variable. * * @param string $line * * @return bool */ private static function looksLikeMultilineStart(string $line) { return Str::pos($line, '="')->map(static function () use ($line) { return self::looksLikeMultilineStop($line, true) === false; })->getOrElse(false); } /** * Determine if the given line can be the start of a multiline variable. * * @param string $line * @param bool $started * * @return bool */ private static function looksLikeMultilineStop(string $line, bool $started) { if ($line === '"') { return true; } return Regex::occurrences('/(?=([^\\\\]"))/', \str_replace('\\\\', '', $line))->map(static function (int $count) use ($started) { return $started ? $count > 1 : $count >= 1; })->success()->getOrElse(false); } /** * Determine if the line in the file is a comment or whitespace. * * @param string $line * * @return bool */ private static function isCommentOrWhitespace(string $line) { $line = \trim($line); return $line === '' || (isset($line[0]) && $line[0] === '#'); } } PK������@ZyoC 0��0����Parser/EntryParser.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Parser; use Dotenv\Util\Regex; use Dotenv\Util\Str; use GrahamCampbell\ResultType\Error; use GrahamCampbell\ResultType\Result; use GrahamCampbell\ResultType\Success; final class EntryParser { private const INITIAL_STATE = 0; private const UNQUOTED_STATE = 1; private const SINGLE_QUOTED_STATE = 2; private const DOUBLE_QUOTED_STATE = 3; private const ESCAPE_SEQUENCE_STATE = 4; private const WHITESPACE_STATE = 5; private const COMMENT_STATE = 6; private const REJECT_STATES = [self::SINGLE_QUOTED_STATE, self::DOUBLE_QUOTED_STATE, self::ESCAPE_SEQUENCE_STATE]; /** * This class is a singleton. * * @codeCoverageIgnore * * @return void */ private function __construct() { // } /** * Parse a raw entry into a proper entry. * * That is, turn a raw environment variable entry into a name and possibly * a value. We wrap the answer in a result type. * * @param string $entry * * @return \GrahamCampbell\ResultType\Result<\Dotenv\Parser\Entry,string> */ public static function parse(string $entry) { return self::splitStringIntoParts($entry)->flatMap(static function (array $parts) { [$name, $value] = $parts; return self::parseName($name)->flatMap(static function (string $name) use ($value) { /** @var Result<Value|null,string> */ $parsedValue = $value === null ? Success::create(null) : self::parseValue($value); return $parsedValue->map(static function (?Value $value) use ($name) { return new Entry($name, $value); }); }); }); } /** * Split the compound string into parts. * * @param string $line * * @return \GrahamCampbell\ResultType\Result<array{string,string|null},string> */ private static function splitStringIntoParts(string $line) { /** @var array{string,string|null} */ $result = Str::pos($line, '=')->map(static function () use ($line) { return \array_map('trim', \explode('=', $line, 2)); })->getOrElse([$line, null]); if ($result[0] === '') { /** @var \GrahamCampbell\ResultType\Result<array{string,string|null},string> */ return Error::create(self::getErrorMessage('an unexpected equals', $line)); } /** @var \GrahamCampbell\ResultType\Result<array{string,string|null},string> */ return Success::create($result); } /** * Parse the given variable name. * * That is, strip the optional quotes and leading "export" from the * variable name. We wrap the answer in a result type. * * @param string $name * * @return \GrahamCampbell\ResultType\Result<string,string> */ private static function parseName(string $name) { if (Str::len($name) > 8 && Str::substr($name, 0, 6) === 'export' && \ctype_space(Str::substr($name, 6, 1))) { $name = \ltrim(Str::substr($name, 6)); } if (self::isQuotedName($name)) { $name = Str::substr($name, 1, -1); } if (!self::isValidName($name)) { /** @var \GrahamCampbell\ResultType\Result<string,string> */ return Error::create(self::getErrorMessage('an invalid name', $name)); } /** @var \GrahamCampbell\ResultType\Result<string,string> */ return Success::create($name); } /** * Is the given variable name quoted? * * @param string $name * * @return bool */ private static function isQuotedName(string $name) { if (Str::len($name) < 3) { return false; } $first = Str::substr($name, 0, 1); $last = Str::substr($name, -1, 1); return ($first === '"' && $last === '"') || ($first === '\'' && $last === '\''); } /** * Is the given variable name valid? * * @param string $name * * @return bool */ private static function isValidName(string $name) { return Regex::matches('~(*UTF8)\A[\p{Ll}\p{Lu}\p{M}\p{N}_.]+\z~', $name)->success()->getOrElse(false); } /** * Parse the given variable value. * * This has the effect of stripping quotes and comments, dealing with * special characters, and locating nested variables, but not resolving * them. Formally, we run a finite state automaton with an output tape: a * transducer. We wrap the answer in a result type. * * @param string $value * * @return \GrahamCampbell\ResultType\Result<\Dotenv\Parser\Value,string> */ private static function parseValue(string $value) { if (\trim($value) === '') { /** @var \GrahamCampbell\ResultType\Result<\Dotenv\Parser\Value,string> */ return Success::create(Value::blank()); } return \array_reduce(\iterator_to_array(Lexer::lex($value)), static function (Result $data, string $token) { return $data->flatMap(static function (array $data) use ($token) { return self::processToken($data[1], $token)->map(static function (array $val) use ($data) { return [$data[0]->append($val[0], $val[1]), $val[2]]; }); }); }, Success::create([Value::blank(), self::INITIAL_STATE]))->flatMap(static function (array $result) { /** @psalm-suppress DocblockTypeContradiction */ if (in_array($result[1], self::REJECT_STATES, true)) { /** @var \GrahamCampbell\ResultType\Result<\Dotenv\Parser\Value,string> */ return Error::create('a missing closing quote'); } /** @var \GrahamCampbell\ResultType\Result<\Dotenv\Parser\Value,string> */ return Success::create($result[0]); })->mapError(static function (string $err) use ($value) { return self::getErrorMessage($err, $value); }); } /** * Process the given token. * * @param int $state * @param string $token * * @return \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ private static function processToken(int $state, string $token) { switch ($state) { case self::INITIAL_STATE: if ($token === '\'') { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create(['', false, self::SINGLE_QUOTED_STATE]); } elseif ($token === '"') { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create(['', false, self::DOUBLE_QUOTED_STATE]); } elseif ($token === '#') { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create(['', false, self::COMMENT_STATE]); } elseif ($token === '$') { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create([$token, true, self::UNQUOTED_STATE]); } else { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create([$token, false, self::UNQUOTED_STATE]); } case self::UNQUOTED_STATE: if ($token === '#') { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create(['', false, self::COMMENT_STATE]); } elseif (\ctype_space($token)) { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create(['', false, self::WHITESPACE_STATE]); } elseif ($token === '$') { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create([$token, true, self::UNQUOTED_STATE]); } else { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create([$token, false, self::UNQUOTED_STATE]); } case self::SINGLE_QUOTED_STATE: if ($token === '\'') { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create(['', false, self::WHITESPACE_STATE]); } else { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create([$token, false, self::SINGLE_QUOTED_STATE]); } case self::DOUBLE_QUOTED_STATE: if ($token === '"') { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create(['', false, self::WHITESPACE_STATE]); } elseif ($token === '\\') { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create(['', false, self::ESCAPE_SEQUENCE_STATE]); } elseif ($token === '$') { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create([$token, true, self::DOUBLE_QUOTED_STATE]); } else { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create([$token, false, self::DOUBLE_QUOTED_STATE]); } case self::ESCAPE_SEQUENCE_STATE: if ($token === '"' || $token === '\\') { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create([$token, false, self::DOUBLE_QUOTED_STATE]); } elseif ($token === '$') { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create([$token, false, self::DOUBLE_QUOTED_STATE]); } else { $first = Str::substr($token, 0, 1); if (\in_array($first, ['f', 'n', 'r', 't', 'v'], true)) { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create([\stripcslashes('\\'.$first).Str::substr($token, 1), false, self::DOUBLE_QUOTED_STATE]); } else { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Error::create('an unexpected escape sequence'); } } case self::WHITESPACE_STATE: if ($token === '#') { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create(['', false, self::COMMENT_STATE]); } elseif (!\ctype_space($token)) { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Error::create('unexpected whitespace'); } else { /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create(['', false, self::WHITESPACE_STATE]); } case self::COMMENT_STATE: /** @var \GrahamCampbell\ResultType\Result<array{string,bool,int},string> */ return Success::create(['', false, self::COMMENT_STATE]); default: throw new \Error('Parser entered invalid state.'); } } /** * Generate a friendly error message. * * @param string $cause * @param string $subject * * @return string */ private static function getErrorMessage(string $cause, string $subject) { return \sprintf( 'Encountered %s at [%s].', $cause, \strtok($subject, "\n") ); } } PK������@Zj> 4��4����Parser/Value.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Parser; use Dotenv\Util\Str; final class Value { /** * The string representation of the parsed value. * * @var string */ private $chars; /** * The locations of the variables in the value. * * @var int[] */ private $vars; /** * Internal constructor for a value. * * @param string $chars * @param int[] $vars * * @return void */ private function __construct(string $chars, array $vars) { $this->chars = $chars; $this->vars = $vars; } /** * Create an empty value instance. * * @return \Dotenv\Parser\Value */ public static function blank() { return new self('', []); } /** * Create a new value instance, appending the characters. * * @param string $chars * @param bool $var * * @return \Dotenv\Parser\Value */ public function append(string $chars, bool $var) { return new self( $this->chars.$chars, $var ? \array_merge($this->vars, [Str::len($this->chars)]) : $this->vars ); } /** * Get the string representation of the parsed value. * * @return string */ public function getChars() { return $this->chars; } /** * Get the locations of the variables in the value. * * @return int[] */ public function getVars() { $vars = $this->vars; \rsort($vars); return $vars; } } PK������@Z]������Parser/Entry.phpnu�W+A��������<?php declare(strict_types=1); namespace Dotenv\Parser; use PhpOption\Option; final class Entry { /** * The entry name. * * @var string */ private $name; /** * The entry value. * * @var \Dotenv\Parser\Value|null */ private $value; /** * Create a new entry instance. * * @param string $name * @param \Dotenv\Parser\Value|null $value * * @return void */ public function __construct(string $name, ?Value $value = null) { $this->name = $name; $this->value = $value; } /** * Get the entry name. * * @return string */ public function getName() { return $this->name; } /** * Get the entry value. * * @return \PhpOption\Option<\Dotenv\Parser\Value> */ public function getValue() { /** @var \PhpOption\Option<\Dotenv\Parser\Value> */ return Option::fromValue($this->value); } } PK������EZ & �� �� ��Wizard.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/code-unit-reverse-lookup. * * (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\CodeUnitReverseLookup; use function array_merge; use function assert; use function get_declared_classes; use function get_declared_traits; use function get_defined_functions; use function is_array; use function range; use ReflectionClass; use ReflectionFunction; use ReflectionFunctionAbstract; use ReflectionMethod; /** * @since Class available since Release 1.0.0 */ class Wizard { /** * @var array */ private $lookupTable = []; /** * @var array */ private $processedClasses = []; /** * @var array */ private $processedFunctions = []; /** * @param string $filename * @param int $lineNumber * * @return string */ public function lookup($filename, $lineNumber) { if (!isset($this->lookupTable[$filename][$lineNumber])) { $this->updateLookupTable(); } if (isset($this->lookupTable[$filename][$lineNumber])) { return $this->lookupTable[$filename][$lineNumber]; } return $filename . ':' . $lineNumber; } private function updateLookupTable(): void { $this->processClassesAndTraits(); $this->processFunctions(); } private function processClassesAndTraits(): void { $classes = get_declared_classes(); $traits = get_declared_traits(); assert(is_array($classes)); assert(is_array($traits)); foreach (array_merge($classes, $traits) as $classOrTrait) { if (isset($this->processedClasses[$classOrTrait])) { continue; } $reflector = new ReflectionClass($classOrTrait); foreach ($reflector->getMethods() as $method) { $this->processFunctionOrMethod($method); } $this->processedClasses[$classOrTrait] = true; } } private function processFunctions(): void { foreach (get_defined_functions()['user'] as $function) { if (isset($this->processedFunctions[$function])) { continue; } $this->processFunctionOrMethod(new ReflectionFunction($function)); $this->processedFunctions[$function] = true; } } private function processFunctionOrMethod(ReflectionFunctionAbstract $functionOrMethod): void { if ($functionOrMethod->isInternal()) { return; } $name = $functionOrMethod->getName(); if ($functionOrMethod instanceof ReflectionMethod) { $name = $functionOrMethod->getDeclaringClass()->getName() . '::' . $name; } if (!isset($this->lookupTable[$functionOrMethod->getFileName()])) { $this->lookupTable[$functionOrMethod->getFileName()] = []; } foreach (range($functionOrMethod->getStartLine(), $functionOrMethod->getEndLine()) as $line) { $this->lookupTable[$functionOrMethod->getFileName()][$line] = $name; } } } PK������qYZ? �� ����ServiceProvider.phpnu�W+A��������<?php namespace Barryvdh\DomPDF; use Dompdf\Dompdf; use Exception; use Illuminate\Support\Str; use Illuminate\Support\ServiceProvider as IlluminateServiceProvider; class ServiceProvider extends IlluminateServiceProvider { /** * Indicates if loading of the provider is deferred. * * @var bool */ protected $defer = false; /** * Register the service provider. * * @throws \Exception * @return void */ public function register(): void { $configPath = __DIR__ . '/../config/dompdf.php'; $this->mergeConfigFrom($configPath, 'dompdf'); $this->app->bind('dompdf.options', function ($app) { $defines = $app['config']->get('dompdf.defines'); if ($defines) { $options = []; /** * @var string $key * @var mixed $value */ foreach ($defines as $key => $value) { $key = strtolower(str_replace('DOMPDF_', '', $key)); $options[$key] = $value; } } else { $options = $app['config']->get('dompdf.options'); } return $options; }); $this->app->bind('dompdf', function ($app) { $options = $app->make('dompdf.options'); $dompdf = new Dompdf($options); $path = realpath($app['config']->get('dompdf.public_path') ?: base_path('public')); if ($path === false) { throw new \RuntimeException('Cannot resolve public path'); } $dompdf->setBasePath($path); return $dompdf; }); $this->app->alias('dompdf', Dompdf::class); $this->app->bind('dompdf.wrapper', function ($app) { return new PDF($app['dompdf'], $app['config'], $app['files'], $app['view']); }); } /** * Check if package is running under Lumen app */ protected function isLumen(): bool { return Str::contains($this->app->version(), 'Lumen') === true; } public function boot(): void { if (! $this->isLumen()) { $configPath = __DIR__ . '/../config/dompdf.php'; $this->publishes([$configPath => config_path('dompdf.php')], 'config'); } } /** * Get the services provided by the provider. * * @return array<string> */ public function provides(): array { return ['dompdf', 'dompdf.options', 'dompdf.wrapper']; } } PK������qYZ Y �� ����Facade/Pdf.phpnu�W+A��������<?php namespace Barryvdh\DomPDF\Facade; use Barryvdh\DomPDF\PDF as BasePDF; use Illuminate\Support\Facades\Facade as IlluminateFacade; use RuntimeException; /** * @method static BasePDF setBaseHost(string $baseHost) * @method static BasePDF setBasePath(string $basePath) * @method static BasePDF setCanvas(\Dompdf\Canvas $canvas) * @method static BasePDF setCallbacks(array $callbacks) * @method static BasePDF setCss(\Dompdf\Css\Stylesheet $css) * @method static BasePDF setDefaultView(string $defaultView, array $options) * @method static BasePDF setDom(\DOMDocument $dom) * @method static BasePDF setFontMetrics(\Dompdf\FontMetrics $fontMetrics) * @method static BasePDF setHttpContext(resource|array $httpContext) * @method static BasePDF setPaper(string|float[] $paper, string $orientation = 'portrait') * @method static BasePDF setProtocol(string $protocol) * @method static BasePDF setTree(\Dompdf\Frame\FrameTree $tree) * @method static BasePDF setWarnings(bool $warnings) * @method static BasePDF setOption(array|string $attribute, $value = null) * @method static BasePDF setOptions(array $options) * @method static BasePDF loadView(string $view, array $data = [], array $mergeData = [], ?string $encoding = null) * @method static BasePDF loadHTML(string $string, ?string $encoding = null) * @method static BasePDF loadFile(string $file) * @method static BasePDF addInfo(array $info) * @method static string output(array $options = []) * @method static BasePDF save() * @method static \Illuminate\Http\Response download(string $filename = 'document.pdf') * @method static \Illuminate\Http\Response stream(string $filename = 'document.pdf') */ class Pdf extends IlluminateFacade { /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return 'dompdf.wrapper'; } /** * Handle dynamic, static calls to the object. * * @param string $method * @param array<mixed> $args * @return mixed * * @throws \RuntimeException */ public static function __callStatic($method, $args) { /** @var \Illuminate\Contracts\Foundation\Application|null */ $app = static::getFacadeApplication(); if (! $app) { throw new RuntimeException('Facade application has not been set.'); } // Resolve a new instance, avoid using a cached instance $instance = $app->make(static::getFacadeAccessor()); return $instance->$method(...$args); } } PK������qYZXC!��C!����PDF.phpnu�W+A��������<?php namespace Barryvdh\DomPDF; use Dompdf\Adapter\CPDF; use Dompdf\Dompdf; use Dompdf\Options; use Exception; use Illuminate\Filesystem\Filesystem; use Illuminate\Contracts\View\Factory as ViewFactory; use Illuminate\Contracts\Config\Repository as ConfigRepository; use Illuminate\Http\Response; use Illuminate\Support\Facades\Storage; /** * A Laravel wrapper for Dompdf * * @package laravel-dompdf * @author Barry vd. Heuvel * * @method PDF setBaseHost(string $baseHost) * @method PDF setBasePath(string $basePath) * @method PDF setCanvas(\Dompdf\Canvas $canvas) * @method PDF setCallbacks(array $callbacks) * @method PDF setCss(\Dompdf\Css\Stylesheet $css) * @method PDF setDefaultView(string $defaultView, array $options) * @method PDF setDom(\DOMDocument $dom) * @method PDF setFontMetrics(\Dompdf\FontMetrics $fontMetrics) * @method PDF setHttpContext(resource|array $httpContext) * @method PDF setPaper(string|float[] $paper, string $orientation = 'portrait') * @method PDF setProtocol(string $protocol) * @method PDF setTree(\Dompdf\Frame\FrameTree $tree) * @method string getBaseHost() * @method string getBasePath() * @method \Dompdf\Canvas getCanvas() * @method array getCallbacks() * @method \Dompdf\Css\Stylesheet getCss() * @method \DOMDocument getDom() * @method \Dompdf\FontMetrics getFontMetrics() * @method resource getHttpContext() * @method Options getOptions() * @method \Dompdf\Frame\FrameTree getTree() * @method string getPaperOrientation() * @method float[] getPaperSize() * @method string getProtocol() */ class PDF { /** @var Dompdf */ protected $dompdf; /** @var \Illuminate\Contracts\Config\Repository */ protected $config; /** @var \Illuminate\Filesystem\Filesystem */ protected $files; /** @var \Illuminate\Contracts\View\Factory */ protected $view; /** @var bool */ protected $rendered = false; /** @var bool */ protected $showWarnings; /** @var string */ protected $public_path; public function __construct(Dompdf $dompdf, ConfigRepository $config, Filesystem $files, ViewFactory $view) { $this->dompdf = $dompdf; $this->config = $config; $this->files = $files; $this->view = $view; $this->showWarnings = $this->config->get('dompdf.show_warnings', false); } /** * Get the DomPDF instance */ public function getDomPDF(): Dompdf { return $this->dompdf; } /** * Show or hide warnings */ public function setWarnings(bool $warnings): self { $this->showWarnings = $warnings; return $this; } /** * Load a HTML string * * @param string|null $encoding Not used yet */ public function loadHTML(string $string, ?string $encoding = null): self { $string = $this->convertEntities($string); $this->dompdf->loadHtml($string, $encoding); $this->rendered = false; return $this; } /** * Load a HTML file */ public function loadFile(string $file): self { $this->dompdf->loadHtmlFile($file); $this->rendered = false; return $this; } /** * Add metadata info * @param array<string, string> $info */ public function addInfo(array $info): self { foreach ($info as $name => $value) { $this->dompdf->add_info($name, $value); } return $this; } /** * Load a View and convert to HTML * @param array<string, mixed> $data * @param array<string, mixed> $mergeData * @param string|null $encoding Not used yet */ public function loadView(string $view, array $data = [], array $mergeData = [], ?string $encoding = null): self { $html = $this->view->make($view, $data, $mergeData)->render(); return $this->loadHTML($html, $encoding); } /** * Set/Change an option (or array of options) in Dompdf * * @param array<string, mixed>|string $attribute * @param null|mixed $value */ public function setOption($attribute, $value = null): self { $this->dompdf->getOptions()->set($attribute, $value); return $this; } /** * Replace all the Options from DomPDF * * @deprecated Use setOption to override individual options. * @param array<string, mixed> $options */ public function setOptions(array $options): self { $options = new Options($options); $this->dompdf->setOptions($options); return $this; } /** * Output the PDF as a string. * * The options parameter controls the output. Accepted options are: * * 'compress' = > 1 or 0 - apply content stream compression, this is * on (1) by default * * @param array<string, int> $options * * @return string The rendered PDF as string */ public function output(array $options = []): string { if (!$this->rendered) { $this->render(); } return (string) $this->dompdf->output($options); } /** * Save the PDF to a file */ public function save(string $filename, string $disk = null): self { $disk = $disk ?: $this->config->get('dompdf.disk'); if (! is_null($disk)) { Storage::disk($disk)->put($filename, $this->output()); return $this; } $this->files->put($filename, $this->output()); return $this; } /** * Make the PDF downloadable by the user */ public function download(string $filename = 'document.pdf'): Response { $output = $this->output(); return new Response($output, 200, [ 'Content-Type' => 'application/pdf', 'Content-Disposition' => 'attachment; filename="' . $filename . '"', 'Content-Length' => strlen($output), ]); } /** * Return a response with the PDF to show in the browser */ public function stream(string $filename = 'document.pdf'): Response { $output = $this->output(); return new Response($output, 200, [ 'Content-Type' => 'application/pdf', 'Content-Disposition' => 'inline; filename="' . $filename . '"', ]); } /** * Render the PDF */ public function render(): void { $this->dompdf->render(); if ($this->showWarnings) { global $_dompdf_warnings; if (!empty($_dompdf_warnings) && count($_dompdf_warnings)) { $warnings = ''; foreach ($_dompdf_warnings as $msg) { $warnings .= $msg . "\n"; } // $warnings .= $this->dompdf->get_canvas()->get_cpdf()->messages; if (!empty($warnings)) { throw new Exception($warnings); } } } $this->rendered = true; } /** @param array<string> $pc */ public function setEncryption(string $password, string $ownerpassword = '', array $pc = []): void { $this->render(); $canvas = $this->dompdf->getCanvas(); if (! $canvas instanceof CPDF) { throw new \RuntimeException('Encryption is only supported when using CPDF'); } $canvas->get_cpdf()->setEncryption($password, $ownerpassword, $pc); } protected function convertEntities(string $subject): string { if (false === $this->config->get('dompdf.convert_entities', true)) { return $subject; } $entities = [ '€' => '€', '£' => '£', ]; foreach ($entities as $search => $replace) { $subject = str_replace($search, $replace, $subject); } return $subject; } /** * Dynamically handle calls into the dompdf instance. * * @param string $method * @param array<mixed> $parameters * @return $this|mixed */ public function __call($method, $parameters) { if (method_exists($this, $method)) { return $this->$method(...$parameters); } if (method_exists($this->dompdf, $method)) { $return = $this->dompdf->$method(...$parameters); return $return == $this->dompdf ? $this : $return; } throw new \UnexpectedValueException("Method [{$method}] does not exist on PDF instance."); } } PK������sYZXbpԊ������*��exceptions/NoPreReleaseSuffixException.phpnu�W+A��������<?php declare(strict_types = 1); namespace PharIo\Version; class NoPreReleaseSuffixException extends \Exception implements Exception { } PK������sYZ|������&��exceptions/InvalidVersionException.phpnu�W+A��������<?php declare(strict_types = 1); namespace PharIo\Version; class InvalidVersionException extends \InvalidArgumentException implements Exception { } PK������sYZ������/��exceptions/InvalidPreReleaseSuffixException.phpnu�W+A��������<?php declare(strict_types = 1); namespace PharIo\Version; class InvalidPreReleaseSuffixException extends \Exception implements Exception { } PK������sYZGd����4��exceptions/UnsupportedVersionConstraintException.phpnu�W+A��������<?php declare(strict_types = 1); /* * This file is part of PharIo\Version. * * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, 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 PharIo\Version; final class UnsupportedVersionConstraintException extends \RuntimeException implements Exception { } PK������sYZ������'��exceptions/NoBuildMetaDataException.phpnu�W+A��������<?php declare(strict_types = 1); namespace PharIo\Version; class NoBuildMetaDataException extends \Exception implements Exception { } PK������sYZH������BuildMetaData.phpnu�W+A��������<?php declare(strict_types = 1); /* * This file is part of PharIo\Version. * * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, 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 PharIo\Version; class BuildMetaData { /** @var string */ private $value; public function __construct(string $value) { $this->value = $value; } public function asString(): string { return $this->value; } public function equals(BuildMetaData $other): bool { return $this->asString() === $other->asString(); } } PK������sYZJ}r������VersionNumber.phpnu�W+A��������<?php declare(strict_types = 1); /* * This file is part of PharIo\Version. * * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, 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 PharIo\Version; class VersionNumber { /** @var ?int */ private $value; public function __construct(?int $value) { $this->value = $value; } public function isAny(): bool { return $this->value === null; } public function getValue(): ?int { return $this->value; } } PK������sYZ<P6������VersionConstraintParser.phpnu�W+A��������<?php declare(strict_types = 1); /* * This file is part of PharIo\Version. * * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, 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 PharIo\Version; class VersionConstraintParser { /** * @throws UnsupportedVersionConstraintException */ public function parse(string $value): VersionConstraint { if (\strpos($value, '|') !== false) { return $this->handleOrGroup($value); } if (!\preg_match('/^[\^~*]?v?[\d.*]+(?:-.*)?$/i', $value)) { throw new UnsupportedVersionConstraintException( \sprintf('Version constraint %s is not supported.', $value) ); } switch ($value[0]) { case '~': return $this->handleTildeOperator($value); case '^': return $this->handleCaretOperator($value); } $constraint = new VersionConstraintValue($value); if ($constraint->getMajor()->isAny()) { return new AnyVersionConstraint(); } if ($constraint->getMinor()->isAny()) { return new SpecificMajorVersionConstraint( $constraint->getVersionString(), $constraint->getMajor()->getValue() ?? 0 ); } if ($constraint->getPatch()->isAny()) { return new SpecificMajorAndMinorVersionConstraint( $constraint->getVersionString(), $constraint->getMajor()->getValue() ?? 0, $constraint->getMinor()->getValue() ?? 0 ); } return new ExactVersionConstraint($constraint->getVersionString()); } private function handleOrGroup(string $value): OrVersionConstraintGroup { $constraints = []; foreach (\preg_split('{\s*\|\|?\s*}', \trim($value)) as $groupSegment) { $constraints[] = $this->parse(\trim($groupSegment)); } return new OrVersionConstraintGroup($value, $constraints); } private function handleTildeOperator(string $value): AndVersionConstraintGroup { $constraintValue = new VersionConstraintValue(\substr($value, 1)); if ($constraintValue->getPatch()->isAny()) { return $this->handleCaretOperator($value); } $constraints = [ new GreaterThanOrEqualToVersionConstraint( $value, new Version(\substr($value, 1)) ), new SpecificMajorAndMinorVersionConstraint( $value, $constraintValue->getMajor()->getValue() ?? 0, $constraintValue->getMinor()->getValue() ?? 0 ) ]; return new AndVersionConstraintGroup($value, $constraints); } private function handleCaretOperator(string $value): AndVersionConstraintGroup { $constraintValue = new VersionConstraintValue(\substr($value, 1)); $constraints = [ new GreaterThanOrEqualToVersionConstraint($value, new Version(\substr($value, 1))) ]; if ($constraintValue->getMajor()->getValue() === 0) { $constraints[] = new SpecificMajorAndMinorVersionConstraint( $value, $constraintValue->getMajor()->getValue() ?? 0, $constraintValue->getMinor()->getValue() ?? 0 ); } else { $constraints[] = new SpecificMajorVersionConstraint( $value, $constraintValue->getMajor()->getValue() ?? 0 ); } return new AndVersionConstraintGroup( $value, $constraints ); } } PK������sYZP>13& ��& ����VersionConstraintValue.phpnu�W+A��������<?php declare(strict_types = 1); namespace PharIo\Version; class VersionConstraintValue { /** @var VersionNumber */ private $major; /** @var VersionNumber */ private $minor; /** @var VersionNumber */ private $patch; /** @var string */ private $label = ''; /** @var string */ private $buildMetaData = ''; /** @var string */ private $versionString = ''; public function __construct(string $versionString) { $this->versionString = $versionString; $this->parseVersion($versionString); } public function getLabel(): string { return $this->label; } public function getBuildMetaData(): string { return $this->buildMetaData; } public function getVersionString(): string { return $this->versionString; } public function getMajor(): VersionNumber { return $this->major; } public function getMinor(): VersionNumber { return $this->minor; } public function getPatch(): VersionNumber { return $this->patch; } private function parseVersion(string $versionString): void { $this->extractBuildMetaData($versionString); $this->extractLabel($versionString); $this->stripPotentialVPrefix($versionString); $versionSegments = \explode('.', $versionString); $this->major = new VersionNumber(\is_numeric($versionSegments[0]) ? (int)$versionSegments[0] : null); $minorValue = isset($versionSegments[1]) && \is_numeric($versionSegments[1]) ? (int)$versionSegments[1] : null; $patchValue = isset($versionSegments[2]) && \is_numeric($versionSegments[2]) ? (int)$versionSegments[2] : null; $this->minor = new VersionNumber($minorValue); $this->patch = new VersionNumber($patchValue); } private function extractBuildMetaData(string &$versionString): void { if (\preg_match('/\+(.*)/', $versionString, $matches) === 1) { $this->buildMetaData = $matches[1]; $versionString = \str_replace($matches[0], '', $versionString); } } private function extractLabel(string &$versionString): void { if (\preg_match('/-(.*)/', $versionString, $matches) === 1) { $this->label = $matches[1]; $versionString = \str_replace($matches[0], '', $versionString); } } private function stripPotentialVPrefix(string &$versionString): void { if ($versionString[0] !== 'v') { return; } $versionString = \substr($versionString, 1); } } PK������sYZ.o ^��^����PreReleaseSuffix.phpnu�W+A��������<?php declare(strict_types = 1); namespace PharIo\Version; class PreReleaseSuffix { private const valueScoreMap = [ 'dev' => 0, 'a' => 1, 'alpha' => 1, 'b' => 2, 'beta' => 2, 'rc' => 3, 'p' => 4, 'pl' => 4, 'patch' => 4, ]; /** @var string */ private $value; /** @var int */ private $valueScore; /** @var int */ private $number = 0; /** @var string */ private $full; /** * @throws InvalidPreReleaseSuffixException */ public function __construct(string $value) { $this->parseValue($value); } public function asString(): string { return $this->full; } public function getValue(): string { return $this->value; } public function getNumber(): ?int { return $this->number; } public function isGreaterThan(PreReleaseSuffix $suffix): bool { if ($this->valueScore > $suffix->valueScore) { return true; } if ($this->valueScore < $suffix->valueScore) { return false; } return $this->getNumber() > $suffix->getNumber(); } private function mapValueToScore(string $value): int { $value = \strtolower($value); return self::valueScoreMap[$value]; } private function parseValue(string $value): void { $regex = '/-?((dev|beta|b|rc|alpha|a|patch|p|pl)\.?(\d*)).*$/i'; if (\preg_match($regex, $value, $matches) !== 1) { throw new InvalidPreReleaseSuffixException(\sprintf('Invalid label %s', $value)); } $this->full = $matches[1]; $this->value = $matches[2]; if ($matches[3] !== '') { $this->number = (int)$matches[3]; } $this->valueScore = $this->mapValueToScore($matches[2]); } } PK������sYZv&E}���� ��Version.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (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\CodeCoverage; use function dirname; use SebastianBergmann\Version as VersionId; final class Version { /** * @var string */ private static $version; public static function id(): string { if (self::$version === null) { self::$version = (new VersionId('9.2.26', dirname(__DIR__)))->getVersion(); } return self::$version; } } PK������sYZ����(��constraints/OrVersionConstraintGroup.phpnu�W+A��������<?php declare(strict_types = 1); /* * This file is part of PharIo\Version. * * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, 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 PharIo\Version; class OrVersionConstraintGroup extends AbstractVersionConstraint { /** @var VersionConstraint[] */ private $constraints = []; /** * @param string $originalValue * @param VersionConstraint[] $constraints */ public function __construct($originalValue, array $constraints) { parent::__construct($originalValue); $this->constraints = $constraints; } public function complies(Version $version): bool { foreach ($this->constraints as $constraint) { if ($constraint->complies($version)) { return true; } } return false; } } PK������sYZ/j-����)��constraints/AndVersionConstraintGroup.phpnu�W+A��������<?php declare(strict_types = 1); /* * This file is part of PharIo\Version. * * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, 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 PharIo\Version; class AndVersionConstraintGroup extends AbstractVersionConstraint { /** @var VersionConstraint[] */ private $constraints = []; /** * @param VersionConstraint[] $constraints */ public function __construct(string $originalValue, array $constraints) { parent::__construct($originalValue); $this->constraints = $constraints; } public function complies(Version $version): bool { foreach ($this->constraints as $constraint) { if (!$constraint->complies($version)) { return false; } } return true; } } PK������sYZ ����.��constraints/SpecificMajorVersionConstraint.phpnu�W+A��������<?php declare(strict_types = 1); /* * This file is part of PharIo\Version. * * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, 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 PharIo\Version; class SpecificMajorVersionConstraint extends AbstractVersionConstraint { /** @var int */ private $major; public function __construct(string $originalValue, int $major) { parent::__construct($originalValue); $this->major = $major; } public function complies(Version $version): bool { return $version->getMajor()->getValue() === $this->major; } } PK������sYZ[ @��@��$��constraints/AnyVersionConstraint.phpnu�W+A��������<?php declare(strict_types = 1); /* * This file is part of PharIo\Version. * * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, 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 PharIo\Version; class AnyVersionConstraint implements VersionConstraint { public function complies(Version $version): bool { return true; } public function asString(): string { return '*'; } } PK������sYZ:B����&��constraints/ExactVersionConstraint.phpnu�W+A��������<?php declare(strict_types = 1); /* * This file is part of PharIo\Version. * * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, 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 PharIo\Version; class ExactVersionConstraint extends AbstractVersionConstraint { public function complies(Version $version): bool { $other = $version->getVersionString(); if ($version->hasBuildMetaData()) { $other .= '+' . $version->getBuildMetaData()->asString(); } return $this->asString() === $other; } } PK������sYZoSMy����)��constraints/AbstractVersionConstraint.phpnu�W+A��������<?php declare(strict_types = 1); /* * This file is part of PharIo\Version. * * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, 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 PharIo\Version; abstract class AbstractVersionConstraint implements VersionConstraint { /** @var string */ private $originalValue; public function __construct(string $originalValue) { $this->originalValue = $originalValue; } public function asString(): string { return $this->originalValue; } } PK������sYZ^����5��constraints/GreaterThanOrEqualToVersionConstraint.phpnu�W+A��������<?php declare(strict_types = 1); /* * This file is part of PharIo\Version. * * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, 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 PharIo\Version; class GreaterThanOrEqualToVersionConstraint extends AbstractVersionConstraint { /** @var Version */ private $minimalVersion; public function __construct(string $originalValue, Version $minimalVersion) { parent::__construct($originalValue); $this->minimalVersion = $minimalVersion; } public function complies(Version $version): bool { return $version->getVersionString() === $this->minimalVersion->getVersionString() || $version->isGreaterThan($this->minimalVersion); } } PK������sYZW����!��constraints/VersionConstraint.phpnu�W+A��������<?php declare(strict_types = 1); /* * This file is part of PharIo\Version. * * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, 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 PharIo\Version; interface VersionConstraint { public function complies(Version $version): bool; public function asString(): string; } PK������sYZLK����6��constraints/SpecificMajorAndMinorVersionConstraint.phpnu�W+A��������<?php declare(strict_types = 1); /* * This file is part of PharIo\Version. * * (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de>, 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 PharIo\Version; class SpecificMajorAndMinorVersionConstraint extends AbstractVersionConstraint { /** @var int */ private $major; /** @var int */ private $minor; public function __construct(string $originalValue, int $major, int $minor) { parent::__construct($originalValue); $this->major = $major; $this->minor = $minor; } public function complies(Version $version): bool { if ($version->getMajor()->getValue() !== $this->major) { return false; } return $version->getMinor()->getValue() === $this->minor; } } PK������aZ7m��m����ValueObjects/Styles.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\ValueObjects; use Closure; use Termwind\Actions\StyleToMethod; use Termwind\Components\Element; use Termwind\Components\Hr; use Termwind\Components\Li; use Termwind\Components\Ol; use Termwind\Components\Ul; use Termwind\Enums\Color; use Termwind\Exceptions\ColorNotFound; use Termwind\Exceptions\InvalidStyle; use Termwind\Repositories\Styles as StyleRepository; use function Termwind\terminal; /** * @internal */ final class Styles { /** * Finds all the styling on a string. */ public const STYLING_REGEX = "/\<[\w=#\/\;,:.&,%?-]+\>|\\e\[\d+m/"; /** @var array<int, string> */ private array $styles = []; private ?Element $element = null; /** * Creates a Style formatter instance. * * @param array<string, mixed> $properties * @param array<string, Closure(string, array<string, string|int>, array<string, int[]>): string> $textModifiers * @param array<string, Closure(string, array<string, string|int>): string> $styleModifiers * @param string[] $defaultStyles */ final public function __construct( private array $properties = [ 'colors' => [], 'options' => [], 'isFirstChild' => false, ], private array $textModifiers = [], private array $styleModifiers = [], private array $defaultStyles = [] ) {} /** * @return $this */ public function setElement(Element $element): self { $this->element = $element; return $this; } /** * Gets default styles. * * @return string[] */ public function defaultStyles(): array { return $this->defaultStyles; } /** * Gets the element's style properties. * * @return array<string, mixed> */ final public function getProperties(): array { return $this->properties; } /** * Sets the element's style properties. * * @param array<string, mixed> $properties */ public function setProperties(array $properties): self { $this->properties = $properties; return $this; } /** * Sets the styles to the element. */ final public function setStyle(string $style): self { $this->styles = array_unique(array_merge($this->styles, [$style])); return $this; } /** * Checks if the element has the style. */ final public function hasStyle(string $style): bool { return in_array($style, $this->styles, true); } /** * Adds a style to the element. */ final public function addStyle(string $style): self { return StyleToMethod::multiple($this, $style); } /** * Inherit styles from given Styles object. */ final public function inheritFromStyles(self $styles): self { foreach (['ml', 'mr', 'pl', 'pr', 'width', 'minWidth', 'maxWidth', 'spaceY', 'spaceX'] as $style) { $this->properties['parentStyles'][$style] = array_merge( $this->properties['parentStyles'][$style] ?? [], $styles->properties['parentStyles'][$style] ?? [] ); $this->properties['parentStyles'][$style][] = $styles->properties['styles'][$style] ?? 0; } $this->properties['parentStyles']['justifyContent'] = $styles->properties['styles']['justifyContent'] ?? false; foreach (['bg', 'fg'] as $colorType) { $value = (array) ($this->properties['colors'][$colorType] ?? []); $parentValue = (array) ($styles->properties['colors'][$colorType] ?? []); if ($value === [] && $parentValue !== []) { $this->properties['colors'][$colorType] = $styles->properties['colors'][$colorType]; } } if (! is_null($this->properties['options']['bold'] ?? null) || ! is_null($styles->properties['options']['bold'] ?? null)) { $this->properties['options']['bold'] = $this->properties['options']['bold'] ?? $styles->properties['options']['bold'] ?? false; } return $this; } /** * Adds a background color to the element. */ final public function bg(string $color, int $variant = 0): self { return $this->with(['colors' => [ 'bg' => $this->getColorVariant($color, $variant), ]]); } /** * Adds a bold style to the element. */ final public function fontBold(): self { return $this->with(['options' => [ 'bold' => true, ]]); } /** * Removes the bold style on the element. */ final public function fontNormal(): self { return $this->with(['options' => [ 'bold' => false, ]]); } /** * Adds a bold style to the element. */ final public function strong(): self { $this->styleModifiers[__METHOD__] = static fn ($text): string => sprintf("\e[1m%s\e[0m", $text); return $this; } /** * Adds an italic style to the element. */ final public function italic(): self { $this->styleModifiers[__METHOD__] = static fn ($text): string => sprintf("\e[3m%s\e[0m", $text); return $this; } /** * Adds an underline style. */ final public function underline(): self { $this->styleModifiers[__METHOD__] = static fn ($text): string => sprintf("\e[4m%s\e[0m", $text); return $this; } /** * Adds the given margin left to the element. */ final public function ml(int $margin): self { return $this->with(['styles' => [ 'ml' => $margin, ]]); } /** * Adds the given margin right to the element. */ final public function mr(int $margin): self { return $this->with(['styles' => [ 'mr' => $margin, ]]); } /** * Adds the given margin bottom to the element. */ final public function mb(int $margin): self { return $this->with(['styles' => [ 'mb' => $margin, ]]); } /** * Adds the given margin top to the element. */ final public function mt(int $margin): self { return $this->with(['styles' => [ 'mt' => $margin, ]]); } /** * Adds the given horizontal margin to the element. */ final public function mx(int $margin): self { return $this->with(['styles' => [ 'ml' => $margin, 'mr' => $margin, ]]); } /** * Adds the given vertical margin to the element. */ final public function my(int $margin): self { return $this->with(['styles' => [ 'mt' => $margin, 'mb' => $margin, ]]); } /** * Adds the given margin to the element. */ final public function m(int $margin): self { return $this->my($margin)->mx($margin); } /** * Adds the given padding left to the element. */ final public function pl(int $padding): static { return $this->with(['styles' => [ 'pl' => $padding, ]]); } /** * Adds the given padding right. */ final public function pr(int $padding): static { return $this->with(['styles' => [ 'pr' => $padding, ]]); } /** * Adds the given horizontal padding. */ final public function px(int $padding): self { return $this->pl($padding)->pr($padding); } /** * Adds the given padding top. */ final public function pt(int $padding): static { return $this->with(['styles' => [ 'pt' => $padding, ]]); } /** * Adds the given padding bottom. */ final public function pb(int $padding): static { return $this->with(['styles' => [ 'pb' => $padding, ]]); } /** * Adds the given vertical padding. */ final public function py(int $padding): self { return $this->pt($padding)->pb($padding); } /** * Adds the given padding. */ final public function p(int $padding): self { return $this->pt($padding)->pr($padding)->pb($padding)->pl($padding); } /** * Adds the given vertical margin to the childs, ignoring the first child. */ final public function spaceY(int $space): self { return $this->with(['styles' => [ 'spaceY' => $space, ]]); } /** * Adds the given horizontal margin to the childs, ignoring the first child. */ final public function spaceX(int $space): self { return $this->with(['styles' => [ 'spaceX' => $space, ]]); } /** * Adds a border on top of each element. */ final public function borderT(int $width = 1): self { if (! $this->element instanceof Hr) { throw new InvalidStyle('`border-t` can only be used on an "hr" element.'); } $this->styleModifiers[__METHOD__] = function ($text, $styles): string { $length = $this->getLength($text); if ($length < 1) { $margins = (int) ($styles['ml'] ?? 0) + ($styles['mr'] ?? 0); return str_repeat('─', self::getParentWidth($this->properties['parentStyles'] ?? []) - $margins); } return str_repeat('─', $length); }; return $this; } /** * Adds a text alignment or color to the element. */ final public function text(string $value, int $variant = 0): self { if (in_array($value, ['left', 'right', 'center'], true)) { return $this->with(['styles' => [ 'text-align' => $value, ]]); } return $this->with(['colors' => [ 'fg' => $this->getColorVariant($value, $variant), ]]); } /** * Truncates the text of the element. */ final public function truncate(int $limit = 0, string $end = '…'): self { $this->textModifiers[__METHOD__] = function ($text, $styles) use ($limit, $end): string { $width = $styles['width'] ?? 0; if (is_string($width)) { $width = self::calcWidthFromFraction( $width, $styles, $this->properties['parentStyles'] ?? [] ); } [, $paddingRight, , $paddingLeft] = $this->getPaddings(); $width -= $paddingRight + $paddingLeft; $limit = $limit > 0 ? $limit : $width; if ($limit === 0) { return $text; } $limit -= mb_strwidth($end, 'UTF-8'); if ($this->getLength($text) <= $limit) { return $text; } return rtrim(self::trimText($text, $limit).$end); }; return $this; } /** * Forces the width of the element. */ final public function w(int|string $width): static { return $this->with(['styles' => [ 'width' => $width, ]]); } /** * Forces the element width to the full width of the terminal. */ final public function wFull(): static { return $this->w('1/1'); } /** * Removes the width set on the element. */ final public function wAuto(): static { return $this->with(['styles' => [ 'width' => null, ]]); } /** * Defines a minimum width of an element. */ final public function minW(int|string $width): static { return $this->with(['styles' => [ 'minWidth' => $width, ]]); } /** * Defines a maximum width of an element. */ final public function maxW(int|string $width): static { return $this->with(['styles' => [ 'maxWidth' => $width, ]]); } /** * Makes the element's content uppercase. */ final public function uppercase(): self { $this->textModifiers[__METHOD__] = static fn ($text): string => mb_strtoupper($text, 'UTF-8'); return $this; } /** * Makes the element's content lowercase. */ final public function lowercase(): self { $this->textModifiers[__METHOD__] = static fn ($text): string => mb_strtolower($text, 'UTF-8'); return $this; } /** * Makes the element's content capitalize. */ final public function capitalize(): self { $this->textModifiers[__METHOD__] = static fn ($text): string => mb_convert_case($text, MB_CASE_TITLE, 'UTF-8'); return $this; } /** * Makes the element's content in snakecase. */ final public function snakecase(): self { $this->textModifiers[__METHOD__] = static fn ($text): string => mb_strtolower( (string) preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $text), 'UTF-8' ); return $this; } /** * Makes the element's content with a line through. */ final public function lineThrough(): self { $this->styleModifiers[__METHOD__] = static fn ($text): string => sprintf("\e[9m%s\e[0m", $text); return $this; } /** * Makes the element's content invisible. */ final public function invisible(): self { $this->styleModifiers[__METHOD__] = static fn ($text): string => sprintf("\e[8m%s\e[0m", $text); return $this; } /** * Do not display element's content. */ final public function hidden(): self { return $this->with(['styles' => [ 'display' => 'hidden', ]]); } /** * Makes a line break before the element's content. */ final public function block(): self { return $this->with(['styles' => [ 'display' => 'block', ]]); } /** * Makes an element eligible to work with flex-1 element's style. */ final public function flex(): self { return $this->with(['styles' => [ 'display' => 'flex', ]]); } /** * Makes an element grow and shrink as needed, ignoring the initial size. */ final public function flex1(): self { return $this->with(['styles' => [ 'flex-1' => true, ]]); } /** * Justifies childs along the element with an equal amount of space between. */ final public function justifyBetween(): self { return $this->with(['styles' => [ 'justifyContent' => 'between', ]]); } /** * Justifies childs along the element with an equal amount of space between * each item and half around. */ final public function justifyAround(): self { return $this->with(['styles' => [ 'justifyContent' => 'around', ]]); } /** * Justifies childs along the element with an equal amount of space around each item. */ final public function justifyEvenly(): self { return $this->with(['styles' => [ 'justifyContent' => 'evenly', ]]); } /** * Justifies childs along the center of the container’s main axis. */ final public function justifyCenter(): self { return $this->with(['styles' => [ 'justifyContent' => 'center', ]]); } /** * Repeats the string given until it fills all the content. */ final public function contentRepeat(string $string): self { $string = preg_replace("/\[?'?([^'|\]]+)'?\]?/", '$1', $string) ?? ''; $this->textModifiers[__METHOD__] = static fn (): string => str_repeat($string, (int) floor(terminal()->width() / mb_strlen($string, 'UTF-8'))); return $this->with(['styles' => [ 'contentRepeat' => true, ]]); } /** * Prepends text to the content. */ final public function prepend(string $string): self { $this->textModifiers[__METHOD__] = static fn ($text): string => $string.$text; return $this; } /** * Appends text to the content. */ final public function append(string $string): self { $this->textModifiers[__METHOD__] = static fn ($text): string => $text.$string; return $this; } /** * Prepends the list style type to the content. */ final public function list(string $type, int $index = 0): self { if (! $this->element instanceof Ul && ! $this->element instanceof Ol && ! $this->element instanceof Li) { throw new InvalidStyle(sprintf( 'Style list-none cannot be used with %s', $this->element !== null ? $this->element::class : 'unknown element' )); } if (! $this->element instanceof Li) { return $this; } return match ($type) { 'square' => $this->prepend('▪ '), 'disc' => $this->prepend('• '), 'decimal' => $this->prepend(sprintf('%d. ', $index)), default => $this, }; } /** * Adds the given properties to the element. * * @param array<string, mixed> $properties */ public function with(array $properties): self { $this->properties = array_replace_recursive($this->properties, $properties); return $this; } /** * Sets the href property to the element. */ final public function href(string $href): self { $href = str_replace('%', '%%', $href); return $this->with(['href' => array_filter([$href])]); } /** * Formats a given string. */ final public function format(string $content): string { foreach ($this->textModifiers as $modifier) { $content = $modifier( $content, $this->properties['styles'] ?? [], $this->properties['parentStyles'] ?? [] ); } $content = $this->applyWidth($content); foreach ($this->styleModifiers as $modifier) { $content = $modifier($content, $this->properties['styles'] ?? []); } return $this->applyStyling($content); } /** * Get the format string including required styles. */ private function getFormatString(): string { $styles = []; /** @var array<int, string> $href */ $href = $this->properties['href'] ?? []; if ($href !== []) { $styles[] = sprintf('href=%s', array_pop($href)); } $colors = $this->properties['colors'] ?? []; foreach ($colors as $option => $content) { if (in_array($option, ['fg', 'bg'], true)) { $content = is_array($content) ? array_pop($content) : $content; $styles[] = "$option=$content"; } } $options = $this->properties['options'] ?? []; if ($options !== []) { $options = array_keys(array_filter( $options, fn ($option) => $option === true )); $styles[] = count($options) > 0 ? 'options='.implode(',', $options) : 'options=,'; } // If there are no styles we don't need extra tags if ($styles === []) { return '%s%s%s%s%s'; } return '%s<'.implode(';', $styles).'>%s%s%s</>%s'; } /** * Get the margins applied to the element. * * @return array{0: int, 1: int, 2: int, 3: int} */ private function getMargins(): array { $isFirstChild = (bool) $this->properties['isFirstChild']; $spaceY = $this->properties['parentStyles']['spaceY'] ?? []; $spaceY = ! $isFirstChild ? end($spaceY) : 0; $spaceX = $this->properties['parentStyles']['spaceX'] ?? []; $spaceX = ! $isFirstChild ? end($spaceX) : 0; return [ $spaceY > 0 ? $spaceY : $this->properties['styles']['mt'] ?? 0, $this->properties['styles']['mr'] ?? 0, $this->properties['styles']['mb'] ?? 0, $spaceX > 0 ? $spaceX : $this->properties['styles']['ml'] ?? 0, ]; } /** * Get the paddings applied to the element. * * @return array{0: int, 1: int, 2: int, 3: int} */ private function getPaddings(): array { return [ $this->properties['styles']['pt'] ?? 0, $this->properties['styles']['pr'] ?? 0, $this->properties['styles']['pb'] ?? 0, $this->properties['styles']['pl'] ?? 0, ]; } /** * It applies the correct width for the content. */ private function applyWidth(string $content): string { $styles = $this->properties['styles'] ?? []; $minWidth = $styles['minWidth'] ?? -1; $width = max($styles['width'] ?? -1, $minWidth); $maxWidth = $styles['maxWidth'] ?? 0; if ($width < 0) { return $content; } if ($width === 0) { return ''; } if (is_string($width)) { $width = self::calcWidthFromFraction( $width, $styles, $this->properties['parentStyles'] ?? [] ); } if ($maxWidth > 0) { $width = min($styles['maxWidth'], $width); } $width -= ($styles['pl'] ?? 0) + ($styles['pr'] ?? 0); $length = $this->getLength($content); preg_match_all("/\n+/", $content, $matches); $width *= count($matches[0] ?? []) + 1; // @phpstan-ignore-line $width += mb_strlen($matches[0][0] ?? '', 'UTF-8'); if ($length <= $width) { $space = $width - $length; return match ($styles['text-align'] ?? '') { 'right' => str_repeat(' ', $space).$content, 'center' => str_repeat(' ', (int) floor($space / 2)).$content.str_repeat(' ', (int) ceil($space / 2)), default => $content.str_repeat(' ', $space), }; } return self::trimText($content, $width); } /** * It applies the styling for the content. */ private function applyStyling(string $content): string { $display = $this->properties['styles']['display'] ?? 'inline'; if ($display === 'hidden') { return ''; } $isFirstChild = (bool) $this->properties['isFirstChild']; [$marginTop, $marginRight, $marginBottom, $marginLeft] = $this->getMargins(); [$paddingTop, $paddingRight, $paddingBottom, $paddingLeft] = $this->getPaddings(); $content = (string) preg_replace('/\r[ \t]?/', "\n", (string) preg_replace( '/\n/', str_repeat(' ', $marginRight + $paddingRight) ."\n". str_repeat(' ', $marginLeft + $paddingLeft), $content) ); $formatted = sprintf( $this->getFormatString(), str_repeat(' ', $marginLeft), str_repeat(' ', $paddingLeft), $content, str_repeat(' ', $paddingRight), str_repeat(' ', $marginRight), ); $empty = str_replace( $content, str_repeat(' ', $this->getLength($content)), $formatted ); $items = []; if (in_array($display, ['block', 'flex'], true) && ! $isFirstChild) { $items[] = "\n"; } if ($marginTop > 0) { $items[] = str_repeat("\n", $marginTop); } if ($paddingTop > 0) { $items[] = $empty."\n"; } $items[] = $formatted; if ($paddingBottom > 0) { $items[] = "\n".$empty; } if ($marginBottom > 0) { $items[] = str_repeat("\n", $marginBottom); } return implode('', $items); } /** * Get the length of the text provided without the styling tags. */ public function getLength(?string $text = null): int { return mb_strlen(preg_replace( self::STYLING_REGEX, '', $text ?? $this->element?->toString() ?? '' ) ?? '', 'UTF-8'); } /** * Get the length of the element without margins. */ public function getInnerWidth(): int { $innerLength = $this->getLength(); [, $marginRight, , $marginLeft] = $this->getMargins(); return $innerLength - $marginLeft - $marginRight; } /** * Get the constant variant color from Color class. */ private function getColorVariant(string $color, int $variant): string { if ($variant > 0) { $color .= '-'.$variant; } if (StyleRepository::has($color)) { return StyleRepository::get($color)->getColor(); } $colorConstant = mb_strtoupper(str_replace('-', '_', $color), 'UTF-8'); if (! defined(Color::class."::$colorConstant")) { throw new ColorNotFound($colorConstant); } return constant(Color::class."::$colorConstant"); } /** * Calculates the width based on the fraction provided. * * @param array<string, int> $styles * @param array<string, array<int, int|string>> $parentStyles */ private static function calcWidthFromFraction(string $fraction, array $styles, array $parentStyles): int { $width = self::getParentWidth($parentStyles); preg_match('/(\d+)\/(\d+)/', $fraction, $matches); if (count($matches) !== 3 || $matches[2] === '0') { throw new InvalidStyle(sprintf('Style [%s] is invalid.', "w-$fraction")); } $width = (int) floor($width * $matches[1] / $matches[2]); $width -= ($styles['ml'] ?? 0) + ($styles['mr'] ?? 0); return $width; } /** * Gets the width of the parent element. * * @param array<string, array<int|string>> $styles */ public static function getParentWidth(array $styles): int { $width = terminal()->width(); foreach ($styles['width'] ?? [] as $index => $parentWidth) { $minWidth = (int) $styles['minWidth'][$index]; $maxWidth = (int) $styles['maxWidth'][$index]; $margins = (int) $styles['ml'][$index] + (int) $styles['mr'][$index]; $parentWidth = max($parentWidth, $minWidth); if ($parentWidth < 1) { $parentWidth = $width; } elseif (is_int($parentWidth)) { $parentWidth += $margins; } preg_match('/(\d+)\/(\d+)/', (string) $parentWidth, $matches); $width = count($matches) !== 3 ? (int) $parentWidth : (int) floor($width * $matches[1] / $matches[2]); if ($maxWidth > 0) { $width = min($maxWidth, $width); } $width -= $margins; $width -= (int) $styles['pl'][$index] + (int) $styles['pr'][$index]; } return $width; } /** * It trims the text properly ignoring all escape codes and * `<bg;fg;options>` tags. */ private static function trimText(string $text, int $width): string { preg_match_all(self::STYLING_REGEX, $text, $matches, PREG_OFFSET_CAPTURE); $text = rtrim(mb_strimwidth(preg_replace(self::STYLING_REGEX, '', $text) ?? '', 0, $width, '', 'UTF-8')); // @phpstan-ignore-next-line foreach ($matches[0] ?? [] as [$part, $index]) { $text = substr($text, 0, $index).$part.substr($text, $index, null); } return $text; } } PK������aZ媁\��\����ValueObjects/Node.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\ValueObjects; use Generator; /** * @internal */ final class Node { /** * A value object with helper methods for working with DOM node. */ public function __construct(private \DOMNode $node) {} /** * Gets the value of the node. */ public function getValue(): string { return $this->node->nodeValue ?? ''; } /** * Gets child nodes of the node. * * @return Generator<Node> */ public function getChildNodes(): Generator { foreach ($this->node->childNodes as $node) { yield new self($node); } } /** * Checks if the node is a text. */ public function isText(): bool { return $this->node instanceof \DOMText; } /** * Checks if the node is a comment. */ public function isComment(): bool { return $this->node instanceof \DOMComment; } /** * Compares the current node name with a given name. */ public function isName(string $name): bool { return $this->getName() === $name; } /** * Returns the current node type name. */ public function getName(): string { return $this->node->nodeName; } /** * Returns value of [class] attribute. */ public function getClassAttribute(): string { return $this->getAttribute('class'); } /** * Returns value of attribute with a given name. */ public function getAttribute(string $name): string { if ($this->node instanceof \DOMElement) { return $this->node->getAttribute($name); } return ''; } /** * Checks if the node is empty. */ public function isEmpty(): bool { return $this->isText() && preg_replace('/\s+/', '', $this->getValue()) === ''; } /** * Gets the previous sibling from the node. */ public function getPreviousSibling(): static|null { $node = $this->node; while ($node = $node->previousSibling) { $node = new self($node); if ($node->isEmpty()) { $node = $node->node; continue; } if (! $node->isComment()) { return $node; } $node = $node->node; } return is_null($node) ? null : new self($node); } /** * Gets the next sibling from the node. */ public function getNextSibling(): static|null { $node = $this->node; while ($node = $node->nextSibling) { $node = new self($node); if ($node->isEmpty()) { $node = $node->node; continue; } if (! $node->isComment()) { return $node; } $node = $node->node; } return is_null($node) ? null : new self($node); } /** * Checks if the node is the first child. */ public function isFirstChild(): bool { return is_null($this->getPreviousSibling()); } /** * Gets the inner HTML representation of the node including child nodes. */ public function getHtml(): string { $html = ''; foreach ($this->node->childNodes as $child) { if ($child->ownerDocument instanceof \DOMDocument) { $html .= $child->ownerDocument->saveXML($child); } } return html_entity_decode($html); } /** * Converts the node to a string. */ public function __toString(): string { if ($this->isComment()) { return ''; } if ($this->getValue() === ' ') { return ' '; } if ($this->isEmpty()) { return ''; } $text = preg_replace('/\s+/', ' ', $this->getValue()) ?? ''; if (is_null($this->getPreviousSibling())) { $text = ltrim($text); } if (is_null($this->getNextSibling())) { $text = rtrim($text); } return $text; } } PK������aZ;lE-��-����ValueObjects/Style.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\ValueObjects; use Closure; use Termwind\Actions\StyleToMethod; use Termwind\Exceptions\InvalidColor; /** * @internal */ final class Style { /** * Creates a new value object instance. * * @param Closure(Styles $styles, string|int ...$argument): Styles $callback */ public function __construct(private Closure $callback, private string $color = '') { // .. } /** * Apply the given set of styles to the styles. */ public function apply(string $styles): void { $callback = clone $this->callback; $this->callback = static function ( Styles $formatter, string|int ...$arguments ) use ($callback, $styles): Styles { $formatter = $callback($formatter, ...$arguments); return StyleToMethod::multiple($formatter, $styles); }; } /** * Sets the color to the style. */ public function color(string $color): void { if (preg_match('/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/', $color) < 1) { throw new InvalidColor(sprintf('The color %s is invalid.', $color)); } $this->color = $color; } /** * Gets the color. */ public function getColor(): string { return $this->color; } /** * Styles the given formatter with this style. */ public function __invoke(Styles $styles, string|int ...$arguments): Styles { return ($this->callback)($styles, ...$arguments); } } PK������aZ �� �� ��Question.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind; use ReflectionClass; use Symfony\Component\Console\Helper\SymfonyQuestionHelper; use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\StreamableInputInterface; use Symfony\Component\Console\Question\Question as SymfonyQuestion; use Symfony\Component\Console\Style\SymfonyStyle; use Termwind\Helpers\QuestionHelper; /** * @internal */ final class Question { /** * The streamable input to receive the input from the user. */ private static StreamableInputInterface|null $streamableInput; /** * An instance of Symfony's question helper. */ private SymfonyQuestionHelper $helper; public function __construct(?SymfonyQuestionHelper $helper = null) { $this->helper = $helper ?? new QuestionHelper; } /** * Sets the streamable input implementation. */ public static function setStreamableInput(StreamableInputInterface|null $streamableInput): void { self::$streamableInput = $streamableInput ?? new ArgvInput; } /** * Gets the streamable input implementation. */ public static function getStreamableInput(): StreamableInputInterface { return self::$streamableInput ??= new ArgvInput; } /** * Renders a prompt to the user. * * @param iterable<array-key, string>|null $autocomplete */ public function ask(string $question, ?iterable $autocomplete = null): mixed { $html = (new HtmlRenderer)->parse($question)->toString(); $question = new SymfonyQuestion($html); if ($autocomplete !== null) { $question->setAutocompleterValues($autocomplete); } $output = Termwind::getRenderer(); if ($output instanceof SymfonyStyle) { $property = (new ReflectionClass(SymfonyStyle::class)) ->getProperty('questionHelper'); $property->setAccessible(true); $currentHelper = $property->isInitialized($output) ? $property->getValue($output) : new SymfonyQuestionHelper; $property->setValue($output, new QuestionHelper); try { return $output->askQuestion($question); } finally { $property->setValue($output, $currentHelper); } } return $this->helper->ask( self::getStreamableInput(), Termwind::getRenderer(), $question, ); } } PK������aZ$o@5��5����HtmlRenderer.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind; use DOMDocument; use DOMNode; use Termwind\Html\CodeRenderer; use Termwind\Html\PreRenderer; use Termwind\Html\TableRenderer; use Termwind\ValueObjects\Node; /** * @internal */ final class HtmlRenderer { /** * Renders the given html. */ public function render(string $html, int $options): void { $this->parse($html)->render($options); } /** * Parses the given html. */ public function parse(string $html): Components\Element { $dom = new DOMDocument; if (strip_tags($html) === $html) { return Termwind::span($html); } $html = '<?xml encoding="UTF-8">'.trim($html); $dom->loadHTML($html, LIBXML_NOERROR | LIBXML_COMPACT | LIBXML_HTML_NODEFDTD | LIBXML_NOBLANKS | LIBXML_NOXMLDECL); /** @var DOMNode $body */ $body = $dom->getElementsByTagName('body')->item(0); $el = $this->convert(new Node($body)); // @codeCoverageIgnoreStart return is_string($el) ? Termwind::span($el) : $el; // @codeCoverageIgnoreEnd } /** * Convert a tree of DOM nodes to a tree of termwind elements. */ private function convert(Node $node): Components\Element|string { $children = []; if ($node->isName('table')) { return (new TableRenderer)->toElement($node); } elseif ($node->isName('code')) { return (new CodeRenderer)->toElement($node); } elseif ($node->isName('pre')) { return (new PreRenderer)->toElement($node); } foreach ($node->getChildNodes() as $child) { $children[] = $this->convert($child); } $children = array_filter($children, fn ($child) => $child !== ''); return $this->toElement($node, $children); } /** * Convert a given DOM node to it's termwind element equivalent. * * @param array<int, Components\Element|string> $children */ private function toElement(Node $node, array $children): Components\Element|string { if ($node->isText() || $node->isComment()) { return (string) $node; } /** @var array<string, mixed> $properties */ $properties = [ 'isFirstChild' => $node->isFirstChild(), ]; $styles = $node->getClassAttribute(); return match ($node->getName()) { 'body' => $children[0], // Pick only the first element from the body node 'div' => Termwind::div($children, $styles, $properties), 'p' => Termwind::paragraph($children, $styles, $properties), 'ul' => Termwind::ul($children, $styles, $properties), 'ol' => Termwind::ol($children, $styles, $properties), 'li' => Termwind::li($children, $styles, $properties), 'dl' => Termwind::dl($children, $styles, $properties), 'dt' => Termwind::dt($children, $styles, $properties), 'dd' => Termwind::dd($children, $styles, $properties), 'span' => Termwind::span($children, $styles, $properties), 'br' => Termwind::breakLine($styles, $properties), 'strong' => Termwind::span($children, $styles, $properties)->strong(), 'b' => Termwind::span($children, $styles, $properties)->fontBold(), 'em', 'i' => Termwind::span($children, $styles, $properties)->italic(), 'u' => Termwind::span($children, $styles, $properties)->underline(), 's' => Termwind::span($children, $styles, $properties)->lineThrough(), 'a' => Termwind::anchor($children, $styles, $properties)->href($node->getAttribute('href')), 'hr' => Termwind::hr($styles, $properties), default => Termwind::div($children, $styles, $properties), }; } } PK������aZ)e��������Components/Ol.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Components; final class Ol extends Element { protected static array $defaultStyles = ['block', 'list-decimal']; } PK������aZtDop���p�����Components/Span.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Components; final class Span extends Element { // .. } PK������aZ_HǨ��������Components/Ul.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Components; final class Ul extends Element { protected static array $defaultStyles = ['block', 'list-disc']; } PK������aZ>��������Components/Dd.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Components; final class Dd extends Element { protected static array $defaultStyles = ['block', 'ml-4']; } PK������aZ<&.��������Components/Li.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Components; final class Li extends Element { protected static array $defaultStyles = ['block']; } PK������aZ3#��������Components/Div.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Components; final class Div extends Element { protected static array $defaultStyles = ['block']; } PK������aZO.������Components/BreakLine.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Components; final class BreakLine extends Element { /** * Get the string representation of the element. */ public function toString(): string { $display = $this->styles->getProperties()['styles']['display'] ?? 'inline'; if ($display === 'hidden') { return ''; } if ($display === 'block') { return parent::toString(); } return parent::toString()."\r"; } } PK������aZ}omJ��J����Components/Raw.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Components; /** * @internal */ final class Raw extends Element { /** * Get the string representation of the element. */ public function toString(): string { return is_array($this->content) ? implode('', $this->content) : $this->content; } } PK������aZ3z,��������Components/Paragraph.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Components; final class Paragraph extends Element { protected static array $defaultStyles = ['block', 'my-1']; } PK������aZj X��������Components/Dt.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Components; final class Dt extends Element { protected static array $defaultStyles = ['block', 'font-bold']; } PK������aZ g���g�����Components/Anchor.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Components; final class Anchor extends Element {} PK������aZࡀޛ��������Components/Dl.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Components; final class Dl extends Element { protected static array $defaultStyles = ['block']; } PK������aZ)FE��������Components/Hr.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Components; final class Hr extends Element { protected static array $defaultStyles = ['block', 'border-t']; } PK������aZ% �� ����Components/Element.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Components; use Symfony\Component\Console\Output\OutputInterface; use Termwind\Actions\StyleToMethod; use Termwind\Html\InheritStyles; use Termwind\ValueObjects\Styles; /** * @internal * * @method Element inheritFromStyles(Styles $styles) * @method Element fontBold() * @method Element strong() * @method Element italic() * @method Element underline() * @method Element lineThrough() * @method int getLength() * @method int getInnerWidth() * @method array getProperties() * @method Element href(string $href) * @method bool hasStyle(string $style) * @method Element addStyle(string $style) */ abstract class Element { /** @var string[] */ protected static array $defaultStyles = []; protected Styles $styles; /** * Creates an element instance. * * @param array<int, Element|string>|string $content */ final public function __construct( protected OutputInterface $output, protected array|string $content, Styles|null $styles = null ) { $this->styles = $styles ?? new Styles(defaultStyles: static::$defaultStyles); $this->styles->setElement($this); } /** * Creates an element instance with the given styles. * * @param array<int, Element|string>|string $content * @param array<string, mixed> $properties */ final public static function fromStyles(OutputInterface $output, array|string $content, string $styles = '', array $properties = []): static { $element = new static($output, $content); if ($properties !== []) { $element->styles->setProperties($properties); } $elementStyles = StyleToMethod::multiple($element->styles, $styles); return new static($output, $content, $elementStyles); } /** * Get the string representation of the element. */ public function toString(): string { if (is_array($this->content)) { $inheritance = new InheritStyles; $this->content = implode('', $inheritance($this->content, $this->styles)); } return $this->styles->format($this->content); } /** * @param array<int, mixed> $arguments */ public function __call(string $name, array $arguments): mixed { if (method_exists($this->styles, $name)) { // @phpstan-ignore-next-line $result = $this->styles->{$name}(...$arguments); if (str_starts_with($name, 'get') || str_starts_with($name, 'has')) { return $result; } } return $this; } /** * Sets the content of the element. * * @param array<int, Element|string>|string $content */ final public function setContent(array|string $content): static { return new static($this->output, $content, $this->styles); } /** * Renders the string representation of the element on the output. */ final public function render(int $options): void { $this->output->writeln($this->toString(), $options); } /** * Get the string representation of the element. */ final public function __toString(): string { return $this->toString(); } } PK������aZ5a������Html/InheritStyles.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Html; use Termwind\Components\Element; use Termwind\Termwind; use Termwind\ValueObjects\Styles; /** * @internal */ final class InheritStyles { /** * Applies styles from parent element to child elements. * * @param array<int, Element|string> $elements * @return array<int, Element|string> */ public function __invoke(array $elements, Styles $styles): array { $elements = array_values($elements); foreach ($elements as &$element) { if (is_string($element)) { $element = Termwind::raw($element); } $element->inheritFromStyles($styles); } /** @var Element[] $elements */ if (($styles->getProperties()['styles']['display'] ?? 'inline') === 'flex') { $elements = $this->applyFlex($elements); } return match ($styles->getProperties()['styles']['justifyContent'] ?? false) { 'between' => $this->applyJustifyBetween($elements), 'evenly' => $this->applyJustifyEvenly($elements), 'around' => $this->applyJustifyAround($elements), 'center' => $this->applyJustifyCenter($elements), default => $elements, }; } /** * Applies flex-1 to child elements with the class. * * @param array<int, Element> $elements * @return array<int, Element> */ private function applyFlex(array $elements): array { [$totalWidth, $parentWidth] = $this->getWidthFromElements($elements); $width = max(0, array_reduce($elements, function ($carry, $element) { return $carry += $element->hasStyle('flex-1') ? $element->getInnerWidth() : 0; }, $parentWidth - $totalWidth)); $flexed = array_values(array_filter( $elements, fn ($element) => $element->hasStyle('flex-1') )); foreach ($flexed as $index => &$element) { if ($width === 0 && ! ($element->getProperties()['styles']['contentRepeat'] ?? false)) { continue; } $float = $width / count($flexed); $elementWidth = floor($float); if ($index === count($flexed) - 1) { $elementWidth += ($float - floor($float)) * count($flexed); } $element->addStyle("w-{$elementWidth}"); } return $elements; } /** * Applies the space between the elements. * * @param array<int, Element> $elements * @return array<int, Element|string> */ private function applyJustifyBetween(array $elements): array { if (count($elements) <= 1) { return $elements; } [$totalWidth, $parentWidth] = $this->getWidthFromElements($elements); $space = ($parentWidth - $totalWidth) / (count($elements) - 1); if ($space < 1) { return $elements; } $arr = []; foreach ($elements as $index => &$element) { if ($index !== 0) { // Since there is no float pixel, on the last one it should round up... $length = $index === count($elements) - 1 ? ceil($space) : floor($space); $arr[] = str_repeat(' ', (int) $length); } $arr[] = $element; } return $arr; } /** * Applies the space between and around the elements. * * @param array<int, Element> $elements * @return array<int, Element|string> */ private function applyJustifyEvenly(array $elements): array { [$totalWidth, $parentWidth] = $this->getWidthFromElements($elements); $space = ($parentWidth - $totalWidth) / (count($elements) + 1); if ($space < 1) { return $elements; } $arr = []; foreach ($elements as &$element) { $arr[] = str_repeat(' ', (int) floor($space)); $arr[] = $element; } $decimals = ceil(($space - floor($space)) * (count($elements) + 1)); $arr[] = str_repeat(' ', (int) (floor($space) + $decimals)); return $arr; } /** * Applies the space around the elements. * * @param array<int, Element> $elements * @return array<int, Element|string> */ private function applyJustifyAround(array $elements): array { if (count($elements) === 0) { return $elements; } [$totalWidth, $parentWidth] = $this->getWidthFromElements($elements); $space = ($parentWidth - $totalWidth) / count($elements); if ($space < 1) { return $elements; } $contentSize = $totalWidth; $arr = []; foreach ($elements as $index => &$element) { if ($index !== 0) { $arr[] = str_repeat(' ', (int) ceil($space)); $contentSize += ceil($space); } $arr[] = $element; } return [ str_repeat(' ', (int) floor(($parentWidth - $contentSize) / 2)), ...$arr, str_repeat(' ', (int) ceil(($parentWidth - $contentSize) / 2)), ]; } /** * Applies the space on before first element and after last element. * * @param array<int, Element> $elements * @return array<int, Element|string> */ private function applyJustifyCenter(array $elements): array { [$totalWidth, $parentWidth] = $this->getWidthFromElements($elements); $space = $parentWidth - $totalWidth; if ($space < 1) { return $elements; } return [ str_repeat(' ', (int) floor($space / 2)), ...$elements, str_repeat(' ', (int) ceil($space / 2)), ]; } /** * Gets the total width for the elements and their parent width. * * @param array<int, Element> $elements * @return int[] */ private function getWidthFromElements(array $elements) { $totalWidth = (int) array_reduce($elements, fn ($carry, $element) => $carry += $element->getLength(), 0); $parentWidth = Styles::getParentWidth($elements[0]->getProperties()['parentStyles'] ?? []); return [$totalWidth, $parentWidth]; } } PK������aZ������Html/TableRenderer.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Html; use Iterator; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Helper\TableCell; use Symfony\Component\Console\Helper\TableCellStyle; use Symfony\Component\Console\Helper\TableSeparator; use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Output\OutputInterface; use Termwind\Components\Element; use Termwind\HtmlRenderer; use Termwind\Termwind; use Termwind\ValueObjects\Node; use Termwind\ValueObjects\Styles; /** * @internal */ final class TableRenderer { /** * Symfony table object uses for table generation. */ private Table $table; /** * This object is used for accumulating output data from Symfony table object and return it as a string. */ private BufferedOutput $output; public function __construct() { $this->output = new BufferedOutput( // Content should output as is, without changes OutputInterface::VERBOSITY_NORMAL | OutputInterface::OUTPUT_RAW, true ); $this->table = new Table($this->output); } /** * Converts table output to the content element. */ public function toElement(Node $node): Element { $this->parseTable($node); $this->table->render(); $content = preg_replace('/\n$/', '', $this->output->fetch()) ?? ''; return Termwind::div($content, '', [ 'isFirstChild' => $node->isFirstChild(), ]); } /** * Looks for thead, tfoot, tbody, tr elements in a given DOM and appends rows from them to the Symfony table object. */ private function parseTable(Node $node): void { $style = $node->getAttribute('style'); if ($style !== '') { $this->table->setStyle($style); } foreach ($node->getChildNodes() as $child) { match ($child->getName()) { 'thead' => $this->parseHeader($child), 'tfoot' => $this->parseFoot($child), 'tbody' => $this->parseBody($child), default => $this->parseRows($child) }; } } /** * Looks for table header title and tr elements in a given thead DOM node and adds them to the Symfony table object. */ private function parseHeader(Node $node): void { $title = $node->getAttribute('title'); if ($title !== '') { $this->table->getStyle()->setHeaderTitleFormat( $this->parseTitleStyle($node) ); $this->table->setHeaderTitle($title); } foreach ($node->getChildNodes() as $child) { if ($child->isName('tr')) { foreach ($this->parseRow($child) as $row) { if (! is_array($row)) { continue; } $this->table->setHeaders($row); } } } } /** * Looks for table footer and tr elements in a given tfoot DOM node and adds them to the Symfony table object. */ private function parseFoot(Node $node): void { $title = $node->getAttribute('title'); if ($title !== '') { $this->table->getStyle()->setFooterTitleFormat( $this->parseTitleStyle($node) ); $this->table->setFooterTitle($title); } foreach ($node->getChildNodes() as $child) { if ($child->isName('tr')) { $rows = iterator_to_array($this->parseRow($child)); if (count($rows) > 0) { $this->table->addRow(new TableSeparator); $this->table->addRows($rows); } } } } /** * Looks for tr elements in a given DOM node and adds them to the Symfony table object. */ private function parseBody(Node $node): void { foreach ($node->getChildNodes() as $child) { if ($child->isName('tr')) { $this->parseRows($child); } } } /** * Parses table tr elements. */ private function parseRows(Node $node): void { foreach ($this->parseRow($node) as $row) { $this->table->addRow($row); } } /** * Looks for th, td elements in a given DOM node and converts them to a table cells. * * @return Iterator<array<int, TableCell>|TableSeparator> */ private function parseRow(Node $node): Iterator { $row = []; foreach ($node->getChildNodes() as $child) { if ($child->isName('th') || $child->isName('td')) { $align = $child->getAttribute('align'); $class = $child->getClassAttribute(); if ($child->isName('th')) { $class .= ' strong'; } $text = (string) (new HtmlRenderer)->parse( trim(preg_replace('/<br\s?+\/?>/', "\n", $child->getHtml()) ?? '') ); if ((bool) preg_match(Styles::STYLING_REGEX, $text)) { $class .= ' font-normal'; } $row[] = new TableCell( // I need only spaces after applying margin, padding and width except tags. // There is no place for tags, they broke cell formatting. (string) Termwind::span($text, $class), [ // Gets rowspan and colspan from tr and td tag attributes 'colspan' => max((int) $child->getAttribute('colspan'), 1), 'rowspan' => max((int) $child->getAttribute('rowspan'), 1), // There are background and foreground and options 'style' => $this->parseCellStyle( $class, $align === '' ? TableCellStyle::DEFAULT_ALIGN : $align ), ] ); } } if ($row !== []) { yield $row; } $border = (int) $node->getAttribute('border'); for ($i = $border; $i--; $i > 0) { yield new TableSeparator; } } /** * Parses tr, td tag class attribute and passes bg, fg and options to a table cell style. */ private function parseCellStyle(string $styles, string $align = TableCellStyle::DEFAULT_ALIGN): TableCellStyle { // I use this empty span for getting styles for bg, fg and options // It will be a good idea to get properties without element object and then pass them to an element object $element = Termwind::span('%s', $styles); $styles = []; $colors = $element->getProperties()['colors'] ?? []; foreach ($colors as $option => $content) { if (in_array($option, ['fg', 'bg'], true)) { $content = is_array($content) ? array_pop($content) : $content; $styles[] = "$option=$content"; } } // If there are no styles we don't need extra tags if ($styles === []) { $cellFormat = '%s'; } else { $cellFormat = '<'.implode(';', $styles).'>%s</>'; } return new TableCellStyle([ 'align' => $align, 'cellFormat' => $cellFormat, ]); } /** * Get styled representation of title. */ private function parseTitleStyle(Node $node): string { return (string) Termwind::span(' %s ', $node->getClassAttribute()); } } PK������aZ6������Html/PreRenderer.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Html; use Termwind\Components\Element; use Termwind\Termwind; use Termwind\ValueObjects\Node; /** * @internal */ final class PreRenderer { /** * Gets HTML content from a given node and converts to the content element. */ public function toElement(Node $node): Element { $lines = explode("\n", $node->getHtml()); if (reset($lines) === '') { array_shift($lines); } if (end($lines) === '') { array_pop($lines); } $maxStrLen = array_reduce( $lines, static fn (int $max, string $line) => ($max < strlen($line)) ? strlen($line) : $max, 0 ); $styles = $node->getClassAttribute(); $html = array_map( static fn (string $line) => (string) Termwind::div(str_pad($line, $maxStrLen + 3), $styles), $lines ); return Termwind::raw( implode('', $html) ); } } PK������aZ@������Html/CodeRenderer.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Html; use Termwind\Components\Element; use Termwind\Termwind; use Termwind\ValueObjects\Node; /** * @internal */ final class CodeRenderer { public const TOKEN_DEFAULT = 'token_default'; public const TOKEN_COMMENT = 'token_comment'; public const TOKEN_STRING = 'token_string'; public const TOKEN_HTML = 'token_html'; public const TOKEN_KEYWORD = 'token_keyword'; public const ACTUAL_LINE_MARK = 'actual_line_mark'; public const LINE_NUMBER = 'line_number'; private const ARROW_SYMBOL_UTF8 = '➜'; private const DELIMITER_UTF8 = '▕ '; // '▶'; private const LINE_NUMBER_DIVIDER = 'line_divider'; private const MARKED_LINE_NUMBER = 'marked_line'; private const WIDTH = 3; /** * Holds the theme. * * @var array<string, string> */ private const THEME = [ self::TOKEN_STRING => 'text-gray', self::TOKEN_COMMENT => 'text-gray italic', self::TOKEN_KEYWORD => 'text-magenta strong', self::TOKEN_DEFAULT => 'strong', self::TOKEN_HTML => 'text-blue strong', self::ACTUAL_LINE_MARK => 'text-red strong', self::LINE_NUMBER => 'text-gray', self::MARKED_LINE_NUMBER => 'italic strong', self::LINE_NUMBER_DIVIDER => 'text-gray', ]; private string $delimiter = self::DELIMITER_UTF8; private string $arrow = self::ARROW_SYMBOL_UTF8; private const NO_MARK = ' '; /** * Highlights HTML content from a given node and converts to the content element. */ public function toElement(Node $node): Element { $line = max((int) $node->getAttribute('line'), 0); $startLine = max((int) $node->getAttribute('start-line'), 1); $html = $node->getHtml(); $lines = explode("\n", $html); $extraSpaces = $this->findExtraSpaces($lines); if ($extraSpaces !== '') { $lines = array_map(static function (string $line) use ($extraSpaces): string { return str_starts_with($line, $extraSpaces) ? substr($line, strlen($extraSpaces)) : $line; }, $lines); $html = implode("\n", $lines); } $tokenLines = $this->getHighlightedLines(trim($html, "\n"), $startLine); $lines = $this->colorLines($tokenLines); $lines = $this->lineNumbers($lines, $line); return Termwind::div(trim($lines, "\n")); } /** * Finds extra spaces which should be removed from HTML. * * @param array<int, string> $lines */ private function findExtraSpaces(array $lines): string { foreach ($lines as $line) { if ($line === '') { continue; } if (preg_replace('/\s+/', '', $line) === '') { return $line; } } return ''; } /** * Returns content split into lines with numbers. * * @return array<int, array<int, array{0: string, 1: non-empty-string}>> */ private function getHighlightedLines(string $source, int $startLine): array { $source = str_replace(["\r\n", "\r"], "\n", $source); $tokens = $this->tokenize($source); return $this->splitToLines($tokens, $startLine - 1); } /** * Splits content into tokens. * * @return array<int, array{0: string, 1: string}> */ private function tokenize(string $source): array { $tokens = token_get_all($source); $output = []; $currentType = null; $newType = self::TOKEN_KEYWORD; $buffer = ''; foreach ($tokens as $token) { if (is_array($token)) { if ($token[0] !== T_WHITESPACE) { $newType = match ($token[0]) { T_OPEN_TAG, T_OPEN_TAG_WITH_ECHO, T_CLOSE_TAG, T_STRING, T_VARIABLE, T_DIR, T_FILE, T_METHOD_C, T_DNUMBER, T_LNUMBER, T_NS_C, T_LINE, T_CLASS_C, T_FUNC_C, T_TRAIT_C => self::TOKEN_DEFAULT, T_COMMENT, T_DOC_COMMENT => self::TOKEN_COMMENT, T_ENCAPSED_AND_WHITESPACE, T_CONSTANT_ENCAPSED_STRING => self::TOKEN_STRING, T_INLINE_HTML => self::TOKEN_HTML, default => self::TOKEN_KEYWORD }; } } else { $newType = $token === '"' ? self::TOKEN_STRING : self::TOKEN_KEYWORD; } if ($currentType === null) { $currentType = $newType; } if ($currentType !== $newType) { $output[] = [$currentType, $buffer]; $buffer = ''; $currentType = $newType; } $buffer .= is_array($token) ? $token[1] : $token; } $output[] = [$newType, $buffer]; return $output; } /** * Splits tokens into lines. * * @param array<int, array{0: string, 1: string}> $tokens * @return array<int, array<int, array{0: string, 1: non-empty-string}>> */ private function splitToLines(array $tokens, int $startLine): array { $lines = []; $line = []; foreach ($tokens as $token) { foreach (explode("\n", $token[1]) as $count => $tokenLine) { if ($count > 0) { $lines[$startLine++] = $line; $line = []; } if ($tokenLine === '') { continue; } $line[] = [$token[0], $tokenLine]; } } $lines[$startLine++] = $line; return $lines; } /** * Applies colors to tokens according to a color schema. * * @param array<int, array<int, array{0: string, 1: non-empty-string}>> $tokenLines * @return array<int, string> */ private function colorLines(array $tokenLines): array { $lines = []; foreach ($tokenLines as $lineCount => $tokenLine) { $line = ''; foreach ($tokenLine as $token) { [$tokenType, $tokenValue] = $token; $line .= $this->styleToken($tokenType, $tokenValue); } $lines[$lineCount] = $line; } return $lines; } /** * Prepends line numbers into lines. * * @param array<int, string> $lines */ private function lineNumbers(array $lines, int $markLine): string { $lastLine = (int) array_key_last($lines); $lineLength = strlen((string) ($lastLine + 1)); $lineLength = $lineLength < self::WIDTH ? self::WIDTH : $lineLength; $snippet = ''; $mark = ' '.$this->arrow.' '; foreach ($lines as $i => $line) { $coloredLineNumber = $this->coloredLineNumber(self::LINE_NUMBER, $i, $lineLength); if (0 !== $markLine) { $snippet .= ($markLine === $i + 1 ? $this->styleToken(self::ACTUAL_LINE_MARK, $mark) : self::NO_MARK ); $coloredLineNumber = ($markLine === $i + 1 ? $this->coloredLineNumber(self::MARKED_LINE_NUMBER, $i, $lineLength) : $coloredLineNumber ); } $snippet .= $coloredLineNumber; $snippet .= $this->styleToken(self::LINE_NUMBER_DIVIDER, $this->delimiter); $snippet .= $line.PHP_EOL; } return $snippet; } /** * Formats line number and applies color according to a color schema. */ private function coloredLineNumber(string $token, int $lineNumber, int $length): string { return $this->styleToken( $token, str_pad((string) ($lineNumber + 1), $length, ' ', STR_PAD_LEFT) ); } /** * Formats string and applies color according to a color schema. */ private function styleToken(string $token, string $string): string { return (string) Termwind::span($string, self::THEME[$token]); } } PK������aZ�ܲ��������Exceptions/InvalidStyle.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Exceptions; use InvalidArgumentException; /** * @internal */ final class InvalidStyle extends InvalidArgumentException {} PK������aZlײ��������Exceptions/InvalidChild.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Exceptions; use InvalidArgumentException; /** * @internal */ final class InvalidChild extends InvalidArgumentException {} PK������aZ#DO��O����Exceptions/StyleNotFound.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Exceptions; use InvalidArgumentException; /** * @internal */ final class StyleNotFound extends InvalidArgumentException { /** * Creates a new style not found instance. */ private function __construct(string $message) { parent::__construct($message, 0, $this->getPrevious()); } /** * Creates a new style not found instance from the given style. */ public static function fromStyle(string $style): self { return new self(sprintf('Style [%s] not found.', $style)); } } PK������aZ@&_��������Exceptions/ColorNotFound.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Exceptions; use InvalidArgumentException; /** * @internal */ final class ColorNotFound extends InvalidArgumentException {} PK������aZ}��������Exceptions/InvalidColor.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Exceptions; use InvalidArgumentException; /** * @internal */ final class InvalidColor extends InvalidArgumentException {} PK������aZS��S����Actions/StyleToMethod.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Actions; use Termwind\Exceptions\StyleNotFound; use Termwind\Repositories\Styles as StyleRepository; use Termwind\Terminal; use Termwind\ValueObjects\Styles; /** * @internal */ final class StyleToMethod { /** * Finds if there is any media query on the style class. */ private const MEDIA_QUERIES_REGEX = "/^(sm|md|lg|xl|2xl)\:(.*)/"; /** * Defines the Media Query Breakpoints. */ public const MEDIA_QUERY_BREAKPOINTS = [ 'sm' => 64, 'md' => 76, 'lg' => 102, 'xl' => 128, '2xl' => 153, ]; /** * Creates a new action instance. */ public function __construct( private Styles $styles, private string $style, ) { // .. } /** * Applies multiple styles to the given styles. */ public static function multiple(Styles $styles, string $stylesString): Styles { $stylesString = self::sortStyles(array_merge( $styles->defaultStyles(), array_filter((array) preg_split('/(?![^\[]*\])\s/', $stylesString)) )); foreach ($stylesString as $style) { $styles = (new self($styles, $style))->__invoke(); } return $styles; } /** * Converts the given style to a method name. */ public function __invoke(string|int ...$arguments): Styles { if (StyleRepository::has($this->style)) { return StyleRepository::get($this->style)($this->styles, ...$arguments); } $method = $this->applyMediaQuery($this->style); if ($method === '') { return $this->styles; } $method = array_filter( (array) preg_split('/(?![^\[]*\])-/', $method), fn ($item) => $item !== false ); $method = array_slice($method, 0, count($method) - count($arguments)); $methodName = implode(' ', $method); $methodName = ucwords($methodName); $methodName = lcfirst($methodName); $methodName = str_replace(' ', '', $methodName); if ($methodName === '') { throw StyleNotFound::fromStyle($this->style); } if (! method_exists($this->styles, $methodName)) { $argument = array_pop($method); $arguments[] = is_numeric($argument) ? (int) $argument : (string) $argument; return $this->__invoke(...$arguments); } // @phpstan-ignore-next-line return $this->styles ->setStyle($this->style) ->$methodName(...array_reverse($arguments)); } /** * Sorts all the styles based on the correct render order. * * @param string[] $styles * @return string[] */ private static function sortStyles(array $styles): array { $keys = array_keys(self::MEDIA_QUERY_BREAKPOINTS); usort($styles, function ($a, $b) use ($keys) { $existsA = (bool) preg_match(self::MEDIA_QUERIES_REGEX, $a, $matchesA); $existsB = (bool) preg_match(self::MEDIA_QUERIES_REGEX, $b, $matchesB); if ($existsA && ! $existsB) { return 1; } if ($existsA && array_search($matchesA[1], $keys, true) > array_search($matchesB[1], $keys, true)) { return 1; } return -1; }); return $styles; } /** * Applies the media query if exists. */ private function applyMediaQuery(string $method): string { $matches = []; preg_match(self::MEDIA_QUERIES_REGEX, $method, $matches); if (count($matches) < 1) { return $method; } [, $size, $method] = $matches; if ((new Terminal)->width() >= self::MEDIA_QUERY_BREAKPOINTS[$size]) { return $method; } return ''; } } PK������aZzӖu��u�� ��Terminal.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind; use Symfony\Component\Console\Terminal as ConsoleTerminal; /** * @internal */ final class Terminal { /** * An instance of Symfony's console terminal. */ private ConsoleTerminal $terminal; /** * Creates a new terminal instance. */ public function __construct(?ConsoleTerminal $terminal = null) { $this->terminal = $terminal ?? new ConsoleTerminal; } /** * Gets the terminal width. */ public function width(): int { return $this->terminal->getWidth(); } /** * Gets the terminal height. */ public function height(): int { return $this->terminal->getHeight(); } /** * Clears the terminal screen. */ public function clear(): void { Termwind::getRenderer()->write("\ec"); } } PK������aZD,Zg��g����Helpers/QuestionHelper.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Helpers; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Helper\SymfonyQuestionHelper; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\Question; /** * @internal */ final class QuestionHelper extends SymfonyQuestionHelper { /** * {@inheritdoc} */ protected function writePrompt(OutputInterface $output, Question $question): void { $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion()); $output->write($text); } } PK������aZQ#p����#��Laravel/TermwindServiceProvider.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Laravel; use Illuminate\Console\OutputStyle; use Illuminate\Support\ServiceProvider; use Termwind\Termwind; final class TermwindServiceProvider extends ServiceProvider { /** * Sets the correct renderer to be used. */ public function register(): void { $this->app->resolving(OutputStyle::class, function ($style): void { Termwind::renderUsing($style->getOutput()); }); } } PK������aZcq&$��&$�� ��Termwind.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind; use Closure; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\OutputInterface; use Termwind\Components\Element; use Termwind\Exceptions\InvalidChild; /** * @internal */ final class Termwind { /** * The implementation of the output. */ private static OutputInterface|null $renderer; /** * Sets the renderer implementation. */ public static function renderUsing(OutputInterface|null $renderer): void { self::$renderer = $renderer ?? new ConsoleOutput; } /** * Creates a div element instance. * * @param array<int, Element|string>|string $content * @param array<string, mixed> $properties */ public static function div(array|string $content = '', string $styles = '', array $properties = []): Components\Div { $content = self::prepareElements($content, $styles); return Components\Div::fromStyles( self::getRenderer(), $content, $styles, $properties ); } /** * Creates a paragraph element instance. * * @param array<int, Element|string>|string $content * @param array<string, mixed> $properties */ public static function paragraph(array|string $content = '', string $styles = '', array $properties = []): Components\Paragraph { $content = self::prepareElements($content, $styles); return Components\Paragraph::fromStyles( self::getRenderer(), $content, $styles, $properties ); } /** * Creates a span element instance with the given style. * * @param array<int, Element|string>|string $content * @param array<string, mixed> $properties */ public static function span(array|string $content = '', string $styles = '', array $properties = []): Components\Span { $content = self::prepareElements($content, $styles); return Components\Span::fromStyles( self::getRenderer(), $content, $styles, $properties ); } /** * Creates an element instance with raw content. * * @param array<int, Element|string>|string $content */ public static function raw(array|string $content = ''): Components\Raw { return Components\Raw::fromStyles( self::getRenderer(), $content ); } /** * Creates an anchor element instance with the given style. * * @param array<int, Element|string>|string $content * @param array<string, mixed> $properties */ public static function anchor(array|string $content = '', string $styles = '', array $properties = []): Components\Anchor { $content = self::prepareElements($content, $styles); return Components\Anchor::fromStyles( self::getRenderer(), $content, $styles, $properties ); } /** * Creates an unordered list instance. * * @param array<int, string|Element> $content * @param array<string, mixed> $properties */ public static function ul(array $content = [], string $styles = '', array $properties = []): Components\Ul { $ul = Components\Ul::fromStyles( self::getRenderer(), '', $styles, $properties ); $content = self::prepareElements( $content, $styles, static function ($li) use ($ul): string|Element { if (is_string($li)) { return $li; } if (! $li instanceof Components\Li) { throw new InvalidChild('Unordered lists only accept `li` as child'); } return match (true) { $li->hasStyle('list-none') => $li, $ul->hasStyle('list-none') => $li->addStyle('list-none'), $ul->hasStyle('list-square') => $li->addStyle('list-square'), $ul->hasStyle('list-disc') => $li->addStyle('list-disc'), default => $li->addStyle('list-none'), }; } ); return $ul->setContent($content); } /** * Creates an ordered list instance. * * @param array<int, string|Element> $content * @param array<string, mixed> $properties */ public static function ol(array $content = [], string $styles = '', array $properties = []): Components\Ol { $ol = Components\Ol::fromStyles( self::getRenderer(), '', $styles, $properties ); $index = 0; $content = self::prepareElements( $content, $styles, static function ($li) use ($ol, &$index): string|Element { if (is_string($li)) { return $li; } if (! $li instanceof Components\Li) { throw new InvalidChild('Ordered lists only accept `li` as child'); } return match (true) { $li->hasStyle('list-none') => $li->addStyle('list-none'), $ol->hasStyle('list-none') => $li->addStyle('list-none'), $ol->hasStyle('list-decimal') => $li->addStyle('list-decimal-'.(++$index)), default => $li->addStyle('list-none'), }; } ); return $ol->setContent($content); } /** * Creates a list item instance. * * @param array<int, Element|string>|string $content * @param array<string, mixed> $properties */ public static function li(array|string $content = '', string $styles = '', array $properties = []): Components\Li { $content = self::prepareElements($content, $styles); return Components\Li::fromStyles( self::getRenderer(), $content, $styles, $properties ); } /** * Creates a description list instance. * * @param array<int, string|Element> $content * @param array<string, mixed> $properties */ public static function dl(array $content = [], string $styles = '', array $properties = []): Components\Dl { $content = self::prepareElements( $content, $styles, static function ($element): string|Element { if (is_string($element)) { return $element; } if (! $element instanceof Components\Dt && ! $element instanceof Components\Dd) { throw new InvalidChild('Description lists only accept `dt` and `dd` as children'); } return $element; } ); return Components\Dl::fromStyles( self::getRenderer(), $content, $styles, $properties ); } /** * Creates a description term instance. * * @param array<int, Element|string>|string $content * @param array<string, mixed> $properties */ public static function dt(array|string $content = '', string $styles = '', array $properties = []): Components\Dt { $content = self::prepareElements($content, $styles); return Components\Dt::fromStyles( self::getRenderer(), $content, $styles, $properties ); } /** * Creates a description details instance. * * @param array<int, Element|string>|string $content * @param array<string, mixed> $properties */ public static function dd(array|string $content = '', string $styles = '', array $properties = []): Components\Dd { $content = self::prepareElements($content, $styles); return Components\Dd::fromStyles( self::getRenderer(), $content, $styles, $properties ); } /** * Creates a horizontal rule instance. * * @param array<string, mixed> $properties */ public static function hr(string $styles = '', array $properties = []): Components\Hr { return Components\Hr::fromStyles( self::getRenderer(), '', $styles, $properties ); } /** * Creates an break line element instance. * * @param array<string, mixed> $properties */ public static function breakLine(string $styles = '', array $properties = []): Components\BreakLine { return Components\BreakLine::fromStyles( self::getRenderer(), '', $styles, $properties ); } /** * Gets the current renderer instance. */ public static function getRenderer(): OutputInterface { return self::$renderer ??= new ConsoleOutput; } /** * Convert child elements to a string. * * @param array<int, string|Element>|string $elements * @return array<int, string|Element> */ private static function prepareElements($elements, string $styles = '', Closure|null $callback = null): array { if ($callback === null) { $callback = static fn ($element): string|Element => $element; } $elements = is_array($elements) ? $elements : [$elements]; return array_map($callback, $elements); } } PK������aZ`P������Repositories/Styles.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Repositories; use Closure; use Termwind\ValueObjects\Style; use Termwind\ValueObjects\Styles as StylesValueObject; /** * @internal */ final class Styles { /** * @var array<string, Style> */ private static array $storage = []; /** * Creates a new style from the given arguments. * * @param (Closure(StylesValueObject $element, string|int ...$arguments): StylesValueObject)|null $callback */ public static function create(string $name, ?Closure $callback = null): Style { self::$storage[$name] = $style = new Style( $callback ?? static fn (StylesValueObject $styles) => $styles ); return $style; } /** * Removes all existing styles. */ public static function flush(): void { self::$storage = []; } /** * Checks a style with the given name exists. */ public static function has(string $name): bool { return array_key_exists($name, self::$storage); } /** * Gets the style with the given name. */ public static function get(string $name): Style { return self::$storage[$name]; } } PK������aZ&��&����Enums/Color.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind\Enums; final class Color { public const BLACK = 'black'; public const WHITE = 'white'; public const BRIGHTWHITE = 'bright-white'; public const SLATE_50 = '#f8fafc'; public const SLATE_100 = '#f1f5f9'; public const SLATE_200 = '#e2e8f0'; public const SLATE_300 = '#cbd5e1'; public const SLATE_400 = '#94a3b8'; public const SLATE_500 = '#64748b'; public const SLATE_600 = '#475569'; public const SLATE_700 = '#334155'; public const SLATE_800 = '#1e293b'; public const SLATE_900 = '#0f172a'; public const GRAY = 'gray'; public const GRAY_50 = '#f9fafb'; public const GRAY_100 = '#f3f4f6'; public const GRAY_200 = '#e5e7eb'; public const GRAY_300 = '#d1d5db'; public const GRAY_400 = '#9ca3af'; public const GRAY_500 = '#6b7280'; public const GRAY_600 = '#4b5563'; public const GRAY_700 = '#374151'; public const GRAY_800 = '#1f2937'; public const GRAY_900 = '#111827'; public const ZINC_50 = '#fafafa'; public const ZINC_100 = '#f4f4f5'; public const ZINC_200 = '#e4e4e7'; public const ZINC_300 = '#d4d4d8'; public const ZINC_400 = '#a1a1aa'; public const ZINC_500 = '#71717a'; public const ZINC_600 = '#52525b'; public const ZINC_700 = '#3f3f46'; public const ZINC_800 = '#27272a'; public const ZINC_900 = '#18181b'; public const NEUTRAL_50 = '#fafafa'; public const NEUTRAL_100 = '#f5f5f5'; public const NEUTRAL_200 = '#e5e5e5'; public const NEUTRAL_300 = '#d4d4d4'; public const NEUTRAL_400 = '#a3a3a3'; public const NEUTRAL_500 = '#737373'; public const NEUTRAL_600 = '#525252'; public const NEUTRAL_700 = '#404040'; public const NEUTRAL_800 = '#262626'; public const NEUTRAL_900 = '#171717'; public const STONE_50 = '#fafaf9'; public const STONE_100 = '#f5f5f4'; public const STONE_200 = '#e7e5e4'; public const STONE_300 = '#d6d3d1'; public const STONE_400 = '#a8a29e'; public const STONE_500 = '#78716c'; public const STONE_600 = '#57534e'; public const STONE_700 = '#44403c'; public const STONE_800 = '#292524'; public const STONE_900 = '#1c1917'; public const RED = 'red'; public const BRIGHTRED = 'bright-red'; public const RED_50 = '#fef2f2'; public const RED_100 = '#fee2e2'; public const RED_200 = '#fecaca'; public const RED_300 = '#fca5a5'; public const RED_400 = '#f87171'; public const RED_500 = '#ef4444'; public const RED_600 = '#dc2626'; public const RED_700 = '#b91c1c'; public const RED_800 = '#991b1b'; public const RED_900 = '#7f1d1d'; public const ORANGE = '#f97316'; public const ORANGE_50 = '#fff7ed'; public const ORANGE_100 = '#ffedd5'; public const ORANGE_200 = '#fed7aa'; public const ORANGE_300 = '#fdba74'; public const ORANGE_400 = '#fb923c'; public const ORANGE_500 = '#f97316'; public const ORANGE_600 = '#ea580c'; public const ORANGE_700 = '#c2410c'; public const ORANGE_800 = '#9a3412'; public const ORANGE_900 = '#7c2d12'; public const AMBER_50 = '#fffbeb'; public const AMBER_100 = '#fef3c7'; public const AMBER_200 = '#fde68a'; public const AMBER_300 = '#fcd34d'; public const AMBER_400 = '#fbbf24'; public const AMBER_500 = '#f59e0b'; public const AMBER_600 = '#d97706'; public const AMBER_700 = '#b45309'; public const AMBER_800 = '#92400e'; public const AMBER_900 = '#78350f'; public const YELLOW = 'yellow'; public const BRIGHTYELLOW = 'bright-yellow'; public const YELLOW_50 = '#fefce8'; public const YELLOW_100 = '#fef9c3'; public const YELLOW_200 = '#fef08a'; public const YELLOW_300 = '#fde047'; public const YELLOW_400 = '#facc15'; public const YELLOW_500 = '#eab308'; public const YELLOW_600 = '#ca8a04'; public const YELLOW_700 = '#a16207'; public const YELLOW_800 = '#854d0e'; public const YELLOW_900 = '#713f12'; public const LIME_50 = '#f7fee7'; public const LIME_100 = '#ecfccb'; public const LIME_200 = '#d9f99d'; public const LIME_300 = '#bef264'; public const LIME_400 = '#a3e635'; public const LIME_500 = '#84cc16'; public const LIME_600 = '#65a30d'; public const LIME_700 = '#4d7c0f'; public const LIME_800 = '#3f6212'; public const LIME_900 = '#365314'; public const GREEN = 'green'; public const BRIGHTGREEN = 'bright-green'; public const GREEN_50 = '#f0fdf4'; public const GREEN_100 = '#dcfce7'; public const GREEN_200 = '#bbf7d0'; public const GREEN_300 = '#86efac'; public const GREEN_400 = '#4ade80'; public const GREEN_500 = '#22c55e'; public const GREEN_600 = '#16a34a'; public const GREEN_700 = '#15803d'; public const GREEN_800 = '#166534'; public const GREEN_900 = '#14532d'; public const EMERALD_50 = '#ecfdf5'; public const EMERALD_100 = '#d1fae5'; public const EMERALD_200 = '#a7f3d0'; public const EMERALD_300 = '#6ee7b7'; public const EMERALD_400 = '#34d399'; public const EMERALD_500 = '#10b981'; public const EMERALD_600 = '#059669'; public const EMERALD_700 = '#047857'; public const EMERALD_800 = '#065f46'; public const EMERALD_900 = '#064e3b'; public const TEAL_50 = '#f0fdfa'; public const TEAL_100 = '#ccfbf1'; public const TEAL_200 = '#99f6e4'; public const TEAL_300 = '#5eead4'; public const TEAL_400 = '#2dd4bf'; public const TEAL_500 = '#14b8a6'; public const TEAL_600 = '#0d9488'; public const TEAL_700 = '#0f766e'; public const TEAL_800 = '#115e59'; public const TEAL_900 = '#134e4a'; public const CYAN = 'cyan'; public const BRIGHTCYAN = 'bright-cyan'; public const CYAN_50 = '#ecfeff'; public const CYAN_100 = '#cffafe'; public const CYAN_200 = '#a5f3fc'; public const CYAN_300 = '#67e8f9'; public const CYAN_400 = '#22d3ee'; public const CYAN_500 = '#06b6d4'; public const CYAN_600 = '#0891b2'; public const CYAN_700 = '#0e7490'; public const CYAN_800 = '#155e75'; public const CYAN_900 = '#164e63'; public const SKY_50 = '#f0f9ff'; public const SKY_100 = '#e0f2fe'; public const SKY_200 = '#bae6fd'; public const SKY_300 = '#7dd3fc'; public const SKY_400 = '#38bdf8'; public const SKY_500 = '#0ea5e9'; public const SKY_600 = '#0284c7'; public const SKY_700 = '#0369a1'; public const SKY_800 = '#075985'; public const SKY_900 = '#0c4a6e'; public const BLUE = 'blue'; public const BRIGHTBLUE = 'bright-blue'; public const BLUE_50 = '#eff6ff'; public const BLUE_100 = '#dbeafe'; public const BLUE_200 = '#bfdbfe'; public const BLUE_300 = '#93c5fd'; public const BLUE_400 = '#60a5fa'; public const BLUE_500 = '#3b82f6'; public const BLUE_600 = '#2563eb'; public const BLUE_700 = '#1d4ed8'; public const BLUE_800 = '#1e40af'; public const BLUE_900 = '#1e3a8a'; public const INDIGO_50 = '#eef2ff'; public const INDIGO_100 = '#e0e7ff'; public const INDIGO_200 = '#c7d2fe'; public const INDIGO_300 = '#a5b4fc'; public const INDIGO_400 = '#818cf8'; public const INDIGO_500 = '#6366f1'; public const INDIGO_600 = '#4f46e5'; public const INDIGO_700 = '#4338ca'; public const INDIGO_800 = '#3730a3'; public const INDIGO_900 = '#312e81'; public const VIOLET_50 = '#f5f3ff'; public const VIOLET_100 = '#ede9fe'; public const VIOLET_200 = '#ddd6fe'; public const VIOLET_300 = '#c4b5fd'; public const VIOLET_400 = '#a78bfa'; public const VIOLET_500 = '#8b5cf6'; public const VIOLET_600 = '#7c3aed'; public const VIOLET_700 = '#6d28d9'; public const VIOLET_800 = '#5b21b6'; public const VIOLET_900 = '#4c1d95'; public const PURPLE_50 = '#faf5ff'; public const PURPLE_100 = '#f3e8ff'; public const PURPLE_200 = '#e9d5ff'; public const PURPLE_300 = '#d8b4fe'; public const PURPLE_400 = '#c084fc'; public const PURPLE_500 = '#a855f7'; public const PURPLE_600 = '#9333ea'; public const PURPLE_700 = '#7e22ce'; public const PURPLE_800 = '#6b21a8'; public const PURPLE_900 = '#581c87'; public const FUCHSIA_50 = '#fdf4ff'; public const FUCHSIA_100 = '#fae8ff'; public const FUCHSIA_200 = '#f5d0fe'; public const FUCHSIA_300 = '#f0abfc'; public const FUCHSIA_400 = '#e879f9'; public const FUCHSIA_500 = '#d946ef'; public const FUCHSIA_600 = '#c026d3'; public const FUCHSIA_700 = '#a21caf'; public const FUCHSIA_800 = '#86198f'; public const FUCHSIA_900 = '#701a75'; public const PINK_50 = '#fdf2f8'; public const PINK_100 = '#fce7f3'; public const PINK_200 = '#fbcfe8'; public const PINK_300 = '#f9a8d4'; public const PINK_400 = '#f472b6'; public const PINK_500 = '#ec4899'; public const PINK_600 = '#db2777'; public const PINK_700 = '#be185d'; public const PINK_800 = '#9d174d'; public const PINK_900 = '#831843'; public const ROSE_50 = '#fff1f2'; public const ROSE_100 = '#ffe4e6'; public const ROSE_200 = '#fecdd3'; public const ROSE_300 = '#fda4af'; public const ROSE_400 = '#fb7185'; public const ROSE_500 = '#f43f5e'; public const ROSE_600 = '#e11d48'; public const ROSE_700 = '#be123c'; public const ROSE_800 = '#9f1239'; public const ROSE_900 = '#881337'; public const MAGENTA = 'magenta'; public const BRIGHTMAGENTA = 'bright-magenta'; } PK������aZh���� ��Functions.phpnu�W+A��������<?php declare(strict_types=1); namespace Termwind; use Closure; use Symfony\Component\Console\Output\OutputInterface; use Termwind\Repositories\Styles as StyleRepository; use Termwind\ValueObjects\Style; use Termwind\ValueObjects\Styles; if (! function_exists('Termwind\renderUsing')) { /** * Sets the renderer implementation. */ function renderUsing(?OutputInterface $renderer): void { Termwind::renderUsing($renderer); } } if (! function_exists('Termwind\style')) { /** * Creates a new style. * * @param (Closure(Styles $renderable, string|int ...$arguments): Styles)|null $callback */ function style(string $name, ?Closure $callback = null): Style { return StyleRepository::create($name, $callback); } } if (! function_exists('Termwind\render')) { /** * Render HTML to a string. */ function render(string $html, int $options = OutputInterface::OUTPUT_NORMAL): void { (new HtmlRenderer)->render($html, $options); } } if (! function_exists('Termwind\terminal')) { /** * Returns a Terminal instance. */ function terminal(): Terminal { return new Terminal; } } if (! function_exists('Termwind\ask')) { /** * Renders a prompt to the user. * * @param iterable<array-key, string>|null $autocomplete */ function ask(string $question, ?iterable $autocomplete = null): mixed { return (new Question)->ask($question, $autocomplete); } } PK������iZæx��x����Css/Processor.phpnu�W+A��������<?php namespace TijsVerkoyen\CssToInlineStyles\Css; use TijsVerkoyen\CssToInlineStyles\Css\Rule\Processor as RuleProcessor; use TijsVerkoyen\CssToInlineStyles\Css\Rule\Rule; class Processor { /** * Get the rules from a given CSS-string * * @param string $css * @param Rule[] $existingRules * * @return Rule[] */ public function getRules($css, $existingRules = array()) { $css = $this->doCleanup($css); $rulesProcessor = new RuleProcessor(); $rules = $rulesProcessor->splitIntoSeparateRules($css); return $rulesProcessor->convertArrayToObjects($rules, $existingRules); } /** * Get the CSS from the style-tags in the given HTML-string * * @param string $html * * @return string */ public function getCssFromStyleTags($html) { $css = ''; $matches = array(); $htmlNoComments = preg_replace('|<!--.*?-->|s', '', $html) ?? $html; preg_match_all('|<style(?:\s.*)?>(.*)</style>|isU', $htmlNoComments, $matches); if (!empty($matches[1])) { foreach ($matches[1] as $match) { $css .= trim($match) . "\n"; } } return $css; } /** * @param string $css * * @return string */ private function doCleanup($css) { // remove charset $css = preg_replace('/@charset "[^"]++";/', '', $css) ?? $css; // remove media queries $css = preg_replace('/@media [^{]*+{([^{}]++|{[^{}]*+})*+}/', '', $css) ?? $css; $css = str_replace(array("\r", "\n"), '', $css); $css = str_replace(array("\t"), ' ', $css); $css = str_replace('"', '\'', $css); $css = preg_replace('|/\*.*?\*/|', '', $css) ?? $css; $css = preg_replace('/\s\s++/', ' ', $css) ?? $css; $css = trim($css); return $css; } } PK������iZ �� ����Css/Property/Processor.phpnu�W+A��������<?php namespace TijsVerkoyen\CssToInlineStyles\Css\Property; use Symfony\Component\CssSelector\Node\Specificity; class Processor { /** * Split a string into separate properties * * @param string $propertiesString * * @return string[] */ public function splitIntoSeparateProperties($propertiesString) { $propertiesString = $this->cleanup($propertiesString); $properties = (array) explode(';', $propertiesString); $keysToRemove = array(); $numberOfProperties = count($properties); for ($i = 0; $i < $numberOfProperties; $i++) { $properties[$i] = trim($properties[$i]); // if the new property begins with base64 it is part of the current property if (isset($properties[$i + 1]) && strpos(trim($properties[$i + 1]), 'base64,') === 0) { $properties[$i] .= ';' . trim($properties[$i + 1]); $keysToRemove[] = $i + 1; } } if (!empty($keysToRemove)) { foreach ($keysToRemove as $key) { unset($properties[$key]); } } return array_values($properties); } /** * @param string $string * * @return string */ private function cleanup($string) { $string = str_replace(array("\r", "\n"), '', $string); $string = str_replace(array("\t"), ' ', $string); $string = str_replace('"', '\'', $string); $string = preg_replace('|/\*.*?\*/|', '', $string) ?? $string; $string = preg_replace('/\s\s+/', ' ', $string) ?? $string; $string = trim($string); $string = rtrim($string, ';'); return $string; } /** * Converts a property-string into an object * * @param string $property * * @return Property|null */ public function convertToObject($property, ?Specificity $specificity = null) { if (strpos($property, ':') === false) { return null; } list($name, $value) = explode(':', $property, 2); $name = trim($name); $value = trim($value); if ($value === '') { return null; } return new Property($name, $value, $specificity); } /** * Converts an array of property-strings into objects * * @param string[] $properties * * @return Property[] */ public function convertArrayToObjects(array $properties, ?Specificity $specificity = null) { $objects = array(); foreach ($properties as $property) { $object = $this->convertToObject($property, $specificity); if ($object === null) { continue; } $objects[] = $object; } return $objects; } /** * Build the property-string for multiple properties * * @param Property[] $properties * * @return string */ public function buildPropertiesString(array $properties) { $chunks = array(); foreach ($properties as $property) { $chunks[] = $property->toString(); } return implode(' ', $chunks); } } PK������iZ!>��>����Css/Property/Property.phpnu�W+A��������<?php namespace TijsVerkoyen\CssToInlineStyles\Css\Property; use Symfony\Component\CssSelector\Node\Specificity; final class Property { /** * @var string */ private $name; /** * @var string */ private $value; /** * @var Specificity|null */ private $originalSpecificity; /** * Property constructor. * @param string $name * @param string $value * @param Specificity|null $specificity */ public function __construct($name, $value, ?Specificity $specificity = null) { $this->name = $name; $this->value = $value; $this->originalSpecificity = $specificity; } /** * Get name * * @return string */ public function getName() { return $this->name; } /** * Get value * * @return string */ public function getValue() { return $this->value; } /** * Get originalSpecificity * * @return Specificity|null */ public function getOriginalSpecificity() { return $this->originalSpecificity; } /** * Is this property important? * * @return bool */ public function isImportant() { return (stripos($this->value, '!important') !== false); } /** * Get the textual representation of the property * * @return string */ public function toString() { return sprintf( '%1$s: %2$s;', $this->name, $this->value ); } } PK������iZ@QÎ������Css/Rule/Processor.phpnu�W+A��������<?php namespace TijsVerkoyen\CssToInlineStyles\Css\Rule; use Symfony\Component\CssSelector\Node\Specificity; use \TijsVerkoyen\CssToInlineStyles\Css\Property\Processor as PropertyProcessor; class Processor { /** * Splits a string into separate rules * * @param string $rulesString * * @return string[] */ public function splitIntoSeparateRules($rulesString) { $rulesString = $this->cleanup($rulesString); return (array) explode('}', $rulesString); } /** * @param string $string * * @return string */ private function cleanup($string) { $string = str_replace(array("\r", "\n"), '', $string); $string = str_replace(array("\t"), ' ', $string); $string = str_replace('"', '\'', $string); $string = preg_replace('|/\*.*?\*/|', '', $string) ?? $string; $string = preg_replace('/\s\s+/', ' ', $string) ?? $string; $string = trim($string); $string = rtrim($string, '}'); return $string; } /** * Converts a rule-string into an object * * @param string $rule * @param int $originalOrder * * @return Rule[] */ public function convertToObjects($rule, $originalOrder) { $rule = $this->cleanup($rule); $chunks = explode('{', $rule); if (!isset($chunks[1])) { return array(); } $propertiesProcessor = new PropertyProcessor(); $rules = array(); $selectors = (array) explode(',', trim($chunks[0])); $properties = $propertiesProcessor->splitIntoSeparateProperties($chunks[1]); foreach ($selectors as $selector) { $selector = trim($selector); $specificity = $this->calculateSpecificityBasedOnASelector($selector); $rules[] = new Rule( $selector, $propertiesProcessor->convertArrayToObjects($properties, $specificity), $specificity, $originalOrder ); } return $rules; } /** * Calculates the specificity based on a CSS Selector string, * Based on the patterns from premailer/css_parser by Alex Dunae * * @see https://github.com/premailer/css_parser/blob/master/lib/css_parser/regexps.rb * * @param string $selector * * @return Specificity */ public function calculateSpecificityBasedOnASelector($selector) { $idSelectorCount = preg_match_all("/ \#/ix", $selector, $matches); $classAttributesPseudoClassesSelectorsPattern = " (\.[\w]+) # classes | \[(\w+) # attributes | (\:( # pseudo classes link|visited|active |hover|focus |lang |target |enabled|disabled|checked|indeterminate |root |nth-child|nth-last-child|nth-of-type|nth-last-of-type |first-child|last-child|first-of-type|last-of-type |only-child|only-of-type |empty|contains ))"; $classAttributesPseudoClassesSelectorCount = preg_match_all("/{$classAttributesPseudoClassesSelectorsPattern}/ix", $selector, $matches); $typePseudoElementsSelectorPattern = " ((^|[\s\+\>\~]+)[\w]+ # elements | \:{1,2}( # pseudo-elements after|before |first-letter|first-line |selection ) )"; $typePseudoElementsSelectorCount = preg_match_all("/{$typePseudoElementsSelectorPattern}/ix", $selector, $matches); if ($idSelectorCount === false || $classAttributesPseudoClassesSelectorCount === false || $typePseudoElementsSelectorCount === false) { throw new \RuntimeException('Failed to calculate specificity based on selector.'); } return new Specificity( $idSelectorCount, $classAttributesPseudoClassesSelectorCount, $typePseudoElementsSelectorCount ); } /** * @param string[] $rules * @param Rule[] $objects * * @return Rule[] */ public function convertArrayToObjects(array $rules, array $objects = array()) { $order = 1; foreach ($rules as $rule) { $objects = array_merge($objects, $this->convertToObjects($rule, $order)); $order++; } return $objects; } /** * Sorts an array on the specificity element in an ascending way * Lower specificity will be sorted to the beginning of the array * * @param Rule $e1 The first element. * @param Rule $e2 The second element. * * @return int */ public static function sortOnSpecificity(Rule $e1, Rule $e2) { $e1Specificity = $e1->getSpecificity(); $value = $e1Specificity->compareTo($e2->getSpecificity()); // if the specificity is the same, use the order in which the element appeared if ($value === 0) { $value = $e1->getOrder() - $e2->getOrder(); } return $value; } } PK������iZ0������Css/Rule/Rule.phpnu�W+A��������<?php namespace TijsVerkoyen\CssToInlineStyles\Css\Rule; use Symfony\Component\CssSelector\Node\Specificity; use TijsVerkoyen\CssToInlineStyles\Css\Property\Property; final class Rule { /** * @var string */ private $selector; /** * @var Property[] */ private $properties; /** * @var Specificity */ private $specificity; /** * @var integer */ private $order; /** * Rule constructor. * * @param string $selector * @param Property[] $properties * @param Specificity $specificity * @param int $order */ public function __construct($selector, array $properties, Specificity $specificity, $order) { $this->selector = $selector; $this->properties = $properties; $this->specificity = $specificity; $this->order = $order; } /** * Get selector * * @return string */ public function getSelector() { return $this->selector; } /** * Get properties * * @return Property[] */ public function getProperties() { return $this->properties; } /** * Get specificity * * @return Specificity */ public function getSpecificity() { return $this->specificity; } /** * Get order * * @return int */ public function getOrder() { return $this->order; } } PK������iZ^p������CssToInlineStyles.phpnu�W+A��������<?php namespace TijsVerkoyen\CssToInlineStyles; use Symfony\Component\CssSelector\CssSelectorConverter; use Symfony\Component\CssSelector\Exception\ExceptionInterface; use TijsVerkoyen\CssToInlineStyles\Css\Processor; use TijsVerkoyen\CssToInlineStyles\Css\Property\Processor as PropertyProcessor; use TijsVerkoyen\CssToInlineStyles\Css\Property\Property; use TijsVerkoyen\CssToInlineStyles\Css\Rule\Processor as RuleProcessor; class CssToInlineStyles { /** * @var CssSelectorConverter */ private $cssConverter; public function __construct() { $this->cssConverter = new CssSelectorConverter(); } /** * Will inline the $css into the given $html * * Remark: if the html contains <style>-tags those will be used, the rules * in $css will be appended. * * @param string $html * @param string $css * * @return string */ public function convert($html, $css = null) { $document = $this->createDomDocumentFromHtml($html); $processor = new Processor(); // get all styles from the style-tags $rules = $processor->getRules( $processor->getCssFromStyleTags($html) ); if ($css !== null) { $rules = $processor->getRules($css, $rules); } $document = $this->inline($document, $rules); return $this->getHtmlFromDocument($document); } /** * Inline the given properties on a given DOMElement * * @param \DOMElement $element * @param Property[] $properties * * @return \DOMElement */ public function inlineCssOnElement(\DOMElement $element, array $properties) { if (empty($properties)) { return $element; } $cssProperties = array(); $inlineProperties = array(); foreach ($this->getInlineStyles($element) as $property) { $inlineProperties[$property->getName()] = $property; } foreach ($properties as $property) { if (!isset($inlineProperties[$property->getName()])) { $cssProperties[$property->getName()] = $property; } } $rules = array(); foreach (array_merge($cssProperties, $inlineProperties) as $property) { $rules[] = $property->toString(); } $element->setAttribute('style', implode(' ', $rules)); return $element; } /** * Get the current inline styles for a given DOMElement * * @param \DOMElement $element * * @return Property[] */ public function getInlineStyles(\DOMElement $element) { $processor = new PropertyProcessor(); return $processor->convertArrayToObjects( $processor->splitIntoSeparateProperties( $element->getAttribute('style') ) ); } /** * @param string $html * * @return \DOMDocument */ protected function createDomDocumentFromHtml($html) { $document = new \DOMDocument('1.0', 'UTF-8'); $internalErrors = libxml_use_internal_errors(true); $document->loadHTML(mb_encode_numericentity($html, [0x80, 0x10FFFF, 0, 0x1FFFFF], 'UTF-8')); libxml_use_internal_errors($internalErrors); $document->formatOutput = true; return $document; } /** * @param \DOMDocument $document * * @return string */ protected function getHtmlFromDocument(\DOMDocument $document) { // retrieve the document element // we do it this way to preserve the utf-8 encoding $htmlElement = $document->documentElement; if ($htmlElement === null) { throw new \RuntimeException('Failed to get HTML from empty document.'); } $html = $document->saveHTML($htmlElement); if ($html === false) { throw new \RuntimeException('Failed to get HTML from document.'); } $html = trim($html); // retrieve the doctype $document->removeChild($htmlElement); $doctype = $document->saveHTML(); if ($doctype === false) { $doctype = ''; } $doctype = trim($doctype); // if it is the html5 doctype convert it to lowercase if ($doctype === '<!DOCTYPE html>') { $doctype = strtolower($doctype); } return $doctype."\n".$html; } /** * @param \DOMDocument $document * @param Css\Rule\Rule[] $rules * * @return \DOMDocument */ protected function inline(\DOMDocument $document, array $rules) { if (empty($rules)) { return $document; } /** @var \SplObjectStorage<\DOMElement, array<string, Property>> $propertyStorage */ $propertyStorage = new \SplObjectStorage(); $xPath = new \DOMXPath($document); usort($rules, array(RuleProcessor::class, 'sortOnSpecificity')); foreach ($rules as $rule) { try { $expression = $this->cssConverter->toXPath($rule->getSelector()); } catch (ExceptionInterface $e) { continue; } $elements = $xPath->query($expression); if ($elements === false) { continue; } foreach ($elements as $element) { \assert($element instanceof \DOMElement); $propertyStorage[$element] = $this->calculatePropertiesToBeApplied( $rule->getProperties(), $propertyStorage->contains($element) ? $propertyStorage[$element] : array() ); } } foreach ($propertyStorage as $element) { $this->inlineCssOnElement($element, $propertyStorage[$element]); } return $document; } /** * Merge the CSS rules to determine the applied properties. * * @param Property[] $properties * @param array<string, Property> $cssProperties existing applied properties indexed by name * * @return array<string, Property> updated properties, indexed by name */ private function calculatePropertiesToBeApplied(array $properties, array $cssProperties): array { if (empty($properties)) { return $cssProperties; } foreach ($properties as $property) { if (isset($cssProperties[$property->getName()])) { $existingProperty = $cssProperties[$property->getName()]; //skip check to overrule if existing property is important and current is not if ($existingProperty->isImportant() && !$property->isImportant()) { continue; } //overrule if current property is important and existing is not, else check specificity $overrule = !$existingProperty->isImportant() && $property->isImportant(); if (!$overrule) { \assert($existingProperty->getOriginalSpecificity() !== null, 'Properties created for parsed CSS always have their associated specificity.'); \assert($property->getOriginalSpecificity() !== null, 'Properties created for parsed CSS always have their associated specificity.'); $overrule = $existingProperty->getOriginalSpecificity()->compareTo($property->getOriginalSpecificity()) <= 0; } if ($overrule) { unset($cssProperties[$property->getName()]); $cssProperties[$property->getName()] = $property; } } else { $cssProperties[$property->getName()] = $property; } } return $cssProperties; } } PK������AyZO4Wt������Support/SelfReference.phpnu�W+A��������<?php namespace Laravel\SerializableClosure\Support; class SelfReference { /** * The unique hash representing the object. * * @var string */ public $hash; /** * Creates a new self reference instance. * * @param string $hash * @return void */ public function __construct($hash) { $this->hash = $hash; } } PK������AyZJsxz��z����Support/ClosureScope.phpnu�W+A��������<?php namespace Laravel\SerializableClosure\Support; use SplObjectStorage; class ClosureScope extends SplObjectStorage { /** * The number of serializations in current scope. * * @var int */ public $serializations = 0; /** * The number of closures that have to be serialized. * * @var int */ public $toSerialize = 0; } PK������AyZ������Support/ClosureStream.phpnu�W+A��������<?php namespace Laravel\SerializableClosure\Support; #[\AllowDynamicProperties] class ClosureStream { /** * The stream protocol. */ const STREAM_PROTO = 'laravel-serializable-closure'; /** * Checks if this stream is registered. * * @var bool */ protected static $isRegistered = false; /** * The stream content. * * @var string */ protected $content; /** * The stream content. * * @var int */ protected $length; /** * The stream pointer. * * @var int */ protected $pointer = 0; /** * Opens file or URL. * * @param string $path * @param string $mode * @param string $options * @param string|null $opened_path * @return bool */ public function stream_open($path, $mode, $options, &$opened_path) { $this->content = "<?php\nreturn ".substr($path, strlen(static::STREAM_PROTO.'://')).';'; $this->length = strlen($this->content); return true; } /** * Read from stream. * * @param int $count * @return string */ public function stream_read($count) { $value = substr($this->content, $this->pointer, $count); $this->pointer += $count; return $value; } /** * Tests for end-of-file on a file pointer. * * @return bool */ public function stream_eof() { return $this->pointer >= $this->length; } /** * Change stream options. * * @param int $option * @param int $arg1 * @param int $arg2 * @return bool */ public function stream_set_option($option, $arg1, $arg2) { return false; } /** * Retrieve information about a file resource. * * @return array|bool */ public function stream_stat() { $stat = stat(__FILE__); // @phpstan-ignore-next-line $stat[7] = $stat['size'] = $this->length; return $stat; } /** * Retrieve information about a file. * * @param string $path * @param int $flags * @return array|bool */ public function url_stat($path, $flags) { $stat = stat(__FILE__); // @phpstan-ignore-next-line $stat[7] = $stat['size'] = $this->length; return $stat; } /** * Seeks to specific location in a stream. * * @param int $offset * @param int $whence * @return bool */ public function stream_seek($offset, $whence = SEEK_SET) { $crt = $this->pointer; switch ($whence) { case SEEK_SET: $this->pointer = $offset; break; case SEEK_CUR: $this->pointer += $offset; break; case SEEK_END: $this->pointer = $this->length + $offset; break; } if ($this->pointer < 0 || $this->pointer >= $this->length) { $this->pointer = $crt; return false; } return true; } /** * Retrieve the current position of a stream. * * @return int */ public function stream_tell() { return $this->pointer; } /** * Registers the stream. * * @return void */ public static function register() { if (! static::$isRegistered) { static::$isRegistered = stream_wrapper_register(static::STREAM_PROTO, __CLASS__); } } } PK������AyZSf������Support/ReflectionClosure.phpnu�W+A��������<?php namespace Laravel\SerializableClosure\Support; defined('T_NAME_QUALIFIED') || define('T_NAME_QUALIFIED', -4); defined('T_NAME_FULLY_QUALIFIED') || define('T_NAME_FULLY_QUALIFIED', -5); defined('T_FN') || define('T_FN', -6); defined('T_NULLSAFE_OBJECT_OPERATOR') || define('T_NULLSAFE_OBJECT_OPERATOR', -7); use Closure; use ReflectionFunction; class ReflectionClosure extends ReflectionFunction { protected $code; protected $tokens; protected $hashedName; protected $useVariables; protected $isStaticClosure; protected $isScopeRequired; protected $isBindingRequired; protected $isShortClosure; protected static $files = []; protected static $classes = []; protected static $functions = []; protected static $constants = []; protected static $structures = []; /** * Creates a new reflection closure instance. * * @param \Closure $closure * @param string|null $code * @return void */ public function __construct(Closure $closure, $code = null) { parent::__construct($closure); } /** * Checks if the closure is "static". * * @return bool */ public function isStatic(): bool { if ($this->isStaticClosure === null) { $this->isStaticClosure = strtolower(substr($this->getCode(), 0, 6)) === 'static'; } return $this->isStaticClosure; } /** * Checks if the closure is a "short closure". * * @return bool */ public function isShortClosure() { if ($this->isShortClosure === null) { $code = $this->getCode(); if ($this->isStatic()) { $code = substr($code, 6); } $this->isShortClosure = strtolower(substr(trim($code), 0, 2)) === 'fn'; } return $this->isShortClosure; } /** * Get the closure's code. * * @return string */ public function getCode() { if ($this->code !== null) { return $this->code; } $fileName = $this->getFileName(); $line = $this->getStartLine() - 1; $className = null; if (null !== $className = $this->getClosureScopeClass()) { $className = '\\'.trim($className->getName(), '\\'); } $builtin_types = self::getBuiltinTypes(); $class_keywords = ['self', 'static', 'parent']; $ns = $this->getClosureNamespaceName(); $nsf = $ns == '' ? '' : ($ns[0] == '\\' ? $ns : '\\'.$ns); $_file = var_export($fileName, true); $_dir = var_export(dirname($fileName), true); $_namespace = var_export($ns, true); $_class = var_export(trim($className ?: '', '\\'), true); $_function = $ns.($ns == '' ? '' : '\\').'{closure}'; $_method = ($className == '' ? '' : trim($className, '\\').'::').$_function; $_function = var_export($_function, true); $_method = var_export($_method, true); $_trait = null; $tokens = $this->getTokens(); $state = $lastState = 'start'; $inside_structure = false; $isFirstClassCallable = false; $isShortClosure = false; $inside_structure_mark = 0; $open = 0; $code = ''; $id_start = $id_start_ci = $id_name = $context = ''; $classes = $functions = $constants = null; $use = []; $lineAdd = 0; $isUsingScope = false; $isUsingThisObject = false; for ($i = 0, $l = count($tokens); $i < $l; $i++) { $token = $tokens[$i]; switch ($state) { case 'start': if ($token[0] === T_FUNCTION || $token[0] === T_STATIC) { $code .= $token[1]; $state = $token[0] === T_FUNCTION ? 'function' : 'static'; } elseif ($token[0] === T_FN) { $isShortClosure = true; $code .= $token[1]; $state = 'closure_args'; } elseif ($token[0] === T_PUBLIC || $token[0] === T_PROTECTED || $token[0] === T_PRIVATE) { $code = ''; $isFirstClassCallable = true; } break; case 'static': if ($token[0] === T_WHITESPACE || $token[0] === T_COMMENT || $token[0] === T_FUNCTION) { $code .= $token[1]; if ($token[0] === T_FUNCTION) { $state = 'function'; } } elseif ($token[0] === T_FN) { $isShortClosure = true; $code .= $token[1]; $state = 'closure_args'; } else { $code = ''; $state = 'start'; } break; case 'function': switch ($token[0]) { case T_STRING: if ($isFirstClassCallable) { $state = 'closure_args'; break; } $code = ''; $state = 'named_function'; break; case '(': $code .= '('; $state = 'closure_args'; break; default: $code .= is_array($token) ? $token[1] : $token; } break; case 'named_function': if ($token[0] === T_FUNCTION || $token[0] === T_STATIC) { $code = $token[1]; $state = $token[0] === T_FUNCTION ? 'function' : 'static'; } elseif ($token[0] === T_FN) { $isShortClosure = true; $code .= $token[1]; $state = 'closure_args'; } break; case 'closure_args': switch ($token[0]) { case T_NAME_QUALIFIED: [$id_start, $id_start_ci, $id_name] = $this->parseNameQualified($token[1]); $context = 'args'; $state = 'id_name'; $lastState = 'closure_args'; break; case T_NS_SEPARATOR: case T_STRING: $id_start = $token[1]; $id_start_ci = strtolower($id_start); $id_name = ''; $context = 'args'; $state = 'id_name'; $lastState = 'closure_args'; break; case T_USE: $code .= $token[1]; $state = 'use'; break; case T_DOUBLE_ARROW: $code .= $token[1]; if ($isShortClosure) { $state = 'closure'; } break; case ':': $code .= ':'; $state = 'return'; break; case '{': $code .= '{'; $state = 'closure'; $open++; break; default: $code .= is_array($token) ? $token[1] : $token; } break; case 'use': switch ($token[0]) { case T_VARIABLE: $use[] = substr($token[1], 1); $code .= $token[1]; break; case '{': $code .= '{'; $state = 'closure'; $open++; break; case ':': $code .= ':'; $state = 'return'; break; default: $code .= is_array($token) ? $token[1] : $token; break; } break; case 'return': switch ($token[0]) { case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: $code .= $token[1]; break; case T_NS_SEPARATOR: case T_STRING: $id_start = $token[1]; $id_start_ci = strtolower($id_start); $id_name = ''; $context = 'return_type'; $state = 'id_name'; $lastState = 'return'; break 2; case T_NAME_QUALIFIED: [$id_start, $id_start_ci, $id_name] = $this->parseNameQualified($token[1]); $context = 'return_type'; $state = 'id_name'; $lastState = 'return'; break 2; case T_DOUBLE_ARROW: $code .= $token[1]; if ($isShortClosure) { $state = 'closure'; } break; case '{': $code .= '{'; $state = 'closure'; $open++; break; default: $code .= is_array($token) ? $token[1] : $token; break; } break; case 'closure': switch ($token[0]) { case T_CURLY_OPEN: case T_DOLLAR_OPEN_CURLY_BRACES: case '{': $code .= is_array($token) ? $token[1] : $token; $open++; break; case '}': $code .= '}'; if (--$open === 0 && ! $isShortClosure) { break 3; } elseif ($inside_structure) { $inside_structure = ! ($open === $inside_structure_mark); } break; case '(': case '[': $code .= $token[0]; if ($isShortClosure) { $open++; } break; case ')': case ']': if ($isShortClosure) { if ($open === 0) { break 3; } $open--; } $code .= $token[0]; break; case ',': case ';': if ($isShortClosure && $open === 0) { break 3; } $code .= $token[0]; break; case T_LINE: $code .= $token[2] - $line + $lineAdd; break; case T_FILE: $code .= $_file; break; case T_DIR: $code .= $_dir; break; case T_NS_C: $code .= $_namespace; break; case T_CLASS_C: $code .= $inside_structure ? $token[1] : $_class; break; case T_FUNC_C: $code .= $inside_structure ? $token[1] : $_function; break; case T_METHOD_C: $code .= $inside_structure ? $token[1] : $_method; break; case T_COMMENT: if (substr($token[1], 0, 8) === '#trackme') { $timestamp = time(); $code .= '/**'.PHP_EOL; $code .= '* Date : '.date(DATE_W3C, $timestamp).PHP_EOL; $code .= '* Timestamp : '.$timestamp.PHP_EOL; $code .= '* Line : '.($line + 1).PHP_EOL; $code .= '* File : '.$_file.PHP_EOL.'*/'.PHP_EOL; $lineAdd += 5; } else { $code .= $token[1]; } break; case T_VARIABLE: if ($token[1] == '$this' && ! $inside_structure) { $isUsingThisObject = true; } $code .= $token[1]; break; case T_STATIC: case T_NS_SEPARATOR: case T_STRING: $id_start = $token[1]; $id_start_ci = strtolower($id_start); $id_name = ''; $context = 'root'; $state = 'id_name'; $lastState = 'closure'; break 2; case T_NAME_QUALIFIED: [$id_start, $id_start_ci, $id_name] = $this->parseNameQualified($token[1]); $context = 'root'; $state = 'id_name'; $lastState = 'closure'; break 2; case T_NEW: $code .= $token[1]; $context = 'new'; $state = 'id_start'; $lastState = 'closure'; break 2; case T_USE: $code .= $token[1]; $context = 'use'; $state = 'id_start'; $lastState = 'closure'; break; case T_INSTANCEOF: case T_INSTEADOF: $code .= $token[1]; $context = 'instanceof'; $state = 'id_start'; $lastState = 'closure'; break; case T_OBJECT_OPERATOR: case T_NULLSAFE_OBJECT_OPERATOR: case T_DOUBLE_COLON: $code .= $token[1]; $lastState = 'closure'; $state = 'ignore_next'; break; case T_FUNCTION: $code .= $token[1]; $state = 'closure_args'; if (! $inside_structure) { $inside_structure = true; $inside_structure_mark = $open; } break; case T_TRAIT_C: if ($_trait === null) { $startLine = $this->getStartLine(); $endLine = $this->getEndLine(); $structures = $this->getStructures(); $_trait = ''; foreach ($structures as &$struct) { if ($struct['type'] === 'trait' && $struct['start'] <= $startLine && $struct['end'] >= $endLine ) { $_trait = ($ns == '' ? '' : $ns.'\\').$struct['name']; break; } } $_trait = var_export($_trait, true); } $code .= $_trait; break; default: $code .= is_array($token) ? $token[1] : $token; } break; case 'ignore_next': switch ($token[0]) { case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: $code .= $token[1]; break; case T_CLASS: case T_NEW: case T_STATIC: case T_VARIABLE: case T_STRING: case T_CLASS_C: case T_FILE: case T_DIR: case T_METHOD_C: case T_FUNC_C: case T_FUNCTION: case T_INSTANCEOF: case T_LINE: case T_NS_C: case T_TRAIT_C: case T_USE: $code .= $token[1]; $state = $lastState; break; default: $state = $lastState; $i--; } break; case 'id_start': switch ($token[0]) { case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: $code .= $token[1]; break; case T_NS_SEPARATOR: case T_NAME_FULLY_QUALIFIED: case T_STRING: case T_STATIC: $id_start = $token[1]; $id_start_ci = strtolower($id_start); $id_name = ''; $state = 'id_name'; break 2; case T_NAME_QUALIFIED: [$id_start, $id_start_ci, $id_name] = $this->parseNameQualified($token[1]); $state = 'id_name'; break 2; case T_VARIABLE: $code .= $token[1]; $state = $lastState; break; case T_CLASS: $code .= $token[1]; $state = 'anonymous'; break; default: $i--; //reprocess last $state = 'id_name'; } break; case 'id_name': switch ($token[0]) { case $token[0] === ':' && $context !== 'instanceof': if ($lastState === 'closure' && $context === 'root') { $state = 'closure'; $code .= $id_start.$token; } break; case T_NAME_QUALIFIED: case T_NS_SEPARATOR: case T_STRING: case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: $id_name .= $token[1]; break; case '(': if ($isShortClosure) { $open++; } if ($context === 'new' || false !== strpos($id_name, '\\')) { if ($id_start_ci === 'self' || $id_start_ci === 'static') { if (! $inside_structure) { $isUsingScope = true; } } elseif ($id_start !== '\\' && ! in_array($id_start_ci, $class_keywords)) { if ($classes === null) { $classes = $this->getClasses(); } if (isset($classes[$id_start_ci])) { $id_start = $classes[$id_start_ci]; } if ($id_start[0] !== '\\') { $id_start = $nsf.'\\'.$id_start; } } } else { if ($id_start !== '\\') { if ($functions === null) { $functions = $this->getFunctions(); } if (isset($functions[$id_start_ci])) { $id_start = $functions[$id_start_ci]; } elseif ($nsf !== '\\' && function_exists($nsf.'\\'.$id_start)) { $id_start = $nsf.'\\'.$id_start; // Cache it to functions array $functions[$id_start_ci] = $id_start; } } } $code .= $id_start.$id_name.'('; $state = $lastState; break; case T_VARIABLE: case T_DOUBLE_COLON: if ($id_start !== '\\') { if ($id_start_ci === 'self' || $id_start_ci === 'parent') { if (! $inside_structure) { $isUsingScope = true; } } elseif ($id_start_ci === 'static') { if (! $inside_structure) { $isUsingScope = $token[0] === T_DOUBLE_COLON; } } elseif (! (\PHP_MAJOR_VERSION >= 7 && in_array($id_start_ci, $builtin_types))) { if ($classes === null) { $classes = $this->getClasses(); } if (isset($classes[$id_start_ci])) { $id_start = $classes[$id_start_ci]; } if ($id_start[0] !== '\\') { $id_start = $nsf.'\\'.$id_start; } } } $code .= $id_start.$id_name.$token[1]; $state = $token[0] === T_DOUBLE_COLON ? 'ignore_next' : $lastState; break; default: if ($id_start !== '\\' && ! defined($id_start)) { if ($constants === null) { $constants = $this->getConstants(); } if (isset($constants[$id_start])) { $id_start = $constants[$id_start]; } elseif ($context === 'new') { if (in_array($id_start_ci, $class_keywords)) { if (! $inside_structure) { $isUsingScope = true; } } else { if ($classes === null) { $classes = $this->getClasses(); } if (isset($classes[$id_start_ci])) { $id_start = $classes[$id_start_ci]; } if ($id_start[0] !== '\\') { $id_start = $nsf.'\\'.$id_start; } } } elseif ($context === 'use' || $context === 'instanceof' || $context === 'args' || $context === 'return_type' || $context === 'extends' || $context === 'root' ) { if (in_array($id_start_ci, $class_keywords)) { if (! $inside_structure && ! $id_start_ci === 'static') { $isUsingScope = true; } } elseif (! (\PHP_MAJOR_VERSION >= 7 && in_array($id_start_ci, $builtin_types))) { if ($classes === null) { $classes = $this->getClasses(); } if (isset($classes[$id_start_ci])) { $id_start = $classes[$id_start_ci]; } if ($id_start[0] !== '\\') { $id_start = $nsf.'\\'.$id_start; } } } } $code .= $id_start.$id_name; $state = $lastState; $i--; //reprocess last token } break; case 'anonymous': switch ($token[0]) { case T_NAME_QUALIFIED: [$id_start, $id_start_ci, $id_name] = $this->parseNameQualified($token[1]); $state = 'id_name'; $lastState = 'anonymous'; break 2; case T_NS_SEPARATOR: case T_STRING: $id_start = $token[1]; $id_start_ci = strtolower($id_start); $id_name = ''; $state = 'id_name'; $context = 'extends'; $lastState = 'anonymous'; break; case '{': $state = 'closure'; if (! $inside_structure) { $inside_structure = true; $inside_structure_mark = $open; } $i--; break; default: $code .= is_array($token) ? $token[1] : $token; } break; } } if ($isShortClosure) { $this->useVariables = $this->getStaticVariables(); } else { $this->useVariables = empty($use) ? $use : array_intersect_key($this->getStaticVariables(), array_flip($use)); } $this->isShortClosure = $isShortClosure; $this->isBindingRequired = $isUsingThisObject; $this->isScopeRequired = $isUsingScope; if (PHP_VERSION_ID >= 80100) { $attributesCode = array_map(function ($attribute) { $arguments = $attribute->getArguments(); $name = $attribute->getName(); $arguments = implode(', ', array_map(function ($argument, $key) { $argument = sprintf("'%s'", str_replace("'", "\\'", $argument)); if (is_string($key)) { $argument = sprintf('%s: %s', $key, $argument); } return $argument; }, $arguments, array_keys($arguments))); return "#[$name($arguments)]"; }, $this->getAttributes()); if (! empty($attributesCode)) { $code = implode("\n", array_merge($attributesCode, [$code])); } } $this->code = $code; return $this->code; } /** * Get PHP native built in types. * * @return array */ protected static function getBuiltinTypes() { // PHP 8.1 if (PHP_VERSION_ID >= 80100) { return ['array', 'callable', 'string', 'int', 'bool', 'float', 'iterable', 'void', 'object', 'mixed', 'false', 'null', 'never']; } // PHP 8 if (\PHP_MAJOR_VERSION === 8) { return ['array', 'callable', 'string', 'int', 'bool', 'float', 'iterable', 'void', 'object', 'mixed', 'false', 'null']; } // PHP 7 switch (\PHP_MINOR_VERSION) { case 0: return ['array', 'callable', 'string', 'int', 'bool', 'float']; case 1: return ['array', 'callable', 'string', 'int', 'bool', 'float', 'iterable', 'void']; default: return ['array', 'callable', 'string', 'int', 'bool', 'float', 'iterable', 'void', 'object']; } } /** * Gets the use variables by the closure. * * @return array */ public function getUseVariables() { if ($this->useVariables !== null) { return $this->useVariables; } $tokens = $this->getTokens(); $use = []; $state = 'start'; foreach ($tokens as &$token) { $is_array = is_array($token); switch ($state) { case 'start': if ($is_array && $token[0] === T_USE) { $state = 'use'; } break; case 'use': if ($is_array) { if ($token[0] === T_VARIABLE) { $use[] = substr($token[1], 1); } } elseif ($token == ')') { break 2; } break; } } $this->useVariables = empty($use) ? $use : array_intersect_key($this->getStaticVariables(), array_flip($use)); return $this->useVariables; } /** * Checks if binding is required. * * @return bool */ public function isBindingRequired() { if ($this->isBindingRequired === null) { $this->getCode(); } return $this->isBindingRequired; } /** * Checks if access to the scope is required. * * @return bool */ public function isScopeRequired() { if ($this->isScopeRequired === null) { $this->getCode(); } return $this->isScopeRequired; } /** * The hash of the current file name. * * @return string */ protected function getHashedFileName() { if ($this->hashedName === null) { $this->hashedName = sha1($this->getFileName()); } return $this->hashedName; } /** * Get the file tokens. * * @return array */ protected function getFileTokens() { $key = $this->getHashedFileName(); if (! isset(static::$files[$key])) { static::$files[$key] = token_get_all(file_get_contents($this->getFileName())); } return static::$files[$key]; } /** * Get the tokens. * * @return array */ protected function getTokens() { if ($this->tokens === null) { $tokens = $this->getFileTokens(); $startLine = $this->getStartLine(); $endLine = $this->getEndLine(); $results = []; $start = false; foreach ($tokens as &$token) { if (! is_array($token)) { if ($start) { $results[] = $token; } continue; } $line = $token[2]; if ($line <= $endLine) { if ($line >= $startLine) { $start = true; $results[] = $token; } continue; } break; } $this->tokens = $results; } return $this->tokens; } /** * Get the classes. * * @return array */ protected function getClasses() { $key = $this->getHashedFileName(); if (! isset(static::$classes[$key])) { $this->fetchItems(); } return static::$classes[$key]; } /** * Get the functions. * * @return array */ protected function getFunctions() { $key = $this->getHashedFileName(); if (! isset(static::$functions[$key])) { $this->fetchItems(); } return static::$functions[$key]; } /** * Gets the constants. * * @return array */ protected function getConstants() { $key = $this->getHashedFileName(); if (! isset(static::$constants[$key])) { $this->fetchItems(); } return static::$constants[$key]; } /** * Get the structures. * * @return array */ protected function getStructures() { $key = $this->getHashedFileName(); if (! isset(static::$structures[$key])) { $this->fetchItems(); } return static::$structures[$key]; } /** * Fetch the items. * * @return void. */ protected function fetchItems() { $key = $this->getHashedFileName(); $classes = []; $functions = []; $constants = []; $structures = []; $tokens = $this->getFileTokens(); $open = 0; $state = 'start'; $lastState = ''; $prefix = ''; $name = ''; $alias = ''; $isFunc = $isConst = false; $startLine = $endLine = 0; $structType = $structName = ''; $structIgnore = false; foreach ($tokens as $token) { switch ($state) { case 'start': switch ($token[0]) { case T_CLASS: case T_INTERFACE: case T_TRAIT: $state = 'before_structure'; $startLine = $token[2]; $structType = $token[0] == T_CLASS ? 'class' : ($token[0] == T_INTERFACE ? 'interface' : 'trait'); break; case T_USE: $state = 'use'; $prefix = $name = $alias = ''; $isFunc = $isConst = false; break; case T_FUNCTION: $state = 'structure'; $structIgnore = true; break; case T_NEW: $state = 'new'; break; case T_OBJECT_OPERATOR: case T_DOUBLE_COLON: $state = 'invoke'; break; } break; case 'use': switch ($token[0]) { case T_FUNCTION: $isFunc = true; break; case T_CONST: $isConst = true; break; case T_NS_SEPARATOR: $name .= $token[1]; break; case T_STRING: $name .= $token[1]; $alias = $token[1]; break; case T_NAME_QUALIFIED: $name .= $token[1]; $pieces = explode('\\', $token[1]); $alias = end($pieces); break; case T_AS: $lastState = 'use'; $state = 'alias'; break; case '{': $prefix = $name; $name = $alias = ''; $state = 'use-group'; break; case ',': case ';': if ($name === '' || $name[0] !== '\\') { $name = '\\'.$name; } if ($alias !== '') { if ($isFunc) { $functions[strtolower($alias)] = $name; } elseif ($isConst) { $constants[$alias] = $name; } else { $classes[strtolower($alias)] = $name; } } $name = $alias = ''; $state = $token === ';' ? 'start' : 'use'; break; } break; case 'use-group': switch ($token[0]) { case T_NS_SEPARATOR: $name .= $token[1]; break; case T_NAME_QUALIFIED: $name .= $token[1]; $pieces = explode('\\', $token[1]); $alias = end($pieces); break; case T_STRING: $name .= $token[1]; $alias = $token[1]; break; case T_AS: $lastState = 'use-group'; $state = 'alias'; break; case ',': case '}': if ($prefix === '' || $prefix[0] !== '\\') { $prefix = '\\'.$prefix; } if ($alias !== '') { if ($isFunc) { $functions[strtolower($alias)] = $prefix.$name; } elseif ($isConst) { $constants[$alias] = $prefix.$name; } else { $classes[strtolower($alias)] = $prefix.$name; } } $name = $alias = ''; $state = $token === '}' ? 'use' : 'use-group'; break; } break; case 'alias': if ($token[0] === T_STRING) { $alias = $token[1]; $state = $lastState; } break; case 'new': switch ($token[0]) { case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: break 2; case T_CLASS: $state = 'structure'; $structIgnore = true; break; default: $state = 'start'; } break; case 'invoke': switch ($token[0]) { case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: break 2; default: $state = 'start'; } break; case 'before_structure': if ($token[0] == T_STRING) { $structName = $token[1]; $state = 'structure'; } break; case 'structure': switch ($token[0]) { case '{': case T_CURLY_OPEN: case T_DOLLAR_OPEN_CURLY_BRACES: $open++; break; case '}': if (--$open == 0) { if (! $structIgnore) { $structures[] = [ 'type' => $structType, 'name' => $structName, 'start' => $startLine, 'end' => $endLine, ]; } $structIgnore = false; $state = 'start'; } break; default: if (is_array($token)) { $endLine = $token[2]; } } break; } } static::$classes[$key] = $classes; static::$functions[$key] = $functions; static::$constants[$key] = $constants; static::$structures[$key] = $structures; } /** * Returns the namespace associated to the closure. * * @return string */ protected function getClosureNamespaceName() { $ns = $this->getNamespaceName(); // First class callables... if ($this->getName() !== '{closure}' && empty($ns) && ! is_null($this->getClosureScopeClass())) { $ns = $this->getClosureScopeClass()->getNamespaceName(); } return $ns; } /** * Parse the given token. * * @param string $token * @return array */ protected function parseNameQualified($token) { $pieces = explode('\\', $token); $id_start = array_shift($pieces); $id_start_ci = strtolower($id_start); $id_name = '\\'.implode('\\', $pieces); return [$id_start, $id_start_ci, $id_name]; } } PK������AyZ&K^T��T����Serializers/Signed.phpnu�W+A��������<?php namespace Laravel\SerializableClosure\Serializers; use Laravel\SerializableClosure\Contracts\Serializable; use Laravel\SerializableClosure\Exceptions\InvalidSignatureException; use Laravel\SerializableClosure\Exceptions\MissingSecretKeyException; class Signed implements Serializable { /** * The signer that will sign and verify the closure's signature. * * @var \Laravel\SerializableClosure\Contracts\Signer|null */ public static $signer; /** * The closure to be serialized/unserialized. * * @var \Closure */ protected $closure; /** * Creates a new serializable closure instance. * * @param \Closure $closure * @return void */ public function __construct($closure) { $this->closure = $closure; } /** * Resolve the closure with the given arguments. * * @return mixed */ public function __invoke() { return call_user_func_array($this->closure, func_get_args()); } /** * Gets the closure. * * @return \Closure */ public function getClosure() { return $this->closure; } /** * Get the serializable representation of the closure. * * @return array */ public function __serialize() { if (! static::$signer) { throw new MissingSecretKeyException(); } return static::$signer->sign( serialize(new Native($this->closure)) ); } /** * Restore the closure after serialization. * * @param array $signature * @return void * * @throws \Laravel\SerializableClosure\Exceptions\InvalidSignatureException */ public function __unserialize($signature) { if (static::$signer && ! static::$signer->verify($signature)) { throw new InvalidSignatureException(); } /** @var \Laravel\SerializableClosure\Contracts\Serializable $serializable */ $serializable = unserialize($signature['serializable']); $this->closure = $serializable->getClosure(); } } PK������AyZ~(>9��>9����Serializers/Native.phpnu�W+A��������<?php namespace Laravel\SerializableClosure\Serializers; use Closure; use DateTimeInterface; use Laravel\SerializableClosure\Contracts\Serializable; use Laravel\SerializableClosure\SerializableClosure; use Laravel\SerializableClosure\Support\ClosureScope; use Laravel\SerializableClosure\Support\ClosureStream; use Laravel\SerializableClosure\Support\ReflectionClosure; use Laravel\SerializableClosure\Support\SelfReference; use Laravel\SerializableClosure\UnsignedSerializableClosure; use ReflectionObject; use UnitEnum; class Native implements Serializable { /** * Transform the use variables before serialization. * * @var \Closure|null */ public static $transformUseVariables; /** * Resolve the use variables after unserialization. * * @var \Closure|null */ public static $resolveUseVariables; /** * The closure to be serialized/unserialized. * * @var \Closure */ protected $closure; /** * The closure's reflection. * * @var \Laravel\SerializableClosure\Support\ReflectionClosure|null */ protected $reflector; /** * The closure's code. * * @var array|null */ protected $code; /** * The closure's reference. * * @var string */ protected $reference; /** * The closure's scope. * * @var \Laravel\SerializableClosure\Support\ClosureScope|null */ protected $scope; /** * The "key" that marks an array as recursive. */ const ARRAY_RECURSIVE_KEY = 'LARAVEL_SERIALIZABLE_RECURSIVE_KEY'; /** * Creates a new serializable closure instance. * * @param \Closure $closure * @return void */ public function __construct(Closure $closure) { $this->closure = $closure; } /** * Resolve the closure with the given arguments. * * @return mixed */ public function __invoke() { return call_user_func_array($this->closure, func_get_args()); } /** * Gets the closure. * * @return \Closure */ public function getClosure() { return $this->closure; } /** * Get the serializable representation of the closure. * * @return array */ public function __serialize() { if ($this->scope === null) { $this->scope = new ClosureScope(); $this->scope->toSerialize++; } $this->scope->serializations++; $scope = $object = null; $reflector = $this->getReflector(); if ($reflector->isBindingRequired()) { $object = $reflector->getClosureThis(); static::wrapClosures($object, $this->scope); } if ($scope = $reflector->getClosureScopeClass()) { $scope = $scope->name; } $this->reference = spl_object_hash($this->closure); $this->scope[$this->closure] = $this; $use = $reflector->getUseVariables(); if (static::$transformUseVariables) { $use = call_user_func(static::$transformUseVariables, $reflector->getUseVariables()); } $code = $reflector->getCode(); $this->mapByReference($use); $data = [ 'use' => $use, 'function' => $code, 'scope' => $scope, 'this' => $object, 'self' => $this->reference, ]; if (! --$this->scope->serializations && ! --$this->scope->toSerialize) { $this->scope = null; } return $data; } /** * Restore the closure after serialization. * * @param array $data * @return void */ public function __unserialize($data) { ClosureStream::register(); $this->code = $data; unset($data); $this->code['objects'] = []; if ($this->code['use']) { $this->scope = new ClosureScope(); if (static::$resolveUseVariables) { $this->code['use'] = call_user_func(static::$resolveUseVariables, $this->code['use']); } $this->mapPointers($this->code['use']); extract($this->code['use'], EXTR_OVERWRITE | EXTR_REFS); $this->scope = null; } $this->closure = include ClosureStream::STREAM_PROTO.'://'.$this->code['function']; if ($this->code['this'] === $this) { $this->code['this'] = null; } $this->closure = $this->closure->bindTo($this->code['this'], $this->code['scope']); if (! empty($this->code['objects'])) { foreach ($this->code['objects'] as $item) { $item['property']->setValue($item['instance'], $item['object']->getClosure()); } } $this->code = $this->code['function']; } /** * Ensures the given closures are serializable. * * @param mixed $data * @param \Laravel\SerializableClosure\Support\ClosureScope $storage * @return void */ public static function wrapClosures(&$data, $storage) { if ($data instanceof Closure) { $data = new static($data); } elseif (is_array($data)) { if (isset($data[self::ARRAY_RECURSIVE_KEY])) { return; } $data[self::ARRAY_RECURSIVE_KEY] = true; foreach ($data as $key => &$value) { if ($key === self::ARRAY_RECURSIVE_KEY) { continue; } static::wrapClosures($value, $storage); } unset($value); unset($data[self::ARRAY_RECURSIVE_KEY]); } elseif ($data instanceof \stdClass) { if (isset($storage[$data])) { $data = $storage[$data]; return; } $data = $storage[$data] = clone $data; foreach ($data as &$value) { static::wrapClosures($value, $storage); } unset($value); } elseif (is_object($data) && ! $data instanceof static && ! $data instanceof UnitEnum) { if (isset($storage[$data])) { $data = $storage[$data]; return; } $instance = $data; $reflection = new ReflectionObject($instance); if (! $reflection->isUserDefined()) { $storage[$instance] = $data; return; } $storage[$instance] = $data = $reflection->newInstanceWithoutConstructor(); do { if (! $reflection->isUserDefined()) { break; } foreach ($reflection->getProperties() as $property) { if ($property->isStatic() || ! $property->getDeclaringClass()->isUserDefined()) { continue; } $property->setAccessible(true); if (PHP_VERSION >= 7.4 && ! $property->isInitialized($instance)) { continue; } $value = $property->getValue($instance); if (is_array($value) || is_object($value)) { static::wrapClosures($value, $storage); } $property->setValue($data, $value); } } while ($reflection = $reflection->getParentClass()); } } /** * Gets the closure's reflector. * * @return \Laravel\SerializableClosure\Support\ReflectionClosure */ public function getReflector() { if ($this->reflector === null) { $this->code = null; $this->reflector = new ReflectionClosure($this->closure); } return $this->reflector; } /** * Internal method used to map closure pointers. * * @param mixed $data * @return void */ protected function mapPointers(&$data) { $scope = $this->scope; if ($data instanceof static) { $data = &$data->closure; } elseif (is_array($data)) { if (isset($data[self::ARRAY_RECURSIVE_KEY])) { return; } $data[self::ARRAY_RECURSIVE_KEY] = true; foreach ($data as $key => &$value) { if ($key === self::ARRAY_RECURSIVE_KEY) { continue; } elseif ($value instanceof static) { $data[$key] = &$value->closure; } elseif ($value instanceof SelfReference && $value->hash === $this->code['self']) { $data[$key] = &$this->closure; } else { $this->mapPointers($value); } } unset($value); unset($data[self::ARRAY_RECURSIVE_KEY]); } elseif ($data instanceof \stdClass) { if (isset($scope[$data])) { return; } $scope[$data] = true; foreach ($data as $key => &$value) { if ($value instanceof SelfReference && $value->hash === $this->code['self']) { $data->{$key} = &$this->closure; } elseif (is_array($value) || is_object($value)) { $this->mapPointers($value); } } unset($value); } elseif (is_object($data) && ! ($data instanceof Closure)) { if (isset($scope[$data])) { return; } $scope[$data] = true; $reflection = new ReflectionObject($data); do { if (! $reflection->isUserDefined()) { break; } foreach ($reflection->getProperties() as $property) { if ($property->isStatic() || ! $property->getDeclaringClass()->isUserDefined()) { continue; } $property->setAccessible(true); if (PHP_VERSION >= 7.4 && ! $property->isInitialized($data)) { continue; } if (PHP_VERSION >= 8.1 && $property->isReadOnly()) { continue; } $item = $property->getValue($data); if ($item instanceof SerializableClosure || $item instanceof UnsignedSerializableClosure || ($item instanceof SelfReference && $item->hash === $this->code['self'])) { $this->code['objects'][] = [ 'instance' => $data, 'property' => $property, 'object' => $item instanceof SelfReference ? $this : $item, ]; } elseif (is_array($item) || is_object($item)) { $this->mapPointers($item); $property->setValue($data, $item); } } } while ($reflection = $reflection->getParentClass()); } } /** * Internal method used to map closures by reference. * * @param mixed $data * @return void */ protected function mapByReference(&$data) { if ($data instanceof Closure) { if ($data === $this->closure) { $data = new SelfReference($this->reference); return; } if (isset($this->scope[$data])) { $data = $this->scope[$data]; return; } $instance = new static($data); $instance->scope = $this->scope; $data = $this->scope[$data] = $instance; } elseif (is_array($data)) { if (isset($data[self::ARRAY_RECURSIVE_KEY])) { return; } $data[self::ARRAY_RECURSIVE_KEY] = true; foreach ($data as $key => &$value) { if ($key === self::ARRAY_RECURSIVE_KEY) { continue; } $this->mapByReference($value); } unset($value); unset($data[self::ARRAY_RECURSIVE_KEY]); } elseif ($data instanceof \stdClass) { if (isset($this->scope[$data])) { $data = $this->scope[$data]; return; } $instance = $data; $this->scope[$instance] = $data = clone $data; foreach ($data as &$value) { $this->mapByReference($value); } unset($value); } elseif (is_object($data) && ! $data instanceof SerializableClosure && ! $data instanceof UnsignedSerializableClosure) { if (isset($this->scope[$data])) { $data = $this->scope[$data]; return; } $instance = $data; if ($data instanceof DateTimeInterface) { $this->scope[$instance] = $data; return; } if ($data instanceof UnitEnum) { $this->scope[$instance] = $data; return; } $reflection = new ReflectionObject($data); if (! $reflection->isUserDefined()) { $this->scope[$instance] = $data; return; } $this->scope[$instance] = $data = $reflection->newInstanceWithoutConstructor(); do { if (! $reflection->isUserDefined()) { break; } foreach ($reflection->getProperties() as $property) { if ($property->isStatic() || ! $property->getDeclaringClass()->isUserDefined()) { continue; } $property->setAccessible(true); if (PHP_VERSION >= 7.4 && ! $property->isInitialized($instance)) { continue; } if (PHP_VERSION >= 8.1 && $property->isReadOnly() && $property->class !== $reflection->name) { continue; } $value = $property->getValue($instance); if (is_array($value) || is_object($value)) { $this->mapByReference($value); } $property->setValue($data, $value); } } while ($reflection = $reflection->getParentClass()); } } } PK������AyZ<_.+ ��+ ����SerializableClosure.phpnu�W+A��������<?php namespace Laravel\SerializableClosure; use Closure; use Laravel\SerializableClosure\Exceptions\InvalidSignatureException; use Laravel\SerializableClosure\Exceptions\PhpVersionNotSupportedException; use Laravel\SerializableClosure\Serializers\Signed; use Laravel\SerializableClosure\Signers\Hmac; class SerializableClosure { /** * The closure's serializable. * * @var \Laravel\SerializableClosure\Contracts\Serializable */ protected $serializable; /** * Creates a new serializable closure instance. * * @param \Closure $closure * @return void */ public function __construct(Closure $closure) { if (\PHP_VERSION_ID < 70400) { throw new PhpVersionNotSupportedException(); } $this->serializable = Serializers\Signed::$signer ? new Serializers\Signed($closure) : new Serializers\Native($closure); } /** * Resolve the closure with the given arguments. * * @return mixed */ public function __invoke() { if (\PHP_VERSION_ID < 70400) { throw new PhpVersionNotSupportedException(); } return call_user_func_array($this->serializable, func_get_args()); } /** * Gets the closure. * * @return \Closure */ public function getClosure() { if (\PHP_VERSION_ID < 70400) { throw new PhpVersionNotSupportedException(); } return $this->serializable->getClosure(); } /** * Create a new unsigned serializable closure instance. * * @param Closure $closure * @return \Laravel\SerializableClosure\UnsignedSerializableClosure */ public static function unsigned(Closure $closure) { return new UnsignedSerializableClosure($closure); } /** * Sets the serializable closure secret key. * * @param string|null $secret * @return void */ public static function setSecretKey($secret) { Serializers\Signed::$signer = $secret ? new Hmac($secret) : null; } /** * Sets the serializable closure secret key. * * @param \Closure|null $transformer * @return void */ public static function transformUseVariablesUsing($transformer) { Serializers\Native::$transformUseVariables = $transformer; } /** * Sets the serializable closure secret key. * * @param \Closure|null $resolver * @return void */ public static function resolveUseVariablesUsing($resolver) { Serializers\Native::$resolveUseVariables = $resolver; } /** * Get the serializable representation of the closure. * * @return array */ public function __serialize() { return [ 'serializable' => $this->serializable, ]; } /** * Restore the closure after serialization. * * @param array $data * @return void * * @throws \Laravel\SerializableClosure\Exceptions\InvalidSignatureException */ public function __unserialize($data) { if (Signed::$signer && ! $data['serializable'] instanceof Signed) { throw new InvalidSignatureException(); } $this->serializable = $data['serializable']; } } PK������AyZh~������UnsignedSerializableClosure.phpnu�W+A��������<?php namespace Laravel\SerializableClosure; use Closure; use Laravel\SerializableClosure\Exceptions\PhpVersionNotSupportedException; class UnsignedSerializableClosure { /** * The closure's serializable. * * @var \Laravel\SerializableClosure\Contracts\Serializable */ protected $serializable; /** * Creates a new serializable closure instance. * * @param \Closure $closure * @return void */ public function __construct(Closure $closure) { if (\PHP_VERSION_ID < 70400) { throw new PhpVersionNotSupportedException(); } $this->serializable = new Serializers\Native($closure); } /** * Resolve the closure with the given arguments. * * @return mixed */ public function __invoke() { if (\PHP_VERSION_ID < 70400) { throw new PhpVersionNotSupportedException(); } return call_user_func_array($this->serializable, func_get_args()); } /** * Gets the closure. * * @return \Closure */ public function getClosure() { if (\PHP_VERSION_ID < 70400) { throw new PhpVersionNotSupportedException(); } return $this->serializable->getClosure(); } /** * Get the serializable representation of the closure. * * @return array */ public function __serialize() { return [ 'serializable' => $this->serializable, ]; } /** * Restore the closure after serialization. * * @param array $data * @return void */ public function __unserialize($data) { $this->serializable = $data['serializable']; } } PK������AyZf����(��Exceptions/MissingSecretKeyException.phpnu�W+A��������<?php namespace Laravel\SerializableClosure\Exceptions; use Exception; class MissingSecretKeyException extends Exception { /** * Create a new exception instance. * * @param string $message * @return void */ public function __construct($message = 'No serializable closure secret key has been specified.') { parent::__construct($message); } } PK������AyZ,����(��Exceptions/InvalidSignatureException.phpnu�W+A��������<?php namespace Laravel\SerializableClosure\Exceptions; use Exception; class InvalidSignatureException extends Exception { /** * Create a new exception instance. * * @param string $message * @return void */ public function __construct($message = 'Your serialized closure might have been modified or it\'s unsafe to be unserialized.') { parent::__construct($message); } } PK������AyZ*Kt��t��.��Exceptions/PhpVersionNotSupportedException.phpnu�W+A��������<?php namespace Laravel\SerializableClosure\Exceptions; use Exception; class PhpVersionNotSupportedException extends Exception { /** * Create a new exception instance. * * @param string $message * @return void */ public function __construct($message = 'PHP 7.3 is not supported.') { parent::__construct($message); } } PK������AyZt{QD1��1����Signers/Hmac.phpnu�W+A��������<?php namespace Laravel\SerializableClosure\Signers; use Laravel\SerializableClosure\Contracts\Signer; class Hmac implements Signer { /** * The secret key. * * @var string */ protected $secret; /** * Creates a new signer instance. * * @param string $secret * @return void */ public function __construct($secret) { $this->secret = $secret; } /** * Sign the given serializable. * * @param string $serialized * @return array */ public function sign($serialized) { return [ 'serializable' => $serialized, 'hash' => base64_encode(hash_hmac('sha256', $serialized, $this->secret, true)), ]; } /** * Verify the given signature. * * @param array $signature * @return bool */ public function verify($signature) { return hash_equals(base64_encode( hash_hmac('sha256', $signature['serializable'], $this->secret, true) ), $signature['hash']); } } PK������AyZwa��a����Contracts/Serializable.phpnu�W+A��������<?php namespace Laravel\SerializableClosure\Contracts; interface Serializable { /** * Resolve the closure with the given arguments. * * @return mixed */ public function __invoke(); /** * Gets the closure that got serialized/unserialized. * * @return \Closure */ public function getClosure(); } PK������AyZڜ������Contracts/Signer.phpnu�W+A��������<?php namespace Laravel\SerializableClosure\Contracts; interface Signer { /** * Sign the given serializable. * * @param string $serializable * @return array */ public function sign($serializable); /** * Verify the given signature. * * @param array $signature * @return bool */ public function verify($signature); } PK������Zu@��@����LazyOpenStream.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** * Lazily reads or writes to a file that is opened only after an IO operation * take place on the stream. */ final class LazyOpenStream implements StreamInterface { use StreamDecoratorTrait; /** @var string */ private $filename; /** @var string */ private $mode; /** * @var StreamInterface */ private $stream; /** * @param string $filename File to lazily open * @param string $mode fopen mode to use when opening the stream */ public function __construct(string $filename, string $mode) { $this->filename = $filename; $this->mode = $mode; // unsetting the property forces the first access to go through // __get(). unset($this->stream); } /** * Creates the underlying stream lazily when required. */ protected function createStream(): StreamInterface { return Utils::streamFor(Utils::tryFopen($this->filename, $this->mode)); } } PK������Z>l���� ��FnStream.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** * Compose stream implementations based on a hash of functions. * * Allows for easy testing and extension of a provided stream without needing * to create a concrete class for a simple extension point. */ #[\AllowDynamicProperties] final class FnStream implements StreamInterface { private const SLOTS = [ '__toString', 'close', 'detach', 'rewind', 'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write', 'isReadable', 'read', 'getContents', 'getMetadata' ]; /** @var array<string, callable> */ private $methods; /** * @param array<string, callable> $methods Hash of method name to a callable. */ public function __construct(array $methods) { $this->methods = $methods; // Create the functions on the class foreach ($methods as $name => $fn) { $this->{'_fn_' . $name} = $fn; } } /** * Lazily determine which methods are not implemented. * * @throws \BadMethodCallException */ public function __get(string $name): void { throw new \BadMethodCallException(str_replace('_fn_', '', $name) . '() is not implemented in the FnStream'); } /** * The close method is called on the underlying stream only if possible. */ public function __destruct() { if (isset($this->_fn_close)) { call_user_func($this->_fn_close); } } /** * An unserialize would allow the __destruct to run when the unserialized value goes out of scope. * * @throws \LogicException */ public function __wakeup(): void { throw new \LogicException('FnStream should never be unserialized'); } /** * Adds custom functionality to an underlying stream by intercepting * specific method calls. * * @param StreamInterface $stream Stream to decorate * @param array<string, callable> $methods Hash of method name to a closure * * @return FnStream */ public static function decorate(StreamInterface $stream, array $methods) { // If any of the required methods were not provided, then simply // proxy to the decorated stream. foreach (array_diff(self::SLOTS, array_keys($methods)) as $diff) { /** @var callable $callable */ $callable = [$stream, $diff]; $methods[$diff] = $callable; } return new self($methods); } public function __toString(): string { try { return call_user_func($this->_fn___toString); } catch (\Throwable $e) { if (\PHP_VERSION_ID >= 70400) { throw $e; } trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); return ''; } } public function close(): void { call_user_func($this->_fn_close); } public function detach() { return call_user_func($this->_fn_detach); } public function getSize(): ?int { return call_user_func($this->_fn_getSize); } public function tell(): int { return call_user_func($this->_fn_tell); } public function eof(): bool { return call_user_func($this->_fn_eof); } public function isSeekable(): bool { return call_user_func($this->_fn_isSeekable); } public function rewind(): void { call_user_func($this->_fn_rewind); } public function seek($offset, $whence = SEEK_SET): void { call_user_func($this->_fn_seek, $offset, $whence); } public function isWritable(): bool { return call_user_func($this->_fn_isWritable); } public function write($string): int { return call_user_func($this->_fn_write, $string); } public function isReadable(): bool { return call_user_func($this->_fn_isReadable); } public function read($length): string { return call_user_func($this->_fn_read, $length); } public function getContents(): string { return call_user_func($this->_fn_getContents); } /** * {@inheritdoc} * * @return mixed */ public function getMetadata($key = null) { return call_user_func($this->_fn_getMetadata, $key); } } PK������Z2zn��n����InflateStream.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** * Uses PHP's zlib.inflate filter to inflate zlib (HTTP deflate, RFC1950) or gzipped (RFC1952) content. * * This stream decorator converts the provided stream to a PHP stream resource, * then appends the zlib.inflate filter. The stream is then converted back * to a Guzzle stream resource to be used as a Guzzle stream. * * @link http://tools.ietf.org/html/rfc1950 * @link http://tools.ietf.org/html/rfc1952 * @link http://php.net/manual/en/filters.compression.php */ final class InflateStream implements StreamInterface { use StreamDecoratorTrait; /** @var StreamInterface */ private $stream; public function __construct(StreamInterface $stream) { $resource = StreamWrapper::getResource($stream); // Specify window=15+32, so zlib will use header detection to both gzip (with header) and zlib data // See http://www.zlib.net/manual.html#Advanced definition of inflateInit2 // "Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection" // Default window size is 15. stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ, ['window' => 15 + 32]); $this->stream = $stream->isSeekable() ? new Stream($resource) : new NoSeekStream(new Stream($resource)); } } PK������Z`(;���� ��Rfc7230.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; /** * @internal */ final class Rfc7230 { /** * Header related regular expressions (based on amphp/http package) * * Note: header delimiter (\r\n) is modified to \r?\n to accept line feed only delimiters for BC reasons. * * @link https://github.com/amphp/http/blob/v1.0.1/src/Rfc7230.php#L12-L15 * * @license https://github.com/amphp/http/blob/v1.0.1/LICENSE */ public const HEADER_REGEX = "(^([^()<>@,;:\\\"/[\]?={}\x01-\x20\x7F]++):[ \t]*+((?:[ \t]*+[\x21-\x7E\x80-\xFF]++)*+)[ \t]*+\r?\n)m"; public const HEADER_FOLD_REGEX = "(\r?\n[ \t]++)"; } PK������ZN|������#��Exception/MalformedUriException.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7\Exception; use InvalidArgumentException; /** * Exception thrown if a URI cannot be parsed because it's malformed. */ class MalformedUriException extends InvalidArgumentException { } PK������Zח���� ��Response.phpnu�W+A��������<?php /** * HTTP response class * * Contains a response from \WpOrg\Requests\Requests::request() * * @package Requests */ namespace WpOrg\Requests; use WpOrg\Requests\Cookie\Jar; use WpOrg\Requests\Exception; use WpOrg\Requests\Exception\Http; use WpOrg\Requests\Response\Headers; /** * HTTP response class * * Contains a response from \WpOrg\Requests\Requests::request() * * @package Requests */ class Response { /** * Response body * * @var string */ public $body = ''; /** * Raw HTTP data from the transport * * @var string */ public $raw = ''; /** * Headers, as an associative array * * @var \WpOrg\Requests\Response\Headers Array-like object representing headers */ public $headers = []; /** * Status code, false if non-blocking * * @var integer|boolean */ public $status_code = false; /** * Protocol version, false if non-blocking * * @var float|boolean */ public $protocol_version = false; /** * Whether the request succeeded or not * * @var boolean */ public $success = false; /** * Number of redirects the request used * * @var integer */ public $redirects = 0; /** * URL requested * * @var string */ public $url = ''; /** * Previous requests (from redirects) * * @var array Array of \WpOrg\Requests\Response objects */ public $history = []; /** * Cookies from the request * * @var \WpOrg\Requests\Cookie\Jar Array-like object representing a cookie jar */ public $cookies = []; /** * Constructor */ public function __construct() { $this->headers = new Headers(); $this->cookies = new Jar(); } /** * Is the response a redirect? * * @return boolean True if redirect (3xx status), false if not. */ public function is_redirect() { $code = $this->status_code; return in_array($code, [300, 301, 302, 303, 307], true) || $code > 307 && $code < 400; } /** * Throws an exception if the request was not successful * * @param boolean $allow_redirects Set to false to throw on a 3xx as well * * @throws \WpOrg\Requests\Exception If `$allow_redirects` is false, and code is 3xx (`response.no_redirects`) * @throws \WpOrg\Requests\Exception\Http On non-successful status code. Exception class corresponds to "Status" + code (e.g. {@see \WpOrg\Requests\Exception\Http\Status404}) */ public function throw_for_status($allow_redirects = true) { if ($this->is_redirect()) { if ($allow_redirects !== true) { throw new Exception('Redirection not allowed', 'response.no_redirects', $this); } } elseif (!$this->success) { $exception = Http::get_class($this->status_code); throw new $exception(null, $this); } } /** * JSON decode the response body. * * The method parameters are the same as those for the PHP native `json_decode()` function. * * @link https://php.net/json-decode * * @param bool|null $associative Optional. When `true`, JSON objects will be returned as associative arrays; * When `false`, JSON objects will be returned as objects. * When `null`, JSON objects will be returned as associative arrays * or objects depending on whether `JSON_OBJECT_AS_ARRAY` is set in the flags. * Defaults to `true` (in contrast to the PHP native default of `null`). * @param int $depth Optional. Maximum nesting depth of the structure being decoded. * Defaults to `512`. * @param int $options Optional. Bitmask of JSON_BIGINT_AS_STRING, JSON_INVALID_UTF8_IGNORE, * JSON_INVALID_UTF8_SUBSTITUTE, JSON_OBJECT_AS_ARRAY, JSON_THROW_ON_ERROR. * Defaults to `0` (no options set). * * @return array * * @throws \WpOrg\Requests\Exception If `$this->body` is not valid json. */ public function decode_body($associative = true, $depth = 512, $options = 0) { $data = json_decode($this->body, $associative, $depth, $options); if (json_last_error() !== JSON_ERROR_NONE) { $last_error = json_last_error_msg(); throw new Exception('Unable to parse JSON data: ' . $last_error, 'response.invalid', $this); } return $data; } } PK������ZPM �� ����StreamDecoratorTrait.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** * Stream decorator trait * * @property StreamInterface $stream */ trait StreamDecoratorTrait { /** * @param StreamInterface $stream Stream to decorate */ public function __construct(StreamInterface $stream) { $this->stream = $stream; } /** * Magic method used to create a new stream if streams are not added in * the constructor of a decorator (e.g., LazyOpenStream). * * @return StreamInterface */ public function __get(string $name) { if ($name === 'stream') { $this->stream = $this->createStream(); return $this->stream; } throw new \UnexpectedValueException("$name not found on class"); } public function __toString(): string { try { if ($this->isSeekable()) { $this->seek(0); } return $this->getContents(); } catch (\Throwable $e) { if (\PHP_VERSION_ID >= 70400) { throw $e; } trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); return ''; } } public function getContents(): string { return Utils::copyToString($this); } /** * Allow decorators to implement custom methods * * @return mixed */ public function __call(string $method, array $args) { /** @var callable $callable */ $callable = [$this->stream, $method]; $result = call_user_func_array($callable, $args); // Always return the wrapped object if the result is a return $this return $result === $this->stream ? $this : $result; } public function close(): void { $this->stream->close(); } /** * {@inheritdoc} * * @return mixed */ public function getMetadata($key = null) { return $this->stream->getMetadata($key); } public function detach() { return $this->stream->detach(); } public function getSize(): ?int { return $this->stream->getSize(); } public function eof(): bool { return $this->stream->eof(); } public function tell(): int { return $this->stream->tell(); } public function isReadable(): bool { return $this->stream->isReadable(); } public function isWritable(): bool { return $this->stream->isWritable(); } public function isSeekable(): bool { return $this->stream->isSeekable(); } public function rewind(): void { $this->seek(0); } public function seek($offset, $whence = SEEK_SET): void { $this->stream->seek($offset, $whence); } public function read($length): string { return $this->stream->read($length); } public function write($string): int { return $this->stream->write($string); } /** * Implement in subclasses to dynamically create streams when requested. * * @throws \BadMethodCallException */ protected function createStream(): StreamInterface { throw new \BadMethodCallException('Not implemented'); } } PK������Z⣲pU��pU����Uri.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use GuzzleHttp\Psr7\Exception\MalformedUriException; use Psr\Http\Message\UriInterface; /** * PSR-7 URI implementation. * * @author Michael Dowling * @author Tobias Schultze * @author Matthew Weier O'Phinney */ class Uri implements UriInterface, \JsonSerializable { /** * Absolute http and https URIs require a host per RFC 7230 Section 2.7 * but in generic URIs the host can be empty. So for http(s) URIs * we apply this default host when no host is given yet to form a * valid URI. */ private const HTTP_DEFAULT_HOST = 'localhost'; private const DEFAULT_PORTS = [ 'http' => 80, 'https' => 443, 'ftp' => 21, 'gopher' => 70, 'nntp' => 119, 'news' => 119, 'telnet' => 23, 'tn3270' => 23, 'imap' => 143, 'pop' => 110, 'ldap' => 389, ]; /** * Unreserved characters for use in a regex. * * @link https://tools.ietf.org/html/rfc3986#section-2.3 */ private const CHAR_UNRESERVED = 'a-zA-Z0-9_\-\.~'; /** * Sub-delims for use in a regex. * * @link https://tools.ietf.org/html/rfc3986#section-2.2 */ private const CHAR_SUB_DELIMS = '!\$&\'\(\)\*\+,;='; private const QUERY_SEPARATORS_REPLACEMENT = ['=' => '%3D', '&' => '%26']; /** @var string Uri scheme. */ private $scheme = ''; /** @var string Uri user info. */ private $userInfo = ''; /** @var string Uri host. */ private $host = ''; /** @var int|null Uri port. */ private $port; /** @var string Uri path. */ private $path = ''; /** @var string Uri query string. */ private $query = ''; /** @var string Uri fragment. */ private $fragment = ''; /** @var string|null String representation */ private $composedComponents; public function __construct(string $uri = '') { if ($uri !== '') { $parts = self::parse($uri); if ($parts === false) { throw new MalformedUriException("Unable to parse URI: $uri"); } $this->applyParts($parts); } } /** * UTF-8 aware \parse_url() replacement. * * The internal function produces broken output for non ASCII domain names * (IDN) when used with locales other than "C". * * On the other hand, cURL understands IDN correctly only when UTF-8 locale * is configured ("C.UTF-8", "en_US.UTF-8", etc.). * * @see https://bugs.php.net/bug.php?id=52923 * @see https://www.php.net/manual/en/function.parse-url.php#114817 * @see https://curl.haxx.se/libcurl/c/CURLOPT_URL.html#ENCODING * * @return array|false */ private static function parse(string $url) { // If IPv6 $prefix = ''; if (preg_match('%^(.*://\[[0-9:a-f]+\])(.*?)$%', $url, $matches)) { /** @var array{0:string, 1:string, 2:string} $matches */ $prefix = $matches[1]; $url = $matches[2]; } /** @var string */ $encodedUrl = preg_replace_callback( '%[^:/@?&=#]+%usD', static function ($matches) { return urlencode($matches[0]); }, $url ); $result = parse_url($prefix . $encodedUrl); if ($result === false) { return false; } return array_map('urldecode', $result); } public function __toString(): string { if ($this->composedComponents === null) { $this->composedComponents = self::composeComponents( $this->scheme, $this->getAuthority(), $this->path, $this->query, $this->fragment ); } return $this->composedComponents; } /** * Composes a URI reference string from its various components. * * Usually this method does not need to be called manually but instead is used indirectly via * `Psr\Http\Message\UriInterface::__toString`. * * PSR-7 UriInterface treats an empty component the same as a missing component as * getQuery(), getFragment() etc. always return a string. This explains the slight * difference to RFC 3986 Section 5.3. * * Another adjustment is that the authority separator is added even when the authority is missing/empty * for the "file" scheme. This is because PHP stream functions like `file_get_contents` only work with * `file:///myfile` but not with `file:/myfile` although they are equivalent according to RFC 3986. But * `file:///` is the more common syntax for the file scheme anyway (Chrome for example redirects to * that format). * * @link https://tools.ietf.org/html/rfc3986#section-5.3 */ public static function composeComponents(?string $scheme, ?string $authority, string $path, ?string $query, ?string $fragment): string { $uri = ''; // weak type checks to also accept null until we can add scalar type hints if ($scheme != '') { $uri .= $scheme . ':'; } if ($authority != '' || $scheme === 'file') { $uri .= '//' . $authority; } if ($authority != '' && $path != '' && $path[0] != '/') { $path = '/' . $path; } $uri .= $path; if ($query != '') { $uri .= '?' . $query; } if ($fragment != '') { $uri .= '#' . $fragment; } return $uri; } /** * Whether the URI has the default port of the current scheme. * * `Psr\Http\Message\UriInterface::getPort` may return null or the standard port. This method can be used * independently of the implementation. */ public static function isDefaultPort(UriInterface $uri): bool { return $uri->getPort() === null || (isset(self::DEFAULT_PORTS[$uri->getScheme()]) && $uri->getPort() === self::DEFAULT_PORTS[$uri->getScheme()]); } /** * Whether the URI is absolute, i.e. it has a scheme. * * An instance of UriInterface can either be an absolute URI or a relative reference. This method returns true * if it is the former. An absolute URI has a scheme. A relative reference is used to express a URI relative * to another URI, the base URI. Relative references can be divided into several forms: * - network-path references, e.g. '//example.com/path' * - absolute-path references, e.g. '/path' * - relative-path references, e.g. 'subpath' * * @see Uri::isNetworkPathReference * @see Uri::isAbsolutePathReference * @see Uri::isRelativePathReference * @link https://tools.ietf.org/html/rfc3986#section-4 */ public static function isAbsolute(UriInterface $uri): bool { return $uri->getScheme() !== ''; } /** * Whether the URI is a network-path reference. * * A relative reference that begins with two slash characters is termed an network-path reference. * * @link https://tools.ietf.org/html/rfc3986#section-4.2 */ public static function isNetworkPathReference(UriInterface $uri): bool { return $uri->getScheme() === '' && $uri->getAuthority() !== ''; } /** * Whether the URI is a absolute-path reference. * * A relative reference that begins with a single slash character is termed an absolute-path reference. * * @link https://tools.ietf.org/html/rfc3986#section-4.2 */ public static function isAbsolutePathReference(UriInterface $uri): bool { return $uri->getScheme() === '' && $uri->getAuthority() === '' && isset($uri->getPath()[0]) && $uri->getPath()[0] === '/'; } /** * Whether the URI is a relative-path reference. * * A relative reference that does not begin with a slash character is termed a relative-path reference. * * @link https://tools.ietf.org/html/rfc3986#section-4.2 */ public static function isRelativePathReference(UriInterface $uri): bool { return $uri->getScheme() === '' && $uri->getAuthority() === '' && (!isset($uri->getPath()[0]) || $uri->getPath()[0] !== '/'); } /** * Whether the URI is a same-document reference. * * A same-document reference refers to a URI that is, aside from its fragment * component, identical to the base URI. When no base URI is given, only an empty * URI reference (apart from its fragment) is considered a same-document reference. * * @param UriInterface $uri The URI to check * @param UriInterface|null $base An optional base URI to compare against * * @link https://tools.ietf.org/html/rfc3986#section-4.4 */ public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null): bool { if ($base !== null) { $uri = UriResolver::resolve($base, $uri); return ($uri->getScheme() === $base->getScheme()) && ($uri->getAuthority() === $base->getAuthority()) && ($uri->getPath() === $base->getPath()) && ($uri->getQuery() === $base->getQuery()); } return $uri->getScheme() === '' && $uri->getAuthority() === '' && $uri->getPath() === '' && $uri->getQuery() === ''; } /** * Creates a new URI with a specific query string value removed. * * Any existing query string values that exactly match the provided key are * removed. * * @param UriInterface $uri URI to use as a base. * @param string $key Query string key to remove. */ public static function withoutQueryValue(UriInterface $uri, string $key): UriInterface { $result = self::getFilteredQueryString($uri, [$key]); return $uri->withQuery(implode('&', $result)); } /** * Creates a new URI with a specific query string value. * * Any existing query string values that exactly match the provided key are * removed and replaced with the given key value pair. * * A value of null will set the query string key without a value, e.g. "key" * instead of "key=value". * * @param UriInterface $uri URI to use as a base. * @param string $key Key to set. * @param string|null $value Value to set */ public static function withQueryValue(UriInterface $uri, string $key, ?string $value): UriInterface { $result = self::getFilteredQueryString($uri, [$key]); $result[] = self::generateQueryString($key, $value); return $uri->withQuery(implode('&', $result)); } /** * Creates a new URI with multiple specific query string values. * * It has the same behavior as withQueryValue() but for an associative array of key => value. * * @param UriInterface $uri URI to use as a base. * @param array<string, string|null> $keyValueArray Associative array of key and values */ public static function withQueryValues(UriInterface $uri, array $keyValueArray): UriInterface { $result = self::getFilteredQueryString($uri, array_keys($keyValueArray)); foreach ($keyValueArray as $key => $value) { $result[] = self::generateQueryString((string) $key, $value !== null ? (string) $value : null); } return $uri->withQuery(implode('&', $result)); } /** * Creates a URI from a hash of `parse_url` components. * * @link http://php.net/manual/en/function.parse-url.php * * @throws MalformedUriException If the components do not form a valid URI. */ public static function fromParts(array $parts): UriInterface { $uri = new self(); $uri->applyParts($parts); $uri->validateState(); return $uri; } public function getScheme(): string { return $this->scheme; } public function getAuthority(): string { $authority = $this->host; if ($this->userInfo !== '') { $authority = $this->userInfo . '@' . $authority; } if ($this->port !== null) { $authority .= ':' . $this->port; } return $authority; } public function getUserInfo(): string { return $this->userInfo; } public function getHost(): string { return $this->host; } public function getPort(): ?int { return $this->port; } public function getPath(): string { return $this->path; } public function getQuery(): string { return $this->query; } public function getFragment(): string { return $this->fragment; } public function withScheme($scheme): UriInterface { $scheme = $this->filterScheme($scheme); if ($this->scheme === $scheme) { return $this; } $new = clone $this; $new->scheme = $scheme; $new->composedComponents = null; $new->removeDefaultPort(); $new->validateState(); return $new; } public function withUserInfo($user, $password = null): UriInterface { $info = $this->filterUserInfoComponent($user); if ($password !== null) { $info .= ':' . $this->filterUserInfoComponent($password); } if ($this->userInfo === $info) { return $this; } $new = clone $this; $new->userInfo = $info; $new->composedComponents = null; $new->validateState(); return $new; } public function withHost($host): UriInterface { $host = $this->filterHost($host); if ($this->host === $host) { return $this; } $new = clone $this; $new->host = $host; $new->composedComponents = null; $new->validateState(); return $new; } public function withPort($port): UriInterface { $port = $this->filterPort($port); if ($this->port === $port) { return $this; } $new = clone $this; $new->port = $port; $new->composedComponents = null; $new->removeDefaultPort(); $new->validateState(); return $new; } public function withPath($path): UriInterface { $path = $this->filterPath($path); if ($this->path === $path) { return $this; } $new = clone $this; $new->path = $path; $new->composedComponents = null; $new->validateState(); return $new; } public function withQuery($query): UriInterface { $query = $this->filterQueryAndFragment($query); if ($this->query === $query) { return $this; } $new = clone $this; $new->query = $query; $new->composedComponents = null; return $new; } public function withFragment($fragment): UriInterface { $fragment = $this->filterQueryAndFragment($fragment); if ($this->fragment === $fragment) { return $this; } $new = clone $this; $new->fragment = $fragment; $new->composedComponents = null; return $new; } public function jsonSerialize(): string { return $this->__toString(); } /** * Apply parse_url parts to a URI. * * @param array $parts Array of parse_url parts to apply. */ private function applyParts(array $parts): void { $this->scheme = isset($parts['scheme']) ? $this->filterScheme($parts['scheme']) : ''; $this->userInfo = isset($parts['user']) ? $this->filterUserInfoComponent($parts['user']) : ''; $this->host = isset($parts['host']) ? $this->filterHost($parts['host']) : ''; $this->port = isset($parts['port']) ? $this->filterPort($parts['port']) : null; $this->path = isset($parts['path']) ? $this->filterPath($parts['path']) : ''; $this->query = isset($parts['query']) ? $this->filterQueryAndFragment($parts['query']) : ''; $this->fragment = isset($parts['fragment']) ? $this->filterQueryAndFragment($parts['fragment']) : ''; if (isset($parts['pass'])) { $this->userInfo .= ':' . $this->filterUserInfoComponent($parts['pass']); } $this->removeDefaultPort(); } /** * @param mixed $scheme * * @throws \InvalidArgumentException If the scheme is invalid. */ private function filterScheme($scheme): string { if (!is_string($scheme)) { throw new \InvalidArgumentException('Scheme must be a string'); } return \strtr($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); } /** * @param mixed $component * * @throws \InvalidArgumentException If the user info is invalid. */ private function filterUserInfoComponent($component): string { if (!is_string($component)) { throw new \InvalidArgumentException('User info must be a string'); } return preg_replace_callback( '/(?:[^%' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . ']+|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $component ); } /** * @param mixed $host * * @throws \InvalidArgumentException If the host is invalid. */ private function filterHost($host): string { if (!is_string($host)) { throw new \InvalidArgumentException('Host must be a string'); } return \strtr($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); } /** * @param mixed $port * * @throws \InvalidArgumentException If the port is invalid. */ private function filterPort($port): ?int { if ($port === null) { return null; } $port = (int) $port; if (0 > $port || 0xffff < $port) { throw new \InvalidArgumentException( sprintf('Invalid port: %d. Must be between 0 and 65535', $port) ); } return $port; } /** * @param string[] $keys * * @return string[] */ private static function getFilteredQueryString(UriInterface $uri, array $keys): array { $current = $uri->getQuery(); if ($current === '') { return []; } $decodedKeys = array_map('rawurldecode', $keys); return array_filter(explode('&', $current), function ($part) use ($decodedKeys) { return !in_array(rawurldecode(explode('=', $part)[0]), $decodedKeys, true); }); } private static function generateQueryString(string $key, ?string $value): string { // Query string separators ("=", "&") within the key or value need to be encoded // (while preventing double-encoding) before setting the query string. All other // chars that need percent-encoding will be encoded by withQuery(). $queryString = strtr($key, self::QUERY_SEPARATORS_REPLACEMENT); if ($value !== null) { $queryString .= '=' . strtr($value, self::QUERY_SEPARATORS_REPLACEMENT); } return $queryString; } private function removeDefaultPort(): void { if ($this->port !== null && self::isDefaultPort($this)) { $this->port = null; } } /** * Filters the path of a URI * * @param mixed $path * * @throws \InvalidArgumentException If the path is invalid. */ private function filterPath($path): string { if (!is_string($path)) { throw new \InvalidArgumentException('Path must be a string'); } return preg_replace_callback( '/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\/]++|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $path ); } /** * Filters the query string or fragment of a URI. * * @param mixed $str * * @throws \InvalidArgumentException If the query or fragment is invalid. */ private function filterQueryAndFragment($str): string { if (!is_string($str)) { throw new \InvalidArgumentException('Query and fragment must be a string'); } return preg_replace_callback( '/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\/\?]++|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $str ); } private function rawurlencodeMatchZero(array $match): string { return rawurlencode($match[0]); } private function validateState(): void { if ($this->host === '' && ($this->scheme === 'http' || $this->scheme === 'https')) { $this->host = self::HTTP_DEFAULT_HOST; } if ($this->getAuthority() === '') { if (0 === strpos($this->path, '//')) { throw new MalformedUriException('The path of a URI without an authority must not start with two slashes "//"'); } if ($this->scheme === '' && false !== strpos(explode('/', $this->path, 2)[0], ':')) { throw new MalformedUriException('A relative URI must not have a path beginning with a segment containing a colon'); } } } } PK������ZŜ ~��~����UriComparator.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\UriInterface; /** * Provides methods to determine if a modified URL should be considered cross-origin. * * @author Graham Campbell */ final class UriComparator { /** * Determines if a modified URL should be considered cross-origin with * respect to an original URL. */ public static function isCrossOrigin(UriInterface $original, UriInterface $modified): bool { if (\strcasecmp($original->getHost(), $modified->getHost()) !== 0) { return true; } if ($original->getScheme() !== $modified->getScheme()) { return true; } if (self::computePort($original) !== self::computePort($modified)) { return true; } return false; } private static function computePort(UriInterface $uri): int { $port = $uri->getPort(); if (null !== $port) { return $port; } return 'https' === $uri->getScheme() ? 443 : 80; } private function __construct() { // cannot be instantiated } } PK������Z%��%����ServerRequest.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use InvalidArgumentException; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\StreamInterface; use Psr\Http\Message\UploadedFileInterface; use Psr\Http\Message\UriInterface; /** * Server-side HTTP request * * Extends the Request definition to add methods for accessing incoming data, * specifically server parameters, cookies, matched path parameters, query * string arguments, body parameters, and upload file information. * * "Attributes" are discovered via decomposing the request (and usually * specifically the URI path), and typically will be injected by the application. * * Requests are considered immutable; all methods that might change state are * implemented such that they retain the internal state of the current * message and return a new instance that contains the changed state. */ class ServerRequest extends Request implements ServerRequestInterface { /** * @var array */ private $attributes = []; /** * @var array */ private $cookieParams = []; /** * @var array|object|null */ private $parsedBody; /** * @var array */ private $queryParams = []; /** * @var array */ private $serverParams; /** * @var array */ private $uploadedFiles = []; /** * @param string $method HTTP method * @param string|UriInterface $uri URI * @param array<string, string|string[]> $headers Request headers * @param string|resource|StreamInterface|null $body Request body * @param string $version Protocol version * @param array $serverParams Typically the $_SERVER superglobal */ public function __construct( string $method, $uri, array $headers = [], $body = null, string $version = '1.1', array $serverParams = [] ) { $this->serverParams = $serverParams; parent::__construct($method, $uri, $headers, $body, $version); } /** * Return an UploadedFile instance array. * * @param array $files An array which respect $_FILES structure * * @throws InvalidArgumentException for unrecognized values */ public static function normalizeFiles(array $files): array { $normalized = []; foreach ($files as $key => $value) { if ($value instanceof UploadedFileInterface) { $normalized[$key] = $value; } elseif (is_array($value) && isset($value['tmp_name'])) { $normalized[$key] = self::createUploadedFileFromSpec($value); } elseif (is_array($value)) { $normalized[$key] = self::normalizeFiles($value); continue; } else { throw new InvalidArgumentException('Invalid value in files specification'); } } return $normalized; } /** * Create and return an UploadedFile instance from a $_FILES specification. * * If the specification represents an array of values, this method will * delegate to normalizeNestedFileSpec() and return that return value. * * @param array $value $_FILES struct * * @return UploadedFileInterface|UploadedFileInterface[] */ private static function createUploadedFileFromSpec(array $value) { if (is_array($value['tmp_name'])) { return self::normalizeNestedFileSpec($value); } return new UploadedFile( $value['tmp_name'], (int) $value['size'], (int) $value['error'], $value['name'], $value['type'] ); } /** * Normalize an array of file specifications. * * Loops through all nested files and returns a normalized array of * UploadedFileInterface instances. * * @return UploadedFileInterface[] */ private static function normalizeNestedFileSpec(array $files = []): array { $normalizedFiles = []; foreach (array_keys($files['tmp_name']) as $key) { $spec = [ 'tmp_name' => $files['tmp_name'][$key], 'size' => $files['size'][$key] ?? null, 'error' => $files['error'][$key] ?? null, 'name' => $files['name'][$key] ?? null, 'type' => $files['type'][$key] ?? null, ]; $normalizedFiles[$key] = self::createUploadedFileFromSpec($spec); } return $normalizedFiles; } /** * Return a ServerRequest populated with superglobals: * $_GET * $_POST * $_COOKIE * $_FILES * $_SERVER */ public static function fromGlobals(): ServerRequestInterface { $method = $_SERVER['REQUEST_METHOD'] ?? 'GET'; $headers = getallheaders(); $uri = self::getUriFromGlobals(); $body = new CachingStream(new LazyOpenStream('php://input', 'r+')); $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1'; $serverRequest = new ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER); return $serverRequest ->withCookieParams($_COOKIE) ->withQueryParams($_GET) ->withParsedBody($_POST) ->withUploadedFiles(self::normalizeFiles($_FILES)); } private static function extractHostAndPortFromAuthority(string $authority): array { $uri = 'http://' . $authority; $parts = parse_url($uri); if (false === $parts) { return [null, null]; } $host = $parts['host'] ?? null; $port = $parts['port'] ?? null; return [$host, $port]; } /** * Get a Uri populated with values from $_SERVER. */ public static function getUriFromGlobals(): UriInterface { $uri = new Uri(''); $uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http'); $hasPort = false; if (isset($_SERVER['HTTP_HOST'])) { [$host, $port] = self::extractHostAndPortFromAuthority($_SERVER['HTTP_HOST']); if ($host !== null) { $uri = $uri->withHost($host); } if ($port !== null) { $hasPort = true; $uri = $uri->withPort($port); } } elseif (isset($_SERVER['SERVER_NAME'])) { $uri = $uri->withHost($_SERVER['SERVER_NAME']); } elseif (isset($_SERVER['SERVER_ADDR'])) { $uri = $uri->withHost($_SERVER['SERVER_ADDR']); } if (!$hasPort && isset($_SERVER['SERVER_PORT'])) { $uri = $uri->withPort($_SERVER['SERVER_PORT']); } $hasQuery = false; if (isset($_SERVER['REQUEST_URI'])) { $requestUriParts = explode('?', $_SERVER['REQUEST_URI'], 2); $uri = $uri->withPath($requestUriParts[0]); if (isset($requestUriParts[1])) { $hasQuery = true; $uri = $uri->withQuery($requestUriParts[1]); } } if (!$hasQuery && isset($_SERVER['QUERY_STRING'])) { $uri = $uri->withQuery($_SERVER['QUERY_STRING']); } return $uri; } public function getServerParams(): array { return $this->serverParams; } public function getUploadedFiles(): array { return $this->uploadedFiles; } public function withUploadedFiles(array $uploadedFiles): ServerRequestInterface { $new = clone $this; $new->uploadedFiles = $uploadedFiles; return $new; } public function getCookieParams(): array { return $this->cookieParams; } public function withCookieParams(array $cookies): ServerRequestInterface { $new = clone $this; $new->cookieParams = $cookies; return $new; } public function getQueryParams(): array { return $this->queryParams; } public function withQueryParams(array $query): ServerRequestInterface { $new = clone $this; $new->queryParams = $query; return $new; } /** * {@inheritdoc} * * @return array|object|null */ public function getParsedBody() { return $this->parsedBody; } public function withParsedBody($data): ServerRequestInterface { $new = clone $this; $new->parsedBody = $data; return $new; } public function getAttributes(): array { return $this->attributes; } /** * {@inheritdoc} * * @return mixed */ public function getAttribute($attribute, $default = null) { if (false === array_key_exists($attribute, $this->attributes)) { return $default; } return $this->attributes[$attribute]; } public function withAttribute($attribute, $value): ServerRequestInterface { $new = clone $this; $new->attributes[$attribute] = $value; return $new; } public function withoutAttribute($attribute): ServerRequestInterface { if (false === array_key_exists($attribute, $this->attributes)) { return $this; } $new = clone $this; unset($new->attributes[$attribute]); return $new; } } PK������Zq: t������DroppingStream.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** * Stream decorator that begins dropping data once the size of the underlying * stream becomes too full. */ final class DroppingStream implements StreamInterface { use StreamDecoratorTrait; /** @var int */ private $maxLength; /** @var StreamInterface */ private $stream; /** * @param StreamInterface $stream Underlying stream to decorate. * @param int $maxLength Maximum size before dropping data. */ public function __construct(StreamInterface $stream, int $maxLength) { $this->stream = $stream; $this->maxLength = $maxLength; } public function write($string): int { $diff = $this->maxLength - $this->stream->getSize(); // Begin returning 0 when the underlying stream is too large. if ($diff <= 0) { return 0; } // Write the stream or a subset of the stream if needed. if (strlen($string) < $diff) { return $this->stream->write($string); } return $this->stream->write(substr($string, 0, $diff)); } } PK������Z;������UploadedFile.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use InvalidArgumentException; use Psr\Http\Message\StreamInterface; use Psr\Http\Message\UploadedFileInterface; use RuntimeException; class UploadedFile implements UploadedFileInterface { private const ERRORS = [ UPLOAD_ERR_OK, UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE, UPLOAD_ERR_PARTIAL, UPLOAD_ERR_NO_FILE, UPLOAD_ERR_NO_TMP_DIR, UPLOAD_ERR_CANT_WRITE, UPLOAD_ERR_EXTENSION, ]; /** * @var string|null */ private $clientFilename; /** * @var string|null */ private $clientMediaType; /** * @var int */ private $error; /** * @var string|null */ private $file; /** * @var bool */ private $moved = false; /** * @var int|null */ private $size; /** * @var StreamInterface|null */ private $stream; /** * @param StreamInterface|string|resource $streamOrFile */ public function __construct( $streamOrFile, ?int $size, int $errorStatus, string $clientFilename = null, string $clientMediaType = null ) { $this->setError($errorStatus); $this->size = $size; $this->clientFilename = $clientFilename; $this->clientMediaType = $clientMediaType; if ($this->isOk()) { $this->setStreamOrFile($streamOrFile); } } /** * Depending on the value set file or stream variable * * @param StreamInterface|string|resource $streamOrFile * * @throws InvalidArgumentException */ private function setStreamOrFile($streamOrFile): void { if (is_string($streamOrFile)) { $this->file = $streamOrFile; } elseif (is_resource($streamOrFile)) { $this->stream = new Stream($streamOrFile); } elseif ($streamOrFile instanceof StreamInterface) { $this->stream = $streamOrFile; } else { throw new InvalidArgumentException( 'Invalid stream or file provided for UploadedFile' ); } } /** * @throws InvalidArgumentException */ private function setError(int $error): void { if (false === in_array($error, UploadedFile::ERRORS, true)) { throw new InvalidArgumentException( 'Invalid error status for UploadedFile' ); } $this->error = $error; } private function isStringNotEmpty($param): bool { return is_string($param) && false === empty($param); } /** * Return true if there is no upload error */ private function isOk(): bool { return $this->error === UPLOAD_ERR_OK; } public function isMoved(): bool { return $this->moved; } /** * @throws RuntimeException if is moved or not ok */ private function validateActive(): void { if (false === $this->isOk()) { throw new RuntimeException('Cannot retrieve stream due to upload error'); } if ($this->isMoved()) { throw new RuntimeException('Cannot retrieve stream after it has already been moved'); } } public function getStream(): StreamInterface { $this->validateActive(); if ($this->stream instanceof StreamInterface) { return $this->stream; } /** @var string $file */ $file = $this->file; return new LazyOpenStream($file, 'r+'); } public function moveTo($targetPath): void { $this->validateActive(); if (false === $this->isStringNotEmpty($targetPath)) { throw new InvalidArgumentException( 'Invalid path provided for move operation; must be a non-empty string' ); } if ($this->file) { $this->moved = PHP_SAPI === 'cli' ? rename($this->file, $targetPath) : move_uploaded_file($this->file, $targetPath); } else { Utils::copyToStream( $this->getStream(), new LazyOpenStream($targetPath, 'w') ); $this->moved = true; } if (false === $this->moved) { throw new RuntimeException( sprintf('Uploaded file could not be moved to %s', $targetPath) ); } } public function getSize(): ?int { return $this->size; } public function getError(): int { return $this->error; } public function getClientFilename(): ?string { return $this->clientFilename; } public function getClientMediaType(): ?string { return $this->clientMediaType; } } PK������Z������CachingStream.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** * Stream decorator that can cache previously read bytes from a sequentially * read stream. */ final class CachingStream implements StreamInterface { use StreamDecoratorTrait; /** @var StreamInterface Stream being wrapped */ private $remoteStream; /** @var int Number of bytes to skip reading due to a write on the buffer */ private $skipReadBytes = 0; /** * @var StreamInterface */ private $stream; /** * We will treat the buffer object as the body of the stream * * @param StreamInterface $stream Stream to cache. The cursor is assumed to be at the beginning of the stream. * @param StreamInterface $target Optionally specify where data is cached */ public function __construct( StreamInterface $stream, StreamInterface $target = null ) { $this->remoteStream = $stream; $this->stream = $target ?: new Stream(Utils::tryFopen('php://temp', 'r+')); } public function getSize(): ?int { $remoteSize = $this->remoteStream->getSize(); if (null === $remoteSize) { return null; } return max($this->stream->getSize(), $remoteSize); } public function rewind(): void { $this->seek(0); } public function seek($offset, $whence = SEEK_SET): void { if ($whence === SEEK_SET) { $byte = $offset; } elseif ($whence === SEEK_CUR) { $byte = $offset + $this->tell(); } elseif ($whence === SEEK_END) { $size = $this->remoteStream->getSize(); if ($size === null) { $size = $this->cacheEntireStream(); } $byte = $size + $offset; } else { throw new \InvalidArgumentException('Invalid whence'); } $diff = $byte - $this->stream->getSize(); if ($diff > 0) { // Read the remoteStream until we have read in at least the amount // of bytes requested, or we reach the end of the file. while ($diff > 0 && !$this->remoteStream->eof()) { $this->read($diff); $diff = $byte - $this->stream->getSize(); } } else { // We can just do a normal seek since we've already seen this byte. $this->stream->seek($byte); } } public function read($length): string { // Perform a regular read on any previously read data from the buffer $data = $this->stream->read($length); $remaining = $length - strlen($data); // More data was requested so read from the remote stream if ($remaining) { // If data was written to the buffer in a position that would have // been filled from the remote stream, then we must skip bytes on // the remote stream to emulate overwriting bytes from that // position. This mimics the behavior of other PHP stream wrappers. $remoteData = $this->remoteStream->read( $remaining + $this->skipReadBytes ); if ($this->skipReadBytes) { $len = strlen($remoteData); $remoteData = substr($remoteData, $this->skipReadBytes); $this->skipReadBytes = max(0, $this->skipReadBytes - $len); } $data .= $remoteData; $this->stream->write($remoteData); } return $data; } public function write($string): int { // When appending to the end of the currently read stream, you'll want // to skip bytes from being read from the remote stream to emulate // other stream wrappers. Basically replacing bytes of data of a fixed // length. $overflow = (strlen($string) + $this->tell()) - $this->remoteStream->tell(); if ($overflow > 0) { $this->skipReadBytes += $overflow; } return $this->stream->write($string); } public function eof(): bool { return $this->stream->eof() && $this->remoteStream->eof(); } /** * Close both the remote stream and buffer stream */ public function close(): void { $this->remoteStream->close(); $this->stream->close(); } private function cacheEntireStream(): int { $target = new FnStream(['write' => 'strlen']); Utils::copyToStream($this, $target); return $this->tell(); } } PK������Zixn!��n!����UriResolver.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\UriInterface; /** * Resolves a URI reference in the context of a base URI and the opposite way. * * @author Tobias Schultze * * @link https://tools.ietf.org/html/rfc3986#section-5 */ final class UriResolver { /** * Removes dot segments from a path and returns the new path. * * @link http://tools.ietf.org/html/rfc3986#section-5.2.4 */ public static function removeDotSegments(string $path): string { if ($path === '' || $path === '/') { return $path; } $results = []; $segments = explode('/', $path); foreach ($segments as $segment) { if ($segment === '..') { array_pop($results); } elseif ($segment !== '.') { $results[] = $segment; } } $newPath = implode('/', $results); if ($path[0] === '/' && (!isset($newPath[0]) || $newPath[0] !== '/')) { // Re-add the leading slash if necessary for cases like "/.." $newPath = '/' . $newPath; } elseif ($newPath !== '' && ($segment === '.' || $segment === '..')) { // Add the trailing slash if necessary // If newPath is not empty, then $segment must be set and is the last segment from the foreach $newPath .= '/'; } return $newPath; } /** * Converts the relative URI into a new URI that is resolved against the base URI. * * @link http://tools.ietf.org/html/rfc3986#section-5.2 */ public static function resolve(UriInterface $base, UriInterface $rel): UriInterface { if ((string) $rel === '') { // we can simply return the same base URI instance for this same-document reference return $base; } if ($rel->getScheme() != '') { return $rel->withPath(self::removeDotSegments($rel->getPath())); } if ($rel->getAuthority() != '') { $targetAuthority = $rel->getAuthority(); $targetPath = self::removeDotSegments($rel->getPath()); $targetQuery = $rel->getQuery(); } else { $targetAuthority = $base->getAuthority(); if ($rel->getPath() === '') { $targetPath = $base->getPath(); $targetQuery = $rel->getQuery() != '' ? $rel->getQuery() : $base->getQuery(); } else { if ($rel->getPath()[0] === '/') { $targetPath = $rel->getPath(); } else { if ($targetAuthority != '' && $base->getPath() === '') { $targetPath = '/' . $rel->getPath(); } else { $lastSlashPos = strrpos($base->getPath(), '/'); if ($lastSlashPos === false) { $targetPath = $rel->getPath(); } else { $targetPath = substr($base->getPath(), 0, $lastSlashPos + 1) . $rel->getPath(); } } } $targetPath = self::removeDotSegments($targetPath); $targetQuery = $rel->getQuery(); } } return new Uri(Uri::composeComponents( $base->getScheme(), $targetAuthority, $targetPath, $targetQuery, $rel->getFragment() )); } /** * Returns the target URI as a relative reference from the base URI. * * This method is the counterpart to resolve(): * * (string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target)) * * One use-case is to use the current request URI as base URI and then generate relative links in your documents * to reduce the document size or offer self-contained downloadable document archives. * * $base = new Uri('http://example.com/a/b/'); * echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c')); // prints 'c'. * echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y')); // prints '../x/y'. * echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'. * echo UriResolver::relativize($base, new Uri('http://example.org/a/b/')); // prints '//example.org/a/b/'. * * This method also accepts a target that is already relative and will try to relativize it further. Only a * relative-path reference will be returned as-is. * * echo UriResolver::relativize($base, new Uri('/a/b/c')); // prints 'c' as well */ public static function relativize(UriInterface $base, UriInterface $target): UriInterface { if ($target->getScheme() !== '' && ($base->getScheme() !== $target->getScheme() || $target->getAuthority() === '' && $base->getAuthority() !== '') ) { return $target; } if (Uri::isRelativePathReference($target)) { // As the target is already highly relative we return it as-is. It would be possible to resolve // the target with `$target = self::resolve($base, $target);` and then try make it more relative // by removing a duplicate query. But let's not do that automatically. return $target; } if ($target->getAuthority() !== '' && $base->getAuthority() !== $target->getAuthority()) { return $target->withScheme(''); } // We must remove the path before removing the authority because if the path starts with two slashes, the URI // would turn invalid. And we also cannot set a relative path before removing the authority, as that is also // invalid. $emptyPathUri = $target->withScheme('')->withPath('')->withUserInfo('')->withPort(null)->withHost(''); if ($base->getPath() !== $target->getPath()) { return $emptyPathUri->withPath(self::getRelativePath($base, $target)); } if ($base->getQuery() === $target->getQuery()) { // Only the target fragment is left. And it must be returned even if base and target fragment are the same. return $emptyPathUri->withQuery(''); } // If the base URI has a query but the target has none, we cannot return an empty path reference as it would // inherit the base query component when resolving. if ($target->getQuery() === '') { $segments = explode('/', $target->getPath()); /** @var string $lastSegment */ $lastSegment = end($segments); return $emptyPathUri->withPath($lastSegment === '' ? './' : $lastSegment); } return $emptyPathUri; } private static function getRelativePath(UriInterface $base, UriInterface $target): string { $sourceSegments = explode('/', $base->getPath()); $targetSegments = explode('/', $target->getPath()); array_pop($sourceSegments); $targetLastSegment = array_pop($targetSegments); foreach ($sourceSegments as $i => $segment) { if (isset($targetSegments[$i]) && $segment === $targetSegments[$i]) { unset($sourceSegments[$i], $targetSegments[$i]); } else { break; } } $targetSegments[] = $targetLastSegment; $relativePath = str_repeat('../', count($sourceSegments)) . implode('/', $targetSegments); // A reference to am empty last segment or an empty first sub-segment must be prefixed with "./". // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used // as the first segment of a relative-path reference, as it would be mistaken for a scheme name. if ('' === $relativePath || false !== strpos(explode('/', $relativePath, 2)[0], ':')) { $relativePath = "./$relativePath"; } elseif ('/' === $relativePath[0]) { if ($base->getAuthority() != '' && $base->getPath() === '') { // In this case an extra slash is added by resolve() automatically. So we must not add one here. $relativePath = ".$relativePath"; } else { $relativePath = "./$relativePath"; } } return $relativePath; } private function __construct() { // cannot be instantiated } } PK������Z× �� ����NoSeekStream.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** * Stream decorator that prevents a stream from being seeked. */ final class NoSeekStream implements StreamInterface { use StreamDecoratorTrait; /** @var StreamInterface */ private $stream; public function seek($offset, $whence = SEEK_SET): void { throw new \RuntimeException('Cannot seek a NoSeekStream'); } public function isSeekable(): bool { return false; } } PK������ZtӃE������MultipartStream.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** * Stream that when read returns bytes for a streaming multipart or * multipart/form-data stream. */ final class MultipartStream implements StreamInterface { use StreamDecoratorTrait; /** @var string */ private $boundary; /** @var StreamInterface */ private $stream; /** * @param array $elements Array of associative arrays, each containing a * required "name" key mapping to the form field, * name, a required "contents" key mapping to a * StreamInterface/resource/string, an optional * "headers" associative array of custom headers, * and an optional "filename" key mapping to a * string to send as the filename in the part. * @param string $boundary You can optionally provide a specific boundary * * @throws \InvalidArgumentException */ public function __construct(array $elements = [], string $boundary = null) { $this->boundary = $boundary ?: bin2hex(random_bytes(20)); $this->stream = $this->createStream($elements); } public function getBoundary(): string { return $this->boundary; } public function isWritable(): bool { return false; } /** * Get the headers needed before transferring the content of a POST file * * @param array<string, string> $headers */ private function getHeaders(array $headers): string { $str = ''; foreach ($headers as $key => $value) { $str .= "{$key}: {$value}\r\n"; } return "--{$this->boundary}\r\n" . trim($str) . "\r\n\r\n"; } /** * Create the aggregate stream that will be used to upload the POST data */ protected function createStream(array $elements = []): StreamInterface { $stream = new AppendStream(); foreach ($elements as $element) { if (!is_array($element)) { throw new \UnexpectedValueException("An array is expected"); } $this->addElement($stream, $element); } // Add the trailing boundary with CRLF $stream->addStream(Utils::streamFor("--{$this->boundary}--\r\n")); return $stream; } private function addElement(AppendStream $stream, array $element): void { foreach (['contents', 'name'] as $key) { if (!array_key_exists($key, $element)) { throw new \InvalidArgumentException("A '{$key}' key is required"); } } $element['contents'] = Utils::streamFor($element['contents']); if (empty($element['filename'])) { $uri = $element['contents']->getMetadata('uri'); if ($uri && \is_string($uri) && \substr($uri, 0, 6) !== 'php://' && \substr($uri, 0, 7) !== 'data://') { $element['filename'] = $uri; } } [$body, $headers] = $this->createElement( $element['name'], $element['contents'], $element['filename'] ?? null, $element['headers'] ?? [] ); $stream->addStream(Utils::streamFor($this->getHeaders($headers))); $stream->addStream($body); $stream->addStream(Utils::streamFor("\r\n")); } private function createElement(string $name, StreamInterface $stream, ?string $filename, array $headers): array { // Set a default content-disposition header if one was no provided $disposition = $this->getHeader($headers, 'content-disposition'); if (!$disposition) { $headers['Content-Disposition'] = ($filename === '0' || $filename) ? sprintf( 'form-data; name="%s"; filename="%s"', $name, basename($filename) ) : "form-data; name=\"{$name}\""; } // Set a default content-length header if one was no provided $length = $this->getHeader($headers, 'content-length'); if (!$length) { if ($length = $stream->getSize()) { $headers['Content-Length'] = (string) $length; } } // Set a default Content-Type if one was not supplied $type = $this->getHeader($headers, 'content-type'); if (!$type && ($filename === '0' || $filename)) { if ($type = MimeType::fromFilename($filename)) { $headers['Content-Type'] = $type; } } return [$stream, $headers]; } private function getHeader(array $headers, string $key) { $lowercaseHeader = strtolower($key); foreach ($headers as $k => $v) { if (strtolower($k) === $lowercaseHeader) { return $v; } } return null; } } PK������Z2l5C��C�� ��Query.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; final class Query { /** * Parse a query string into an associative array. * * If multiple values are found for the same key, the value of that key * value pair will become an array. This function does not parse nested * PHP style arrays into an associative array (e.g., `foo[a]=1&foo[b]=2` * will be parsed into `['foo[a]' => '1', 'foo[b]' => '2'])`. * * @param string $str Query string to parse * @param int|bool $urlEncoding How the query string is encoded */ public static function parse(string $str, $urlEncoding = true): array { $result = []; if ($str === '') { return $result; } if ($urlEncoding === true) { $decoder = function ($value) { return rawurldecode(str_replace('+', ' ', (string) $value)); }; } elseif ($urlEncoding === PHP_QUERY_RFC3986) { $decoder = 'rawurldecode'; } elseif ($urlEncoding === PHP_QUERY_RFC1738) { $decoder = 'urldecode'; } else { $decoder = function ($str) { return $str; }; } foreach (explode('&', $str) as $kvp) { $parts = explode('=', $kvp, 2); $key = $decoder($parts[0]); $value = isset($parts[1]) ? $decoder($parts[1]) : null; if (!array_key_exists($key, $result)) { $result[$key] = $value; } else { if (!is_array($result[$key])) { $result[$key] = [$result[$key]]; } $result[$key][] = $value; } } return $result; } /** * Build a query string from an array of key value pairs. * * This function can use the return value of `parse()` to build a query * string. This function does not modify the provided keys when an array is * encountered (like `http_build_query()` would). * * @param array $params Query string parameters. * @param int|false $encoding Set to false to not encode, PHP_QUERY_RFC3986 * to encode using RFC3986, or PHP_QUERY_RFC1738 * to encode using RFC1738. */ public static function build(array $params, $encoding = PHP_QUERY_RFC3986): string { if (!$params) { return ''; } if ($encoding === false) { $encoder = function (string $str): string { return $str; }; } elseif ($encoding === PHP_QUERY_RFC3986) { $encoder = 'rawurlencode'; } elseif ($encoding === PHP_QUERY_RFC1738) { $encoder = 'urlencode'; } else { throw new \InvalidArgumentException('Invalid type'); } $qs = ''; foreach ($params as $k => $v) { $k = $encoder((string) $k); if (!is_array($v)) { $qs .= $k; $v = is_bool($v) ? (int) $v : $v; if ($v !== null) { $qs .= '=' . $encoder((string) $v); } $qs .= '&'; } else { foreach ($v as $vv) { $qs .= $k; $vv = is_bool($vv) ? (int) $vv : $vv; if ($vv !== null) { $qs .= '=' . $encoder((string) $vv); } $qs .= '&'; } } } return $qs ? (string) substr($qs, 0, -1) : ''; } } PK������Zʯ���� ��Stream.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** * PHP stream implementation. */ class Stream implements StreamInterface { /** * @see http://php.net/manual/function.fopen.php * @see http://php.net/manual/en/function.gzopen.php */ private const READABLE_MODES = '/r|a\+|ab\+|w\+|wb\+|x\+|xb\+|c\+|cb\+/'; private const WRITABLE_MODES = '/a|w|r\+|rb\+|rw|x|c/'; /** @var resource */ private $stream; /** @var int|null */ private $size; /** @var bool */ private $seekable; /** @var bool */ private $readable; /** @var bool */ private $writable; /** @var string|null */ private $uri; /** @var mixed[] */ private $customMetadata; /** * This constructor accepts an associative array of options. * * - size: (int) If a read stream would otherwise have an indeterminate * size, but the size is known due to foreknowledge, then you can * provide that size, in bytes. * - metadata: (array) Any additional metadata to return when the metadata * of the stream is accessed. * * @param resource $stream Stream resource to wrap. * @param array{size?: int, metadata?: array} $options Associative array of options. * * @throws \InvalidArgumentException if the stream is not a stream resource */ public function __construct($stream, array $options = []) { if (!is_resource($stream)) { throw new \InvalidArgumentException('Stream must be a resource'); } if (isset($options['size'])) { $this->size = $options['size']; } $this->customMetadata = $options['metadata'] ?? []; $this->stream = $stream; $meta = stream_get_meta_data($this->stream); $this->seekable = $meta['seekable']; $this->readable = (bool)preg_match(self::READABLE_MODES, $meta['mode']); $this->writable = (bool)preg_match(self::WRITABLE_MODES, $meta['mode']); $this->uri = $this->getMetadata('uri'); } /** * Closes the stream when the destructed */ public function __destruct() { $this->close(); } public function __toString(): string { try { if ($this->isSeekable()) { $this->seek(0); } return $this->getContents(); } catch (\Throwable $e) { if (\PHP_VERSION_ID >= 70400) { throw $e; } trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); return ''; } } public function getContents(): string { if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } if (!$this->readable) { throw new \RuntimeException('Cannot read from non-readable stream'); } return Utils::tryGetContents($this->stream); } public function close(): void { if (isset($this->stream)) { if (is_resource($this->stream)) { fclose($this->stream); } $this->detach(); } } public function detach() { if (!isset($this->stream)) { return null; } $result = $this->stream; unset($this->stream); $this->size = $this->uri = null; $this->readable = $this->writable = $this->seekable = false; return $result; } public function getSize(): ?int { if ($this->size !== null) { return $this->size; } if (!isset($this->stream)) { return null; } // Clear the stat cache if the stream has a URI if ($this->uri) { clearstatcache(true, $this->uri); } $stats = fstat($this->stream); if (is_array($stats) && isset($stats['size'])) { $this->size = $stats['size']; return $this->size; } return null; } public function isReadable(): bool { return $this->readable; } public function isWritable(): bool { return $this->writable; } public function isSeekable(): bool { return $this->seekable; } public function eof(): bool { if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } return feof($this->stream); } public function tell(): int { if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } $result = ftell($this->stream); if ($result === false) { throw new \RuntimeException('Unable to determine stream position'); } return $result; } public function rewind(): void { $this->seek(0); } public function seek($offset, $whence = SEEK_SET): void { $whence = (int) $whence; if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } if (!$this->seekable) { throw new \RuntimeException('Stream is not seekable'); } if (fseek($this->stream, $offset, $whence) === -1) { throw new \RuntimeException('Unable to seek to stream position ' . $offset . ' with whence ' . var_export($whence, true)); } } public function read($length): string { if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } if (!$this->readable) { throw new \RuntimeException('Cannot read from non-readable stream'); } if ($length < 0) { throw new \RuntimeException('Length parameter cannot be negative'); } if (0 === $length) { return ''; } try { $string = fread($this->stream, $length); } catch (\Exception $e) { throw new \RuntimeException('Unable to read from stream', 0, $e); } if (false === $string) { throw new \RuntimeException('Unable to read from stream'); } return $string; } public function write($string): int { if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } if (!$this->writable) { throw new \RuntimeException('Cannot write to a non-writable stream'); } // We can't know the size after writing anything $this->size = null; $result = fwrite($this->stream, $string); if ($result === false) { throw new \RuntimeException('Unable to write to stream'); } return $result; } /** * {@inheritdoc} * * @return mixed */ public function getMetadata($key = null) { if (!isset($this->stream)) { return $key ? null : []; } elseif (!$key) { return $this->customMetadata + stream_get_meta_data($this->stream); } elseif (isset($this->customMetadata[$key])) { return $this->customMetadata[$key]; } $meta = stream_get_meta_data($this->stream); return $meta[$key] ?? null; } } PK������ZoK^;��;�� ��Request.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use InvalidArgumentException; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\StreamInterface; use Psr\Http\Message\UriInterface; /** * PSR-7 request implementation. */ class Request implements RequestInterface { use MessageTrait; /** @var string */ private $method; /** @var string|null */ private $requestTarget; /** @var UriInterface */ private $uri; /** * @param string $method HTTP method * @param string|UriInterface $uri URI * @param array<string, string|string[]> $headers Request headers * @param string|resource|StreamInterface|null $body Request body * @param string $version Protocol version */ public function __construct( string $method, $uri, array $headers = [], $body = null, string $version = '1.1' ) { $this->assertMethod($method); if (!($uri instanceof UriInterface)) { $uri = new Uri($uri); } $this->method = strtoupper($method); $this->uri = $uri; $this->setHeaders($headers); $this->protocol = $version; if (!isset($this->headerNames['host'])) { $this->updateHostFromUri(); } if ($body !== '' && $body !== null) { $this->stream = Utils::streamFor($body); } } public function getRequestTarget(): string { if ($this->requestTarget !== null) { return $this->requestTarget; } $target = $this->uri->getPath(); if ($target === '') { $target = '/'; } if ($this->uri->getQuery() != '') { $target .= '?' . $this->uri->getQuery(); } return $target; } public function withRequestTarget($requestTarget): RequestInterface { if (preg_match('#\s#', $requestTarget)) { throw new InvalidArgumentException( 'Invalid request target provided; cannot contain whitespace' ); } $new = clone $this; $new->requestTarget = $requestTarget; return $new; } public function getMethod(): string { return $this->method; } public function withMethod($method): RequestInterface { $this->assertMethod($method); $new = clone $this; $new->method = strtoupper($method); return $new; } public function getUri(): UriInterface { return $this->uri; } public function withUri(UriInterface $uri, $preserveHost = false): RequestInterface { if ($uri === $this->uri) { return $this; } $new = clone $this; $new->uri = $uri; if (!$preserveHost || !isset($this->headerNames['host'])) { $new->updateHostFromUri(); } return $new; } private function updateHostFromUri(): void { $host = $this->uri->getHost(); if ($host == '') { return; } if (($port = $this->uri->getPort()) !== null) { $host .= ':' . $port; } if (isset($this->headerNames['host'])) { $header = $this->headerNames['host']; } else { $header = 'Host'; $this->headerNames['host'] = 'Host'; } // Ensure Host is the first header. // See: http://tools.ietf.org/html/rfc7230#section-5.4 $this->headers = [$header => [$host]] + $this->headers; } /** * @param mixed $method */ private function assertMethod($method): void { if (!is_string($method) || $method === '') { throw new InvalidArgumentException('Method must be a non-empty string.'); } } } PK������ZEGO������LimitStream.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** * Decorator used to return only a subset of a stream. */ final class LimitStream implements StreamInterface { use StreamDecoratorTrait; /** @var int Offset to start reading from */ private $offset; /** @var int Limit the number of bytes that can be read */ private $limit; /** @var StreamInterface */ private $stream; /** * @param StreamInterface $stream Stream to wrap * @param int $limit Total number of bytes to allow to be read * from the stream. Pass -1 for no limit. * @param int $offset Position to seek to before reading (only * works on seekable streams). */ public function __construct( StreamInterface $stream, int $limit = -1, int $offset = 0 ) { $this->stream = $stream; $this->setLimit($limit); $this->setOffset($offset); } public function eof(): bool { // Always return true if the underlying stream is EOF if ($this->stream->eof()) { return true; } // No limit and the underlying stream is not at EOF if ($this->limit === -1) { return false; } return $this->stream->tell() >= $this->offset + $this->limit; } /** * Returns the size of the limited subset of data */ public function getSize(): ?int { if (null === ($length = $this->stream->getSize())) { return null; } elseif ($this->limit === -1) { return $length - $this->offset; } else { return min($this->limit, $length - $this->offset); } } /** * Allow for a bounded seek on the read limited stream */ public function seek($offset, $whence = SEEK_SET): void { if ($whence !== SEEK_SET || $offset < 0) { throw new \RuntimeException(sprintf( 'Cannot seek to offset %s with whence %s', $offset, $whence )); } $offset += $this->offset; if ($this->limit !== -1) { if ($offset > $this->offset + $this->limit) { $offset = $this->offset + $this->limit; } } $this->stream->seek($offset); } /** * Give a relative tell() */ public function tell(): int { return $this->stream->tell() - $this->offset; } /** * Set the offset to start limiting from * * @param int $offset Offset to seek to and begin byte limiting from * * @throws \RuntimeException if the stream cannot be seeked. */ public function setOffset(int $offset): void { $current = $this->stream->tell(); if ($current !== $offset) { // If the stream cannot seek to the offset position, then read to it if ($this->stream->isSeekable()) { $this->stream->seek($offset); } elseif ($current > $offset) { throw new \RuntimeException("Could not seek to stream offset $offset"); } else { $this->stream->read($offset - $current); } } $this->offset = $offset; } /** * Set the limit of bytes that the decorator allows to be read from the * stream. * * @param int $limit Number of bytes to allow to be read from the stream. * Use -1 for no limit. */ public function setLimit(int $limit): void { $this->limit = $limit; } public function read($length): string { if ($this->limit === -1) { return $this->stream->read($length); } // Check if the current position is less than the total allowed // bytes + original offset $remaining = ($this->offset + $this->limit) - $this->stream->tell(); if ($remaining > 0) { // Only return the amount of requested data, ensuring that the byte // limit is not exceeded return $this->stream->read(min($remaining, $length)); } return ''; } } PK������ZW2���� ��MimeType.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; final class MimeType { private const MIME_TYPES = [ '1km' => 'application/vnd.1000minds.decision-model+xml', '3dml' => 'text/vnd.in3d.3dml', '3ds' => 'image/x-3ds', '3g2' => 'video/3gpp2', '3gp' => 'video/3gp', '3gpp' => 'video/3gpp', '3mf' => 'model/3mf', '7z' => 'application/x-7z-compressed', '7zip' => 'application/x-7z-compressed', '123' => 'application/vnd.lotus-1-2-3', 'aab' => 'application/x-authorware-bin', 'aac' => 'audio/x-acc', 'aam' => 'application/x-authorware-map', 'aas' => 'application/x-authorware-seg', 'abw' => 'application/x-abiword', 'ac' => 'application/vnd.nokia.n-gage.ac+xml', 'ac3' => 'audio/ac3', 'acc' => 'application/vnd.americandynamics.acc', 'ace' => 'application/x-ace-compressed', 'acu' => 'application/vnd.acucobol', 'acutc' => 'application/vnd.acucorp', 'adp' => 'audio/adpcm', 'aep' => 'application/vnd.audiograph', 'afm' => 'application/x-font-type1', 'afp' => 'application/vnd.ibm.modcap', 'age' => 'application/vnd.age', 'ahead' => 'application/vnd.ahead.space', 'ai' => 'application/pdf', 'aif' => 'audio/x-aiff', 'aifc' => 'audio/x-aiff', 'aiff' => 'audio/x-aiff', 'air' => 'application/vnd.adobe.air-application-installer-package+zip', 'ait' => 'application/vnd.dvb.ait', 'ami' => 'application/vnd.amiga.ami', 'amr' => 'audio/amr', 'apk' => 'application/vnd.android.package-archive', 'apng' => 'image/apng', 'appcache' => 'text/cache-manifest', 'application' => 'application/x-ms-application', 'apr' => 'application/vnd.lotus-approach', 'arc' => 'application/x-freearc', 'arj' => 'application/x-arj', 'asc' => 'application/pgp-signature', 'asf' => 'video/x-ms-asf', 'asm' => 'text/x-asm', 'aso' => 'application/vnd.accpac.simply.aso', 'asx' => 'video/x-ms-asf', 'atc' => 'application/vnd.acucorp', 'atom' => 'application/atom+xml', 'atomcat' => 'application/atomcat+xml', 'atomdeleted' => 'application/atomdeleted+xml', 'atomsvc' => 'application/atomsvc+xml', 'atx' => 'application/vnd.antix.game-component', 'au' => 'audio/x-au', 'avci' => 'image/avci', 'avcs' => 'image/avcs', 'avi' => 'video/x-msvideo', 'avif' => 'image/avif', 'aw' => 'application/applixware', 'azf' => 'application/vnd.airzip.filesecure.azf', 'azs' => 'application/vnd.airzip.filesecure.azs', 'azv' => 'image/vnd.airzip.accelerator.azv', 'azw' => 'application/vnd.amazon.ebook', 'b16' => 'image/vnd.pco.b16', 'bat' => 'application/x-msdownload', 'bcpio' => 'application/x-bcpio', 'bdf' => 'application/x-font-bdf', 'bdm' => 'application/vnd.syncml.dm+wbxml', 'bdoc' => 'application/x-bdoc', 'bed' => 'application/vnd.realvnc.bed', 'bh2' => 'application/vnd.fujitsu.oasysprs', 'bin' => 'application/octet-stream', 'blb' => 'application/x-blorb', 'blorb' => 'application/x-blorb', 'bmi' => 'application/vnd.bmi', 'bmml' => 'application/vnd.balsamiq.bmml+xml', 'bmp' => 'image/bmp', 'book' => 'application/vnd.framemaker', 'box' => 'application/vnd.previewsystems.box', 'boz' => 'application/x-bzip2', 'bpk' => 'application/octet-stream', 'bpmn' => 'application/octet-stream', 'bsp' => 'model/vnd.valve.source.compiled-map', 'btif' => 'image/prs.btif', 'buffer' => 'application/octet-stream', 'bz' => 'application/x-bzip', 'bz2' => 'application/x-bzip2', 'c' => 'text/x-c', 'c4d' => 'application/vnd.clonk.c4group', 'c4f' => 'application/vnd.clonk.c4group', 'c4g' => 'application/vnd.clonk.c4group', 'c4p' => 'application/vnd.clonk.c4group', 'c4u' => 'application/vnd.clonk.c4group', 'c11amc' => 'application/vnd.cluetrust.cartomobile-config', 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg', 'cab' => 'application/vnd.ms-cab-compressed', 'caf' => 'audio/x-caf', 'cap' => 'application/vnd.tcpdump.pcap', 'car' => 'application/vnd.curl.car', 'cat' => 'application/vnd.ms-pki.seccat', 'cb7' => 'application/x-cbr', 'cba' => 'application/x-cbr', 'cbr' => 'application/x-cbr', 'cbt' => 'application/x-cbr', 'cbz' => 'application/x-cbr', 'cc' => 'text/x-c', 'cco' => 'application/x-cocoa', 'cct' => 'application/x-director', 'ccxml' => 'application/ccxml+xml', 'cdbcmsg' => 'application/vnd.contact.cmsg', 'cdf' => 'application/x-netcdf', 'cdfx' => 'application/cdfx+xml', 'cdkey' => 'application/vnd.mediastation.cdkey', 'cdmia' => 'application/cdmi-capability', 'cdmic' => 'application/cdmi-container', 'cdmid' => 'application/cdmi-domain', 'cdmio' => 'application/cdmi-object', 'cdmiq' => 'application/cdmi-queue', 'cdr' => 'application/cdr', 'cdx' => 'chemical/x-cdx', 'cdxml' => 'application/vnd.chemdraw+xml', 'cdy' => 'application/vnd.cinderella', 'cer' => 'application/pkix-cert', 'cfs' => 'application/x-cfs-compressed', 'cgm' => 'image/cgm', 'chat' => 'application/x-chat', 'chm' => 'application/vnd.ms-htmlhelp', 'chrt' => 'application/vnd.kde.kchart', 'cif' => 'chemical/x-cif', 'cii' => 'application/vnd.anser-web-certificate-issue-initiation', 'cil' => 'application/vnd.ms-artgalry', 'cjs' => 'application/node', 'cla' => 'application/vnd.claymore', 'class' => 'application/octet-stream', 'clkk' => 'application/vnd.crick.clicker.keyboard', 'clkp' => 'application/vnd.crick.clicker.palette', 'clkt' => 'application/vnd.crick.clicker.template', 'clkw' => 'application/vnd.crick.clicker.wordbank', 'clkx' => 'application/vnd.crick.clicker', 'clp' => 'application/x-msclip', 'cmc' => 'application/vnd.cosmocaller', 'cmdf' => 'chemical/x-cmdf', 'cml' => 'chemical/x-cml', 'cmp' => 'application/vnd.yellowriver-custom-menu', 'cmx' => 'image/x-cmx', 'cod' => 'application/vnd.rim.cod', 'coffee' => 'text/coffeescript', 'com' => 'application/x-msdownload', 'conf' => 'text/plain', 'cpio' => 'application/x-cpio', 'cpl' => 'application/cpl+xml', 'cpp' => 'text/x-c', 'cpt' => 'application/mac-compactpro', 'crd' => 'application/x-mscardfile', 'crl' => 'application/pkix-crl', 'crt' => 'application/x-x509-ca-cert', 'crx' => 'application/x-chrome-extension', 'cryptonote' => 'application/vnd.rig.cryptonote', 'csh' => 'application/x-csh', 'csl' => 'application/vnd.citationstyles.style+xml', 'csml' => 'chemical/x-csml', 'csp' => 'application/vnd.commonspace', 'csr' => 'application/octet-stream', 'css' => 'text/css', 'cst' => 'application/x-director', 'csv' => 'text/csv', 'cu' => 'application/cu-seeme', 'curl' => 'text/vnd.curl', 'cww' => 'application/prs.cww', 'cxt' => 'application/x-director', 'cxx' => 'text/x-c', 'dae' => 'model/vnd.collada+xml', 'daf' => 'application/vnd.mobius.daf', 'dart' => 'application/vnd.dart', 'dataless' => 'application/vnd.fdsn.seed', 'davmount' => 'application/davmount+xml', 'dbf' => 'application/vnd.dbf', 'dbk' => 'application/docbook+xml', 'dcr' => 'application/x-director', 'dcurl' => 'text/vnd.curl.dcurl', 'dd2' => 'application/vnd.oma.dd2+xml', 'ddd' => 'application/vnd.fujixerox.ddd', 'ddf' => 'application/vnd.syncml.dmddf+xml', 'dds' => 'image/vnd.ms-dds', 'deb' => 'application/x-debian-package', 'def' => 'text/plain', 'deploy' => 'application/octet-stream', 'der' => 'application/x-x509-ca-cert', 'dfac' => 'application/vnd.dreamfactory', 'dgc' => 'application/x-dgc-compressed', 'dic' => 'text/x-c', 'dir' => 'application/x-director', 'dis' => 'application/vnd.mobius.dis', 'disposition-notification' => 'message/disposition-notification', 'dist' => 'application/octet-stream', 'distz' => 'application/octet-stream', 'djv' => 'image/vnd.djvu', 'djvu' => 'image/vnd.djvu', 'dll' => 'application/octet-stream', 'dmg' => 'application/x-apple-diskimage', 'dmn' => 'application/octet-stream', 'dmp' => 'application/vnd.tcpdump.pcap', 'dms' => 'application/octet-stream', 'dna' => 'application/vnd.dna', 'doc' => 'application/msword', 'docm' => 'application/vnd.ms-word.template.macroEnabled.12', 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'dot' => 'application/msword', 'dotm' => 'application/vnd.ms-word.template.macroEnabled.12', 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', 'dp' => 'application/vnd.osgi.dp', 'dpg' => 'application/vnd.dpgraph', 'dra' => 'audio/vnd.dra', 'drle' => 'image/dicom-rle', 'dsc' => 'text/prs.lines.tag', 'dssc' => 'application/dssc+der', 'dtb' => 'application/x-dtbook+xml', 'dtd' => 'application/xml-dtd', 'dts' => 'audio/vnd.dts', 'dtshd' => 'audio/vnd.dts.hd', 'dump' => 'application/octet-stream', 'dvb' => 'video/vnd.dvb.file', 'dvi' => 'application/x-dvi', 'dwd' => 'application/atsc-dwd+xml', 'dwf' => 'model/vnd.dwf', 'dwg' => 'image/vnd.dwg', 'dxf' => 'image/vnd.dxf', 'dxp' => 'application/vnd.spotfire.dxp', 'dxr' => 'application/x-director', 'ear' => 'application/java-archive', 'ecelp4800' => 'audio/vnd.nuera.ecelp4800', 'ecelp7470' => 'audio/vnd.nuera.ecelp7470', 'ecelp9600' => 'audio/vnd.nuera.ecelp9600', 'ecma' => 'application/ecmascript', 'edm' => 'application/vnd.novadigm.edm', 'edx' => 'application/vnd.novadigm.edx', 'efif' => 'application/vnd.picsel', 'ei6' => 'application/vnd.pg.osasli', 'elc' => 'application/octet-stream', 'emf' => 'image/emf', 'eml' => 'message/rfc822', 'emma' => 'application/emma+xml', 'emotionml' => 'application/emotionml+xml', 'emz' => 'application/x-msmetafile', 'eol' => 'audio/vnd.digital-winds', 'eot' => 'application/vnd.ms-fontobject', 'eps' => 'application/postscript', 'epub' => 'application/epub+zip', 'es' => 'application/ecmascript', 'es3' => 'application/vnd.eszigno3+xml', 'esa' => 'application/vnd.osgi.subsystem', 'esf' => 'application/vnd.epson.esf', 'et3' => 'application/vnd.eszigno3+xml', 'etx' => 'text/x-setext', 'eva' => 'application/x-eva', 'evy' => 'application/x-envoy', 'exe' => 'application/octet-stream', 'exi' => 'application/exi', 'exp' => 'application/express', 'exr' => 'image/aces', 'ext' => 'application/vnd.novadigm.ext', 'ez' => 'application/andrew-inset', 'ez2' => 'application/vnd.ezpix-album', 'ez3' => 'application/vnd.ezpix-package', 'f' => 'text/x-fortran', 'f4v' => 'video/mp4', 'f77' => 'text/x-fortran', 'f90' => 'text/x-fortran', 'fbs' => 'image/vnd.fastbidsheet', 'fcdt' => 'application/vnd.adobe.formscentral.fcdt', 'fcs' => 'application/vnd.isac.fcs', 'fdf' => 'application/vnd.fdf', 'fdt' => 'application/fdt+xml', 'fe_launch' => 'application/vnd.denovo.fcselayout-link', 'fg5' => 'application/vnd.fujitsu.oasysgp', 'fgd' => 'application/x-director', 'fh' => 'image/x-freehand', 'fh4' => 'image/x-freehand', 'fh5' => 'image/x-freehand', 'fh7' => 'image/x-freehand', 'fhc' => 'image/x-freehand', 'fig' => 'application/x-xfig', 'fits' => 'image/fits', 'flac' => 'audio/x-flac', 'fli' => 'video/x-fli', 'flo' => 'application/vnd.micrografx.flo', 'flv' => 'video/x-flv', 'flw' => 'application/vnd.kde.kivio', 'flx' => 'text/vnd.fmi.flexstor', 'fly' => 'text/vnd.fly', 'fm' => 'application/vnd.framemaker', 'fnc' => 'application/vnd.frogans.fnc', 'fo' => 'application/vnd.software602.filler.form+xml', 'for' => 'text/x-fortran', 'fpx' => 'image/vnd.fpx', 'frame' => 'application/vnd.framemaker', 'fsc' => 'application/vnd.fsc.weblaunch', 'fst' => 'image/vnd.fst', 'ftc' => 'application/vnd.fluxtime.clip', 'fti' => 'application/vnd.anser-web-funds-transfer-initiation', 'fvt' => 'video/vnd.fvt', 'fxp' => 'application/vnd.adobe.fxp', 'fxpl' => 'application/vnd.adobe.fxp', 'fzs' => 'application/vnd.fuzzysheet', 'g2w' => 'application/vnd.geoplan', 'g3' => 'image/g3fax', 'g3w' => 'application/vnd.geospace', 'gac' => 'application/vnd.groove-account', 'gam' => 'application/x-tads', 'gbr' => 'application/rpki-ghostbusters', 'gca' => 'application/x-gca-compressed', 'gdl' => 'model/vnd.gdl', 'gdoc' => 'application/vnd.google-apps.document', 'ged' => 'text/vnd.familysearch.gedcom', 'geo' => 'application/vnd.dynageo', 'geojson' => 'application/geo+json', 'gex' => 'application/vnd.geometry-explorer', 'ggb' => 'application/vnd.geogebra.file', 'ggt' => 'application/vnd.geogebra.tool', 'ghf' => 'application/vnd.groove-help', 'gif' => 'image/gif', 'gim' => 'application/vnd.groove-identity-message', 'glb' => 'model/gltf-binary', 'gltf' => 'model/gltf+json', 'gml' => 'application/gml+xml', 'gmx' => 'application/vnd.gmx', 'gnumeric' => 'application/x-gnumeric', 'gpg' => 'application/gpg-keys', 'gph' => 'application/vnd.flographit', 'gpx' => 'application/gpx+xml', 'gqf' => 'application/vnd.grafeq', 'gqs' => 'application/vnd.grafeq', 'gram' => 'application/srgs', 'gramps' => 'application/x-gramps-xml', 'gre' => 'application/vnd.geometry-explorer', 'grv' => 'application/vnd.groove-injector', 'grxml' => 'application/srgs+xml', 'gsf' => 'application/x-font-ghostscript', 'gsheet' => 'application/vnd.google-apps.spreadsheet', 'gslides' => 'application/vnd.google-apps.presentation', 'gtar' => 'application/x-gtar', 'gtm' => 'application/vnd.groove-tool-message', 'gtw' => 'model/vnd.gtw', 'gv' => 'text/vnd.graphviz', 'gxf' => 'application/gxf', 'gxt' => 'application/vnd.geonext', 'gz' => 'application/gzip', 'gzip' => 'application/gzip', 'h' => 'text/x-c', 'h261' => 'video/h261', 'h263' => 'video/h263', 'h264' => 'video/h264', 'hal' => 'application/vnd.hal+xml', 'hbci' => 'application/vnd.hbci', 'hbs' => 'text/x-handlebars-template', 'hdd' => 'application/x-virtualbox-hdd', 'hdf' => 'application/x-hdf', 'heic' => 'image/heic', 'heics' => 'image/heic-sequence', 'heif' => 'image/heif', 'heifs' => 'image/heif-sequence', 'hej2' => 'image/hej2k', 'held' => 'application/atsc-held+xml', 'hh' => 'text/x-c', 'hjson' => 'application/hjson', 'hlp' => 'application/winhlp', 'hpgl' => 'application/vnd.hp-hpgl', 'hpid' => 'application/vnd.hp-hpid', 'hps' => 'application/vnd.hp-hps', 'hqx' => 'application/mac-binhex40', 'hsj2' => 'image/hsj2', 'htc' => 'text/x-component', 'htke' => 'application/vnd.kenameaapp', 'htm' => 'text/html', 'html' => 'text/html', 'hvd' => 'application/vnd.yamaha.hv-dic', 'hvp' => 'application/vnd.yamaha.hv-voice', 'hvs' => 'application/vnd.yamaha.hv-script', 'i2g' => 'application/vnd.intergeo', 'icc' => 'application/vnd.iccprofile', 'ice' => 'x-conference/x-cooltalk', 'icm' => 'application/vnd.iccprofile', 'ico' => 'image/x-icon', 'ics' => 'text/calendar', 'ief' => 'image/ief', 'ifb' => 'text/calendar', 'ifm' => 'application/vnd.shana.informed.formdata', 'iges' => 'model/iges', 'igl' => 'application/vnd.igloader', 'igm' => 'application/vnd.insors.igm', 'igs' => 'model/iges', 'igx' => 'application/vnd.micrografx.igx', 'iif' => 'application/vnd.shana.informed.interchange', 'img' => 'application/octet-stream', 'imp' => 'application/vnd.accpac.simply.imp', 'ims' => 'application/vnd.ms-ims', 'in' => 'text/plain', 'ini' => 'text/plain', 'ink' => 'application/inkml+xml', 'inkml' => 'application/inkml+xml', 'install' => 'application/x-install-instructions', 'iota' => 'application/vnd.astraea-software.iota', 'ipfix' => 'application/ipfix', 'ipk' => 'application/vnd.shana.informed.package', 'irm' => 'application/vnd.ibm.rights-management', 'irp' => 'application/vnd.irepository.package+xml', 'iso' => 'application/x-iso9660-image', 'itp' => 'application/vnd.shana.informed.formtemplate', 'its' => 'application/its+xml', 'ivp' => 'application/vnd.immervision-ivp', 'ivu' => 'application/vnd.immervision-ivu', 'jad' => 'text/vnd.sun.j2me.app-descriptor', 'jade' => 'text/jade', 'jam' => 'application/vnd.jam', 'jar' => 'application/java-archive', 'jardiff' => 'application/x-java-archive-diff', 'java' => 'text/x-java-source', 'jhc' => 'image/jphc', 'jisp' => 'application/vnd.jisp', 'jls' => 'image/jls', 'jlt' => 'application/vnd.hp-jlyt', 'jng' => 'image/x-jng', 'jnlp' => 'application/x-java-jnlp-file', 'joda' => 'application/vnd.joost.joda-archive', 'jp2' => 'image/jp2', 'jpe' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'jpf' => 'image/jpx', 'jpg' => 'image/jpeg', 'jpg2' => 'image/jp2', 'jpgm' => 'video/jpm', 'jpgv' => 'video/jpeg', 'jph' => 'image/jph', 'jpm' => 'video/jpm', 'jpx' => 'image/jpx', 'js' => 'application/javascript', 'json' => 'application/json', 'json5' => 'application/json5', 'jsonld' => 'application/ld+json', 'jsonml' => 'application/jsonml+json', 'jsx' => 'text/jsx', 'jxr' => 'image/jxr', 'jxra' => 'image/jxra', 'jxrs' => 'image/jxrs', 'jxs' => 'image/jxs', 'jxsc' => 'image/jxsc', 'jxsi' => 'image/jxsi', 'jxss' => 'image/jxss', 'kar' => 'audio/midi', 'karbon' => 'application/vnd.kde.karbon', 'kdb' => 'application/octet-stream', 'kdbx' => 'application/x-keepass2', 'key' => 'application/x-iwork-keynote-sffkey', 'kfo' => 'application/vnd.kde.kformula', 'kia' => 'application/vnd.kidspiration', 'kml' => 'application/vnd.google-earth.kml+xml', 'kmz' => 'application/vnd.google-earth.kmz', 'kne' => 'application/vnd.kinar', 'knp' => 'application/vnd.kinar', 'kon' => 'application/vnd.kde.kontour', 'kpr' => 'application/vnd.kde.kpresenter', 'kpt' => 'application/vnd.kde.kpresenter', 'kpxx' => 'application/vnd.ds-keypoint', 'ksp' => 'application/vnd.kde.kspread', 'ktr' => 'application/vnd.kahootz', 'ktx' => 'image/ktx', 'ktx2' => 'image/ktx2', 'ktz' => 'application/vnd.kahootz', 'kwd' => 'application/vnd.kde.kword', 'kwt' => 'application/vnd.kde.kword', 'lasxml' => 'application/vnd.las.las+xml', 'latex' => 'application/x-latex', 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop', 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml', 'les' => 'application/vnd.hhe.lesson-player', 'less' => 'text/less', 'lgr' => 'application/lgr+xml', 'lha' => 'application/octet-stream', 'link66' => 'application/vnd.route66.link66+xml', 'list' => 'text/plain', 'list3820' => 'application/vnd.ibm.modcap', 'listafp' => 'application/vnd.ibm.modcap', 'litcoffee' => 'text/coffeescript', 'lnk' => 'application/x-ms-shortcut', 'log' => 'text/plain', 'lostxml' => 'application/lost+xml', 'lrf' => 'application/octet-stream', 'lrm' => 'application/vnd.ms-lrm', 'ltf' => 'application/vnd.frogans.ltf', 'lua' => 'text/x-lua', 'luac' => 'application/x-lua-bytecode', 'lvp' => 'audio/vnd.lucent.voice', 'lwp' => 'application/vnd.lotus-wordpro', 'lzh' => 'application/octet-stream', 'm1v' => 'video/mpeg', 'm2a' => 'audio/mpeg', 'm2v' => 'video/mpeg', 'm3a' => 'audio/mpeg', 'm3u' => 'text/plain', 'm3u8' => 'application/vnd.apple.mpegurl', 'm4a' => 'audio/x-m4a', 'm4p' => 'application/mp4', 'm4s' => 'video/iso.segment', 'm4u' => 'application/vnd.mpegurl', 'm4v' => 'video/x-m4v', 'm13' => 'application/x-msmediaview', 'm14' => 'application/x-msmediaview', 'm21' => 'application/mp21', 'ma' => 'application/mathematica', 'mads' => 'application/mads+xml', 'maei' => 'application/mmt-aei+xml', 'mag' => 'application/vnd.ecowin.chart', 'maker' => 'application/vnd.framemaker', 'man' => 'text/troff', 'manifest' => 'text/cache-manifest', 'map' => 'application/json', 'mar' => 'application/octet-stream', 'markdown' => 'text/markdown', 'mathml' => 'application/mathml+xml', 'mb' => 'application/mathematica', 'mbk' => 'application/vnd.mobius.mbk', 'mbox' => 'application/mbox', 'mc1' => 'application/vnd.medcalcdata', 'mcd' => 'application/vnd.mcd', 'mcurl' => 'text/vnd.curl.mcurl', 'md' => 'text/markdown', 'mdb' => 'application/x-msaccess', 'mdi' => 'image/vnd.ms-modi', 'mdx' => 'text/mdx', 'me' => 'text/troff', 'mesh' => 'model/mesh', 'meta4' => 'application/metalink4+xml', 'metalink' => 'application/metalink+xml', 'mets' => 'application/mets+xml', 'mfm' => 'application/vnd.mfmp', 'mft' => 'application/rpki-manifest', 'mgp' => 'application/vnd.osgeo.mapguide.package', 'mgz' => 'application/vnd.proteus.magazine', 'mid' => 'audio/midi', 'midi' => 'audio/midi', 'mie' => 'application/x-mie', 'mif' => 'application/vnd.mif', 'mime' => 'message/rfc822', 'mj2' => 'video/mj2', 'mjp2' => 'video/mj2', 'mjs' => 'application/javascript', 'mk3d' => 'video/x-matroska', 'mka' => 'audio/x-matroska', 'mkd' => 'text/x-markdown', 'mks' => 'video/x-matroska', 'mkv' => 'video/x-matroska', 'mlp' => 'application/vnd.dolby.mlp', 'mmd' => 'application/vnd.chipnuts.karaoke-mmd', 'mmf' => 'application/vnd.smaf', 'mml' => 'text/mathml', 'mmr' => 'image/vnd.fujixerox.edmics-mmr', 'mng' => 'video/x-mng', 'mny' => 'application/x-msmoney', 'mobi' => 'application/x-mobipocket-ebook', 'mods' => 'application/mods+xml', 'mov' => 'video/quicktime', 'movie' => 'video/x-sgi-movie', 'mp2' => 'audio/mpeg', 'mp2a' => 'audio/mpeg', 'mp3' => 'audio/mpeg', 'mp4' => 'video/mp4', 'mp4a' => 'audio/mp4', 'mp4s' => 'application/mp4', 'mp4v' => 'video/mp4', 'mp21' => 'application/mp21', 'mpc' => 'application/vnd.mophun.certificate', 'mpd' => 'application/dash+xml', 'mpe' => 'video/mpeg', 'mpeg' => 'video/mpeg', 'mpf' => 'application/media-policy-dataset+xml', 'mpg' => 'video/mpeg', 'mpg4' => 'video/mp4', 'mpga' => 'audio/mpeg', 'mpkg' => 'application/vnd.apple.installer+xml', 'mpm' => 'application/vnd.blueice.multipass', 'mpn' => 'application/vnd.mophun.application', 'mpp' => 'application/vnd.ms-project', 'mpt' => 'application/vnd.ms-project', 'mpy' => 'application/vnd.ibm.minipay', 'mqy' => 'application/vnd.mobius.mqy', 'mrc' => 'application/marc', 'mrcx' => 'application/marcxml+xml', 'ms' => 'text/troff', 'mscml' => 'application/mediaservercontrol+xml', 'mseed' => 'application/vnd.fdsn.mseed', 'mseq' => 'application/vnd.mseq', 'msf' => 'application/vnd.epson.msf', 'msg' => 'application/vnd.ms-outlook', 'msh' => 'model/mesh', 'msi' => 'application/x-msdownload', 'msl' => 'application/vnd.mobius.msl', 'msm' => 'application/octet-stream', 'msp' => 'application/octet-stream', 'msty' => 'application/vnd.muvee.style', 'mtl' => 'model/mtl', 'mts' => 'model/vnd.mts', 'mus' => 'application/vnd.musician', 'musd' => 'application/mmt-usd+xml', 'musicxml' => 'application/vnd.recordare.musicxml+xml', 'mvb' => 'application/x-msmediaview', 'mvt' => 'application/vnd.mapbox-vector-tile', 'mwf' => 'application/vnd.mfer', 'mxf' => 'application/mxf', 'mxl' => 'application/vnd.recordare.musicxml', 'mxmf' => 'audio/mobile-xmf', 'mxml' => 'application/xv+xml', 'mxs' => 'application/vnd.triscape.mxs', 'mxu' => 'video/vnd.mpegurl', 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install', 'n3' => 'text/n3', 'nb' => 'application/mathematica', 'nbp' => 'application/vnd.wolfram.player', 'nc' => 'application/x-netcdf', 'ncx' => 'application/x-dtbncx+xml', 'nfo' => 'text/x-nfo', 'ngdat' => 'application/vnd.nokia.n-gage.data', 'nitf' => 'application/vnd.nitf', 'nlu' => 'application/vnd.neurolanguage.nlu', 'nml' => 'application/vnd.enliven', 'nnd' => 'application/vnd.noblenet-directory', 'nns' => 'application/vnd.noblenet-sealer', 'nnw' => 'application/vnd.noblenet-web', 'npx' => 'image/vnd.net-fpx', 'nq' => 'application/n-quads', 'nsc' => 'application/x-conference', 'nsf' => 'application/vnd.lotus-notes', 'nt' => 'application/n-triples', 'ntf' => 'application/vnd.nitf', 'numbers' => 'application/x-iwork-numbers-sffnumbers', 'nzb' => 'application/x-nzb', 'oa2' => 'application/vnd.fujitsu.oasys2', 'oa3' => 'application/vnd.fujitsu.oasys3', 'oas' => 'application/vnd.fujitsu.oasys', 'obd' => 'application/x-msbinder', 'obgx' => 'application/vnd.openblox.game+xml', 'obj' => 'model/obj', 'oda' => 'application/oda', 'odb' => 'application/vnd.oasis.opendocument.database', 'odc' => 'application/vnd.oasis.opendocument.chart', 'odf' => 'application/vnd.oasis.opendocument.formula', 'odft' => 'application/vnd.oasis.opendocument.formula-template', 'odg' => 'application/vnd.oasis.opendocument.graphics', 'odi' => 'application/vnd.oasis.opendocument.image', 'odm' => 'application/vnd.oasis.opendocument.text-master', 'odp' => 'application/vnd.oasis.opendocument.presentation', 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', 'odt' => 'application/vnd.oasis.opendocument.text', 'oga' => 'audio/ogg', 'ogex' => 'model/vnd.opengex', 'ogg' => 'audio/ogg', 'ogv' => 'video/ogg', 'ogx' => 'application/ogg', 'omdoc' => 'application/omdoc+xml', 'onepkg' => 'application/onenote', 'onetmp' => 'application/onenote', 'onetoc' => 'application/onenote', 'onetoc2' => 'application/onenote', 'opf' => 'application/oebps-package+xml', 'opml' => 'text/x-opml', 'oprc' => 'application/vnd.palm', 'opus' => 'audio/ogg', 'org' => 'text/x-org', 'osf' => 'application/vnd.yamaha.openscoreformat', 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml', 'osm' => 'application/vnd.openstreetmap.data+xml', 'otc' => 'application/vnd.oasis.opendocument.chart-template', 'otf' => 'font/otf', 'otg' => 'application/vnd.oasis.opendocument.graphics-template', 'oth' => 'application/vnd.oasis.opendocument.text-web', 'oti' => 'application/vnd.oasis.opendocument.image-template', 'otp' => 'application/vnd.oasis.opendocument.presentation-template', 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', 'ott' => 'application/vnd.oasis.opendocument.text-template', 'ova' => 'application/x-virtualbox-ova', 'ovf' => 'application/x-virtualbox-ovf', 'owl' => 'application/rdf+xml', 'oxps' => 'application/oxps', 'oxt' => 'application/vnd.openofficeorg.extension', 'p' => 'text/x-pascal', 'p7a' => 'application/x-pkcs7-signature', 'p7b' => 'application/x-pkcs7-certificates', 'p7c' => 'application/pkcs7-mime', 'p7m' => 'application/pkcs7-mime', 'p7r' => 'application/x-pkcs7-certreqresp', 'p7s' => 'application/pkcs7-signature', 'p8' => 'application/pkcs8', 'p10' => 'application/x-pkcs10', 'p12' => 'application/x-pkcs12', 'pac' => 'application/x-ns-proxy-autoconfig', 'pages' => 'application/x-iwork-pages-sffpages', 'pas' => 'text/x-pascal', 'paw' => 'application/vnd.pawaafile', 'pbd' => 'application/vnd.powerbuilder6', 'pbm' => 'image/x-portable-bitmap', 'pcap' => 'application/vnd.tcpdump.pcap', 'pcf' => 'application/x-font-pcf', 'pcl' => 'application/vnd.hp-pcl', 'pclxl' => 'application/vnd.hp-pclxl', 'pct' => 'image/x-pict', 'pcurl' => 'application/vnd.curl.pcurl', 'pcx' => 'image/x-pcx', 'pdb' => 'application/x-pilot', 'pde' => 'text/x-processing', 'pdf' => 'application/pdf', 'pem' => 'application/x-x509-user-cert', 'pfa' => 'application/x-font-type1', 'pfb' => 'application/x-font-type1', 'pfm' => 'application/x-font-type1', 'pfr' => 'application/font-tdpfr', 'pfx' => 'application/x-pkcs12', 'pgm' => 'image/x-portable-graymap', 'pgn' => 'application/x-chess-pgn', 'pgp' => 'application/pgp', 'phar' => 'application/octet-stream', 'php' => 'application/x-httpd-php', 'php3' => 'application/x-httpd-php', 'php4' => 'application/x-httpd-php', 'phps' => 'application/x-httpd-php-source', 'phtml' => 'application/x-httpd-php', 'pic' => 'image/x-pict', 'pkg' => 'application/octet-stream', 'pki' => 'application/pkixcmp', 'pkipath' => 'application/pkix-pkipath', 'pkpass' => 'application/vnd.apple.pkpass', 'pl' => 'application/x-perl', 'plb' => 'application/vnd.3gpp.pic-bw-large', 'plc' => 'application/vnd.mobius.plc', 'plf' => 'application/vnd.pocketlearn', 'pls' => 'application/pls+xml', 'pm' => 'application/x-perl', 'pml' => 'application/vnd.ctc-posml', 'png' => 'image/png', 'pnm' => 'image/x-portable-anymap', 'portpkg' => 'application/vnd.macports.portpkg', 'pot' => 'application/vnd.ms-powerpoint', 'potm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', 'ppa' => 'application/vnd.ms-powerpoint', 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12', 'ppd' => 'application/vnd.cups-ppd', 'ppm' => 'image/x-portable-pixmap', 'pps' => 'application/vnd.ms-powerpoint', 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12', 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', 'ppt' => 'application/powerpoint', 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'pqa' => 'application/vnd.palm', 'prc' => 'model/prc', 'pre' => 'application/vnd.lotus-freelance', 'prf' => 'application/pics-rules', 'provx' => 'application/provenance+xml', 'ps' => 'application/postscript', 'psb' => 'application/vnd.3gpp.pic-bw-small', 'psd' => 'application/x-photoshop', 'psf' => 'application/x-font-linux-psf', 'pskcxml' => 'application/pskc+xml', 'pti' => 'image/prs.pti', 'ptid' => 'application/vnd.pvi.ptid1', 'pub' => 'application/x-mspublisher', 'pvb' => 'application/vnd.3gpp.pic-bw-var', 'pwn' => 'application/vnd.3m.post-it-notes', 'pya' => 'audio/vnd.ms-playready.media.pya', 'pyv' => 'video/vnd.ms-playready.media.pyv', 'qam' => 'application/vnd.epson.quickanime', 'qbo' => 'application/vnd.intu.qbo', 'qfx' => 'application/vnd.intu.qfx', 'qps' => 'application/vnd.publishare-delta-tree', 'qt' => 'video/quicktime', 'qwd' => 'application/vnd.quark.quarkxpress', 'qwt' => 'application/vnd.quark.quarkxpress', 'qxb' => 'application/vnd.quark.quarkxpress', 'qxd' => 'application/vnd.quark.quarkxpress', 'qxl' => 'application/vnd.quark.quarkxpress', 'qxt' => 'application/vnd.quark.quarkxpress', 'ra' => 'audio/x-realaudio', 'ram' => 'audio/x-pn-realaudio', 'raml' => 'application/raml+yaml', 'rapd' => 'application/route-apd+xml', 'rar' => 'application/x-rar', 'ras' => 'image/x-cmu-raster', 'rcprofile' => 'application/vnd.ipunplugged.rcprofile', 'rdf' => 'application/rdf+xml', 'rdz' => 'application/vnd.data-vision.rdz', 'relo' => 'application/p2p-overlay+xml', 'rep' => 'application/vnd.businessobjects', 'res' => 'application/x-dtbresource+xml', 'rgb' => 'image/x-rgb', 'rif' => 'application/reginfo+xml', 'rip' => 'audio/vnd.rip', 'ris' => 'application/x-research-info-systems', 'rl' => 'application/resource-lists+xml', 'rlc' => 'image/vnd.fujixerox.edmics-rlc', 'rld' => 'application/resource-lists-diff+xml', 'rm' => 'audio/x-pn-realaudio', 'rmi' => 'audio/midi', 'rmp' => 'audio/x-pn-realaudio-plugin', 'rms' => 'application/vnd.jcp.javame.midlet-rms', 'rmvb' => 'application/vnd.rn-realmedia-vbr', 'rnc' => 'application/relax-ng-compact-syntax', 'rng' => 'application/xml', 'roa' => 'application/rpki-roa', 'roff' => 'text/troff', 'rp9' => 'application/vnd.cloanto.rp9', 'rpm' => 'audio/x-pn-realaudio-plugin', 'rpss' => 'application/vnd.nokia.radio-presets', 'rpst' => 'application/vnd.nokia.radio-preset', 'rq' => 'application/sparql-query', 'rs' => 'application/rls-services+xml', 'rsa' => 'application/x-pkcs7', 'rsat' => 'application/atsc-rsat+xml', 'rsd' => 'application/rsd+xml', 'rsheet' => 'application/urc-ressheet+xml', 'rss' => 'application/rss+xml', 'rtf' => 'text/rtf', 'rtx' => 'text/richtext', 'run' => 'application/x-makeself', 'rusd' => 'application/route-usd+xml', 'rv' => 'video/vnd.rn-realvideo', 's' => 'text/x-asm', 's3m' => 'audio/s3m', 'saf' => 'application/vnd.yamaha.smaf-audio', 'sass' => 'text/x-sass', 'sbml' => 'application/sbml+xml', 'sc' => 'application/vnd.ibm.secure-container', 'scd' => 'application/x-msschedule', 'scm' => 'application/vnd.lotus-screencam', 'scq' => 'application/scvp-cv-request', 'scs' => 'application/scvp-cv-response', 'scss' => 'text/x-scss', 'scurl' => 'text/vnd.curl.scurl', 'sda' => 'application/vnd.stardivision.draw', 'sdc' => 'application/vnd.stardivision.calc', 'sdd' => 'application/vnd.stardivision.impress', 'sdkd' => 'application/vnd.solent.sdkm+xml', 'sdkm' => 'application/vnd.solent.sdkm+xml', 'sdp' => 'application/sdp', 'sdw' => 'application/vnd.stardivision.writer', 'sea' => 'application/octet-stream', 'see' => 'application/vnd.seemail', 'seed' => 'application/vnd.fdsn.seed', 'sema' => 'application/vnd.sema', 'semd' => 'application/vnd.semd', 'semf' => 'application/vnd.semf', 'senmlx' => 'application/senml+xml', 'sensmlx' => 'application/sensml+xml', 'ser' => 'application/java-serialized-object', 'setpay' => 'application/set-payment-initiation', 'setreg' => 'application/set-registration-initiation', 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data', 'sfs' => 'application/vnd.spotfire.sfs', 'sfv' => 'text/x-sfv', 'sgi' => 'image/sgi', 'sgl' => 'application/vnd.stardivision.writer-global', 'sgm' => 'text/sgml', 'sgml' => 'text/sgml', 'sh' => 'application/x-sh', 'shar' => 'application/x-shar', 'shex' => 'text/shex', 'shf' => 'application/shf+xml', 'shtml' => 'text/html', 'sid' => 'image/x-mrsid-image', 'sieve' => 'application/sieve', 'sig' => 'application/pgp-signature', 'sil' => 'audio/silk', 'silo' => 'model/mesh', 'sis' => 'application/vnd.symbian.install', 'sisx' => 'application/vnd.symbian.install', 'sit' => 'application/x-stuffit', 'sitx' => 'application/x-stuffitx', 'siv' => 'application/sieve', 'skd' => 'application/vnd.koan', 'skm' => 'application/vnd.koan', 'skp' => 'application/vnd.koan', 'skt' => 'application/vnd.koan', 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12', 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', 'slim' => 'text/slim', 'slm' => 'text/slim', 'sls' => 'application/route-s-tsid+xml', 'slt' => 'application/vnd.epson.salt', 'sm' => 'application/vnd.stepmania.stepchart', 'smf' => 'application/vnd.stardivision.math', 'smi' => 'application/smil', 'smil' => 'application/smil', 'smv' => 'video/x-smv', 'smzip' => 'application/vnd.stepmania.package', 'snd' => 'audio/basic', 'snf' => 'application/x-font-snf', 'so' => 'application/octet-stream', 'spc' => 'application/x-pkcs7-certificates', 'spdx' => 'text/spdx', 'spf' => 'application/vnd.yamaha.smaf-phrase', 'spl' => 'application/x-futuresplash', 'spot' => 'text/vnd.in3d.spot', 'spp' => 'application/scvp-vp-response', 'spq' => 'application/scvp-vp-request', 'spx' => 'audio/ogg', 'sql' => 'application/x-sql', 'src' => 'application/x-wais-source', 'srt' => 'application/x-subrip', 'sru' => 'application/sru+xml', 'srx' => 'application/sparql-results+xml', 'ssdl' => 'application/ssdl+xml', 'sse' => 'application/vnd.kodak-descriptor', 'ssf' => 'application/vnd.epson.ssf', 'ssml' => 'application/ssml+xml', 'sst' => 'application/octet-stream', 'st' => 'application/vnd.sailingtracker.track', 'stc' => 'application/vnd.sun.xml.calc.template', 'std' => 'application/vnd.sun.xml.draw.template', 'stf' => 'application/vnd.wt.stf', 'sti' => 'application/vnd.sun.xml.impress.template', 'stk' => 'application/hyperstudio', 'stl' => 'model/stl', 'stpx' => 'model/step+xml', 'stpxz' => 'model/step-xml+zip', 'stpz' => 'model/step+zip', 'str' => 'application/vnd.pg.format', 'stw' => 'application/vnd.sun.xml.writer.template', 'styl' => 'text/stylus', 'stylus' => 'text/stylus', 'sub' => 'text/vnd.dvb.subtitle', 'sus' => 'application/vnd.sus-calendar', 'susp' => 'application/vnd.sus-calendar', 'sv4cpio' => 'application/x-sv4cpio', 'sv4crc' => 'application/x-sv4crc', 'svc' => 'application/vnd.dvb.service', 'svd' => 'application/vnd.svd', 'svg' => 'image/svg+xml', 'svgz' => 'image/svg+xml', 'swa' => 'application/x-director', 'swf' => 'application/x-shockwave-flash', 'swi' => 'application/vnd.aristanetworks.swi', 'swidtag' => 'application/swid+xml', 'sxc' => 'application/vnd.sun.xml.calc', 'sxd' => 'application/vnd.sun.xml.draw', 'sxg' => 'application/vnd.sun.xml.writer.global', 'sxi' => 'application/vnd.sun.xml.impress', 'sxm' => 'application/vnd.sun.xml.math', 'sxw' => 'application/vnd.sun.xml.writer', 't' => 'text/troff', 't3' => 'application/x-t3vm-image', 't38' => 'image/t38', 'taglet' => 'application/vnd.mynfc', 'tao' => 'application/vnd.tao.intent-module-archive', 'tap' => 'image/vnd.tencent.tap', 'tar' => 'application/x-tar', 'tcap' => 'application/vnd.3gpp2.tcap', 'tcl' => 'application/x-tcl', 'td' => 'application/urc-targetdesc+xml', 'teacher' => 'application/vnd.smart.teacher', 'tei' => 'application/tei+xml', 'teicorpus' => 'application/tei+xml', 'tex' => 'application/x-tex', 'texi' => 'application/x-texinfo', 'texinfo' => 'application/x-texinfo', 'text' => 'text/plain', 'tfi' => 'application/thraud+xml', 'tfm' => 'application/x-tex-tfm', 'tfx' => 'image/tiff-fx', 'tga' => 'image/x-tga', 'tgz' => 'application/x-tar', 'thmx' => 'application/vnd.ms-officetheme', 'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'tk' => 'application/x-tcl', 'tmo' => 'application/vnd.tmobile-livetv', 'toml' => 'application/toml', 'torrent' => 'application/x-bittorrent', 'tpl' => 'application/vnd.groove-tool-template', 'tpt' => 'application/vnd.trid.tpt', 'tr' => 'text/troff', 'tra' => 'application/vnd.trueapp', 'trig' => 'application/trig', 'trm' => 'application/x-msterminal', 'ts' => 'video/mp2t', 'tsd' => 'application/timestamped-data', 'tsv' => 'text/tab-separated-values', 'ttc' => 'font/collection', 'ttf' => 'font/ttf', 'ttl' => 'text/turtle', 'ttml' => 'application/ttml+xml', 'twd' => 'application/vnd.simtech-mindmapper', 'twds' => 'application/vnd.simtech-mindmapper', 'txd' => 'application/vnd.genomatix.tuxedo', 'txf' => 'application/vnd.mobius.txf', 'txt' => 'text/plain', 'u3d' => 'model/u3d', 'u8dsn' => 'message/global-delivery-status', 'u8hdr' => 'message/global-headers', 'u8mdn' => 'message/global-disposition-notification', 'u8msg' => 'message/global', 'u32' => 'application/x-authorware-bin', 'ubj' => 'application/ubjson', 'udeb' => 'application/x-debian-package', 'ufd' => 'application/vnd.ufdl', 'ufdl' => 'application/vnd.ufdl', 'ulx' => 'application/x-glulx', 'umj' => 'application/vnd.umajin', 'unityweb' => 'application/vnd.unity', 'uoml' => 'application/vnd.uoml+xml', 'uri' => 'text/uri-list', 'uris' => 'text/uri-list', 'urls' => 'text/uri-list', 'usdz' => 'model/vnd.usdz+zip', 'ustar' => 'application/x-ustar', 'utz' => 'application/vnd.uiq.theme', 'uu' => 'text/x-uuencode', 'uva' => 'audio/vnd.dece.audio', 'uvd' => 'application/vnd.dece.data', 'uvf' => 'application/vnd.dece.data', 'uvg' => 'image/vnd.dece.graphic', 'uvh' => 'video/vnd.dece.hd', 'uvi' => 'image/vnd.dece.graphic', 'uvm' => 'video/vnd.dece.mobile', 'uvp' => 'video/vnd.dece.pd', 'uvs' => 'video/vnd.dece.sd', 'uvt' => 'application/vnd.dece.ttml+xml', 'uvu' => 'video/vnd.uvvu.mp4', 'uvv' => 'video/vnd.dece.video', 'uvva' => 'audio/vnd.dece.audio', 'uvvd' => 'application/vnd.dece.data', 'uvvf' => 'application/vnd.dece.data', 'uvvg' => 'image/vnd.dece.graphic', 'uvvh' => 'video/vnd.dece.hd', 'uvvi' => 'image/vnd.dece.graphic', 'uvvm' => 'video/vnd.dece.mobile', 'uvvp' => 'video/vnd.dece.pd', 'uvvs' => 'video/vnd.dece.sd', 'uvvt' => 'application/vnd.dece.ttml+xml', 'uvvu' => 'video/vnd.uvvu.mp4', 'uvvv' => 'video/vnd.dece.video', 'uvvx' => 'application/vnd.dece.unspecified', 'uvvz' => 'application/vnd.dece.zip', 'uvx' => 'application/vnd.dece.unspecified', 'uvz' => 'application/vnd.dece.zip', 'vbox' => 'application/x-virtualbox-vbox', 'vbox-extpack' => 'application/x-virtualbox-vbox-extpack', 'vcard' => 'text/vcard', 'vcd' => 'application/x-cdlink', 'vcf' => 'text/x-vcard', 'vcg' => 'application/vnd.groove-vcard', 'vcs' => 'text/x-vcalendar', 'vcx' => 'application/vnd.vcx', 'vdi' => 'application/x-virtualbox-vdi', 'vds' => 'model/vnd.sap.vds', 'vhd' => 'application/x-virtualbox-vhd', 'vis' => 'application/vnd.visionary', 'viv' => 'video/vnd.vivo', 'vlc' => 'application/videolan', 'vmdk' => 'application/x-virtualbox-vmdk', 'vob' => 'video/x-ms-vob', 'vor' => 'application/vnd.stardivision.writer', 'vox' => 'application/x-authorware-bin', 'vrml' => 'model/vrml', 'vsd' => 'application/vnd.visio', 'vsf' => 'application/vnd.vsf', 'vss' => 'application/vnd.visio', 'vst' => 'application/vnd.visio', 'vsw' => 'application/vnd.visio', 'vtf' => 'image/vnd.valve.source.texture', 'vtt' => 'text/vtt', 'vtu' => 'model/vnd.vtu', 'vxml' => 'application/voicexml+xml', 'w3d' => 'application/x-director', 'wad' => 'application/x-doom', 'wadl' => 'application/vnd.sun.wadl+xml', 'war' => 'application/java-archive', 'wasm' => 'application/wasm', 'wav' => 'audio/x-wav', 'wax' => 'audio/x-ms-wax', 'wbmp' => 'image/vnd.wap.wbmp', 'wbs' => 'application/vnd.criticaltools.wbs+xml', 'wbxml' => 'application/wbxml', 'wcm' => 'application/vnd.ms-works', 'wdb' => 'application/vnd.ms-works', 'wdp' => 'image/vnd.ms-photo', 'weba' => 'audio/webm', 'webapp' => 'application/x-web-app-manifest+json', 'webm' => 'video/webm', 'webmanifest' => 'application/manifest+json', 'webp' => 'image/webp', 'wg' => 'application/vnd.pmi.widget', 'wgt' => 'application/widget', 'wif' => 'application/watcherinfo+xml', 'wks' => 'application/vnd.ms-works', 'wm' => 'video/x-ms-wm', 'wma' => 'audio/x-ms-wma', 'wmd' => 'application/x-ms-wmd', 'wmf' => 'image/wmf', 'wml' => 'text/vnd.wap.wml', 'wmlc' => 'application/wmlc', 'wmls' => 'text/vnd.wap.wmlscript', 'wmlsc' => 'application/vnd.wap.wmlscriptc', 'wmv' => 'video/x-ms-wmv', 'wmx' => 'video/x-ms-wmx', 'wmz' => 'application/x-msmetafile', 'woff' => 'font/woff', 'woff2' => 'font/woff2', 'word' => 'application/msword', 'wpd' => 'application/vnd.wordperfect', 'wpl' => 'application/vnd.ms-wpl', 'wps' => 'application/vnd.ms-works', 'wqd' => 'application/vnd.wqd', 'wri' => 'application/x-mswrite', 'wrl' => 'model/vrml', 'wsc' => 'message/vnd.wfa.wsc', 'wsdl' => 'application/wsdl+xml', 'wspolicy' => 'application/wspolicy+xml', 'wtb' => 'application/vnd.webturbo', 'wvx' => 'video/x-ms-wvx', 'x3d' => 'model/x3d+xml', 'x3db' => 'model/x3d+fastinfoset', 'x3dbz' => 'model/x3d+binary', 'x3dv' => 'model/x3d-vrml', 'x3dvz' => 'model/x3d+vrml', 'x3dz' => 'model/x3d+xml', 'x32' => 'application/x-authorware-bin', 'x_b' => 'model/vnd.parasolid.transmit.binary', 'x_t' => 'model/vnd.parasolid.transmit.text', 'xaml' => 'application/xaml+xml', 'xap' => 'application/x-silverlight-app', 'xar' => 'application/vnd.xara', 'xav' => 'application/xcap-att+xml', 'xbap' => 'application/x-ms-xbap', 'xbd' => 'application/vnd.fujixerox.docuworks.binder', 'xbm' => 'image/x-xbitmap', 'xca' => 'application/xcap-caps+xml', 'xcs' => 'application/calendar+xml', 'xdf' => 'application/xcap-diff+xml', 'xdm' => 'application/vnd.syncml.dm+xml', 'xdp' => 'application/vnd.adobe.xdp+xml', 'xdssc' => 'application/dssc+xml', 'xdw' => 'application/vnd.fujixerox.docuworks', 'xel' => 'application/xcap-el+xml', 'xenc' => 'application/xenc+xml', 'xer' => 'application/patch-ops-error+xml', 'xfdf' => 'application/vnd.adobe.xfdf', 'xfdl' => 'application/vnd.xfdl', 'xht' => 'application/xhtml+xml', 'xhtml' => 'application/xhtml+xml', 'xhvml' => 'application/xv+xml', 'xif' => 'image/vnd.xiff', 'xl' => 'application/excel', 'xla' => 'application/vnd.ms-excel', 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', 'xlc' => 'application/vnd.ms-excel', 'xlf' => 'application/xliff+xml', 'xlm' => 'application/vnd.ms-excel', 'xls' => 'application/vnd.ms-excel', 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12', 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'xlt' => 'application/vnd.ms-excel', 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12', 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', 'xlw' => 'application/vnd.ms-excel', 'xm' => 'audio/xm', 'xml' => 'application/xml', 'xns' => 'application/xcap-ns+xml', 'xo' => 'application/vnd.olpc-sugar', 'xop' => 'application/xop+xml', 'xpi' => 'application/x-xpinstall', 'xpl' => 'application/xproc+xml', 'xpm' => 'image/x-xpixmap', 'xpr' => 'application/vnd.is-xpr', 'xps' => 'application/vnd.ms-xpsdocument', 'xpw' => 'application/vnd.intercon.formnet', 'xpx' => 'application/vnd.intercon.formnet', 'xsd' => 'application/xml', 'xsl' => 'application/xml', 'xslt' => 'application/xslt+xml', 'xsm' => 'application/vnd.syncml+xml', 'xspf' => 'application/xspf+xml', 'xul' => 'application/vnd.mozilla.xul+xml', 'xvm' => 'application/xv+xml', 'xvml' => 'application/xv+xml', 'xwd' => 'image/x-xwindowdump', 'xyz' => 'chemical/x-xyz', 'xz' => 'application/x-xz', 'yaml' => 'text/yaml', 'yang' => 'application/yang', 'yin' => 'application/yin+xml', 'yml' => 'text/yaml', 'ymp' => 'text/x-suse-ymp', 'z' => 'application/x-compress', 'z1' => 'application/x-zmachine', 'z2' => 'application/x-zmachine', 'z3' => 'application/x-zmachine', 'z4' => 'application/x-zmachine', 'z5' => 'application/x-zmachine', 'z6' => 'application/x-zmachine', 'z7' => 'application/x-zmachine', 'z8' => 'application/x-zmachine', 'zaz' => 'application/vnd.zzazz.deck+xml', 'zip' => 'application/zip', 'zir' => 'application/vnd.zul', 'zirz' => 'application/vnd.zul', 'zmm' => 'application/vnd.handheld-entertainment+xml', 'zsh' => 'text/x-scriptzsh', ]; /** * Determines the mimetype of a file by looking at its extension. * * @link https://raw.githubusercontent.com/jshttp/mime-db/master/db.json */ public static function fromFilename(string $filename): ?string { return self::fromExtension(pathinfo($filename, PATHINFO_EXTENSION)); } /** * Maps a file extensions to a mimetype. * * @link https://raw.githubusercontent.com/jshttp/mime-db/master/db.json */ public static function fromExtension(string $extension): ?string { return self::MIME_TYPES[strtolower($extension)] ?? null; } } PK������Z �� ����UriNormalizer.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\UriInterface; /** * Provides methods to normalize and compare URIs. * * @author Tobias Schultze * * @link https://tools.ietf.org/html/rfc3986#section-6 */ final class UriNormalizer { /** * Default normalizations which only include the ones that preserve semantics. */ public const PRESERVING_NORMALIZATIONS = self::CAPITALIZE_PERCENT_ENCODING | self::DECODE_UNRESERVED_CHARACTERS | self::CONVERT_EMPTY_PATH | self::REMOVE_DEFAULT_HOST | self::REMOVE_DEFAULT_PORT | self::REMOVE_DOT_SEGMENTS; /** * All letters within a percent-encoding triplet (e.g., "%3A") are case-insensitive, and should be capitalized. * * Example: http://example.org/a%c2%b1b → http://example.org/a%C2%B1b */ public const CAPITALIZE_PERCENT_ENCODING = 1; /** * Decodes percent-encoded octets of unreserved characters. * * For consistency, percent-encoded octets in the ranges of ALPHA (%41–%5A and %61–%7A), DIGIT (%30–%39), * hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should not be created by URI producers and, * when found in a URI, should be decoded to their corresponding unreserved characters by URI normalizers. * * Example: http://example.org/%7Eusern%61me/ → http://example.org/~username/ */ public const DECODE_UNRESERVED_CHARACTERS = 2; /** * Converts the empty path to "/" for http and https URIs. * * Example: http://example.org → http://example.org/ */ public const CONVERT_EMPTY_PATH = 4; /** * Removes the default host of the given URI scheme from the URI. * * Only the "file" scheme defines the default host "localhost". * All of `file:/myfile`, `file:///myfile`, and `file://localhost/myfile` * are equivalent according to RFC 3986. The first format is not accepted * by PHPs stream functions and thus already normalized implicitly to the * second format in the Uri class. See `GuzzleHttp\Psr7\Uri::composeComponents`. * * Example: file://localhost/myfile → file:///myfile */ public const REMOVE_DEFAULT_HOST = 8; /** * Removes the default port of the given URI scheme from the URI. * * Example: http://example.org:80/ → http://example.org/ */ public const REMOVE_DEFAULT_PORT = 16; /** * Removes unnecessary dot-segments. * * Dot-segments in relative-path references are not removed as it would * change the semantics of the URI reference. * * Example: http://example.org/../a/b/../c/./d.html → http://example.org/a/c/d.html */ public const REMOVE_DOT_SEGMENTS = 32; /** * Paths which include two or more adjacent slashes are converted to one. * * Webservers usually ignore duplicate slashes and treat those URIs equivalent. * But in theory those URIs do not need to be equivalent. So this normalization * may change the semantics. Encoded slashes (%2F) are not removed. * * Example: http://example.org//foo///bar.html → http://example.org/foo/bar.html */ public const REMOVE_DUPLICATE_SLASHES = 64; /** * Sort query parameters with their values in alphabetical order. * * However, the order of parameters in a URI may be significant (this is not defined by the standard). * So this normalization is not safe and may change the semantics of the URI. * * Example: ?lang=en&article=fred → ?article=fred&lang=en * * Note: The sorting is neither locale nor Unicode aware (the URI query does not get decoded at all) as the * purpose is to be able to compare URIs in a reproducible way, not to have the params sorted perfectly. */ public const SORT_QUERY_PARAMETERS = 128; /** * Returns a normalized URI. * * The scheme and host component are already normalized to lowercase per PSR-7 UriInterface. * This methods adds additional normalizations that can be configured with the $flags parameter. * * PSR-7 UriInterface cannot distinguish between an empty component and a missing component as * getQuery(), getFragment() etc. always return a string. This means the URIs "/?#" and "/" are * treated equivalent which is not necessarily true according to RFC 3986. But that difference * is highly uncommon in reality. So this potential normalization is implied in PSR-7 as well. * * @param UriInterface $uri The URI to normalize * @param int $flags A bitmask of normalizations to apply, see constants * * @link https://tools.ietf.org/html/rfc3986#section-6.2 */ public static function normalize(UriInterface $uri, int $flags = self::PRESERVING_NORMALIZATIONS): UriInterface { if ($flags & self::CAPITALIZE_PERCENT_ENCODING) { $uri = self::capitalizePercentEncoding($uri); } if ($flags & self::DECODE_UNRESERVED_CHARACTERS) { $uri = self::decodeUnreservedCharacters($uri); } if ($flags & self::CONVERT_EMPTY_PATH && $uri->getPath() === '' && ($uri->getScheme() === 'http' || $uri->getScheme() === 'https') ) { $uri = $uri->withPath('/'); } if ($flags & self::REMOVE_DEFAULT_HOST && $uri->getScheme() === 'file' && $uri->getHost() === 'localhost') { $uri = $uri->withHost(''); } if ($flags & self::REMOVE_DEFAULT_PORT && $uri->getPort() !== null && Uri::isDefaultPort($uri)) { $uri = $uri->withPort(null); } if ($flags & self::REMOVE_DOT_SEGMENTS && !Uri::isRelativePathReference($uri)) { $uri = $uri->withPath(UriResolver::removeDotSegments($uri->getPath())); } if ($flags & self::REMOVE_DUPLICATE_SLASHES) { $uri = $uri->withPath(preg_replace('#//++#', '/', $uri->getPath())); } if ($flags & self::SORT_QUERY_PARAMETERS && $uri->getQuery() !== '') { $queryKeyValues = explode('&', $uri->getQuery()); sort($queryKeyValues); $uri = $uri->withQuery(implode('&', $queryKeyValues)); } return $uri; } /** * Whether two URIs can be considered equivalent. * * Both URIs are normalized automatically before comparison with the given $normalizations bitmask. The method also * accepts relative URI references and returns true when they are equivalent. This of course assumes they will be * resolved against the same base URI. If this is not the case, determination of equivalence or difference of * relative references does not mean anything. * * @param UriInterface $uri1 An URI to compare * @param UriInterface $uri2 An URI to compare * @param int $normalizations A bitmask of normalizations to apply, see constants * * @link https://tools.ietf.org/html/rfc3986#section-6.1 */ public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, int $normalizations = self::PRESERVING_NORMALIZATIONS): bool { return (string) self::normalize($uri1, $normalizations) === (string) self::normalize($uri2, $normalizations); } private static function capitalizePercentEncoding(UriInterface $uri): UriInterface { $regex = '/(?:%[A-Fa-f0-9]{2})++/'; $callback = function (array $match) { return strtoupper($match[0]); }; return $uri->withPath( preg_replace_callback($regex, $callback, $uri->getPath()) )->withQuery( preg_replace_callback($regex, $callback, $uri->getQuery()) ); } private static function decodeUnreservedCharacters(UriInterface $uri): UriInterface { $regex = '/%(?:2D|2E|5F|7E|3[0-9]|[46][1-9A-F]|[57][0-9A])/i'; $callback = function (array $match) { return rawurldecode($match[0]); }; return $uri->withPath( preg_replace_callback($regex, $callback, $uri->getPath()) )->withQuery( preg_replace_callback($regex, $callback, $uri->getQuery()) ); } private function __construct() { // cannot be instantiated } } PK������ZC~ �� ����StreamWrapper.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** * Converts Guzzle streams into PHP stream resources. * * @see https://www.php.net/streamwrapper */ final class StreamWrapper { /** @var resource */ public $context; /** @var StreamInterface */ private $stream; /** @var string r, r+, or w */ private $mode; /** * Returns a resource representing the stream. * * @param StreamInterface $stream The stream to get a resource for * * @return resource * * @throws \InvalidArgumentException if stream is not readable or writable */ public static function getResource(StreamInterface $stream) { self::register(); if ($stream->isReadable()) { $mode = $stream->isWritable() ? 'r+' : 'r'; } elseif ($stream->isWritable()) { $mode = 'w'; } else { throw new \InvalidArgumentException('The stream must be readable, ' . 'writable, or both.'); } return fopen('guzzle://stream', $mode, false, self::createStreamContext($stream)); } /** * Creates a stream context that can be used to open a stream as a php stream resource. * * @return resource */ public static function createStreamContext(StreamInterface $stream) { return stream_context_create([ 'guzzle' => ['stream' => $stream] ]); } /** * Registers the stream wrapper if needed */ public static function register(): void { if (!in_array('guzzle', stream_get_wrappers())) { stream_wrapper_register('guzzle', __CLASS__); } } public function stream_open(string $path, string $mode, int $options, string &$opened_path = null): bool { $options = stream_context_get_options($this->context); if (!isset($options['guzzle']['stream'])) { return false; } $this->mode = $mode; $this->stream = $options['guzzle']['stream']; return true; } public function stream_read(int $count): string { return $this->stream->read($count); } public function stream_write(string $data): int { return $this->stream->write($data); } public function stream_tell(): int { return $this->stream->tell(); } public function stream_eof(): bool { return $this->stream->eof(); } public function stream_seek(int $offset, int $whence): bool { $this->stream->seek($offset, $whence); return true; } /** * @return resource|false */ public function stream_cast(int $cast_as) { $stream = clone($this->stream); $resource = $stream->detach(); return $resource ?? false; } /** * @return array<int|string, int> */ public function stream_stat(): array { static $modeMap = [ 'r' => 33060, 'rb' => 33060, 'r+' => 33206, 'w' => 33188, 'wb' => 33188 ]; return [ 'dev' => 0, 'ino' => 0, 'mode' => $modeMap[$this->mode], 'nlink' => 0, 'uid' => 0, 'gid' => 0, 'rdev' => 0, 'size' => $this->stream->getSize() ?: 0, 'atime' => 0, 'mtime' => 0, 'ctime' => 0, 'blksize' => 0, 'blocks' => 0 ]; } /** * @return array<int|string, int> */ public function url_stat(string $path, int $flags): array { return [ 'dev' => 0, 'ino' => 0, 'mode' => 0, 'nlink' => 0, 'uid' => 0, 'gid' => 0, 'rdev' => 0, 'size' => 0, 'atime' => 0, 'mtime' => 0, 'ctime' => 0, 'blksize' => 0, 'blocks' => 0 ]; } } PK������Z3� �� �� ��Message.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\MessageInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; final class Message { /** * Returns the string representation of an HTTP message. * * @param MessageInterface $message Message to convert to a string. */ public static function toString(MessageInterface $message): string { if ($message instanceof RequestInterface) { $msg = trim($message->getMethod() . ' ' . $message->getRequestTarget()) . ' HTTP/' . $message->getProtocolVersion(); if (!$message->hasHeader('host')) { $msg .= "\r\nHost: " . $message->getUri()->getHost(); } } elseif ($message instanceof ResponseInterface) { $msg = 'HTTP/' . $message->getProtocolVersion() . ' ' . $message->getStatusCode() . ' ' . $message->getReasonPhrase(); } else { throw new \InvalidArgumentException('Unknown message type'); } foreach ($message->getHeaders() as $name => $values) { if (strtolower($name) === 'set-cookie') { foreach ($values as $value) { $msg .= "\r\n{$name}: " . $value; } } else { $msg .= "\r\n{$name}: " . implode(', ', $values); } } return "{$msg}\r\n\r\n" . $message->getBody(); } /** * Get a short summary of the message body. * * Will return `null` if the response is not printable. * * @param MessageInterface $message The message to get the body summary * @param int $truncateAt The maximum allowed size of the summary */ public static function bodySummary(MessageInterface $message, int $truncateAt = 120): ?string { $body = $message->getBody(); if (!$body->isSeekable() || !$body->isReadable()) { return null; } $size = $body->getSize(); if ($size === 0) { return null; } $body->rewind(); $summary = $body->read($truncateAt); $body->rewind(); if ($size > $truncateAt) { $summary .= ' (truncated...)'; } // Matches any printable character, including unicode characters: // letters, marks, numbers, punctuation, spacing, and separators. if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/u', $summary) !== 0) { return null; } return $summary; } /** * Attempts to rewind a message body and throws an exception on failure. * * The body of the message will only be rewound if a call to `tell()` * returns a value other than `0`. * * @param MessageInterface $message Message to rewind * * @throws \RuntimeException */ public static function rewindBody(MessageInterface $message): void { $body = $message->getBody(); if ($body->tell()) { $body->rewind(); } } /** * Parses an HTTP message into an associative array. * * The array contains the "start-line" key containing the start line of * the message, "headers" key containing an associative array of header * array values, and a "body" key containing the body of the message. * * @param string $message HTTP request or response to parse. */ public static function parseMessage(string $message): array { if (!$message) { throw new \InvalidArgumentException('Invalid message'); } $message = ltrim($message, "\r\n"); $messageParts = preg_split("/\r?\n\r?\n/", $message, 2); if ($messageParts === false || count($messageParts) !== 2) { throw new \InvalidArgumentException('Invalid message: Missing header delimiter'); } [$rawHeaders, $body] = $messageParts; $rawHeaders .= "\r\n"; // Put back the delimiter we split previously $headerParts = preg_split("/\r?\n/", $rawHeaders, 2); if ($headerParts === false || count($headerParts) !== 2) { throw new \InvalidArgumentException('Invalid message: Missing status line'); } [$startLine, $rawHeaders] = $headerParts; if (preg_match("/(?:^HTTP\/|^[A-Z]+ \S+ HTTP\/)(\d+(?:\.\d+)?)/i", $startLine, $matches) && $matches[1] === '1.0') { // Header folding is deprecated for HTTP/1.1, but allowed in HTTP/1.0 $rawHeaders = preg_replace(Rfc7230::HEADER_FOLD_REGEX, ' ', $rawHeaders); } /** @var array[] $headerLines */ $count = preg_match_all(Rfc7230::HEADER_REGEX, $rawHeaders, $headerLines, PREG_SET_ORDER); // If these aren't the same, then one line didn't match and there's an invalid header. if ($count !== substr_count($rawHeaders, "\n")) { // Folding is deprecated, see https://tools.ietf.org/html/rfc7230#section-3.2.4 if (preg_match(Rfc7230::HEADER_FOLD_REGEX, $rawHeaders)) { throw new \InvalidArgumentException('Invalid header syntax: Obsolete line folding'); } throw new \InvalidArgumentException('Invalid header syntax'); } $headers = []; foreach ($headerLines as $headerLine) { $headers[$headerLine[1]][] = $headerLine[2]; } return [ 'start-line' => $startLine, 'headers' => $headers, 'body' => $body, ]; } /** * Constructs a URI for an HTTP request message. * * @param string $path Path from the start-line * @param array $headers Array of headers (each value an array). */ public static function parseRequestUri(string $path, array $headers): string { $hostKey = array_filter(array_keys($headers), function ($k) { // Numeric array keys are converted to int by PHP. $k = (string) $k; return strtolower($k) === 'host'; }); // If no host is found, then a full URI cannot be constructed. if (!$hostKey) { return $path; } $host = $headers[reset($hostKey)][0]; $scheme = substr($host, -4) === ':443' ? 'https' : 'http'; return $scheme . '://' . $host . '/' . ltrim($path, '/'); } /** * Parses a request message string into a request object. * * @param string $message Request message string. */ public static function parseRequest(string $message): RequestInterface { $data = self::parseMessage($message); $matches = []; if (!preg_match('/^[\S]+\s+([a-zA-Z]+:\/\/|\/).*/', $data['start-line'], $matches)) { throw new \InvalidArgumentException('Invalid request string'); } $parts = explode(' ', $data['start-line'], 3); $version = isset($parts[2]) ? explode('/', $parts[2])[1] : '1.1'; $request = new Request( $parts[0], $matches[1] === '/' ? self::parseRequestUri($parts[1], $data['headers']) : $parts[1], $data['headers'], $data['body'], $version ); return $matches[1] === '/' ? $request : $request->withRequestTarget($parts[1]); } /** * Parses a response message string into a response object. * * @param string $message Response message string. */ public static function parseResponse(string $message): ResponseInterface { $data = self::parseMessage($message); // According to https://tools.ietf.org/html/rfc7230#section-3.1.2 the space // between status-code and reason-phrase is required. But browsers accept // responses without space and reason as well. if (!preg_match('/^HTTP\/.* [0-9]{3}( .*|$)/', $data['start-line'])) { throw new \InvalidArgumentException('Invalid response string: ' . $data['start-line']); } $parts = explode(' ', $data['start-line'], 3); return new Response( (int) $parts[1], $data['headers'], $data['body'], explode('/', $parts[0])[1], $parts[2] ?? null ); } } PK������ZXX��X����AppendStream.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** * Reads from multiple streams, one after the other. * * This is a read-only stream decorator. */ final class AppendStream implements StreamInterface { /** @var StreamInterface[] Streams being decorated */ private $streams = []; /** @var bool */ private $seekable = true; /** @var int */ private $current = 0; /** @var int */ private $pos = 0; /** * @param StreamInterface[] $streams Streams to decorate. Each stream must * be readable. */ public function __construct(array $streams = []) { foreach ($streams as $stream) { $this->addStream($stream); } } public function __toString(): string { try { $this->rewind(); return $this->getContents(); } catch (\Throwable $e) { if (\PHP_VERSION_ID >= 70400) { throw $e; } trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); return ''; } } /** * Add a stream to the AppendStream * * @param StreamInterface $stream Stream to append. Must be readable. * * @throws \InvalidArgumentException if the stream is not readable */ public function addStream(StreamInterface $stream): void { if (!$stream->isReadable()) { throw new \InvalidArgumentException('Each stream must be readable'); } // The stream is only seekable if all streams are seekable if (!$stream->isSeekable()) { $this->seekable = false; } $this->streams[] = $stream; } public function getContents(): string { return Utils::copyToString($this); } /** * Closes each attached stream. */ public function close(): void { $this->pos = $this->current = 0; $this->seekable = true; foreach ($this->streams as $stream) { $stream->close(); } $this->streams = []; } /** * Detaches each attached stream. * * Returns null as it's not clear which underlying stream resource to return. */ public function detach() { $this->pos = $this->current = 0; $this->seekable = true; foreach ($this->streams as $stream) { $stream->detach(); } $this->streams = []; return null; } public function tell(): int { return $this->pos; } /** * Tries to calculate the size by adding the size of each stream. * * If any of the streams do not return a valid number, then the size of the * append stream cannot be determined and null is returned. */ public function getSize(): ?int { $size = 0; foreach ($this->streams as $stream) { $s = $stream->getSize(); if ($s === null) { return null; } $size += $s; } return $size; } public function eof(): bool { return !$this->streams || ($this->current >= count($this->streams) - 1 && $this->streams[$this->current]->eof()); } public function rewind(): void { $this->seek(0); } /** * Attempts to seek to the given position. Only supports SEEK_SET. */ public function seek($offset, $whence = SEEK_SET): void { if (!$this->seekable) { throw new \RuntimeException('This AppendStream is not seekable'); } elseif ($whence !== SEEK_SET) { throw new \RuntimeException('The AppendStream can only seek with SEEK_SET'); } $this->pos = $this->current = 0; // Rewind each stream foreach ($this->streams as $i => $stream) { try { $stream->rewind(); } catch (\Exception $e) { throw new \RuntimeException('Unable to seek stream ' . $i . ' of the AppendStream', 0, $e); } } // Seek to the actual position by reading from each stream while ($this->pos < $offset && !$this->eof()) { $result = $this->read(min(8096, $offset - $this->pos)); if ($result === '') { break; } } } /** * Reads from all of the appended streams until the length is met or EOF. */ public function read($length): string { $buffer = ''; $total = count($this->streams) - 1; $remaining = $length; $progressToNext = false; while ($remaining > 0) { // Progress to the next stream if needed. if ($progressToNext || $this->streams[$this->current]->eof()) { $progressToNext = false; if ($this->current === $total) { break; } $this->current++; } $result = $this->streams[$this->current]->read($remaining); if ($result === '') { $progressToNext = true; continue; } $buffer .= $result; $remaining = $length - strlen($buffer); } $this->pos += strlen($buffer); return $buffer; } public function isReadable(): bool { return true; } public function isWritable(): bool { return false; } public function isSeekable(): bool { return $this->seekable; } public function write($string): int { throw new \RuntimeException('Cannot write to an AppendStream'); } /** * {@inheritdoc} * * @return mixed */ public function getMetadata($key = null) { return $key ? null : []; } } PK������ZL��L����MessageTrait.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\MessageInterface; use Psr\Http\Message\StreamInterface; /** * Trait implementing functionality common to requests and responses. */ trait MessageTrait { /** @var array<string, string[]> Map of all registered headers, as original name => array of values */ private $headers = []; /** @var array<string, string> Map of lowercase header name => original name at registration */ private $headerNames = []; /** @var string */ private $protocol = '1.1'; /** @var StreamInterface|null */ private $stream; public function getProtocolVersion(): string { return $this->protocol; } public function withProtocolVersion($version): MessageInterface { if ($this->protocol === $version) { return $this; } $new = clone $this; $new->protocol = $version; return $new; } public function getHeaders(): array { return $this->headers; } public function hasHeader($header): bool { return isset($this->headerNames[strtolower($header)]); } public function getHeader($header): array { $header = strtolower($header); if (!isset($this->headerNames[$header])) { return []; } $header = $this->headerNames[$header]; return $this->headers[$header]; } public function getHeaderLine($header): string { return implode(', ', $this->getHeader($header)); } public function withHeader($header, $value): MessageInterface { $this->assertHeader($header); $value = $this->normalizeHeaderValue($value); $normalized = strtolower($header); $new = clone $this; if (isset($new->headerNames[$normalized])) { unset($new->headers[$new->headerNames[$normalized]]); } $new->headerNames[$normalized] = $header; $new->headers[$header] = $value; return $new; } public function withAddedHeader($header, $value): MessageInterface { $this->assertHeader($header); $value = $this->normalizeHeaderValue($value); $normalized = strtolower($header); $new = clone $this; if (isset($new->headerNames[$normalized])) { $header = $this->headerNames[$normalized]; $new->headers[$header] = array_merge($this->headers[$header], $value); } else { $new->headerNames[$normalized] = $header; $new->headers[$header] = $value; } return $new; } public function withoutHeader($header): MessageInterface { $normalized = strtolower($header); if (!isset($this->headerNames[$normalized])) { return $this; } $header = $this->headerNames[$normalized]; $new = clone $this; unset($new->headers[$header], $new->headerNames[$normalized]); return $new; } public function getBody(): StreamInterface { if (!$this->stream) { $this->stream = Utils::streamFor(''); } return $this->stream; } public function withBody(StreamInterface $body): MessageInterface { if ($body === $this->stream) { return $this; } $new = clone $this; $new->stream = $body; return $new; } /** * @param array<string|int, string|string[]> $headers */ private function setHeaders(array $headers): void { $this->headerNames = $this->headers = []; foreach ($headers as $header => $value) { // Numeric array keys are converted to int by PHP. $header = (string) $header; $this->assertHeader($header); $value = $this->normalizeHeaderValue($value); $normalized = strtolower($header); if (isset($this->headerNames[$normalized])) { $header = $this->headerNames[$normalized]; $this->headers[$header] = array_merge($this->headers[$header], $value); } else { $this->headerNames[$normalized] = $header; $this->headers[$header] = $value; } } } /** * @param mixed $value * * @return string[] */ private function normalizeHeaderValue($value): array { if (!is_array($value)) { return $this->trimAndValidateHeaderValues([$value]); } if (count($value) === 0) { throw new \InvalidArgumentException('Header value can not be an empty array.'); } return $this->trimAndValidateHeaderValues($value); } /** * Trims whitespace from the header values. * * Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field. * * header-field = field-name ":" OWS field-value OWS * OWS = *( SP / HTAB ) * * @param mixed[] $values Header values * * @return string[] Trimmed header values * * @see https://tools.ietf.org/html/rfc7230#section-3.2.4 */ private function trimAndValidateHeaderValues(array $values): array { return array_map(function ($value) { if (!is_scalar($value) && null !== $value) { throw new \InvalidArgumentException(sprintf( 'Header value must be scalar or null but %s provided.', is_object($value) ? get_class($value) : gettype($value) )); } $trimmed = trim((string) $value, " \t"); $this->assertValue($trimmed); return $trimmed; }, array_values($values)); } /** * @see https://tools.ietf.org/html/rfc7230#section-3.2 * * @param mixed $header */ private function assertHeader($header): void { if (!is_string($header)) { throw new \InvalidArgumentException(sprintf( 'Header name must be a string but %s provided.', is_object($header) ? get_class($header) : gettype($header) )); } if (! preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/D', $header)) { throw new \InvalidArgumentException( sprintf('"%s" is not valid header name.', $header) ); } } /** * @see https://tools.ietf.org/html/rfc7230#section-3.2 * * field-value = *( field-content / obs-fold ) * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] * field-vchar = VCHAR / obs-text * VCHAR = %x21-7E * obs-text = %x80-FF * obs-fold = CRLF 1*( SP / HTAB ) */ private function assertValue(string $value): void { // The regular expression intentionally does not support the obs-fold production, because as // per RFC 7230#3.2.4: // // A sender MUST NOT generate a message that includes // line folding (i.e., that has any field-value that contains a match to // the obs-fold rule) unless the message is intended for packaging // within the message/http media type. // // Clients must not send a request with line folding and a server sending folded headers is // likely very rare. Line folding is a fairly obscure feature of HTTP/1.1 and thus not accepting // folding is not likely to break any legitimate use case. if (! preg_match('/^[\x20\x09\x21-\x7E\x80-\xFF]*$/D', $value)) { throw new \InvalidArgumentException( sprintf('"%s" is not valid header value.', $value) ); } } } PK������Z �� ����HttpFactory.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\RequestFactoryInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseFactoryInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestFactoryInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\StreamFactoryInterface; use Psr\Http\Message\StreamInterface; use Psr\Http\Message\UploadedFileFactoryInterface; use Psr\Http\Message\UploadedFileInterface; use Psr\Http\Message\UriFactoryInterface; use Psr\Http\Message\UriInterface; /** * Implements all of the PSR-17 interfaces. * * Note: in consuming code it is recommended to require the implemented interfaces * and inject the instance of this class multiple times. */ final class HttpFactory implements RequestFactoryInterface, ResponseFactoryInterface, ServerRequestFactoryInterface, StreamFactoryInterface, UploadedFileFactoryInterface, UriFactoryInterface { public function createUploadedFile( StreamInterface $stream, int $size = null, int $error = \UPLOAD_ERR_OK, string $clientFilename = null, string $clientMediaType = null ): UploadedFileInterface { if ($size === null) { $size = $stream->getSize(); } return new UploadedFile($stream, $size, $error, $clientFilename, $clientMediaType); } public function createStream(string $content = ''): StreamInterface { return Utils::streamFor($content); } public function createStreamFromFile(string $file, string $mode = 'r'): StreamInterface { try { $resource = Utils::tryFopen($file, $mode); } catch (\RuntimeException $e) { if ('' === $mode || false === \in_array($mode[0], ['r', 'w', 'a', 'x', 'c'], true)) { throw new \InvalidArgumentException(sprintf('Invalid file opening mode "%s"', $mode), 0, $e); } throw $e; } return Utils::streamFor($resource); } public function createStreamFromResource($resource): StreamInterface { return Utils::streamFor($resource); } public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface { if (empty($method)) { if (!empty($serverParams['REQUEST_METHOD'])) { $method = $serverParams['REQUEST_METHOD']; } else { throw new \InvalidArgumentException('Cannot determine HTTP method'); } } return new ServerRequest($method, $uri, [], null, '1.1', $serverParams); } public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface { return new Response($code, [], null, '1.1', $reasonPhrase); } public function createRequest(string $method, $uri): RequestInterface { return new Request($method, $uri); } public function createUri(string $uri = ''): UriInterface { return new Uri($uri); } } PK������Z �� �� ��Utils.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Promise; final class Utils { /** * Get the global task queue used for promise resolution. * * This task queue MUST be run in an event loop in order for promises to be * settled asynchronously. It will be automatically run when synchronously * waiting on a promise. * * <code> * while ($eventLoop->isRunning()) { * GuzzleHttp\Promise\Utils::queue()->run(); * } * </code> * * @param TaskQueueInterface|null $assign Optionally specify a new queue instance. */ public static function queue(TaskQueueInterface $assign = null): TaskQueueInterface { static $queue; if ($assign) { $queue = $assign; } elseif (!$queue) { $queue = new TaskQueue(); } return $queue; } /** * Adds a function to run in the task queue when it is next `run()` and * returns a promise that is fulfilled or rejected with the result. * * @param callable $task Task function to run. */ public static function task(callable $task): PromiseInterface { $queue = self::queue(); $promise = new Promise([$queue, 'run']); $queue->add(function () use ($task, $promise): void { try { if (Is::pending($promise)) { $promise->resolve($task()); } } catch (\Throwable $e) { $promise->reject($e); } }); return $promise; } /** * Synchronously waits on a promise to resolve and returns an inspection * state array. * * Returns a state associative array containing a "state" key mapping to a * valid promise state. If the state of the promise is "fulfilled", the * array will contain a "value" key mapping to the fulfilled value of the * promise. If the promise is rejected, the array will contain a "reason" * key mapping to the rejection reason of the promise. * * @param PromiseInterface $promise Promise or value. */ public static function inspect(PromiseInterface $promise): array { try { return [ 'state' => PromiseInterface::FULFILLED, 'value' => $promise->wait(), ]; } catch (RejectionException $e) { return ['state' => PromiseInterface::REJECTED, 'reason' => $e->getReason()]; } catch (\Throwable $e) { return ['state' => PromiseInterface::REJECTED, 'reason' => $e]; } } /** * Waits on all of the provided promises, but does not unwrap rejected * promises as thrown exception. * * Returns an array of inspection state arrays. * * @see inspect for the inspection state array format. * * @param PromiseInterface[] $promises Traversable of promises to wait upon. */ public static function inspectAll($promises): array { $results = []; foreach ($promises as $key => $promise) { $results[$key] = self::inspect($promise); } return $results; } /** * Waits on all of the provided promises and returns the fulfilled values. * * Returns an array that contains the value of each promise (in the same * order the promises were provided). An exception is thrown if any of the * promises are rejected. * * @param iterable<PromiseInterface> $promises Iterable of PromiseInterface objects to wait on. * * @throws \Throwable on error */ public static function unwrap($promises): array { $results = []; foreach ($promises as $key => $promise) { $results[$key] = $promise->wait(); } return $results; } /** * Given an array of promises, return a promise that is fulfilled when all * the items in the array are fulfilled. * * The promise's fulfillment value is an array with fulfillment values at * respective positions to the original array. If any promise in the array * rejects, the returned promise is rejected with the rejection reason. * * @param mixed $promises Promises or values. * @param bool $recursive If true, resolves new promises that might have been added to the stack during its own resolution. */ public static function all($promises, bool $recursive = false): PromiseInterface { $results = []; $promise = Each::of( $promises, function ($value, $idx) use (&$results): void { $results[$idx] = $value; }, function ($reason, $idx, Promise $aggregate): void { $aggregate->reject($reason); } )->then(function () use (&$results) { ksort($results); return $results; }); if (true === $recursive) { $promise = $promise->then(function ($results) use ($recursive, &$promises) { foreach ($promises as $promise) { if (Is::pending($promise)) { return self::all($promises, $recursive); } } return $results; }); } return $promise; } /** * Initiate a competitive race between multiple promises or values (values * will become immediately fulfilled promises). * * When count amount of promises have been fulfilled, the returned promise * is fulfilled with an array that contains the fulfillment values of the * winners in order of resolution. * * This promise is rejected with a {@see AggregateException} if the number * of fulfilled promises is less than the desired $count. * * @param int $count Total number of promises. * @param mixed $promises Promises or values. */ public static function some(int $count, $promises): PromiseInterface { $results = []; $rejections = []; return Each::of( $promises, function ($value, $idx, PromiseInterface $p) use (&$results, $count): void { if (Is::settled($p)) { return; } $results[$idx] = $value; if (count($results) >= $count) { $p->resolve(null); } }, function ($reason) use (&$rejections): void { $rejections[] = $reason; } )->then( function () use (&$results, &$rejections, $count) { if (count($results) !== $count) { throw new AggregateException( 'Not enough promises to fulfill count', $rejections ); } ksort($results); return array_values($results); } ); } /** * Like some(), with 1 as count. However, if the promise fulfills, the * fulfillment value is not an array of 1 but the value directly. * * @param mixed $promises Promises or values. */ public static function any($promises): PromiseInterface { return self::some(1, $promises)->then(function ($values) { return $values[0]; }); } /** * Returns a promise that is fulfilled when all of the provided promises have * been fulfilled or rejected. * * The returned promise is fulfilled with an array of inspection state arrays. * * @see inspect for the inspection state array format. * * @param mixed $promises Promises or values. */ public static function settle($promises): PromiseInterface { $results = []; return Each::of( $promises, function ($value, $idx) use (&$results): void { $results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value]; }, function ($reason, $idx) use (&$results): void { $results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason]; } )->then(function () use (&$results) { ksort($results); return $results; }); } } PK������Zg_��_�� ��Header.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; final class Header { /** * Parse an array of header values containing ";" separated data into an * array of associative arrays representing the header key value pair data * of the header. When a parameter does not contain a value, but just * contains a key, this function will inject a key with a '' string value. * * @param string|array $header Header to parse into components. */ public static function parse($header): array { static $trimmed = "\"' \n\t\r"; $params = $matches = []; foreach ((array) $header as $value) { foreach (self::splitList($value) as $val) { $part = []; foreach (preg_split('/;(?=([^"]*"[^"]*")*[^"]*$)/', $val) as $kvp) { if (preg_match_all('/<[^>]+>|[^=]+/', $kvp, $matches)) { $m = $matches[0]; if (isset($m[1])) { $part[trim($m[0], $trimmed)] = trim($m[1], $trimmed); } else { $part[] = trim($m[0], $trimmed); } } } if ($part) { $params[] = $part; } } } return $params; } /** * Converts an array of header values that may contain comma separated * headers into an array of headers with no comma separated values. * * @param string|array $header Header to normalize. * * @deprecated Use self::splitList() instead. */ public static function normalize($header): array { $result = []; foreach ((array) $header as $value) { foreach (self::splitList($value) as $parsed) { $result[] = $parsed; } } return $result; } /** * Splits a HTTP header defined to contain a comma-separated list into * each individual value. Empty values will be removed. * * Example headers include 'accept', 'cache-control' and 'if-none-match'. * * This method must not be used to parse headers that are not defined as * a list, such as 'user-agent' or 'set-cookie'. * * @param string|string[] $values Header value as returned by MessageInterface::getHeader() * * @return string[] */ public static function splitList($values): array { if (!\is_array($values)) { $values = [$values]; } $result = []; foreach ($values as $value) { if (!\is_string($value)) { throw new \TypeError('$header must either be a string or an array containing strings.'); } $v = ''; $isQuoted = false; $isEscaped = false; for ($i = 0, $max = \strlen($value); $i < $max; $i++) { if ($isEscaped) { $v .= $value[$i]; $isEscaped = false; continue; } if (!$isQuoted && $value[$i] === ',') { $v = \trim($v); if ($v !== '') { $result[] = $v; } $v = ''; continue; } if ($isQuoted && $value[$i] === '\\') { $isEscaped = true; $v .= $value[$i]; continue; } if ($value[$i] === '"') { $isQuoted = !$isQuoted; $v .= $value[$i]; continue; } $v .= $value[$i]; } $v = \trim($v); if ($v !== '') { $result[] = $v; } } return $result; } } PK������Zmd������PumpStream.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** * Provides a read only stream that pumps data from a PHP callable. * * When invoking the provided callable, the PumpStream will pass the amount of * data requested to read to the callable. The callable can choose to ignore * this value and return fewer or more bytes than requested. Any extra data * returned by the provided callable is buffered internally until drained using * the read() function of the PumpStream. The provided callable MUST return * false when there is no more data to read. */ final class PumpStream implements StreamInterface { /** @var callable|null */ private $source; /** @var int|null */ private $size; /** @var int */ private $tellPos = 0; /** @var array */ private $metadata; /** @var BufferStream */ private $buffer; /** * @param callable(int): (string|null|false) $source Source of the stream data. The callable MAY * accept an integer argument used to control the * amount of data to return. The callable MUST * return a string when called, or false|null on error * or EOF. * @param array{size?: int, metadata?: array} $options Stream options: * - metadata: Hash of metadata to use with stream. * - size: Size of the stream, if known. */ public function __construct(callable $source, array $options = []) { $this->source = $source; $this->size = $options['size'] ?? null; $this->metadata = $options['metadata'] ?? []; $this->buffer = new BufferStream(); } public function __toString(): string { try { return Utils::copyToString($this); } catch (\Throwable $e) { if (\PHP_VERSION_ID >= 70400) { throw $e; } trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); return ''; } } public function close(): void { $this->detach(); } public function detach() { $this->tellPos = 0; $this->source = null; return null; } public function getSize(): ?int { return $this->size; } public function tell(): int { return $this->tellPos; } public function eof(): bool { return $this->source === null; } public function isSeekable(): bool { return false; } public function rewind(): void { $this->seek(0); } public function seek($offset, $whence = SEEK_SET): void { throw new \RuntimeException('Cannot seek a PumpStream'); } public function isWritable(): bool { return false; } public function write($string): int { throw new \RuntimeException('Cannot write to a PumpStream'); } public function isReadable(): bool { return true; } public function read($length): string { $data = $this->buffer->read($length); $readLen = strlen($data); $this->tellPos += $readLen; $remaining = $length - $readLen; if ($remaining) { $this->pump($remaining); $data .= $this->buffer->read($remaining); $this->tellPos += strlen($data) - $readLen; } return $data; } public function getContents(): string { $result = ''; while (!$this->eof()) { $result .= $this->read(1000000); } return $result; } /** * {@inheritdoc} * * @return mixed */ public function getMetadata($key = null) { if (!$key) { return $this->metadata; } return $this->metadata[$key] ?? null; } private function pump(int $length): void { if ($this->source) { do { $data = call_user_func($this->source, $length); if ($data === false || $data === null) { $this->source = null; return; } $this->buffer->write($data); $length -= strlen($data); } while ($length > 0); } } } PK������Zcq �� ����BufferStream.phpnu�W+A��������<?php declare(strict_types=1); namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** * Provides a buffer stream that can be written to to fill a buffer, and read * from to remove bytes from the buffer. * * This stream returns a "hwm" metadata value that tells upstream consumers * what the configured high water mark of the stream is, or the maximum * preferred size of the buffer. */ final class BufferStream implements StreamInterface { /** @var int */ private $hwm; /** @var string */ private $buffer = ''; /** * @param int $hwm High water mark, representing the preferred maximum * buffer size. If the size of the buffer exceeds the high * water mark, then calls to write will continue to succeed * but will return 0 to inform writers to slow down * until the buffer has been drained by reading from it. */ public function __construct(int $hwm = 16384) { $this->hwm = $hwm; } public function __toString(): string { return $this->getContents(); } public function getContents(): string { $buffer = $this->buffer; $this->buffer = ''; return $buffer; } public function close(): void { $this->buffer = ''; } public function detach() { $this->close(); return null; } public function getSize(): ?int { return strlen($this->buffer); } public function isReadable(): bool { return true; } public function isWritable(): bool { return true; } public function isSeekable(): bool { return false; } public function rewind(): void { $this->seek(0); } public function seek($offset, $whence = SEEK_SET): void { throw new \RuntimeException('Cannot seek a BufferStream'); } public function eof(): bool { return strlen($this->buffer) === 0; } public function tell(): int { throw new \RuntimeException('Cannot determine the position of a BufferStream'); } /** * Reads data from the buffer. */ public function read($length): string { $currentLength = strlen($this->buffer); if ($length >= $currentLength) { // No need to slice the buffer because we don't have enough data. $result = $this->buffer; $this->buffer = ''; } else { // Slice up the result to provide a subset of the buffer. $result = substr($this->buffer, 0, $length); $this->buffer = substr($this->buffer, $length); } return $result; } /** * Writes data to the buffer. */ public function write($string): int { $this->buffer .= $string; if (strlen($this->buffer) >= $this->hwm) { return 0; } return strlen($string); } /** * {@inheritdoc} * * @return mixed */ public function getMetadata($key = null) { if ($key === 'hwm') { return $this->hwm; } return $key ? null : []; } } PK������Z,7������CodeSnippet.phpnu�W+A��������<?php namespace Spatie\Backtrace; use RuntimeException; class CodeSnippet { /** @var int */ protected $surroundingLine = 1; /** @var int */ protected $snippetLineCount = 9; public function surroundingLine(int $surroundingLine): self { $this->surroundingLine = $surroundingLine; return $this; } public function snippetLineCount(int $snippetLineCount): self { $this->snippetLineCount = $snippetLineCount; return $this; } public function get(string $fileName): array { if (! file_exists($fileName)) { return []; } try { $file = new File($fileName); [$startLineNumber, $endLineNumber] = $this->getBounds($file->numberOfLines()); $code = []; $line = $file->getLine($startLineNumber); $currentLineNumber = $startLineNumber; while ($currentLineNumber <= $endLineNumber) { $code[$currentLineNumber] = rtrim(substr($line, 0, 250)); $line = $file->getNextLine(); $currentLineNumber++; } return $code; } catch (RuntimeException $exception) { return []; } } public function getAsString(string $fileName): string { $snippet = $this->get($fileName); $snippetStrings = array_map(function (string $line, string $number) { return "{$number} {$line}"; }, $snippet, array_keys($snippet)); return implode(PHP_EOL, $snippetStrings); } protected function getBounds(int $totalNumberOfLineInFile): array { $startLine = max($this->surroundingLine - floor($this->snippetLineCount / 2), 1); $endLine = $startLine + ($this->snippetLineCount - 1); if ($endLine > $totalNumberOfLineInFile) { $endLine = $totalNumberOfLineInFile; $startLine = max($endLine - ($this->snippetLineCount - 1), 1); } return [$startLine, $endLine]; } } PK������Z������RetryMiddleware.phpnu�W+A��������<?php namespace GuzzleHttp; use GuzzleHttp\Promise as P; use GuzzleHttp\Promise\PromiseInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; /** * Middleware that retries requests based on the boolean result of * invoking the provided "decider" function. * * @final */ class RetryMiddleware { /** * @var callable(RequestInterface, array): PromiseInterface */ private $nextHandler; /** * @var callable */ private $decider; /** * @var callable(int) */ private $delay; /** * @param callable $decider Function that accepts the number of retries, * a request, [response], and [exception] and * returns true if the request is to be * retried. * @param callable(RequestInterface, array): PromiseInterface $nextHandler Next handler to invoke. * @param (callable(int): int)|null $delay Function that accepts the number of retries * and returns the number of * milliseconds to delay. */ public function __construct(callable $decider, callable $nextHandler, callable $delay = null) { $this->decider = $decider; $this->nextHandler = $nextHandler; $this->delay = $delay ?: __CLASS__.'::exponentialDelay'; } /** * Default exponential backoff delay function. * * @return int milliseconds. */ public static function exponentialDelay(int $retries): int { return (int) 2 ** ($retries - 1) * 1000; } public function __invoke(RequestInterface $request, array $options): PromiseInterface { if (!isset($options['retries'])) { $options['retries'] = 0; } $fn = $this->nextHandler; return $fn($request, $options) ->then( $this->onFulfilled($request, $options), $this->onRejected($request, $options) ); } /** * Execute fulfilled closure */ private function onFulfilled(RequestInterface $request, array $options): callable { return function ($value) use ($request, $options) { if (!($this->decider)( $options['retries'], $request, $value, null )) { return $value; } return $this->doRetry($request, $options, $value); }; } /** * Execute rejected closure */ private function onRejected(RequestInterface $req, array $options): callable { return function ($reason) use ($req, $options) { if (!($this->decider)( $options['retries'], $req, null, $reason )) { return P\Create::rejectionFor($reason); } return $this->doRetry($req, $options); }; } private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null): PromiseInterface { $options['delay'] = ($this->delay)(++$options['retries'], $response, $request); return $this($request, $options); } } PK������ZE9��������functions_include.phpnu�W+A��������<?php // Don't redefine the functions if included multiple times. if (!\function_exists('GuzzleHttp\describe_type')) { require __DIR__.'/functions.php'; } PK������ZL+l��l����Pool.phpnu�W+A��������<?php namespace GuzzleHttp; use GuzzleHttp\Promise as P; use GuzzleHttp\Promise\EachPromise; use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\Promise\PromisorInterface; use Psr\Http\Message\RequestInterface; /** * Sends an iterator of requests concurrently using a capped pool size. * * The pool will read from an iterator until it is cancelled or until the * iterator is consumed. When a request is yielded, the request is sent after * applying the "request_options" request options (if provided in the ctor). * * When a function is yielded by the iterator, the function is provided the * "request_options" array that should be merged on top of any existing * options, and the function MUST then return a wait-able promise. * * @final */ class Pool implements PromisorInterface { /** * @var EachPromise */ private $each; /** * @param ClientInterface $client Client used to send the requests. * @param array|\Iterator $requests Requests or functions that return * requests to send concurrently. * @param array $config Associative array of options * - concurrency: (int) Maximum number of requests to send concurrently * - options: Array of request options to apply to each request. * - fulfilled: (callable) Function to invoke when a request completes. * - rejected: (callable) Function to invoke when a request is rejected. */ public function __construct(ClientInterface $client, $requests, array $config = []) { if (!isset($config['concurrency'])) { $config['concurrency'] = 25; } if (isset($config['options'])) { $opts = $config['options']; unset($config['options']); } else { $opts = []; } $iterable = P\Create::iterFor($requests); $requests = static function () use ($iterable, $client, $opts) { foreach ($iterable as $key => $rfn) { if ($rfn instanceof RequestInterface) { yield $key => $client->sendAsync($rfn, $opts); } elseif (\is_callable($rfn)) { yield $key => $rfn($opts); } else { throw new \InvalidArgumentException('Each value yielded by the iterator must be a Psr7\Http\Message\RequestInterface or a callable that returns a promise that fulfills with a Psr7\Message\Http\ResponseInterface object.'); } } }; $this->each = new EachPromise($requests(), $config); } /** * Get promise */ public function promise(): PromiseInterface { return $this->each->promise(); } /** * Sends multiple requests concurrently and returns an array of responses * and exceptions that uses the same ordering as the provided requests. * * IMPORTANT: This method keeps every request and response in memory, and * as such, is NOT recommended when sending a large number or an * indeterminate number of requests concurrently. * * @param ClientInterface $client Client used to send the requests * @param array|\Iterator $requests Requests to send concurrently. * @param array $options Passes through the options available in * {@see \GuzzleHttp\Pool::__construct} * * @return array Returns an array containing the response or an exception * in the same order that the requests were sent. * * @throws \InvalidArgumentException if the event format is incorrect. */ public static function batch(ClientInterface $client, $requests, array $options = []): array { $res = []; self::cmpCallback($options, 'fulfilled', $res); self::cmpCallback($options, 'rejected', $res); $pool = new static($client, $requests, $options); $pool->promise()->wait(); \ksort($res); return $res; } /** * Execute callback(s) */ private static function cmpCallback(array &$options, string $name, array &$results): void { if (!isset($options[$name])) { $options[$name] = static function ($v, $k) use (&$results) { $results[$k] = $v; }; } else { $currentFn = $options[$name]; $options[$name] = static function ($v, $k) use (&$results, $currentFn) { $currentFn($v, $k); $results[$k] = $v; }; } } } PK������Z+��+����Middleware.phpnu�W+A��������<?php namespace GuzzleHttp; use GuzzleHttp\Cookie\CookieJarInterface; use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Promise as P; use GuzzleHttp\Promise\PromiseInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Log\LoggerInterface; /** * Functions used to create and wrap handlers with handler middleware. */ final class Middleware { /** * Middleware that adds cookies to requests. * * The options array must be set to a CookieJarInterface in order to use * cookies. This is typically handled for you by a client. * * @return callable Returns a function that accepts the next handler. */ public static function cookies(): callable { return static function (callable $handler): callable { return static function ($request, array $options) use ($handler) { if (empty($options['cookies'])) { return $handler($request, $options); } elseif (!($options['cookies'] instanceof CookieJarInterface)) { throw new \InvalidArgumentException('cookies must be an instance of GuzzleHttp\Cookie\CookieJarInterface'); } $cookieJar = $options['cookies']; $request = $cookieJar->withCookieHeader($request); return $handler($request, $options) ->then( static function (ResponseInterface $response) use ($cookieJar, $request): ResponseInterface { $cookieJar->extractCookies($request, $response); return $response; } ); }; }; } /** * Middleware that throws exceptions for 4xx or 5xx responses when the * "http_errors" request option is set to true. * * @param BodySummarizerInterface|null $bodySummarizer The body summarizer to use in exception messages. * * @return callable(callable): callable Returns a function that accepts the next handler. */ public static function httpErrors(BodySummarizerInterface $bodySummarizer = null): callable { return static function (callable $handler) use ($bodySummarizer): callable { return static function ($request, array $options) use ($handler, $bodySummarizer) { if (empty($options['http_errors'])) { return $handler($request, $options); } return $handler($request, $options)->then( static function (ResponseInterface $response) use ($request, $bodySummarizer) { $code = $response->getStatusCode(); if ($code < 400) { return $response; } throw RequestException::create($request, $response, null, [], $bodySummarizer); } ); }; }; } /** * Middleware that pushes history data to an ArrayAccess container. * * @param array|\ArrayAccess<int, array> $container Container to hold the history (by reference). * * @return callable(callable): callable Returns a function that accepts the next handler. * * @throws \InvalidArgumentException if container is not an array or ArrayAccess. */ public static function history(&$container): callable { if (!\is_array($container) && !$container instanceof \ArrayAccess) { throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess'); } return static function (callable $handler) use (&$container): callable { return static function (RequestInterface $request, array $options) use ($handler, &$container) { return $handler($request, $options)->then( static function ($value) use ($request, &$container, $options) { $container[] = [ 'request' => $request, 'response' => $value, 'error' => null, 'options' => $options, ]; return $value; }, static function ($reason) use ($request, &$container, $options) { $container[] = [ 'request' => $request, 'response' => null, 'error' => $reason, 'options' => $options, ]; return P\Create::rejectionFor($reason); } ); }; }; } /** * Middleware that invokes a callback before and after sending a request. * * The provided listener cannot modify or alter the response. It simply * "taps" into the chain to be notified before returning the promise. The * before listener accepts a request and options array, and the after * listener accepts a request, options array, and response promise. * * @param callable $before Function to invoke before forwarding the request. * @param callable $after Function invoked after forwarding. * * @return callable Returns a function that accepts the next handler. */ public static function tap(callable $before = null, callable $after = null): callable { return static function (callable $handler) use ($before, $after): callable { return static function (RequestInterface $request, array $options) use ($handler, $before, $after) { if ($before) { $before($request, $options); } $response = $handler($request, $options); if ($after) { $after($request, $options, $response); } return $response; }; }; } /** * Middleware that handles request redirects. * * @return callable Returns a function that accepts the next handler. */ public static function redirect(): callable { return static function (callable $handler): RedirectMiddleware { return new RedirectMiddleware($handler); }; } /** * Middleware that retries requests based on the boolean result of * invoking the provided "decider" function. * * If no delay function is provided, a simple implementation of exponential * backoff will be utilized. * * @param callable $decider Function that accepts the number of retries, * a request, [response], and [exception] and * returns true if the request is to be retried. * @param callable $delay Function that accepts the number of retries and * returns the number of milliseconds to delay. * * @return callable Returns a function that accepts the next handler. */ public static function retry(callable $decider, callable $delay = null): callable { return static function (callable $handler) use ($decider, $delay): RetryMiddleware { return new RetryMiddleware($decider, $handler, $delay); }; } /** * Middleware that logs requests, responses, and errors using a message * formatter. * * @phpstan-param \Psr\Log\LogLevel::* $logLevel Level at which to log requests. * * @param LoggerInterface $logger Logs messages. * @param MessageFormatterInterface|MessageFormatter $formatter Formatter used to create message strings. * @param string $logLevel Level at which to log requests. * * @return callable Returns a function that accepts the next handler. */ public static function log(LoggerInterface $logger, $formatter, string $logLevel = 'info'): callable { // To be compatible with Guzzle 7.1.x we need to allow users to pass a MessageFormatter if (!$formatter instanceof MessageFormatter && !$formatter instanceof MessageFormatterInterface) { throw new \LogicException(sprintf('Argument 2 to %s::log() must be of type %s', self::class, MessageFormatterInterface::class)); } return static function (callable $handler) use ($logger, $formatter, $logLevel): callable { return static function (RequestInterface $request, array $options = []) use ($handler, $logger, $formatter, $logLevel) { return $handler($request, $options)->then( static function ($response) use ($logger, $request, $formatter, $logLevel): ResponseInterface { $message = $formatter->format($request, $response); $logger->log($logLevel, $message); return $response; }, static function ($reason) use ($logger, $request, $formatter): PromiseInterface { $response = $reason instanceof RequestException ? $reason->getResponse() : null; $message = $formatter->format($request, $response, P\Create::exceptionFor($reason)); $logger->error($message); return P\Create::rejectionFor($reason); } ); }; }; } /** * This middleware adds a default content-type if possible, a default * content-length or transfer-encoding header, and the expect header. */ public static function prepareBody(): callable { return static function (callable $handler): PrepareBodyMiddleware { return new PrepareBodyMiddleware($handler); }; } /** * Middleware that applies a map function to the request before passing to * the next handler. * * @param callable $fn Function that accepts a RequestInterface and returns * a RequestInterface. */ public static function mapRequest(callable $fn): callable { return static function (callable $handler) use ($fn): callable { return static function (RequestInterface $request, array $options) use ($handler, $fn) { return $handler($fn($request), $options); }; }; } /** * Middleware that applies a map function to the resolved promise's * response. * * @param callable $fn Function that accepts a ResponseInterface and * returns a ResponseInterface. */ public static function mapResponse(callable $fn): callable { return static function (callable $handler) use ($fn): callable { return static function (RequestInterface $request, array $options) use ($handler, $fn) { return $handler($request, $options)->then($fn); }; }; } } PK������Z5O\$��������Exception/GuzzleException.phpnu�W+A��������<?php namespace GuzzleHttp\Exception; use Psr\Http\Client\ClientExceptionInterface; interface GuzzleException extends ClientExceptionInterface { } PK������Z/y���y�����Exception/TransferException.phpnu�W+A��������<?php namespace GuzzleHttp\Exception; class TransferException extends \RuntimeException implements GuzzleException { } PK������Zj��������Exception/ClientException.phpnu�W+A��������<?php namespace GuzzleHttp\Exception; /** * Exception when a client error is encountered (4xx codes) */ class ClientException extends BadResponseException { } PK������ZFj��������Exception/ServerException.phpnu�W+A��������<?php namespace GuzzleHttp\Exception; /** * Exception when a server error is encountered (5xx codes) */ class ServerException extends BadResponseException { } PK������ZN ������Exception/ConnectException.phpnu�W+A��������<?php namespace GuzzleHttp\Exception; use Psr\Http\Client\NetworkExceptionInterface; use Psr\Http\Message\RequestInterface; /** * Exception thrown when a connection cannot be established. * * Note that no response is present for a ConnectException */ class ConnectException extends TransferException implements NetworkExceptionInterface { /** * @var RequestInterface */ private $request; /** * @var array */ private $handlerContext; public function __construct( string $message, RequestInterface $request, \Throwable $previous = null, array $handlerContext = [] ) { parent::__construct($message, 0, $previous); $this->request = $request; $this->handlerContext = $handlerContext; } /** * Get the request that caused the exception */ public function getRequest(): RequestInterface { return $this->request; } /** * Get contextual information about the error from the underlying handler. * * The contents of this array will vary depending on which handler you are * using. It may also be just an empty array. Relying on this data will * couple you to a specific handler, but can give more debug information * when needed. */ public function getHandlerContext(): array { return $this->handlerContext; } } PK������ZOm����"��Exception/BadResponseException.phpnu�W+A��������<?php namespace GuzzleHttp\Exception; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; /** * Exception when an HTTP error occurs (4xx or 5xx error) */ class BadResponseException extends RequestException { public function __construct( string $message, RequestInterface $request, ResponseInterface $response, \Throwable $previous = null, array $handlerContext = [] ) { parent::__construct($message, $request, $response, $previous, $handlerContext); } /** * Current exception and the ones that extend it will always have a response. */ public function hasResponse(): bool { return true; } /** * This function narrows the return type from the parent class and does not allow it to be nullable. */ public function getResponse(): ResponseInterface { /** @var ResponseInterface */ return parent::getResponse(); } } PK������Z$�e���e���'��Exception/TooManyRedirectsException.phpnu�W+A��������<?php namespace GuzzleHttp\Exception; class TooManyRedirectsException extends RequestException { } PK������ZTE9����&��Exception/InvalidArgumentException.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (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\CodeCoverage; final class InvalidArgumentException extends \InvalidArgumentException implements Exception { } PK������Z0؜������Exception/RequestException.phpnu�W+A��������<?php namespace GuzzleHttp\Exception; use GuzzleHttp\BodySummarizer; use GuzzleHttp\BodySummarizerInterface; use Psr\Http\Client\RequestExceptionInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\UriInterface; /** * HTTP Request exception */ class RequestException extends TransferException implements RequestExceptionInterface { /** * @var RequestInterface */ private $request; /** * @var ResponseInterface|null */ private $response; /** * @var array */ private $handlerContext; public function __construct( string $message, RequestInterface $request, ResponseInterface $response = null, \Throwable $previous = null, array $handlerContext = [] ) { // Set the code of the exception if the response is set and not future. $code = $response ? $response->getStatusCode() : 0; parent::__construct($message, $code, $previous); $this->request = $request; $this->response = $response; $this->handlerContext = $handlerContext; } /** * Wrap non-RequestExceptions with a RequestException */ public static function wrapException(RequestInterface $request, \Throwable $e): RequestException { return $e instanceof RequestException ? $e : new RequestException($e->getMessage(), $request, null, $e); } /** * Factory method to create a new exception with a normalized error message * * @param RequestInterface $request Request sent * @param ResponseInterface $response Response received * @param \Throwable|null $previous Previous exception * @param array $handlerContext Optional handler context * @param BodySummarizerInterface|null $bodySummarizer Optional body summarizer */ public static function create( RequestInterface $request, ResponseInterface $response = null, \Throwable $previous = null, array $handlerContext = [], BodySummarizerInterface $bodySummarizer = null ): self { if (!$response) { return new self( 'Error completing request', $request, null, $previous, $handlerContext ); } $level = (int) \floor($response->getStatusCode() / 100); if ($level === 4) { $label = 'Client error'; $className = ClientException::class; } elseif ($level === 5) { $label = 'Server error'; $className = ServerException::class; } else { $label = 'Unsuccessful request'; $className = __CLASS__; } $uri = $request->getUri(); $uri = static::obfuscateUri($uri); // Client Error: `GET /` resulted in a `404 Not Found` response: // <html> ... (truncated) $message = \sprintf( '%s: `%s %s` resulted in a `%s %s` response', $label, $request->getMethod(), $uri->__toString(), $response->getStatusCode(), $response->getReasonPhrase() ); $summary = ($bodySummarizer ?? new BodySummarizer())->summarize($response); if ($summary !== null) { $message .= ":\n{$summary}\n"; } return new $className($message, $request, $response, $previous, $handlerContext); } /** * Obfuscates URI if there is a username and a password present */ private static function obfuscateUri(UriInterface $uri): UriInterface { $userInfo = $uri->getUserInfo(); if (false !== ($pos = \strpos($userInfo, ':'))) { return $uri->withUserInfo(\substr($userInfo, 0, $pos), '***'); } return $uri; } /** * Get the request that caused the exception */ public function getRequest(): RequestInterface { return $this->request; } /** * Get the associated response */ public function getResponse(): ?ResponseInterface { return $this->response; } /** * Check if a response was received */ public function hasResponse(): bool { return $this->response !== null; } /** * Get contextual information about the error from the underlying handler. * * The contents of this array will vary depending on which handler you are * using. It may also be just an empty array. Relying on this data will * couple you to a specific handler, but can give more debug information * when needed. */ public function getHandlerContext(): array { return $this->handlerContext; } } PK������Z^:w��w����BodySummarizer.phpnu�W+A��������<?php namespace GuzzleHttp; use Psr\Http\Message\MessageInterface; final class BodySummarizer implements BodySummarizerInterface { /** * @var int|null */ private $truncateAt; public function __construct(int $truncateAt = null) { $this->truncateAt = $truncateAt; } /** * Returns a summarized message body. */ public function summarize(MessageInterface $message): ?string { return $this->truncateAt === null ? \GuzzleHttp\Psr7\Message::bodySummary($message) : \GuzzleHttp\Psr7\Message::bodySummary($message, $this->truncateAt); } } PK������ZVx.#��.#����ClientTrait.phpnu�W+A��������<?php namespace GuzzleHttp; use GuzzleHttp\Exception\GuzzleException; use GuzzleHttp\Promise\PromiseInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\UriInterface; /** * Client interface for sending HTTP requests. */ trait ClientTrait { /** * Create and send an HTTP request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string $method HTTP method. * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. * * @throws GuzzleException */ abstract public function request(string $method, $uri, array $options = []): ResponseInterface; /** * Create and send an HTTP GET request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. * * @throws GuzzleException */ public function get($uri, array $options = []): ResponseInterface { return $this->request('GET', $uri, $options); } /** * Create and send an HTTP HEAD request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. * * @throws GuzzleException */ public function head($uri, array $options = []): ResponseInterface { return $this->request('HEAD', $uri, $options); } /** * Create and send an HTTP PUT request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. * * @throws GuzzleException */ public function put($uri, array $options = []): ResponseInterface { return $this->request('PUT', $uri, $options); } /** * Create and send an HTTP POST request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. * * @throws GuzzleException */ public function post($uri, array $options = []): ResponseInterface { return $this->request('POST', $uri, $options); } /** * Create and send an HTTP PATCH request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. * * @throws GuzzleException */ public function patch($uri, array $options = []): ResponseInterface { return $this->request('PATCH', $uri, $options); } /** * Create and send an HTTP DELETE request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. * * @throws GuzzleException */ public function delete($uri, array $options = []): ResponseInterface { return $this->request('DELETE', $uri, $options); } /** * Create and send an asynchronous HTTP request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string $method HTTP method * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ abstract public function requestAsync(string $method, $uri, array $options = []): PromiseInterface; /** * Create and send an asynchronous HTTP GET request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public function getAsync($uri, array $options = []): PromiseInterface { return $this->requestAsync('GET', $uri, $options); } /** * Create and send an asynchronous HTTP HEAD request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public function headAsync($uri, array $options = []): PromiseInterface { return $this->requestAsync('HEAD', $uri, $options); } /** * Create and send an asynchronous HTTP PUT request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public function putAsync($uri, array $options = []): PromiseInterface { return $this->requestAsync('PUT', $uri, $options); } /** * Create and send an asynchronous HTTP POST request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public function postAsync($uri, array $options = []): PromiseInterface { return $this->requestAsync('POST', $uri, $options); } /** * Create and send an asynchronous HTTP PATCH request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public function patchAsync($uri, array $options = []): PromiseInterface { return $this->requestAsync('PATCH', $uri, $options); } /** * Create and send an asynchronous HTTP DELETE request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public function deleteAsync($uri, array $options = []): PromiseInterface { return $this->requestAsync('DELETE', $uri, $options); } } PK������ZHGM ��M ����PrepareBodyMiddleware.phpnu�W+A��������<?php namespace GuzzleHttp; use GuzzleHttp\Promise\PromiseInterface; use Psr\Http\Message\RequestInterface; /** * Prepares requests that contain a body, adding the Content-Length, * Content-Type, and Expect headers. * * @final */ class PrepareBodyMiddleware { /** * @var callable(RequestInterface, array): PromiseInterface */ private $nextHandler; /** * @param callable(RequestInterface, array): PromiseInterface $nextHandler Next handler to invoke. */ public function __construct(callable $nextHandler) { $this->nextHandler = $nextHandler; } public function __invoke(RequestInterface $request, array $options): PromiseInterface { $fn = $this->nextHandler; // Don't do anything if the request has no body. if ($request->getBody()->getSize() === 0) { return $fn($request, $options); } $modify = []; // Add a default content-type if possible. if (!$request->hasHeader('Content-Type')) { if ($uri = $request->getBody()->getMetadata('uri')) { if (is_string($uri) && $type = Psr7\MimeType::fromFilename($uri)) { $modify['set_headers']['Content-Type'] = $type; } } } // Add a default content-length or transfer-encoding header. if (!$request->hasHeader('Content-Length') && !$request->hasHeader('Transfer-Encoding') ) { $size = $request->getBody()->getSize(); if ($size !== null) { $modify['set_headers']['Content-Length'] = $size; } else { $modify['set_headers']['Transfer-Encoding'] = 'chunked'; } } // Add the expect header if needed. $this->addExpectHeader($request, $options, $modify); return $fn(Psr7\Utils::modifyRequest($request, $modify), $options); } /** * Add expect header */ private function addExpectHeader(RequestInterface $request, array $options, array &$modify): void { // Determine if the Expect header should be used if ($request->hasHeader('Expect')) { return; } $expect = $options['expect'] ?? null; // Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0 if ($expect === false || $request->getProtocolVersion() < 1.1) { return; } // The expect header is unconditionally enabled if ($expect === true) { $modify['set_headers']['Expect'] = '100-Continue'; return; } // By default, send the expect header when the payload is > 1mb if ($expect === null) { $expect = 1048576; } // Always add if the body cannot be rewound, the size cannot be // determined, or the size is greater than the cutoff threshold $body = $request->getBody(); $size = $body->getSize(); if ($size === null || $size >= (int) $expect || !$body->isSeekable()) { $modify['set_headers']['Expect'] = '100-Continue'; } } } PK������Z~sH��H�� ��Client.phpnu�W+A��������<?php namespace GuzzleHttp; use GuzzleHttp\Cookie\CookieJar; use GuzzleHttp\Exception\GuzzleException; use GuzzleHttp\Exception\InvalidArgumentException; use GuzzleHttp\Promise as P; use GuzzleHttp\Promise\PromiseInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\UriInterface; /** * @final */ class Client implements ClientInterface, \Psr\Http\Client\ClientInterface { use ClientTrait; /** * @var array Default request options */ private $config; /** * Clients accept an array of constructor parameters. * * Here's an example of creating a client using a base_uri and an array of * default request options to apply to each request: * * $client = new Client([ * 'base_uri' => 'http://www.foo.com/1.0/', * 'timeout' => 0, * 'allow_redirects' => false, * 'proxy' => '192.168.16.1:10' * ]); * * Client configuration settings include the following options: * * - handler: (callable) Function that transfers HTTP requests over the * wire. The function is called with a Psr7\Http\Message\RequestInterface * and array of transfer options, and must return a * GuzzleHttp\Promise\PromiseInterface that is fulfilled with a * Psr7\Http\Message\ResponseInterface on success. * If no handler is provided, a default handler will be created * that enables all of the request options below by attaching all of the * default middleware to the handler. * - base_uri: (string|UriInterface) Base URI of the client that is merged * into relative URIs. Can be a string or instance of UriInterface. * - **: any request option * * @param array $config Client configuration settings. * * @see \GuzzleHttp\RequestOptions for a list of available request options. */ public function __construct(array $config = []) { if (!isset($config['handler'])) { $config['handler'] = HandlerStack::create(); } elseif (!\is_callable($config['handler'])) { throw new InvalidArgumentException('handler must be a callable'); } // Convert the base_uri to a UriInterface if (isset($config['base_uri'])) { $config['base_uri'] = Psr7\Utils::uriFor($config['base_uri']); } $this->configureDefaults($config); } /** * @param string $method * @param array $args * * @return PromiseInterface|ResponseInterface * * @deprecated Client::__call will be removed in guzzlehttp/guzzle:8.0. */ public function __call($method, $args) { if (\count($args) < 1) { throw new InvalidArgumentException('Magic request methods require a URI and optional options array'); } $uri = $args[0]; $opts = $args[1] ?? []; return \substr($method, -5) === 'Async' ? $this->requestAsync(\substr($method, 0, -5), $uri, $opts) : $this->request($method, $uri, $opts); } /** * Asynchronously send an HTTP request. * * @param array $options Request options to apply to the given * request and to the transfer. See \GuzzleHttp\RequestOptions. */ public function sendAsync(RequestInterface $request, array $options = []): PromiseInterface { // Merge the base URI into the request URI if needed. $options = $this->prepareDefaults($options); return $this->transfer( $request->withUri($this->buildUri($request->getUri(), $options), $request->hasHeader('Host')), $options ); } /** * Send an HTTP request. * * @param array $options Request options to apply to the given * request and to the transfer. See \GuzzleHttp\RequestOptions. * * @throws GuzzleException */ public function send(RequestInterface $request, array $options = []): ResponseInterface { $options[RequestOptions::SYNCHRONOUS] = true; return $this->sendAsync($request, $options)->wait(); } /** * The HttpClient PSR (PSR-18) specify this method. * * {@inheritDoc} */ public function sendRequest(RequestInterface $request): ResponseInterface { $options[RequestOptions::SYNCHRONOUS] = true; $options[RequestOptions::ALLOW_REDIRECTS] = false; $options[RequestOptions::HTTP_ERRORS] = false; return $this->sendAsync($request, $options)->wait(); } /** * Create and send an asynchronous HTTP request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string $method HTTP method * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. See \GuzzleHttp\RequestOptions. */ public function requestAsync(string $method, $uri = '', array $options = []): PromiseInterface { $options = $this->prepareDefaults($options); // Remove request modifying parameter because it can be done up-front. $headers = $options['headers'] ?? []; $body = $options['body'] ?? null; $version = $options['version'] ?? '1.1'; // Merge the URI into the base URI. $uri = $this->buildUri(Psr7\Utils::uriFor($uri), $options); if (\is_array($body)) { throw $this->invalidBody(); } $request = new Psr7\Request($method, $uri, $headers, $body, $version); // Remove the option so that they are not doubly-applied. unset($options['headers'], $options['body'], $options['version']); return $this->transfer($request, $options); } /** * Create and send an HTTP request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string $method HTTP method. * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. See \GuzzleHttp\RequestOptions. * * @throws GuzzleException */ public function request(string $method, $uri = '', array $options = []): ResponseInterface { $options[RequestOptions::SYNCHRONOUS] = true; return $this->requestAsync($method, $uri, $options)->wait(); } /** * Get a client configuration option. * * These options include default request options of the client, a "handler" * (if utilized by the concrete client), and a "base_uri" if utilized by * the concrete client. * * @param string|null $option The config option to retrieve. * * @return mixed * * @deprecated Client::getConfig will be removed in guzzlehttp/guzzle:8.0. */ public function getConfig(?string $option = null) { return $option === null ? $this->config : ($this->config[$option] ?? null); } private function buildUri(UriInterface $uri, array $config): UriInterface { if (isset($config['base_uri'])) { $uri = Psr7\UriResolver::resolve(Psr7\Utils::uriFor($config['base_uri']), $uri); } if (isset($config['idn_conversion']) && ($config['idn_conversion'] !== false)) { $idnOptions = ($config['idn_conversion'] === true) ? \IDNA_DEFAULT : $config['idn_conversion']; $uri = Utils::idnUriConvert($uri, $idnOptions); } return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri; } /** * Configures the default options for a client. */ private function configureDefaults(array $config): void { $defaults = [ 'allow_redirects' => RedirectMiddleware::$defaultSettings, 'http_errors' => true, 'decode_content' => true, 'verify' => true, 'cookies' => false, 'idn_conversion' => false, ]; // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set. // We can only trust the HTTP_PROXY environment variable in a CLI // process due to the fact that PHP has no reliable mechanism to // get environment variables that start with "HTTP_". if (\PHP_SAPI === 'cli' && ($proxy = Utils::getenv('HTTP_PROXY'))) { $defaults['proxy']['http'] = $proxy; } if ($proxy = Utils::getenv('HTTPS_PROXY')) { $defaults['proxy']['https'] = $proxy; } if ($noProxy = Utils::getenv('NO_PROXY')) { $cleanedNoProxy = \str_replace(' ', '', $noProxy); $defaults['proxy']['no'] = \explode(',', $cleanedNoProxy); } $this->config = $config + $defaults; if (!empty($config['cookies']) && $config['cookies'] === true) { $this->config['cookies'] = new CookieJar(); } // Add the default user-agent header. if (!isset($this->config['headers'])) { $this->config['headers'] = ['User-Agent' => Utils::defaultUserAgent()]; } else { // Add the User-Agent header if one was not already set. foreach (\array_keys($this->config['headers']) as $name) { if (\strtolower($name) === 'user-agent') { return; } } $this->config['headers']['User-Agent'] = Utils::defaultUserAgent(); } } /** * Merges default options into the array. * * @param array $options Options to modify by reference */ private function prepareDefaults(array $options): array { $defaults = $this->config; if (!empty($defaults['headers'])) { // Default headers are only added if they are not present. $defaults['_conditional'] = $defaults['headers']; unset($defaults['headers']); } // Special handling for headers is required as they are added as // conditional headers and as headers passed to a request ctor. if (\array_key_exists('headers', $options)) { // Allows default headers to be unset. if ($options['headers'] === null) { $defaults['_conditional'] = []; unset($options['headers']); } elseif (!\is_array($options['headers'])) { throw new InvalidArgumentException('headers must be an array'); } } // Shallow merge defaults underneath options. $result = $options + $defaults; // Remove null values. foreach ($result as $k => $v) { if ($v === null) { unset($result[$k]); } } return $result; } /** * Transfers the given request and applies request options. * * The URI of the request is not modified and the request options are used * as-is without merging in default options. * * @param array $options See \GuzzleHttp\RequestOptions. */ private function transfer(RequestInterface $request, array $options): PromiseInterface { $request = $this->applyOptions($request, $options); /** @var HandlerStack $handler */ $handler = $options['handler']; try { return P\Create::promiseFor($handler($request, $options)); } catch (\Exception $e) { return P\Create::rejectionFor($e); } } /** * Applies the array of request options to a request. */ private function applyOptions(RequestInterface $request, array &$options): RequestInterface { $modify = [ 'set_headers' => [], ]; if (isset($options['headers'])) { if (array_keys($options['headers']) === range(0, count($options['headers']) - 1)) { throw new InvalidArgumentException('The headers array must have header name as keys.'); } $modify['set_headers'] = $options['headers']; unset($options['headers']); } if (isset($options['form_params'])) { if (isset($options['multipart'])) { throw new InvalidArgumentException('You cannot use ' .'form_params and multipart at the same time. Use the ' .'form_params option if you want to send application/' .'x-www-form-urlencoded requests, and the multipart ' .'option to send multipart/form-data requests.'); } $options['body'] = \http_build_query($options['form_params'], '', '&'); unset($options['form_params']); // Ensure that we don't have the header in different case and set the new value. $options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']); $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded'; } if (isset($options['multipart'])) { $options['body'] = new Psr7\MultipartStream($options['multipart']); unset($options['multipart']); } if (isset($options['json'])) { $options['body'] = Utils::jsonEncode($options['json']); unset($options['json']); // Ensure that we don't have the header in different case and set the new value. $options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']); $options['_conditional']['Content-Type'] = 'application/json'; } if (!empty($options['decode_content']) && $options['decode_content'] !== true ) { // Ensure that we don't have the header in different case and set the new value. $options['_conditional'] = Psr7\Utils::caselessRemove(['Accept-Encoding'], $options['_conditional']); $modify['set_headers']['Accept-Encoding'] = $options['decode_content']; } if (isset($options['body'])) { if (\is_array($options['body'])) { throw $this->invalidBody(); } $modify['body'] = Psr7\Utils::streamFor($options['body']); unset($options['body']); } if (!empty($options['auth']) && \is_array($options['auth'])) { $value = $options['auth']; $type = isset($value[2]) ? \strtolower($value[2]) : 'basic'; switch ($type) { case 'basic': // Ensure that we don't have the header in different case and set the new value. $modify['set_headers'] = Psr7\Utils::caselessRemove(['Authorization'], $modify['set_headers']); $modify['set_headers']['Authorization'] = 'Basic ' .\base64_encode("$value[0]:$value[1]"); break; case 'digest': // @todo: Do not rely on curl $options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_DIGEST; $options['curl'][\CURLOPT_USERPWD] = "$value[0]:$value[1]"; break; case 'ntlm': $options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_NTLM; $options['curl'][\CURLOPT_USERPWD] = "$value[0]:$value[1]"; break; } } if (isset($options['query'])) { $value = $options['query']; if (\is_array($value)) { $value = \http_build_query($value, '', '&', \PHP_QUERY_RFC3986); } if (!\is_string($value)) { throw new InvalidArgumentException('query must be a string or array'); } $modify['query'] = $value; unset($options['query']); } // Ensure that sink is not an invalid value. if (isset($options['sink'])) { // TODO: Add more sink validation? if (\is_bool($options['sink'])) { throw new InvalidArgumentException('sink must not be a boolean'); } } if (isset($options['version'])) { $modify['version'] = $options['version']; } $request = Psr7\Utils::modifyRequest($request, $modify); if ($request->getBody() instanceof Psr7\MultipartStream) { // Use a multipart/form-data POST if a Content-Type is not set. // Ensure that we don't have the header in different case and set the new value. $options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']); $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary=' .$request->getBody()->getBoundary(); } // Merge in conditional headers if they are not present. if (isset($options['_conditional'])) { // Build up the changes so it's in a single clone of the message. $modify = []; foreach ($options['_conditional'] as $k => $v) { if (!$request->hasHeader($k)) { $modify['set_headers'][$k] = $v; } } $request = Psr7\Utils::modifyRequest($request, $modify); // Don't pass this internal value along to middleware/handlers. unset($options['_conditional']); } return $request; } /** * Return an InvalidArgumentException with pre-set message. */ private function invalidBody(): InvalidArgumentException { return new InvalidArgumentException('Passing in the "body" request ' .'option as an array to send a request is not supported. ' .'Please use the "form_params" request option to send a ' .'application/x-www-form-urlencoded request, or the "multipart" ' .'request option to send a multipart/form-data request.'); } } PK������ZW?"��"����HandlerStack.phpnu�W+A��������<?php namespace GuzzleHttp; use GuzzleHttp\Promise\PromiseInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; /** * Creates a composed Guzzle handler function by stacking middlewares on top of * an HTTP handler function. * * @final */ class HandlerStack { /** * @var (callable(RequestInterface, array): PromiseInterface)|null */ private $handler; /** * @var array{(callable(callable(RequestInterface, array): PromiseInterface): callable), (string|null)}[] */ private $stack = []; /** * @var (callable(RequestInterface, array): PromiseInterface)|null */ private $cached; /** * Creates a default handler stack that can be used by clients. * * The returned handler will wrap the provided handler or use the most * appropriate default handler for your system. The returned HandlerStack has * support for cookies, redirects, HTTP error exceptions, and preparing a body * before sending. * * The returned handler stack can be passed to a client in the "handler" * option. * * @param (callable(RequestInterface, array): PromiseInterface)|null $handler HTTP handler function to use with the stack. If no * handler is provided, the best handler for your * system will be utilized. */ public static function create(?callable $handler = null): self { $stack = new self($handler ?: Utils::chooseHandler()); $stack->push(Middleware::httpErrors(), 'http_errors'); $stack->push(Middleware::redirect(), 'allow_redirects'); $stack->push(Middleware::cookies(), 'cookies'); $stack->push(Middleware::prepareBody(), 'prepare_body'); return $stack; } /** * @param (callable(RequestInterface, array): PromiseInterface)|null $handler Underlying HTTP handler. */ public function __construct(callable $handler = null) { $this->handler = $handler; } /** * Invokes the handler stack as a composed handler * * @return ResponseInterface|PromiseInterface */ public function __invoke(RequestInterface $request, array $options) { $handler = $this->resolve(); return $handler($request, $options); } /** * Dumps a string representation of the stack. * * @return string */ public function __toString() { $depth = 0; $stack = []; if ($this->handler !== null) { $stack[] = '0) Handler: '.$this->debugCallable($this->handler); } $result = ''; foreach (\array_reverse($this->stack) as $tuple) { ++$depth; $str = "{$depth}) Name: '{$tuple[1]}', "; $str .= 'Function: '.$this->debugCallable($tuple[0]); $result = "> {$str}\n{$result}"; $stack[] = $str; } foreach (\array_keys($stack) as $k) { $result .= "< {$stack[$k]}\n"; } return $result; } /** * Set the HTTP handler that actually returns a promise. * * @param callable(RequestInterface, array): PromiseInterface $handler Accepts a request and array of options and * returns a Promise. */ public function setHandler(callable $handler): void { $this->handler = $handler; $this->cached = null; } /** * Returns true if the builder has a handler. */ public function hasHandler(): bool { return $this->handler !== null; } /** * Unshift a middleware to the bottom of the stack. * * @param callable(callable): callable $middleware Middleware function * @param string $name Name to register for this middleware. */ public function unshift(callable $middleware, ?string $name = null): void { \array_unshift($this->stack, [$middleware, $name]); $this->cached = null; } /** * Push a middleware to the top of the stack. * * @param callable(callable): callable $middleware Middleware function * @param string $name Name to register for this middleware. */ public function push(callable $middleware, string $name = ''): void { $this->stack[] = [$middleware, $name]; $this->cached = null; } /** * Add a middleware before another middleware by name. * * @param string $findName Middleware to find * @param callable(callable): callable $middleware Middleware function * @param string $withName Name to register for this middleware. */ public function before(string $findName, callable $middleware, string $withName = ''): void { $this->splice($findName, $withName, $middleware, true); } /** * Add a middleware after another middleware by name. * * @param string $findName Middleware to find * @param callable(callable): callable $middleware Middleware function * @param string $withName Name to register for this middleware. */ public function after(string $findName, callable $middleware, string $withName = ''): void { $this->splice($findName, $withName, $middleware, false); } /** * Remove a middleware by instance or name from the stack. * * @param callable|string $remove Middleware to remove by instance or name. */ public function remove($remove): void { if (!is_string($remove) && !is_callable($remove)) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a callable or string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->cached = null; $idx = \is_callable($remove) ? 0 : 1; $this->stack = \array_values(\array_filter( $this->stack, static function ($tuple) use ($idx, $remove) { return $tuple[$idx] !== $remove; } )); } /** * Compose the middleware and handler into a single callable function. * * @return callable(RequestInterface, array): PromiseInterface */ public function resolve(): callable { if ($this->cached === null) { if (($prev = $this->handler) === null) { throw new \LogicException('No handler has been specified'); } foreach (\array_reverse($this->stack) as $fn) { /** @var callable(RequestInterface, array): PromiseInterface $prev */ $prev = $fn[0]($prev); } $this->cached = $prev; } return $this->cached; } private function findByName(string $name): int { foreach ($this->stack as $k => $v) { if ($v[1] === $name) { return $k; } } throw new \InvalidArgumentException("Middleware not found: $name"); } /** * Splices a function into the middleware list at a specific position. */ private function splice(string $findName, string $withName, callable $middleware, bool $before): void { $this->cached = null; $idx = $this->findByName($findName); $tuple = [$middleware, $withName]; if ($before) { if ($idx === 0) { \array_unshift($this->stack, $tuple); } else { $replacement = [$tuple, $this->stack[$idx]]; \array_splice($this->stack, $idx, 1, $replacement); } } elseif ($idx === \count($this->stack) - 1) { $this->stack[] = $tuple; } else { $replacement = [$this->stack[$idx], $tuple]; \array_splice($this->stack, $idx, 1, $replacement); } } /** * Provides a debug string for a given callable. * * @param callable|string $fn Function to write as a string. */ private function debugCallable($fn): string { if (\is_string($fn)) { return "callable({$fn})"; } if (\is_array($fn)) { return \is_string($fn[0]) ? "callable({$fn[0]}::{$fn[1]})" : "callable(['".\get_class($fn[0])."', '{$fn[1]}'])"; } /** @var object $fn */ return 'callable('.\spl_object_hash($fn).')'; } } PK������ZoDl ��l ����TransferStats.phpnu�W+A��������<?php namespace GuzzleHttp; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\UriInterface; /** * Represents data at the point after it was transferred either successfully * or after a network error. */ final class TransferStats { /** * @var RequestInterface */ private $request; /** * @var ResponseInterface|null */ private $response; /** * @var float|null */ private $transferTime; /** * @var array */ private $handlerStats; /** * @var mixed|null */ private $handlerErrorData; /** * @param RequestInterface $request Request that was sent. * @param ResponseInterface|null $response Response received (if any) * @param float|null $transferTime Total handler transfer time. * @param mixed $handlerErrorData Handler error data. * @param array $handlerStats Handler specific stats. */ public function __construct( RequestInterface $request, ?ResponseInterface $response = null, ?float $transferTime = null, $handlerErrorData = null, array $handlerStats = [] ) { $this->request = $request; $this->response = $response; $this->transferTime = $transferTime; $this->handlerErrorData = $handlerErrorData; $this->handlerStats = $handlerStats; } public function getRequest(): RequestInterface { return $this->request; } /** * Returns the response that was received (if any). */ public function getResponse(): ?ResponseInterface { return $this->response; } /** * Returns true if a response was received. */ public function hasResponse(): bool { return $this->response !== null; } /** * Gets handler specific error data. * * This might be an exception, a integer representing an error code, or * anything else. Relying on this value assumes that you know what handler * you are using. * * @return mixed */ public function getHandlerErrorData() { return $this->handlerErrorData; } /** * Get the effective URI the request was sent to. */ public function getEffectiveUri(): UriInterface { return $this->request->getUri(); } /** * Get the estimated time the request was being transferred by the handler. * * @return float|null Time in seconds. */ public function getTransferTime(): ?float { return $this->transferTime; } /** * Gets an array of all of the handler specific transfer data. */ public function getHandlerStats(): array { return $this->handlerStats; } /** * Get a specific handler statistic from the handler by name. * * @param string $stat Handler specific transfer stat to retrieve. * * @return mixed|null */ public function getHandlerStat(string $stat) { return $this->handlerStats[$stat] ?? null; } } PK������Z������Cookie/SessionCookieJar.phpnu�W+A��������<?php namespace GuzzleHttp\Cookie; /** * Persists cookies in the client session */ class SessionCookieJar extends CookieJar { /** * @var string session key */ private $sessionKey; /** * @var bool Control whether to persist session cookies or not. */ private $storeSessionCookies; /** * Create a new SessionCookieJar object * * @param string $sessionKey Session key name to store the cookie * data in session * @param bool $storeSessionCookies Set to true to store session cookies * in the cookie jar. */ public function __construct(string $sessionKey, bool $storeSessionCookies = false) { parent::__construct(); $this->sessionKey = $sessionKey; $this->storeSessionCookies = $storeSessionCookies; $this->load(); } /** * Saves cookies to session when shutting down */ public function __destruct() { $this->save(); } /** * Save cookies to the client session */ public function save(): void { $json = []; /** @var SetCookie $cookie */ foreach ($this as $cookie) { if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) { $json[] = $cookie->toArray(); } } $_SESSION[$this->sessionKey] = \json_encode($json); } /** * Load the contents of the client session into the data array */ protected function load(): void { if (!isset($_SESSION[$this->sessionKey])) { return; } $data = \json_decode($_SESSION[$this->sessionKey], true); if (\is_array($data)) { foreach ($data as $cookie) { $this->setCookie(new SetCookie($cookie)); } } elseif (\strlen($data)) { throw new \RuntimeException('Invalid cookie data'); } } } PK������ZY �� ����Cookie/FileCookieJar.phpnu�W+A��������<?php namespace GuzzleHttp\Cookie; use GuzzleHttp\Utils; /** * Persists non-session cookies using a JSON formatted file */ class FileCookieJar extends CookieJar { /** * @var string filename */ private $filename; /** * @var bool Control whether to persist session cookies or not. */ private $storeSessionCookies; /** * Create a new FileCookieJar object * * @param string $cookieFile File to store the cookie data * @param bool $storeSessionCookies Set to true to store session cookies * in the cookie jar. * * @throws \RuntimeException if the file cannot be found or created */ public function __construct(string $cookieFile, bool $storeSessionCookies = false) { parent::__construct(); $this->filename = $cookieFile; $this->storeSessionCookies = $storeSessionCookies; if (\file_exists($cookieFile)) { $this->load($cookieFile); } } /** * Saves the file when shutting down */ public function __destruct() { $this->save($this->filename); } /** * Saves the cookies to a file. * * @param string $filename File to save * * @throws \RuntimeException if the file cannot be found or created */ public function save(string $filename): void { $json = []; /** @var SetCookie $cookie */ foreach ($this as $cookie) { if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) { $json[] = $cookie->toArray(); } } $jsonStr = Utils::jsonEncode($json); if (false === \file_put_contents($filename, $jsonStr, \LOCK_EX)) { throw new \RuntimeException("Unable to save file {$filename}"); } } /** * Load cookies from a JSON formatted file. * * Old cookies are kept unless overwritten by newly loaded ones. * * @param string $filename Cookie file to load. * * @throws \RuntimeException if the file cannot be loaded. */ public function load(string $filename): void { $json = \file_get_contents($filename); if (false === $json) { throw new \RuntimeException("Unable to load file {$filename}"); } if ($json === '') { return; } $data = Utils::jsonDecode($json, true); if (\is_array($data)) { foreach ($data as $cookie) { $this->setCookie(new SetCookie($cookie)); } } elseif (\is_scalar($data) && !empty($data)) { throw new \RuntimeException("Invalid cookie file: {$filename}"); } } } PK������Z hJ7��7����Cookie/SetCookie.phpnu�W+A��������<?php namespace GuzzleHttp\Cookie; /** * Set-Cookie object */ class SetCookie { /** * @var array */ private static $defaults = [ 'Name' => null, 'Value' => null, 'Domain' => null, 'Path' => '/', 'Max-Age' => null, 'Expires' => null, 'Secure' => false, 'Discard' => false, 'HttpOnly' => false, ]; /** * @var array Cookie data */ private $data; /** * Create a new SetCookie object from a string. * * @param string $cookie Set-Cookie header string */ public static function fromString(string $cookie): self { // Create the default return array $data = self::$defaults; // Explode the cookie string using a series of semicolons $pieces = \array_filter(\array_map('trim', \explode(';', $cookie))); // The name of the cookie (first kvp) must exist and include an equal sign. if (!isset($pieces[0]) || \strpos($pieces[0], '=') === false) { return new self($data); } // Add the cookie pieces into the parsed data array foreach ($pieces as $part) { $cookieParts = \explode('=', $part, 2); $key = \trim($cookieParts[0]); $value = isset($cookieParts[1]) ? \trim($cookieParts[1], " \n\r\t\0\x0B") : true; // Only check for non-cookies when cookies have been found if (!isset($data['Name'])) { $data['Name'] = $key; $data['Value'] = $value; } else { foreach (\array_keys(self::$defaults) as $search) { if (!\strcasecmp($search, $key)) { if ($search === 'Max-Age') { if (is_numeric($value)) { $data[$search] = (int) $value; } } else { $data[$search] = $value; } continue 2; } } $data[$key] = $value; } } return new self($data); } /** * @param array $data Array of cookie data provided by a Cookie parser */ public function __construct(array $data = []) { $this->data = self::$defaults; if (isset($data['Name'])) { $this->setName($data['Name']); } if (isset($data['Value'])) { $this->setValue($data['Value']); } if (isset($data['Domain'])) { $this->setDomain($data['Domain']); } if (isset($data['Path'])) { $this->setPath($data['Path']); } if (isset($data['Max-Age'])) { $this->setMaxAge($data['Max-Age']); } if (isset($data['Expires'])) { $this->setExpires($data['Expires']); } if (isset($data['Secure'])) { $this->setSecure($data['Secure']); } if (isset($data['Discard'])) { $this->setDiscard($data['Discard']); } if (isset($data['HttpOnly'])) { $this->setHttpOnly($data['HttpOnly']); } // Set the remaining values that don't have extra validation logic foreach (array_diff(array_keys($data), array_keys(self::$defaults)) as $key) { $this->data[$key] = $data[$key]; } // Extract the Expires value and turn it into a UNIX timestamp if needed if (!$this->getExpires() && $this->getMaxAge()) { // Calculate the Expires date $this->setExpires(\time() + $this->getMaxAge()); } elseif (null !== ($expires = $this->getExpires()) && !\is_numeric($expires)) { $this->setExpires($expires); } } public function __toString() { $str = $this->data['Name'].'='.($this->data['Value'] ?? '').'; '; foreach ($this->data as $k => $v) { if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== false) { if ($k === 'Expires') { $str .= 'Expires='.\gmdate('D, d M Y H:i:s \G\M\T', $v).'; '; } else { $str .= ($v === true ? $k : "{$k}={$v}").'; '; } } } return \rtrim($str, '; '); } public function toArray(): array { return $this->data; } /** * Get the cookie name. * * @return string */ public function getName() { return $this->data['Name']; } /** * Set the cookie name. * * @param string $name Cookie name */ public function setName($name): void { if (!is_string($name)) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Name'] = (string) $name; } /** * Get the cookie value. * * @return string|null */ public function getValue() { return $this->data['Value']; } /** * Set the cookie value. * * @param string $value Cookie value */ public function setValue($value): void { if (!is_string($value)) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Value'] = (string) $value; } /** * Get the domain. * * @return string|null */ public function getDomain() { return $this->data['Domain']; } /** * Set the domain of the cookie. * * @param string|null $domain */ public function setDomain($domain): void { if (!is_string($domain) && null !== $domain) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Domain'] = null === $domain ? null : (string) $domain; } /** * Get the path. * * @return string */ public function getPath() { return $this->data['Path']; } /** * Set the path of the cookie. * * @param string $path Path of the cookie */ public function setPath($path): void { if (!is_string($path)) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Path'] = (string) $path; } /** * Maximum lifetime of the cookie in seconds. * * @return int|null */ public function getMaxAge() { return null === $this->data['Max-Age'] ? null : (int) $this->data['Max-Age']; } /** * Set the max-age of the cookie. * * @param int|null $maxAge Max age of the cookie in seconds */ public function setMaxAge($maxAge): void { if (!is_int($maxAge) && null !== $maxAge) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an int or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Max-Age'] = $maxAge === null ? null : (int) $maxAge; } /** * The UNIX timestamp when the cookie Expires. * * @return string|int|null */ public function getExpires() { return $this->data['Expires']; } /** * Set the unix timestamp for which the cookie will expire. * * @param int|string|null $timestamp Unix timestamp or any English textual datetime description. */ public function setExpires($timestamp): void { if (!is_int($timestamp) && !is_string($timestamp) && null !== $timestamp) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an int, string or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Expires'] = null === $timestamp ? null : (\is_numeric($timestamp) ? (int) $timestamp : \strtotime((string) $timestamp)); } /** * Get whether or not this is a secure cookie. * * @return bool */ public function getSecure() { return $this->data['Secure']; } /** * Set whether or not the cookie is secure. * * @param bool $secure Set to true or false if secure */ public function setSecure($secure): void { if (!is_bool($secure)) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Secure'] = (bool) $secure; } /** * Get whether or not this is a session cookie. * * @return bool|null */ public function getDiscard() { return $this->data['Discard']; } /** * Set whether or not this is a session cookie. * * @param bool $discard Set to true or false if this is a session cookie */ public function setDiscard($discard): void { if (!is_bool($discard)) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Discard'] = (bool) $discard; } /** * Get whether or not this is an HTTP only cookie. * * @return bool */ public function getHttpOnly() { return $this->data['HttpOnly']; } /** * Set whether or not this is an HTTP only cookie. * * @param bool $httpOnly Set to true or false if this is HTTP only */ public function setHttpOnly($httpOnly): void { if (!is_bool($httpOnly)) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['HttpOnly'] = (bool) $httpOnly; } /** * Check if the cookie matches a path value. * * A request-path path-matches a given cookie-path if at least one of * the following conditions holds: * * - The cookie-path and the request-path are identical. * - The cookie-path is a prefix of the request-path, and the last * character of the cookie-path is %x2F ("/"). * - The cookie-path is a prefix of the request-path, and the first * character of the request-path that is not included in the cookie- * path is a %x2F ("/") character. * * @param string $requestPath Path to check against */ public function matchesPath(string $requestPath): bool { $cookiePath = $this->getPath(); // Match on exact matches or when path is the default empty "/" if ($cookiePath === '/' || $cookiePath == $requestPath) { return true; } // Ensure that the cookie-path is a prefix of the request path. if (0 !== \strpos($requestPath, $cookiePath)) { return false; } // Match if the last character of the cookie-path is "/" if (\substr($cookiePath, -1, 1) === '/') { return true; } // Match if the first character not included in cookie path is "/" return \substr($requestPath, \strlen($cookiePath), 1) === '/'; } /** * Check if the cookie matches a domain value. * * @param string $domain Domain to check against */ public function matchesDomain(string $domain): bool { $cookieDomain = $this->getDomain(); if (null === $cookieDomain) { return true; } // Remove the leading '.' as per spec in RFC 6265. // https://tools.ietf.org/html/rfc6265#section-5.2.3 $cookieDomain = \ltrim(\strtolower($cookieDomain), '.'); $domain = \strtolower($domain); // Domain not set or exact match. if ('' === $cookieDomain || $domain === $cookieDomain) { return true; } // Matching the subdomain according to RFC 6265. // https://tools.ietf.org/html/rfc6265#section-5.1.3 if (\filter_var($domain, \FILTER_VALIDATE_IP)) { return false; } return (bool) \preg_match('/\.'.\preg_quote($cookieDomain, '/').'$/', $domain); } /** * Check if the cookie is expired. */ public function isExpired(): bool { return $this->getExpires() !== null && \time() > $this->getExpires(); } /** * Check if the cookie is valid according to RFC 6265. * * @return bool|string Returns true if valid or an error message if invalid */ public function validate() { $name = $this->getName(); if ($name === '') { return 'The cookie name must not be empty'; } // Check if any of the invalid characters are present in the cookie name if (\preg_match( '/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5c\x7b\x7d\x7f]/', $name )) { return 'Cookie name must not contain invalid characters: ASCII ' .'Control characters (0-31;127), space, tab and the ' .'following characters: ()<>@,;:\"/?={}'; } // Value must not be null. 0 and empty string are valid. Empty strings // are technically against RFC 6265, but known to happen in the wild. $value = $this->getValue(); if ($value === null) { return 'The cookie value must not be empty'; } // Domains must not be empty, but can be 0. "0" is not a valid internet // domain, but may be used as server name in a private network. $domain = $this->getDomain(); if ($domain === null || $domain === '') { return 'The cookie domain must not be empty'; } return true; } } PK������ZE CD �� ����Cookie/CookieJarInterface.phpnu�W+A��������<?php namespace GuzzleHttp\Cookie; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; /** * Stores HTTP cookies. * * It extracts cookies from HTTP requests, and returns them in HTTP responses. * CookieJarInterface instances automatically expire contained cookies when * necessary. Subclasses are also responsible for storing and retrieving * cookies from a file, database, etc. * * @see https://docs.python.org/2/library/cookielib.html Inspiration * @extends \IteratorAggregate<SetCookie> */ interface CookieJarInterface extends \Countable, \IteratorAggregate { /** * Create a request with added cookie headers. * * If no matching cookies are found in the cookie jar, then no Cookie * header is added to the request and the same request is returned. * * @param RequestInterface $request Request object to modify. * * @return RequestInterface returns the modified request. */ public function withCookieHeader(RequestInterface $request): RequestInterface; /** * Extract cookies from an HTTP response and store them in the CookieJar. * * @param RequestInterface $request Request that was sent * @param ResponseInterface $response Response that was received */ public function extractCookies(RequestInterface $request, ResponseInterface $response): void; /** * Sets a cookie in the cookie jar. * * @param SetCookie $cookie Cookie to set. * * @return bool Returns true on success or false on failure */ public function setCookie(SetCookie $cookie): bool; /** * Remove cookies currently held in the cookie jar. * * Invoking this method without arguments will empty the whole cookie jar. * If given a $domain argument only cookies belonging to that domain will * be removed. If given a $domain and $path argument, cookies belonging to * the specified path within that domain are removed. If given all three * arguments, then the cookie with the specified name, path and domain is * removed. * * @param string|null $domain Clears cookies matching a domain * @param string|null $path Clears cookies matching a domain and path * @param string|null $name Clears cookies matching a domain, path, and name */ public function clear(?string $domain = null, ?string $path = null, ?string $name = null): void; /** * Discard all sessions cookies. * * Removes cookies that don't have an expire field or a have a discard * field set to true. To be called when the user agent shuts down according * to RFC 2965. */ public function clearSessionCookies(): void; /** * Converts the cookie jar to an array. */ public function toArray(): array; } PK������Zcg%��%����Cookie/CookieJar.phpnu�W+A��������<?php namespace GuzzleHttp\Cookie; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; /** * Cookie jar that stores cookies as an array */ class CookieJar implements CookieJarInterface { /** * @var SetCookie[] Loaded cookie data */ private $cookies = []; /** * @var bool */ private $strictMode; /** * @param bool $strictMode Set to true to throw exceptions when invalid * cookies are added to the cookie jar. * @param array $cookieArray Array of SetCookie objects or a hash of * arrays that can be used with the SetCookie * constructor */ public function __construct(bool $strictMode = false, array $cookieArray = []) { $this->strictMode = $strictMode; foreach ($cookieArray as $cookie) { if (!($cookie instanceof SetCookie)) { $cookie = new SetCookie($cookie); } $this->setCookie($cookie); } } /** * Create a new Cookie jar from an associative array and domain. * * @param array $cookies Cookies to create the jar from * @param string $domain Domain to set the cookies to */ public static function fromArray(array $cookies, string $domain): self { $cookieJar = new self(); foreach ($cookies as $name => $value) { $cookieJar->setCookie(new SetCookie([ 'Domain' => $domain, 'Name' => $name, 'Value' => $value, 'Discard' => true, ])); } return $cookieJar; } /** * Evaluate if this cookie should be persisted to storage * that survives between requests. * * @param SetCookie $cookie Being evaluated. * @param bool $allowSessionCookies If we should persist session cookies */ public static function shouldPersist(SetCookie $cookie, bool $allowSessionCookies = false): bool { if ($cookie->getExpires() || $allowSessionCookies) { if (!$cookie->getDiscard()) { return true; } } return false; } /** * Finds and returns the cookie based on the name * * @param string $name cookie name to search for * * @return SetCookie|null cookie that was found or null if not found */ public function getCookieByName(string $name): ?SetCookie { foreach ($this->cookies as $cookie) { if ($cookie->getName() !== null && \strcasecmp($cookie->getName(), $name) === 0) { return $cookie; } } return null; } /** * {@inheritDoc} */ public function toArray(): array { return \array_map(static function (SetCookie $cookie): array { return $cookie->toArray(); }, $this->getIterator()->getArrayCopy()); } /** * {@inheritDoc} */ public function clear(?string $domain = null, ?string $path = null, ?string $name = null): void { if (!$domain) { $this->cookies = []; return; } elseif (!$path) { $this->cookies = \array_filter( $this->cookies, static function (SetCookie $cookie) use ($domain): bool { return !$cookie->matchesDomain($domain); } ); } elseif (!$name) { $this->cookies = \array_filter( $this->cookies, static function (SetCookie $cookie) use ($path, $domain): bool { return !($cookie->matchesPath($path) && $cookie->matchesDomain($domain)); } ); } else { $this->cookies = \array_filter( $this->cookies, static function (SetCookie $cookie) use ($path, $domain, $name) { return !($cookie->getName() == $name && $cookie->matchesPath($path) && $cookie->matchesDomain($domain)); } ); } } /** * {@inheritDoc} */ public function clearSessionCookies(): void { $this->cookies = \array_filter( $this->cookies, static function (SetCookie $cookie): bool { return !$cookie->getDiscard() && $cookie->getExpires(); } ); } /** * {@inheritDoc} */ public function setCookie(SetCookie $cookie): bool { // If the name string is empty (but not 0), ignore the set-cookie // string entirely. $name = $cookie->getName(); if (!$name && $name !== '0') { return false; } // Only allow cookies with set and valid domain, name, value $result = $cookie->validate(); if ($result !== true) { if ($this->strictMode) { throw new \RuntimeException('Invalid cookie: '.$result); } $this->removeCookieIfEmpty($cookie); return false; } // Resolve conflicts with previously set cookies foreach ($this->cookies as $i => $c) { // Two cookies are identical, when their path, and domain are // identical. if ($c->getPath() != $cookie->getPath() || $c->getDomain() != $cookie->getDomain() || $c->getName() != $cookie->getName() ) { continue; } // The previously set cookie is a discard cookie and this one is // not so allow the new cookie to be set if (!$cookie->getDiscard() && $c->getDiscard()) { unset($this->cookies[$i]); continue; } // If the new cookie's expiration is further into the future, then // replace the old cookie if ($cookie->getExpires() > $c->getExpires()) { unset($this->cookies[$i]); continue; } // If the value has changed, we better change it if ($cookie->getValue() !== $c->getValue()) { unset($this->cookies[$i]); continue; } // The cookie exists, so no need to continue return false; } $this->cookies[] = $cookie; return true; } public function count(): int { return \count($this->cookies); } /** * @return \ArrayIterator<int, SetCookie> */ public function getIterator(): \ArrayIterator { return new \ArrayIterator(\array_values($this->cookies)); } public function extractCookies(RequestInterface $request, ResponseInterface $response): void { if ($cookieHeader = $response->getHeader('Set-Cookie')) { foreach ($cookieHeader as $cookie) { $sc = SetCookie::fromString($cookie); if (!$sc->getDomain()) { $sc->setDomain($request->getUri()->getHost()); } if (0 !== \strpos($sc->getPath(), '/')) { $sc->setPath($this->getCookiePathFromRequest($request)); } if (!$sc->matchesDomain($request->getUri()->getHost())) { continue; } // Note: At this point `$sc->getDomain()` being a public suffix should // be rejected, but we don't want to pull in the full PSL dependency. $this->setCookie($sc); } } } /** * Computes cookie path following RFC 6265 section 5.1.4 * * @see https://tools.ietf.org/html/rfc6265#section-5.1.4 */ private function getCookiePathFromRequest(RequestInterface $request): string { $uriPath = $request->getUri()->getPath(); if ('' === $uriPath) { return '/'; } if (0 !== \strpos($uriPath, '/')) { return '/'; } if ('/' === $uriPath) { return '/'; } $lastSlashPos = \strrpos($uriPath, '/'); if (0 === $lastSlashPos || false === $lastSlashPos) { return '/'; } return \substr($uriPath, 0, $lastSlashPos); } public function withCookieHeader(RequestInterface $request): RequestInterface { $values = []; $uri = $request->getUri(); $scheme = $uri->getScheme(); $host = $uri->getHost(); $path = $uri->getPath() ?: '/'; foreach ($this->cookies as $cookie) { if ($cookie->matchesPath($path) && $cookie->matchesDomain($host) && !$cookie->isExpired() && (!$cookie->getSecure() || $scheme === 'https') ) { $values[] = $cookie->getName().'=' .$cookie->getValue(); } } return $values ? $request->withHeader('Cookie', \implode('; ', $values)) : $request; } /** * If a cookie already exists and the server asks to set it again with a * null value, the cookie must be deleted. */ private function removeCookieIfEmpty(SetCookie $cookie): void { $cookieValue = $cookie->getValue(); if ($cookieValue === null || $cookieValue === '') { $this->clear( $cookie->getDomain(), $cookie->getPath(), $cookie->getName() ); } } } PK������Z yC_��_����Handler/CurlFactory.phpnu�W+A��������<?php namespace GuzzleHttp\Handler; use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Promise as P; use GuzzleHttp\Promise\FulfilledPromise; use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\Psr7\LazyOpenStream; use GuzzleHttp\TransferStats; use GuzzleHttp\Utils; use Psr\Http\Message\RequestInterface; /** * Creates curl resources from a request * * @final */ class CurlFactory implements CurlFactoryInterface { public const CURL_VERSION_STR = 'curl_version'; /** * @deprecated */ public const LOW_CURL_VERSION_NUMBER = '7.21.2'; /** * @var resource[]|\CurlHandle[] */ private $handles = []; /** * @var int Total number of idle handles to keep in cache */ private $maxHandles; /** * @param int $maxHandles Maximum number of idle handles. */ public function __construct(int $maxHandles) { $this->maxHandles = $maxHandles; } public function create(RequestInterface $request, array $options): EasyHandle { if (isset($options['curl']['body_as_string'])) { $options['_body_as_string'] = $options['curl']['body_as_string']; unset($options['curl']['body_as_string']); } $easy = new EasyHandle(); $easy->request = $request; $easy->options = $options; $conf = $this->getDefaultConf($easy); $this->applyMethod($easy, $conf); $this->applyHandlerOptions($easy, $conf); $this->applyHeaders($easy, $conf); unset($conf['_headers']); // Add handler options from the request configuration options if (isset($options['curl'])) { $conf = \array_replace($conf, $options['curl']); } $conf[\CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy); $easy->handle = $this->handles ? \array_pop($this->handles) : \curl_init(); curl_setopt_array($easy->handle, $conf); return $easy; } public function release(EasyHandle $easy): void { $resource = $easy->handle; unset($easy->handle); if (\count($this->handles) >= $this->maxHandles) { \curl_close($resource); } else { // Remove all callback functions as they can hold onto references // and are not cleaned up by curl_reset. Using curl_setopt_array // does not work for some reason, so removing each one // individually. \curl_setopt($resource, \CURLOPT_HEADERFUNCTION, null); \curl_setopt($resource, \CURLOPT_READFUNCTION, null); \curl_setopt($resource, \CURLOPT_WRITEFUNCTION, null); \curl_setopt($resource, \CURLOPT_PROGRESSFUNCTION, null); \curl_reset($resource); $this->handles[] = $resource; } } /** * Completes a cURL transaction, either returning a response promise or a * rejected promise. * * @param callable(RequestInterface, array): PromiseInterface $handler * @param CurlFactoryInterface $factory Dictates how the handle is released */ public static function finish(callable $handler, EasyHandle $easy, CurlFactoryInterface $factory): PromiseInterface { if (isset($easy->options['on_stats'])) { self::invokeStats($easy); } if (!$easy->response || $easy->errno) { return self::finishError($handler, $easy, $factory); } // Return the response if it is present and there is no error. $factory->release($easy); // Rewind the body of the response if possible. $body = $easy->response->getBody(); if ($body->isSeekable()) { $body->rewind(); } return new FulfilledPromise($easy->response); } private static function invokeStats(EasyHandle $easy): void { $curlStats = \curl_getinfo($easy->handle); $curlStats['appconnect_time'] = \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME); $stats = new TransferStats( $easy->request, $easy->response, $curlStats['total_time'], $easy->errno, $curlStats ); ($easy->options['on_stats'])($stats); } /** * @param callable(RequestInterface, array): PromiseInterface $handler */ private static function finishError(callable $handler, EasyHandle $easy, CurlFactoryInterface $factory): PromiseInterface { // Get error information and release the handle to the factory. $ctx = [ 'errno' => $easy->errno, 'error' => \curl_error($easy->handle), 'appconnect_time' => \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME), ] + \curl_getinfo($easy->handle); $ctx[self::CURL_VERSION_STR] = \curl_version()['version']; $factory->release($easy); // Retry when nothing is present or when curl failed to rewind. if (empty($easy->options['_err_message']) && (!$easy->errno || $easy->errno == 65)) { return self::retryFailedRewind($handler, $easy, $ctx); } return self::createRejection($easy, $ctx); } private static function createRejection(EasyHandle $easy, array $ctx): PromiseInterface { static $connectionErrors = [ \CURLE_OPERATION_TIMEOUTED => true, \CURLE_COULDNT_RESOLVE_HOST => true, \CURLE_COULDNT_CONNECT => true, \CURLE_SSL_CONNECT_ERROR => true, \CURLE_GOT_NOTHING => true, ]; if ($easy->createResponseException) { return P\Create::rejectionFor( new RequestException( 'An error was encountered while creating the response', $easy->request, $easy->response, $easy->createResponseException, $ctx ) ); } // If an exception was encountered during the onHeaders event, then // return a rejected promise that wraps that exception. if ($easy->onHeadersException) { return P\Create::rejectionFor( new RequestException( 'An error was encountered during the on_headers event', $easy->request, $easy->response, $easy->onHeadersException, $ctx ) ); } $message = \sprintf( 'cURL error %s: %s (%s)', $ctx['errno'], $ctx['error'], 'see https://curl.haxx.se/libcurl/c/libcurl-errors.html' ); $uriString = (string) $easy->request->getUri(); if ($uriString !== '' && false === \strpos($ctx['error'], $uriString)) { $message .= \sprintf(' for %s', $uriString); } // Create a connection exception if it was a specific error code. $error = isset($connectionErrors[$easy->errno]) ? new ConnectException($message, $easy->request, null, $ctx) : new RequestException($message, $easy->request, $easy->response, null, $ctx); return P\Create::rejectionFor($error); } /** * @return array<int|string, mixed> */ private function getDefaultConf(EasyHandle $easy): array { $conf = [ '_headers' => $easy->request->getHeaders(), \CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(), \CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''), \CURLOPT_RETURNTRANSFER => false, \CURLOPT_HEADER => false, \CURLOPT_CONNECTTIMEOUT => 300, ]; if (\defined('CURLOPT_PROTOCOLS')) { $conf[\CURLOPT_PROTOCOLS] = \CURLPROTO_HTTP | \CURLPROTO_HTTPS; } $version = $easy->request->getProtocolVersion(); if ($version == 1.1) { $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1; } elseif ($version == 2.0) { $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_2_0; } else { $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_0; } return $conf; } private function applyMethod(EasyHandle $easy, array &$conf): void { $body = $easy->request->getBody(); $size = $body->getSize(); if ($size === null || $size > 0) { $this->applyBody($easy->request, $easy->options, $conf); return; } $method = $easy->request->getMethod(); if ($method === 'PUT' || $method === 'POST') { // See https://tools.ietf.org/html/rfc7230#section-3.3.2 if (!$easy->request->hasHeader('Content-Length')) { $conf[\CURLOPT_HTTPHEADER][] = 'Content-Length: 0'; } } elseif ($method === 'HEAD') { $conf[\CURLOPT_NOBODY] = true; unset( $conf[\CURLOPT_WRITEFUNCTION], $conf[\CURLOPT_READFUNCTION], $conf[\CURLOPT_FILE], $conf[\CURLOPT_INFILE] ); } } private function applyBody(RequestInterface $request, array $options, array &$conf): void { $size = $request->hasHeader('Content-Length') ? (int) $request->getHeaderLine('Content-Length') : null; // Send the body as a string if the size is less than 1MB OR if the // [curl][body_as_string] request value is set. if (($size !== null && $size < 1000000) || !empty($options['_body_as_string'])) { $conf[\CURLOPT_POSTFIELDS] = (string) $request->getBody(); // Don't duplicate the Content-Length header $this->removeHeader('Content-Length', $conf); $this->removeHeader('Transfer-Encoding', $conf); } else { $conf[\CURLOPT_UPLOAD] = true; if ($size !== null) { $conf[\CURLOPT_INFILESIZE] = $size; $this->removeHeader('Content-Length', $conf); } $body = $request->getBody(); if ($body->isSeekable()) { $body->rewind(); } $conf[\CURLOPT_READFUNCTION] = static function ($ch, $fd, $length) use ($body) { return $body->read($length); }; } // If the Expect header is not present, prevent curl from adding it if (!$request->hasHeader('Expect')) { $conf[\CURLOPT_HTTPHEADER][] = 'Expect:'; } // cURL sometimes adds a content-type by default. Prevent this. if (!$request->hasHeader('Content-Type')) { $conf[\CURLOPT_HTTPHEADER][] = 'Content-Type:'; } } private function applyHeaders(EasyHandle $easy, array &$conf): void { foreach ($conf['_headers'] as $name => $values) { foreach ($values as $value) { $value = (string) $value; if ($value === '') { // cURL requires a special format for empty headers. // See https://github.com/guzzle/guzzle/issues/1882 for more details. $conf[\CURLOPT_HTTPHEADER][] = "$name;"; } else { $conf[\CURLOPT_HTTPHEADER][] = "$name: $value"; } } } // Remove the Accept header if one was not set if (!$easy->request->hasHeader('Accept')) { $conf[\CURLOPT_HTTPHEADER][] = 'Accept:'; } } /** * Remove a header from the options array. * * @param string $name Case-insensitive header to remove * @param array $options Array of options to modify */ private function removeHeader(string $name, array &$options): void { foreach (\array_keys($options['_headers']) as $key) { if (!\strcasecmp($key, $name)) { unset($options['_headers'][$key]); return; } } } private function applyHandlerOptions(EasyHandle $easy, array &$conf): void { $options = $easy->options; if (isset($options['verify'])) { if ($options['verify'] === false) { unset($conf[\CURLOPT_CAINFO]); $conf[\CURLOPT_SSL_VERIFYHOST] = 0; $conf[\CURLOPT_SSL_VERIFYPEER] = false; } else { $conf[\CURLOPT_SSL_VERIFYHOST] = 2; $conf[\CURLOPT_SSL_VERIFYPEER] = true; if (\is_string($options['verify'])) { // Throw an error if the file/folder/link path is not valid or doesn't exist. if (!\file_exists($options['verify'])) { throw new \InvalidArgumentException("SSL CA bundle not found: {$options['verify']}"); } // If it's a directory or a link to a directory use CURLOPT_CAPATH. // If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO. if ( \is_dir($options['verify']) || ( \is_link($options['verify']) === true && ($verifyLink = \readlink($options['verify'])) !== false && \is_dir($verifyLink) ) ) { $conf[\CURLOPT_CAPATH] = $options['verify']; } else { $conf[\CURLOPT_CAINFO] = $options['verify']; } } } } if (!isset($options['curl'][\CURLOPT_ENCODING]) && !empty($options['decode_content'])) { $accept = $easy->request->getHeaderLine('Accept-Encoding'); if ($accept) { $conf[\CURLOPT_ENCODING] = $accept; } else { // The empty string enables all available decoders and implicitly // sets a matching 'Accept-Encoding' header. $conf[\CURLOPT_ENCODING] = ''; // But as the user did not specify any acceptable encodings we need // to overwrite this implicit header with an empty one. $conf[\CURLOPT_HTTPHEADER][] = 'Accept-Encoding:'; } } if (!isset($options['sink'])) { // Use a default temp stream if no sink was set. $options['sink'] = \GuzzleHttp\Psr7\Utils::tryFopen('php://temp', 'w+'); } $sink = $options['sink']; if (!\is_string($sink)) { $sink = \GuzzleHttp\Psr7\Utils::streamFor($sink); } elseif (!\is_dir(\dirname($sink))) { // Ensure that the directory exists before failing in curl. throw new \RuntimeException(\sprintf('Directory %s does not exist for sink value of %s', \dirname($sink), $sink)); } else { $sink = new LazyOpenStream($sink, 'w+'); } $easy->sink = $sink; $conf[\CURLOPT_WRITEFUNCTION] = static function ($ch, $write) use ($sink): int { return $sink->write($write); }; $timeoutRequiresNoSignal = false; if (isset($options['timeout'])) { $timeoutRequiresNoSignal |= $options['timeout'] < 1; $conf[\CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000; } // CURL default value is CURL_IPRESOLVE_WHATEVER if (isset($options['force_ip_resolve'])) { if ('v4' === $options['force_ip_resolve']) { $conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V4; } elseif ('v6' === $options['force_ip_resolve']) { $conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V6; } } if (isset($options['connect_timeout'])) { $timeoutRequiresNoSignal |= $options['connect_timeout'] < 1; $conf[\CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000; } if ($timeoutRequiresNoSignal && \strtoupper(\substr(\PHP_OS, 0, 3)) !== 'WIN') { $conf[\CURLOPT_NOSIGNAL] = true; } if (isset($options['proxy'])) { if (!\is_array($options['proxy'])) { $conf[\CURLOPT_PROXY] = $options['proxy']; } else { $scheme = $easy->request->getUri()->getScheme(); if (isset($options['proxy'][$scheme])) { $host = $easy->request->getUri()->getHost(); if (isset($options['proxy']['no']) && Utils::isHostInNoProxy($host, $options['proxy']['no'])) { unset($conf[\CURLOPT_PROXY]); } else { $conf[\CURLOPT_PROXY] = $options['proxy'][$scheme]; } } } } if (isset($options['crypto_method'])) { if (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method']) { if (!defined('CURL_SSLVERSION_TLSv1_0')) { throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.0 not supported by your version of cURL'); } $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_0; } elseif (\STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $options['crypto_method']) { if (!defined('CURL_SSLVERSION_TLSv1_1')) { throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.1 not supported by your version of cURL'); } $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_1; } elseif (\STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $options['crypto_method']) { if (!defined('CURL_SSLVERSION_TLSv1_2')) { throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.2 not supported by your version of cURL'); } $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_2; } elseif (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $options['crypto_method']) { if (!defined('CURL_SSLVERSION_TLSv1_3')) { throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL'); } $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_3; } else { throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided'); } } if (isset($options['cert'])) { $cert = $options['cert']; if (\is_array($cert)) { $conf[\CURLOPT_SSLCERTPASSWD] = $cert[1]; $cert = $cert[0]; } if (!\file_exists($cert)) { throw new \InvalidArgumentException("SSL certificate not found: {$cert}"); } // OpenSSL (versions 0.9.3 and later) also support "P12" for PKCS#12-encoded files. // see https://curl.se/libcurl/c/CURLOPT_SSLCERTTYPE.html $ext = pathinfo($cert, \PATHINFO_EXTENSION); if (preg_match('#^(der|p12)$#i', $ext)) { $conf[\CURLOPT_SSLCERTTYPE] = strtoupper($ext); } $conf[\CURLOPT_SSLCERT] = $cert; } if (isset($options['ssl_key'])) { if (\is_array($options['ssl_key'])) { if (\count($options['ssl_key']) === 2) { [$sslKey, $conf[\CURLOPT_SSLKEYPASSWD]] = $options['ssl_key']; } else { [$sslKey] = $options['ssl_key']; } } $sslKey = $sslKey ?? $options['ssl_key']; if (!\file_exists($sslKey)) { throw new \InvalidArgumentException("SSL private key not found: {$sslKey}"); } $conf[\CURLOPT_SSLKEY] = $sslKey; } if (isset($options['progress'])) { $progress = $options['progress']; if (!\is_callable($progress)) { throw new \InvalidArgumentException('progress client option must be callable'); } $conf[\CURLOPT_NOPROGRESS] = false; $conf[\CURLOPT_PROGRESSFUNCTION] = static function ($resource, int $downloadSize, int $downloaded, int $uploadSize, int $uploaded) use ($progress) { $progress($downloadSize, $downloaded, $uploadSize, $uploaded); }; } if (!empty($options['debug'])) { $conf[\CURLOPT_STDERR] = Utils::debugResource($options['debug']); $conf[\CURLOPT_VERBOSE] = true; } } /** * This function ensures that a response was set on a transaction. If one * was not set, then the request is retried if possible. This error * typically means you are sending a payload, curl encountered a * "Connection died, retrying a fresh connect" error, tried to rewind the * stream, and then encountered a "necessary data rewind wasn't possible" * error, causing the request to be sent through curl_multi_info_read() * without an error status. * * @param callable(RequestInterface, array): PromiseInterface $handler */ private static function retryFailedRewind(callable $handler, EasyHandle $easy, array $ctx): PromiseInterface { try { // Only rewind if the body has been read from. $body = $easy->request->getBody(); if ($body->tell() > 0) { $body->rewind(); } } catch (\RuntimeException $e) { $ctx['error'] = 'The connection unexpectedly failed without ' .'providing an error. The request would have been retried, ' .'but attempting to rewind the request body failed. ' .'Exception: '.$e; return self::createRejection($easy, $ctx); } // Retry no more than 3 times before giving up. if (!isset($easy->options['_curl_retries'])) { $easy->options['_curl_retries'] = 1; } elseif ($easy->options['_curl_retries'] == 2) { $ctx['error'] = 'The cURL request was retried 3 times ' .'and did not succeed. The most likely reason for the failure ' .'is that cURL was unable to rewind the body of the request ' .'and subsequent retries resulted in the same error. Turn on ' .'the debug option to see what went wrong. See ' .'https://bugs.php.net/bug.php?id=47204 for more information.'; return self::createRejection($easy, $ctx); } else { ++$easy->options['_curl_retries']; } return $handler($easy->request, $easy->options); } private function createHeaderFn(EasyHandle $easy): callable { if (isset($easy->options['on_headers'])) { $onHeaders = $easy->options['on_headers']; if (!\is_callable($onHeaders)) { throw new \InvalidArgumentException('on_headers must be callable'); } } else { $onHeaders = null; } return static function ($ch, $h) use ( $onHeaders, $easy, &$startingResponse ) { $value = \trim($h); if ($value === '') { $startingResponse = true; try { $easy->createResponse(); } catch (\Exception $e) { $easy->createResponseException = $e; return -1; } if ($onHeaders !== null) { try { $onHeaders($easy->response); } catch (\Exception $e) { // Associate the exception with the handle and trigger // a curl header write error by returning 0. $easy->onHeadersException = $e; return -1; } } } elseif ($startingResponse) { $startingResponse = false; $easy->headers = [$value]; } else { $easy->headers[] = $value; } return \strlen($h); }; } } PK������ZI]2��2����Handler/CurlHandler.phpnu�W+A��������<?php namespace GuzzleHttp\Handler; use GuzzleHttp\Promise\PromiseInterface; use Psr\Http\Message\RequestInterface; /** * HTTP handler that uses cURL easy handles as a transport layer. * * When using the CurlHandler, custom curl options can be specified as an * associative array of curl option constants mapping to values in the * **curl** key of the "client" key of the request. * * @final */ class CurlHandler { /** * @var CurlFactoryInterface */ private $factory; /** * Accepts an associative array of options: * * - handle_factory: Optional curl factory used to create cURL handles. * * @param array{handle_factory?: ?CurlFactoryInterface} $options Array of options to use with the handler */ public function __construct(array $options = []) { $this->factory = $options['handle_factory'] ?? new CurlFactory(3); } public function __invoke(RequestInterface $request, array $options): PromiseInterface { if (isset($options['delay'])) { \usleep($options['delay'] * 1000); } $easy = $this->factory->create($request, $options); \curl_exec($easy->handle); $easy->errno = \curl_errno($easy->handle); return CurlFactory::finish($this, $easy, $this->factory); } } PK������Z9������Handler/Proxy.phpnu�W+A��������<?php namespace GuzzleHttp\Handler; use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\RequestOptions; use Psr\Http\Message\RequestInterface; /** * Provides basic proxies for handlers. * * @final */ class Proxy { /** * Sends synchronous requests to a specific handler while sending all other * requests to another handler. * * @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $default Handler used for normal responses * @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $sync Handler used for synchronous responses. * * @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the composed handler. */ public static function wrapSync(callable $default, callable $sync): callable { return static function (RequestInterface $request, array $options) use ($default, $sync): PromiseInterface { return empty($options[RequestOptions::SYNCHRONOUS]) ? $default($request, $options) : $sync($request, $options); }; } /** * Sends streaming requests to a streaming compatible handler while sending * all other requests to a default handler. * * This, for example, could be useful for taking advantage of the * performance benefits of curl while still supporting true streaming * through the StreamHandler. * * @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $default Handler used for non-streaming responses * @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $streaming Handler used for streaming responses * * @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the composed handler. */ public static function wrapStreaming(callable $default, callable $streaming): callable { return static function (RequestInterface $request, array $options) use ($default, $streaming): PromiseInterface { return empty($options['stream']) ? $default($request, $options) : $streaming($request, $options); }; } } PK������Zaf �� ����Handler/MockHandler.phpnu�W+A��������<?php namespace GuzzleHttp\Handler; use GuzzleHttp\Exception\RequestException; use GuzzleHttp\HandlerStack; use GuzzleHttp\Promise as P; use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\TransferStats; use GuzzleHttp\Utils; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; /** * Handler that returns responses or throw exceptions from a queue. * * @final */ class MockHandler implements \Countable { /** * @var array */ private $queue = []; /** * @var RequestInterface|null */ private $lastRequest; /** * @var array */ private $lastOptions = []; /** * @var callable|null */ private $onFulfilled; /** * @var callable|null */ private $onRejected; /** * Creates a new MockHandler that uses the default handler stack list of * middlewares. * * @param array|null $queue Array of responses, callables, or exceptions. * @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled. * @param callable|null $onRejected Callback to invoke when the return value is rejected. */ public static function createWithMiddleware(array $queue = null, callable $onFulfilled = null, callable $onRejected = null): HandlerStack { return HandlerStack::create(new self($queue, $onFulfilled, $onRejected)); } /** * The passed in value must be an array of * {@see \Psr\Http\Message\ResponseInterface} objects, Exceptions, * callables, or Promises. * * @param array<int, mixed>|null $queue The parameters to be passed to the append function, as an indexed array. * @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled. * @param callable|null $onRejected Callback to invoke when the return value is rejected. */ public function __construct(array $queue = null, callable $onFulfilled = null, callable $onRejected = null) { $this->onFulfilled = $onFulfilled; $this->onRejected = $onRejected; if ($queue) { // array_values included for BC $this->append(...array_values($queue)); } } public function __invoke(RequestInterface $request, array $options): PromiseInterface { if (!$this->queue) { throw new \OutOfBoundsException('Mock queue is empty'); } if (isset($options['delay']) && \is_numeric($options['delay'])) { \usleep((int) $options['delay'] * 1000); } $this->lastRequest = $request; $this->lastOptions = $options; $response = \array_shift($this->queue); if (isset($options['on_headers'])) { if (!\is_callable($options['on_headers'])) { throw new \InvalidArgumentException('on_headers must be callable'); } try { $options['on_headers']($response); } catch (\Exception $e) { $msg = 'An error was encountered during the on_headers event'; $response = new RequestException($msg, $request, $response, $e); } } if (\is_callable($response)) { $response = $response($request, $options); } $response = $response instanceof \Throwable ? P\Create::rejectionFor($response) : P\Create::promiseFor($response); return $response->then( function (?ResponseInterface $value) use ($request, $options) { $this->invokeStats($request, $options, $value); if ($this->onFulfilled) { ($this->onFulfilled)($value); } if ($value !== null && isset($options['sink'])) { $contents = (string) $value->getBody(); $sink = $options['sink']; if (\is_resource($sink)) { \fwrite($sink, $contents); } elseif (\is_string($sink)) { \file_put_contents($sink, $contents); } elseif ($sink instanceof StreamInterface) { $sink->write($contents); } } return $value; }, function ($reason) use ($request, $options) { $this->invokeStats($request, $options, null, $reason); if ($this->onRejected) { ($this->onRejected)($reason); } return P\Create::rejectionFor($reason); } ); } /** * Adds one or more variadic requests, exceptions, callables, or promises * to the queue. * * @param mixed ...$values */ public function append(...$values): void { foreach ($values as $value) { if ($value instanceof ResponseInterface || $value instanceof \Throwable || $value instanceof PromiseInterface || \is_callable($value) ) { $this->queue[] = $value; } else { throw new \TypeError('Expected a Response, Promise, Throwable or callable. Found '.Utils::describeType($value)); } } } /** * Get the last received request. */ public function getLastRequest(): ?RequestInterface { return $this->lastRequest; } /** * Get the last received request options. */ public function getLastOptions(): array { return $this->lastOptions; } /** * Returns the number of remaining items in the queue. */ public function count(): int { return \count($this->queue); } public function reset(): void { $this->queue = []; } /** * @param mixed $reason Promise or reason. */ private function invokeStats( RequestInterface $request, array $options, ResponseInterface $response = null, $reason = null ): void { if (isset($options['on_stats'])) { $transferTime = $options['transfer_time'] ?? 0; $stats = new TransferStats($request, $response, $transferTime, $reason); ($options['on_stats'])($stats); } } } PK������ZbVS��VS����Handler/StreamHandler.phpnu�W+A��������<?php namespace GuzzleHttp\Handler; use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Promise as P; use GuzzleHttp\Promise\FulfilledPromise; use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\Psr7; use GuzzleHttp\TransferStats; use GuzzleHttp\Utils; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; use Psr\Http\Message\UriInterface; /** * HTTP handler that uses PHP's HTTP stream wrapper. * * @final */ class StreamHandler { /** * @var array */ private $lastHeaders = []; /** * Sends an HTTP request. * * @param RequestInterface $request Request to send. * @param array $options Request transfer options. */ public function __invoke(RequestInterface $request, array $options): PromiseInterface { // Sleep if there is a delay specified. if (isset($options['delay'])) { \usleep($options['delay'] * 1000); } $startTime = isset($options['on_stats']) ? Utils::currentTime() : null; try { // Does not support the expect header. $request = $request->withoutHeader('Expect'); // Append a content-length header if body size is zero to match // cURL's behavior. if (0 === $request->getBody()->getSize()) { $request = $request->withHeader('Content-Length', '0'); } return $this->createResponse( $request, $options, $this->createStream($request, $options), $startTime ); } catch (\InvalidArgumentException $e) { throw $e; } catch (\Exception $e) { // Determine if the error was a networking error. $message = $e->getMessage(); // This list can probably get more comprehensive. if (false !== \strpos($message, 'getaddrinfo') // DNS lookup failed || false !== \strpos($message, 'Connection refused') || false !== \strpos($message, "couldn't connect to host") // error on HHVM || false !== \strpos($message, 'connection attempt failed') ) { $e = new ConnectException($e->getMessage(), $request, $e); } else { $e = RequestException::wrapException($request, $e); } $this->invokeStats($options, $request, $startTime, null, $e); return P\Create::rejectionFor($e); } } private function invokeStats( array $options, RequestInterface $request, ?float $startTime, ResponseInterface $response = null, \Throwable $error = null ): void { if (isset($options['on_stats'])) { $stats = new TransferStats($request, $response, Utils::currentTime() - $startTime, $error, []); ($options['on_stats'])($stats); } } /** * @param resource $stream */ private function createResponse(RequestInterface $request, array $options, $stream, ?float $startTime): PromiseInterface { $hdrs = $this->lastHeaders; $this->lastHeaders = []; try { [$ver, $status, $reason, $headers] = HeaderProcessor::parseHeaders($hdrs); } catch (\Exception $e) { return P\Create::rejectionFor( new RequestException('An error was encountered while creating the response', $request, null, $e) ); } [$stream, $headers] = $this->checkDecode($options, $headers, $stream); $stream = Psr7\Utils::streamFor($stream); $sink = $stream; if (\strcasecmp('HEAD', $request->getMethod())) { $sink = $this->createSink($stream, $options); } try { $response = new Psr7\Response($status, $headers, $sink, $ver, $reason); } catch (\Exception $e) { return P\Create::rejectionFor( new RequestException('An error was encountered while creating the response', $request, null, $e) ); } if (isset($options['on_headers'])) { try { $options['on_headers']($response); } catch (\Exception $e) { return P\Create::rejectionFor( new RequestException('An error was encountered during the on_headers event', $request, $response, $e) ); } } // Do not drain when the request is a HEAD request because they have // no body. if ($sink !== $stream) { $this->drain($stream, $sink, $response->getHeaderLine('Content-Length')); } $this->invokeStats($options, $request, $startTime, $response, null); return new FulfilledPromise($response); } private function createSink(StreamInterface $stream, array $options): StreamInterface { if (!empty($options['stream'])) { return $stream; } $sink = $options['sink'] ?? Psr7\Utils::tryFopen('php://temp', 'r+'); return \is_string($sink) ? new Psr7\LazyOpenStream($sink, 'w+') : Psr7\Utils::streamFor($sink); } /** * @param resource $stream */ private function checkDecode(array $options, array $headers, $stream): array { // Automatically decode responses when instructed. if (!empty($options['decode_content'])) { $normalizedKeys = Utils::normalizeHeaderKeys($headers); if (isset($normalizedKeys['content-encoding'])) { $encoding = $headers[$normalizedKeys['content-encoding']]; if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') { $stream = new Psr7\InflateStream(Psr7\Utils::streamFor($stream)); $headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']]; // Remove content-encoding header unset($headers[$normalizedKeys['content-encoding']]); // Fix content-length header if (isset($normalizedKeys['content-length'])) { $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']]; $length = (int) $stream->getSize(); if ($length === 0) { unset($headers[$normalizedKeys['content-length']]); } else { $headers[$normalizedKeys['content-length']] = [$length]; } } } } } return [$stream, $headers]; } /** * Drains the source stream into the "sink" client option. * * @param string $contentLength Header specifying the amount of * data to read. * * @throws \RuntimeException when the sink option is invalid. */ private function drain(StreamInterface $source, StreamInterface $sink, string $contentLength): StreamInterface { // If a content-length header is provided, then stop reading once // that number of bytes has been read. This can prevent infinitely // reading from a stream when dealing with servers that do not honor // Connection: Close headers. Psr7\Utils::copyToStream( $source, $sink, (\strlen($contentLength) > 0 && (int) $contentLength > 0) ? (int) $contentLength : -1 ); $sink->seek(0); $source->close(); return $sink; } /** * Create a resource and check to ensure it was created successfully * * @param callable $callback Callable that returns stream resource * * @return resource * * @throws \RuntimeException on error */ private function createResource(callable $callback) { $errors = []; \set_error_handler(static function ($_, $msg, $file, $line) use (&$errors): bool { $errors[] = [ 'message' => $msg, 'file' => $file, 'line' => $line, ]; return true; }); try { $resource = $callback(); } finally { \restore_error_handler(); } if (!$resource) { $message = 'Error creating resource: '; foreach ($errors as $err) { foreach ($err as $key => $value) { $message .= "[$key] $value".\PHP_EOL; } } throw new \RuntimeException(\trim($message)); } return $resource; } /** * @return resource */ private function createStream(RequestInterface $request, array $options) { static $methods; if (!$methods) { $methods = \array_flip(\get_class_methods(__CLASS__)); } if (!\in_array($request->getUri()->getScheme(), ['http', 'https'])) { throw new RequestException(\sprintf("The scheme '%s' is not supported.", $request->getUri()->getScheme()), $request); } // HTTP/1.1 streams using the PHP stream wrapper require a // Connection: close header if ($request->getProtocolVersion() == '1.1' && !$request->hasHeader('Connection') ) { $request = $request->withHeader('Connection', 'close'); } // Ensure SSL is verified by default if (!isset($options['verify'])) { $options['verify'] = true; } $params = []; $context = $this->getDefaultContext($request); if (isset($options['on_headers']) && !\is_callable($options['on_headers'])) { throw new \InvalidArgumentException('on_headers must be callable'); } if (!empty($options)) { foreach ($options as $key => $value) { $method = "add_{$key}"; if (isset($methods[$method])) { $this->{$method}($request, $context, $value, $params); } } } if (isset($options['stream_context'])) { if (!\is_array($options['stream_context'])) { throw new \InvalidArgumentException('stream_context must be an array'); } $context = \array_replace_recursive($context, $options['stream_context']); } // Microsoft NTLM authentication only supported with curl handler if (isset($options['auth'][2]) && 'ntlm' === $options['auth'][2]) { throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler'); } $uri = $this->resolveHost($request, $options); $contextResource = $this->createResource( static function () use ($context, $params) { return \stream_context_create($context, $params); } ); return $this->createResource( function () use ($uri, &$http_response_header, $contextResource, $context, $options, $request) { $resource = @\fopen((string) $uri, 'r', false, $contextResource); $this->lastHeaders = $http_response_header ?? []; if (false === $resource) { throw new ConnectException(sprintf('Connection refused for URI %s', $uri), $request, null, $context); } if (isset($options['read_timeout'])) { $readTimeout = $options['read_timeout']; $sec = (int) $readTimeout; $usec = ($readTimeout - $sec) * 100000; \stream_set_timeout($resource, $sec, $usec); } return $resource; } ); } private function resolveHost(RequestInterface $request, array $options): UriInterface { $uri = $request->getUri(); if (isset($options['force_ip_resolve']) && !\filter_var($uri->getHost(), \FILTER_VALIDATE_IP)) { if ('v4' === $options['force_ip_resolve']) { $records = \dns_get_record($uri->getHost(), \DNS_A); if (false === $records || !isset($records[0]['ip'])) { throw new ConnectException(\sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request); } return $uri->withHost($records[0]['ip']); } if ('v6' === $options['force_ip_resolve']) { $records = \dns_get_record($uri->getHost(), \DNS_AAAA); if (false === $records || !isset($records[0]['ipv6'])) { throw new ConnectException(\sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request); } return $uri->withHost('['.$records[0]['ipv6'].']'); } } return $uri; } private function getDefaultContext(RequestInterface $request): array { $headers = ''; foreach ($request->getHeaders() as $name => $value) { foreach ($value as $val) { $headers .= "$name: $val\r\n"; } } $context = [ 'http' => [ 'method' => $request->getMethod(), 'header' => $headers, 'protocol_version' => $request->getProtocolVersion(), 'ignore_errors' => true, 'follow_location' => 0, ], 'ssl' => [ 'peer_name' => $request->getUri()->getHost(), ], ]; $body = (string) $request->getBody(); if ('' !== $body) { $context['http']['content'] = $body; // Prevent the HTTP handler from adding a Content-Type header. if (!$request->hasHeader('Content-Type')) { $context['http']['header'] .= "Content-Type:\r\n"; } } $context['http']['header'] = \rtrim($context['http']['header']); return $context; } /** * @param mixed $value as passed via Request transfer options. */ private function add_proxy(RequestInterface $request, array &$options, $value, array &$params): void { $uri = null; if (!\is_array($value)) { $uri = $value; } else { $scheme = $request->getUri()->getScheme(); if (isset($value[$scheme])) { if (!isset($value['no']) || !Utils::isHostInNoProxy($request->getUri()->getHost(), $value['no'])) { $uri = $value[$scheme]; } } } if (!$uri) { return; } $parsed = $this->parse_proxy($uri); $options['http']['proxy'] = $parsed['proxy']; if ($parsed['auth']) { if (!isset($options['http']['header'])) { $options['http']['header'] = []; } $options['http']['header'] .= "\r\nProxy-Authorization: {$parsed['auth']}"; } } /** * Parses the given proxy URL to make it compatible with the format PHP's stream context expects. */ private function parse_proxy(string $url): array { $parsed = \parse_url($url); if ($parsed !== false && isset($parsed['scheme']) && $parsed['scheme'] === 'http') { if (isset($parsed['host']) && isset($parsed['port'])) { $auth = null; if (isset($parsed['user']) && isset($parsed['pass'])) { $auth = \base64_encode("{$parsed['user']}:{$parsed['pass']}"); } return [ 'proxy' => "tcp://{$parsed['host']}:{$parsed['port']}", 'auth' => $auth ? "Basic {$auth}" : null, ]; } } // Return proxy as-is. return [ 'proxy' => $url, 'auth' => null, ]; } /** * @param mixed $value as passed via Request transfer options. */ private function add_timeout(RequestInterface $request, array &$options, $value, array &$params): void { if ($value > 0) { $options['http']['timeout'] = $value; } } /** * @param mixed $value as passed via Request transfer options. */ private function add_crypto_method(RequestInterface $request, array &$options, $value, array &$params): void { if ( $value === \STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT || $value === \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT || $value === \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT || (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && $value === \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT) ) { $options['http']['crypto_method'] = $value; return; } throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided'); } /** * @param mixed $value as passed via Request transfer options. */ private function add_verify(RequestInterface $request, array &$options, $value, array &$params): void { if ($value === false) { $options['ssl']['verify_peer'] = false; $options['ssl']['verify_peer_name'] = false; return; } if (\is_string($value)) { $options['ssl']['cafile'] = $value; if (!\file_exists($value)) { throw new \RuntimeException("SSL CA bundle not found: $value"); } } elseif ($value !== true) { throw new \InvalidArgumentException('Invalid verify request option'); } $options['ssl']['verify_peer'] = true; $options['ssl']['verify_peer_name'] = true; $options['ssl']['allow_self_signed'] = false; } /** * @param mixed $value as passed via Request transfer options. */ private function add_cert(RequestInterface $request, array &$options, $value, array &$params): void { if (\is_array($value)) { $options['ssl']['passphrase'] = $value[1]; $value = $value[0]; } if (!\file_exists($value)) { throw new \RuntimeException("SSL certificate not found: {$value}"); } $options['ssl']['local_cert'] = $value; } /** * @param mixed $value as passed via Request transfer options. */ private function add_progress(RequestInterface $request, array &$options, $value, array &$params): void { self::addNotification( $params, static function ($code, $a, $b, $c, $transferred, $total) use ($value) { if ($code == \STREAM_NOTIFY_PROGRESS) { // The upload progress cannot be determined. Use 0 for cURL compatibility: // https://curl.se/libcurl/c/CURLOPT_PROGRESSFUNCTION.html $value($total, $transferred, 0, 0); } } ); } /** * @param mixed $value as passed via Request transfer options. */ private function add_debug(RequestInterface $request, array &$options, $value, array &$params): void { if ($value === false) { return; } static $map = [ \STREAM_NOTIFY_CONNECT => 'CONNECT', \STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED', \STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT', \STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS', \STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS', \STREAM_NOTIFY_REDIRECTED => 'REDIRECTED', \STREAM_NOTIFY_PROGRESS => 'PROGRESS', \STREAM_NOTIFY_FAILURE => 'FAILURE', \STREAM_NOTIFY_COMPLETED => 'COMPLETED', \STREAM_NOTIFY_RESOLVE => 'RESOLVE', ]; static $args = ['severity', 'message', 'message_code', 'bytes_transferred', 'bytes_max']; $value = Utils::debugResource($value); $ident = $request->getMethod().' '.$request->getUri()->withFragment(''); self::addNotification( $params, static function (int $code, ...$passed) use ($ident, $value, $map, $args): void { \fprintf($value, '<%s> [%s] ', $ident, $map[$code]); foreach (\array_filter($passed) as $i => $v) { \fwrite($value, $args[$i].': "'.$v.'" '); } \fwrite($value, "\n"); } ); } private static function addNotification(array &$params, callable $notify): void { // Wrap the existing function if needed. if (!isset($params['notification'])) { $params['notification'] = $notify; } else { $params['notification'] = self::callArray([ $params['notification'], $notify, ]); } } private static function callArray(array $functions): callable { return static function (...$args) use ($functions) { foreach ($functions as $fn) { $fn(...$args); } }; } } PK������Z^������Handler/CurlMultiHandler.phpnu�W+A��������<?php namespace GuzzleHttp\Handler; use GuzzleHttp\Promise as P; use GuzzleHttp\Promise\Promise; use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\Utils; use Psr\Http\Message\RequestInterface; /** * Returns an asynchronous response using curl_multi_* functions. * * When using the CurlMultiHandler, custom curl options can be specified as an * associative array of curl option constants mapping to values in the * **curl** key of the provided request options. * * @property resource|\CurlMultiHandle $_mh Internal use only. Lazy loaded multi-handle. * * @final */ #[\AllowDynamicProperties] class CurlMultiHandler { /** * @var CurlFactoryInterface */ private $factory; /** * @var int */ private $selectTimeout; /** * @var int Will be higher than 0 when `curl_multi_exec` is still running. */ private $active = 0; /** * @var array Request entry handles, indexed by handle id in `addRequest`. * * @see CurlMultiHandler::addRequest */ private $handles = []; /** * @var array<int, float> An array of delay times, indexed by handle id in `addRequest`. * * @see CurlMultiHandler::addRequest */ private $delays = []; /** * @var array<mixed> An associative array of CURLMOPT_* options and corresponding values for curl_multi_setopt() */ private $options = []; /** * This handler accepts the following options: * * - handle_factory: An optional factory used to create curl handles * - select_timeout: Optional timeout (in seconds) to block before timing * out while selecting curl handles. Defaults to 1 second. * - options: An associative array of CURLMOPT_* options and * corresponding values for curl_multi_setopt() */ public function __construct(array $options = []) { $this->factory = $options['handle_factory'] ?? new CurlFactory(50); if (isset($options['select_timeout'])) { $this->selectTimeout = $options['select_timeout']; } elseif ($selectTimeout = Utils::getenv('GUZZLE_CURL_SELECT_TIMEOUT')) { @trigger_error('Since guzzlehttp/guzzle 7.2.0: Using environment variable GUZZLE_CURL_SELECT_TIMEOUT is deprecated. Use option "select_timeout" instead.', \E_USER_DEPRECATED); $this->selectTimeout = (int) $selectTimeout; } else { $this->selectTimeout = 1; } $this->options = $options['options'] ?? []; } /** * @param string $name * * @return resource|\CurlMultiHandle * * @throws \BadMethodCallException when another field as `_mh` will be gotten * @throws \RuntimeException when curl can not initialize a multi handle */ public function __get($name) { if ($name !== '_mh') { throw new \BadMethodCallException("Can not get other property as '_mh'."); } $multiHandle = \curl_multi_init(); if (false === $multiHandle) { throw new \RuntimeException('Can not initialize curl multi handle.'); } $this->_mh = $multiHandle; foreach ($this->options as $option => $value) { // A warning is raised in case of a wrong option. curl_multi_setopt($this->_mh, $option, $value); } return $this->_mh; } public function __destruct() { if (isset($this->_mh)) { \curl_multi_close($this->_mh); unset($this->_mh); } } public function __invoke(RequestInterface $request, array $options): PromiseInterface { $easy = $this->factory->create($request, $options); $id = (int) $easy->handle; $promise = new Promise( [$this, 'execute'], function () use ($id) { return $this->cancel($id); } ); $this->addRequest(['easy' => $easy, 'deferred' => $promise]); return $promise; } /** * Ticks the curl event loop. */ public function tick(): void { // Add any delayed handles if needed. if ($this->delays) { $currentTime = Utils::currentTime(); foreach ($this->delays as $id => $delay) { if ($currentTime >= $delay) { unset($this->delays[$id]); \curl_multi_add_handle( $this->_mh, $this->handles[$id]['easy']->handle ); } } } // Step through the task queue which may add additional requests. P\Utils::queue()->run(); if ($this->active && \curl_multi_select($this->_mh, $this->selectTimeout) === -1) { // Perform a usleep if a select returns -1. // See: https://bugs.php.net/bug.php?id=61141 \usleep(250); } while (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) { } $this->processMessages(); } /** * Runs until all outstanding connections have completed. */ public function execute(): void { $queue = P\Utils::queue(); while ($this->handles || !$queue->isEmpty()) { // If there are no transfers, then sleep for the next delay if (!$this->active && $this->delays) { \usleep($this->timeToNext()); } $this->tick(); } } private function addRequest(array $entry): void { $easy = $entry['easy']; $id = (int) $easy->handle; $this->handles[$id] = $entry; if (empty($easy->options['delay'])) { \curl_multi_add_handle($this->_mh, $easy->handle); } else { $this->delays[$id] = Utils::currentTime() + ($easy->options['delay'] / 1000); } } /** * Cancels a handle from sending and removes references to it. * * @param int $id Handle ID to cancel and remove. * * @return bool True on success, false on failure. */ private function cancel($id): bool { if (!is_int($id)) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an integer to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } // Cannot cancel if it has been processed. if (!isset($this->handles[$id])) { return false; } $handle = $this->handles[$id]['easy']->handle; unset($this->delays[$id], $this->handles[$id]); \curl_multi_remove_handle($this->_mh, $handle); \curl_close($handle); return true; } private function processMessages(): void { while ($done = \curl_multi_info_read($this->_mh)) { if ($done['msg'] !== \CURLMSG_DONE) { // if it's not done, then it would be premature to remove the handle. ref https://github.com/guzzle/guzzle/pull/2892#issuecomment-945150216 continue; } $id = (int) $done['handle']; \curl_multi_remove_handle($this->_mh, $done['handle']); if (!isset($this->handles[$id])) { // Probably was cancelled. continue; } $entry = $this->handles[$id]; unset($this->handles[$id], $this->delays[$id]); $entry['easy']->errno = $done['result']; $entry['deferred']->resolve( CurlFactory::finish($this, $entry['easy'], $this->factory) ); } } private function timeToNext(): int { $currentTime = Utils::currentTime(); $nextTime = \PHP_INT_MAX; foreach ($this->delays as $time) { if ($time < $nextTime) { $nextTime = $time; } } return ((int) \max(0, $nextTime - $currentTime)) * 1000000; } } PK������Z7{ �� ����Handler/HeaderProcessor.phpnu�W+A��������<?php namespace GuzzleHttp\Handler; use GuzzleHttp\Utils; /** * @internal */ final class HeaderProcessor { /** * Returns the HTTP version, status code, reason phrase, and headers. * * @param string[] $headers * * @return array{0:string, 1:int, 2:?string, 3:array} * * @throws \RuntimeException */ public static function parseHeaders(array $headers): array { if ($headers === []) { throw new \RuntimeException('Expected a non-empty array of header data'); } $parts = \explode(' ', \array_shift($headers), 3); $version = \explode('/', $parts[0])[1] ?? null; if ($version === null) { throw new \RuntimeException('HTTP version missing from header data'); } $status = $parts[1] ?? null; if ($status === null) { throw new \RuntimeException('HTTP status code missing from header data'); } return [$version, (int) $status, $parts[2] ?? null, Utils::headersFromLines($headers)]; } } PK������Z?CT ��T ����Handler/EasyHandle.phpnu�W+A��������<?php namespace GuzzleHttp\Handler; use GuzzleHttp\Psr7\Response; use GuzzleHttp\Utils; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; /** * Represents a cURL easy handle and the data it populates. * * @internal */ final class EasyHandle { /** * @var resource|\CurlHandle cURL resource */ public $handle; /** * @var StreamInterface Where data is being written */ public $sink; /** * @var array Received HTTP headers so far */ public $headers = []; /** * @var ResponseInterface|null Received response (if any) */ public $response; /** * @var RequestInterface Request being sent */ public $request; /** * @var array Request options */ public $options = []; /** * @var int cURL error number (if any) */ public $errno = 0; /** * @var \Throwable|null Exception during on_headers (if any) */ public $onHeadersException; /** * @var \Exception|null Exception during createResponse (if any) */ public $createResponseException; /** * Attach a response to the easy handle based on the received headers. * * @throws \RuntimeException if no headers have been received or the first * header line is invalid. */ public function createResponse(): void { [$ver, $status, $reason, $headers] = HeaderProcessor::parseHeaders($this->headers); $normalizedKeys = Utils::normalizeHeaderKeys($headers); if (!empty($this->options['decode_content']) && isset($normalizedKeys['content-encoding'])) { $headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']]; unset($headers[$normalizedKeys['content-encoding']]); if (isset($normalizedKeys['content-length'])) { $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']]; $bodyLength = (int) $this->sink->getSize(); if ($bodyLength) { $headers[$normalizedKeys['content-length']] = $bodyLength; } else { unset($headers[$normalizedKeys['content-length']]); } } } // Attach a response to the easy handle with the parsed headers. $this->response = new Response( $status, $headers, $this->sink, $ver, $reason ); } /** * @param string $name * * @return void * * @throws \BadMethodCallException */ public function __get($name) { $msg = $name === 'handle' ? 'The EasyHandle has been released' : 'Invalid property: '.$name; throw new \BadMethodCallException($msg); } } PK������ZP���� ��Handler/CurlFactoryInterface.phpnu�W+A��������<?php namespace GuzzleHttp\Handler; use Psr\Http\Message\RequestInterface; interface CurlFactoryInterface { /** * Creates a cURL handle resource. * * @param RequestInterface $request Request * @param array $options Transfer options * * @throws \RuntimeException when an option cannot be applied */ public function create(RequestInterface $request, array $options): EasyHandle; /** * Release an easy handle, allowing it to be reused or closed. * * This function must call unset on the easy handle's "handle" property. */ public function release(EasyHandle $easy): void; } PK������ZS%+��%+����RequestOptions.phpnu�W+A��������<?php namespace GuzzleHttp; /** * This class contains a list of built-in Guzzle request options. * * More documentation for each option can be found at http://guzzlephp.org/. * * @see http://docs.guzzlephp.org/en/v6/request-options.html */ final class RequestOptions { /** * allow_redirects: (bool|array) Controls redirect behavior. Pass false * to disable redirects, pass true to enable redirects, pass an * associative to provide custom redirect settings. Defaults to "false". * This option only works if your handler has the RedirectMiddleware. When * passing an associative array, you can provide the following key value * pairs: * * - max: (int, default=5) maximum number of allowed redirects. * - strict: (bool, default=false) Set to true to use strict redirects * meaning redirect POST requests with POST requests vs. doing what most * browsers do which is redirect POST requests with GET requests * - referer: (bool, default=false) Set to true to enable the Referer * header. * - protocols: (array, default=['http', 'https']) Allowed redirect * protocols. * - on_redirect: (callable) PHP callable that is invoked when a redirect * is encountered. The callable is invoked with the request, the redirect * response that was received, and the effective URI. Any return value * from the on_redirect function is ignored. */ public const ALLOW_REDIRECTS = 'allow_redirects'; /** * auth: (array) Pass an array of HTTP authentication parameters to use * with the request. The array must contain the username in index [0], * the password in index [1], and you can optionally provide a built-in * authentication type in index [2]. Pass null to disable authentication * for a request. */ public const AUTH = 'auth'; /** * body: (resource|string|null|int|float|StreamInterface|callable|\Iterator) * Body to send in the request. */ public const BODY = 'body'; /** * cert: (string|array) Set to a string to specify the path to a file * containing a PEM formatted SSL client side certificate. If a password * is required, then set cert to an array containing the path to the PEM * file in the first array element followed by the certificate password * in the second array element. */ public const CERT = 'cert'; /** * cookies: (bool|GuzzleHttp\Cookie\CookieJarInterface, default=false) * Specifies whether or not cookies are used in a request or what cookie * jar to use or what cookies to send. This option only works if your * handler has the `cookie` middleware. Valid values are `false` and * an instance of {@see \GuzzleHttp\Cookie\CookieJarInterface}. */ public const COOKIES = 'cookies'; /** * connect_timeout: (float, default=0) Float describing the number of * seconds to wait while trying to connect to a server. Use 0 to wait * 300 seconds (the default behavior). */ public const CONNECT_TIMEOUT = 'connect_timeout'; /** * crypto_method: (int) A value describing the minimum TLS protocol * version to use. * * This setting must be set to one of the * ``STREAM_CRYPTO_METHOD_TLS*_CLIENT`` constants. PHP 7.4 or higher is * required in order to use TLS 1.3, and cURL 7.34.0 or higher is required * in order to specify a crypto method, with cURL 7.52.0 or higher being * required to use TLS 1.3. */ public const CRYPTO_METHOD = 'crypto_method'; /** * debug: (bool|resource) Set to true or set to a PHP stream returned by * fopen() enable debug output with the HTTP handler used to send a * request. */ public const DEBUG = 'debug'; /** * decode_content: (bool, default=true) Specify whether or not * Content-Encoding responses (gzip, deflate, etc.) are automatically * decoded. */ public const DECODE_CONTENT = 'decode_content'; /** * delay: (int) The amount of time to delay before sending in milliseconds. */ public const DELAY = 'delay'; /** * expect: (bool|integer) Controls the behavior of the * "Expect: 100-Continue" header. * * Set to `true` to enable the "Expect: 100-Continue" header for all * requests that sends a body. Set to `false` to disable the * "Expect: 100-Continue" header for all requests. Set to a number so that * the size of the payload must be greater than the number in order to send * the Expect header. Setting to a number will send the Expect header for * all requests in which the size of the payload cannot be determined or * where the body is not rewindable. * * By default, Guzzle will add the "Expect: 100-Continue" header when the * size of the body of a request is greater than 1 MB and a request is * using HTTP/1.1. */ public const EXPECT = 'expect'; /** * form_params: (array) Associative array of form field names to values * where each value is a string or array of strings. Sets the Content-Type * header to application/x-www-form-urlencoded when no Content-Type header * is already present. */ public const FORM_PARAMS = 'form_params'; /** * headers: (array) Associative array of HTTP headers. Each value MUST be * a string or array of strings. */ public const HEADERS = 'headers'; /** * http_errors: (bool, default=true) Set to false to disable exceptions * when a non- successful HTTP response is received. By default, * exceptions will be thrown for 4xx and 5xx responses. This option only * works if your handler has the `httpErrors` middleware. */ public const HTTP_ERRORS = 'http_errors'; /** * idn: (bool|int, default=true) A combination of IDNA_* constants for * idn_to_ascii() PHP's function (see "options" parameter). Set to false to * disable IDN support completely, or to true to use the default * configuration (IDNA_DEFAULT constant). */ public const IDN_CONVERSION = 'idn_conversion'; /** * json: (mixed) Adds JSON data to a request. The provided value is JSON * encoded and a Content-Type header of application/json will be added to * the request if no Content-Type header is already present. */ public const JSON = 'json'; /** * multipart: (array) Array of associative arrays, each containing a * required "name" key mapping to the form field, name, a required * "contents" key mapping to a StreamInterface|resource|string, an * optional "headers" associative array of custom headers, and an * optional "filename" key mapping to a string to send as the filename in * the part. If no "filename" key is present, then no "filename" attribute * will be added to the part. */ public const MULTIPART = 'multipart'; /** * on_headers: (callable) A callable that is invoked when the HTTP headers * of the response have been received but the body has not yet begun to * download. */ public const ON_HEADERS = 'on_headers'; /** * on_stats: (callable) allows you to get access to transfer statistics of * a request and access the lower level transfer details of the handler * associated with your client. ``on_stats`` is a callable that is invoked * when a handler has finished sending a request. The callback is invoked * with transfer statistics about the request, the response received, or * the error encountered. Included in the data is the total amount of time * taken to send the request. */ public const ON_STATS = 'on_stats'; /** * progress: (callable) Defines a function to invoke when transfer * progress is made. The function accepts the following positional * arguments: the total number of bytes expected to be downloaded, the * number of bytes downloaded so far, the number of bytes expected to be * uploaded, the number of bytes uploaded so far. */ public const PROGRESS = 'progress'; /** * proxy: (string|array) Pass a string to specify an HTTP proxy, or an * array to specify different proxies for different protocols (where the * key is the protocol and the value is a proxy string). */ public const PROXY = 'proxy'; /** * query: (array|string) Associative array of query string values to add * to the request. This option uses PHP's http_build_query() to create * the string representation. Pass a string value if you need more * control than what this method provides */ public const QUERY = 'query'; /** * sink: (resource|string|StreamInterface) Where the data of the * response is written to. Defaults to a PHP temp stream. Providing a * string will write data to a file by the given name. */ public const SINK = 'sink'; /** * synchronous: (bool) Set to true to inform HTTP handlers that you intend * on waiting on the response. This can be useful for optimizations. Note * that a promise is still returned if you are using one of the async * client methods. */ public const SYNCHRONOUS = 'synchronous'; /** * ssl_key: (array|string) Specify the path to a file containing a private * SSL key in PEM format. If a password is required, then set to an array * containing the path to the SSL key in the first array element followed * by the password required for the certificate in the second element. */ public const SSL_KEY = 'ssl_key'; /** * stream: Set to true to attempt to stream a response rather than * download it all up-front. */ public const STREAM = 'stream'; /** * verify: (bool|string, default=true) Describes the SSL certificate * verification behavior of a request. Set to true to enable SSL * certificate verification using the system CA bundle when available * (the default). Set to false to disable certificate verification (this * is insecure!). Set to a string to provide the path to a CA bundle on * disk to enable verification using a custom certificate. */ public const VERIFY = 'verify'; /** * timeout: (float, default=0) Float describing the timeout of the * request in seconds. Use 0 to wait indefinitely (the default behavior). */ public const TIMEOUT = 'timeout'; /** * read_timeout: (float, default=default_socket_timeout ini setting) Float describing * the body read timeout, for stream requests. */ public const READ_TIMEOUT = 'read_timeout'; /** * version: (float) Specifies the HTTP protocol version to attempt to use. */ public const VERSION = 'version'; /** * force_ip_resolve: (bool) Force client to use only ipv4 or ipv6 protocol */ public const FORCE_IP_RESOLVE = 'force_ip_resolve'; } PK������Z]��������BodySummarizerInterface.phpnu�W+A��������<?php namespace GuzzleHttp; use Psr\Http\Message\MessageInterface; interface BodySummarizerInterface { /** * Returns a summarized message body. */ public function summarize(MessageInterface $message): ?string; } PK������Z3LU ��U ����ClientInterface.phpnu�W+A��������<?php namespace GuzzleHttp; use GuzzleHttp\Exception\GuzzleException; use GuzzleHttp\Promise\PromiseInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\UriInterface; /** * Client interface for sending HTTP requests. */ interface ClientInterface { /** * The Guzzle major version. */ public const MAJOR_VERSION = 7; /** * Send an HTTP request. * * @param RequestInterface $request Request to send * @param array $options Request options to apply to the given * request and to the transfer. * * @throws GuzzleException */ public function send(RequestInterface $request, array $options = []): ResponseInterface; /** * Asynchronously send an HTTP request. * * @param RequestInterface $request Request to send * @param array $options Request options to apply to the given * request and to the transfer. */ public function sendAsync(RequestInterface $request, array $options = []): PromiseInterface; /** * Create and send an HTTP request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string $method HTTP method. * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. * * @throws GuzzleException */ public function request(string $method, $uri, array $options = []): ResponseInterface; /** * Create and send an asynchronous HTTP request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string $method HTTP method * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public function requestAsync(string $method, $uri, array $options = []): PromiseInterface; /** * Get a client configuration option. * * These options include default request options of the client, a "handler" * (if utilized by the concrete client), and a "base_uri" if utilized by * the concrete client. * * @param string|null $option The config option to retrieve. * * @return mixed * * @deprecated ClientInterface::getConfig will be removed in guzzlehttp/guzzle:8.0. */ public function getConfig(?string $option = null); } PK������Z�������RedirectMiddleware.phpnu�W+A��������<?php namespace GuzzleHttp; use GuzzleHttp\Exception\BadResponseException; use GuzzleHttp\Exception\TooManyRedirectsException; use GuzzleHttp\Promise\PromiseInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\UriInterface; /** * Request redirect middleware. * * Apply this middleware like other middleware using * {@see \GuzzleHttp\Middleware::redirect()}. * * @final */ class RedirectMiddleware { public const HISTORY_HEADER = 'X-Guzzle-Redirect-History'; public const STATUS_HISTORY_HEADER = 'X-Guzzle-Redirect-Status-History'; /** * @var array */ public static $defaultSettings = [ 'max' => 5, 'protocols' => ['http', 'https'], 'strict' => false, 'referer' => false, 'track_redirects' => false, ]; /** * @var callable(RequestInterface, array): PromiseInterface */ private $nextHandler; /** * @param callable(RequestInterface, array): PromiseInterface $nextHandler Next handler to invoke. */ public function __construct(callable $nextHandler) { $this->nextHandler = $nextHandler; } public function __invoke(RequestInterface $request, array $options): PromiseInterface { $fn = $this->nextHandler; if (empty($options['allow_redirects'])) { return $fn($request, $options); } if ($options['allow_redirects'] === true) { $options['allow_redirects'] = self::$defaultSettings; } elseif (!\is_array($options['allow_redirects'])) { throw new \InvalidArgumentException('allow_redirects must be true, false, or array'); } else { // Merge the default settings with the provided settings $options['allow_redirects'] += self::$defaultSettings; } if (empty($options['allow_redirects']['max'])) { return $fn($request, $options); } return $fn($request, $options) ->then(function (ResponseInterface $response) use ($request, $options) { return $this->checkRedirect($request, $options, $response); }); } /** * @return ResponseInterface|PromiseInterface */ public function checkRedirect(RequestInterface $request, array $options, ResponseInterface $response) { if (\strpos((string) $response->getStatusCode(), '3') !== 0 || !$response->hasHeader('Location') ) { return $response; } $this->guardMax($request, $response, $options); $nextRequest = $this->modifyRequest($request, $options, $response); // If authorization is handled by curl, unset it if URI is cross-origin. if (Psr7\UriComparator::isCrossOrigin($request->getUri(), $nextRequest->getUri()) && defined('\CURLOPT_HTTPAUTH')) { unset( $options['curl'][\CURLOPT_HTTPAUTH], $options['curl'][\CURLOPT_USERPWD] ); } if (isset($options['allow_redirects']['on_redirect'])) { ($options['allow_redirects']['on_redirect'])( $request, $response, $nextRequest->getUri() ); } $promise = $this($nextRequest, $options); // Add headers to be able to track history of redirects. if (!empty($options['allow_redirects']['track_redirects'])) { return $this->withTracking( $promise, (string) $nextRequest->getUri(), $response->getStatusCode() ); } return $promise; } /** * Enable tracking on promise. */ private function withTracking(PromiseInterface $promise, string $uri, int $statusCode): PromiseInterface { return $promise->then( static function (ResponseInterface $response) use ($uri, $statusCode) { // Note that we are pushing to the front of the list as this // would be an earlier response than what is currently present // in the history header. $historyHeader = $response->getHeader(self::HISTORY_HEADER); $statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER); \array_unshift($historyHeader, $uri); \array_unshift($statusHeader, (string) $statusCode); return $response->withHeader(self::HISTORY_HEADER, $historyHeader) ->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader); } ); } /** * Check for too many redirects. * * @throws TooManyRedirectsException Too many redirects. */ private function guardMax(RequestInterface $request, ResponseInterface $response, array &$options): void { $current = $options['__redirect_count'] ?? 0; $options['__redirect_count'] = $current + 1; $max = $options['allow_redirects']['max']; if ($options['__redirect_count'] > $max) { throw new TooManyRedirectsException("Will not follow more than {$max} redirects", $request, $response); } } public function modifyRequest(RequestInterface $request, array $options, ResponseInterface $response): RequestInterface { // Request modifications to apply. $modify = []; $protocols = $options['allow_redirects']['protocols']; // Use a GET request if this is an entity enclosing request and we are // not forcing RFC compliance, but rather emulating what all browsers // would do. $statusCode = $response->getStatusCode(); if ($statusCode == 303 || ($statusCode <= 302 && !$options['allow_redirects']['strict']) ) { $safeMethods = ['GET', 'HEAD', 'OPTIONS']; $requestMethod = $request->getMethod(); $modify['method'] = in_array($requestMethod, $safeMethods) ? $requestMethod : 'GET'; $modify['body'] = ''; } $uri = self::redirectUri($request, $response, $protocols); if (isset($options['idn_conversion']) && ($options['idn_conversion'] !== false)) { $idnOptions = ($options['idn_conversion'] === true) ? \IDNA_DEFAULT : $options['idn_conversion']; $uri = Utils::idnUriConvert($uri, $idnOptions); } $modify['uri'] = $uri; Psr7\Message::rewindBody($request); // Add the Referer header if it is told to do so and only // add the header if we are not redirecting from https to http. if ($options['allow_redirects']['referer'] && $modify['uri']->getScheme() === $request->getUri()->getScheme() ) { $uri = $request->getUri()->withUserInfo(''); $modify['set_headers']['Referer'] = (string) $uri; } else { $modify['remove_headers'][] = 'Referer'; } // Remove Authorization and Cookie headers if URI is cross-origin. if (Psr7\UriComparator::isCrossOrigin($request->getUri(), $modify['uri'])) { $modify['remove_headers'][] = 'Authorization'; $modify['remove_headers'][] = 'Cookie'; } return Psr7\Utils::modifyRequest($request, $modify); } /** * Set the appropriate URL on the request based on the location header. */ private static function redirectUri( RequestInterface $request, ResponseInterface $response, array $protocols ): UriInterface { $location = Psr7\UriResolver::resolve( $request->getUri(), new Psr7\Uri($response->getHeaderLine('Location')) ); // Ensure that the redirect URI is allowed based on the protocols. if (!\in_array($location->getScheme(), $protocols)) { throw new BadResponseException(\sprintf('Redirect URI, %s, does not use one of the allowed redirect protocols: %s', $location, \implode(', ', $protocols)), $request, $response); } return $location; } } PK������Z1��1����MessageFormatterInterface.phpnu�W+A��������<?php namespace GuzzleHttp; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; interface MessageFormatterInterface { /** * Returns a formatted message string. * * @param RequestInterface $request Request that was sent * @param ResponseInterface|null $response Response that was received * @param \Throwable|null $error Exception that was received */ public function format(RequestInterface $request, ?ResponseInterface $response = null, ?\Throwable $error = null): string; } PK������ZL-u��u����MessageFormatter.phpnu�W+A��������<?php namespace GuzzleHttp; use Psr\Http\Message\MessageInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; /** * Formats log messages using variable substitutions for requests, responses, * and other transactional data. * * The following variable substitutions are supported: * * - {request}: Full HTTP request message * - {response}: Full HTTP response message * - {ts}: ISO 8601 date in GMT * - {date_iso_8601} ISO 8601 date in GMT * - {date_common_log} Apache common log date using the configured timezone. * - {host}: Host of the request * - {method}: Method of the request * - {uri}: URI of the request * - {version}: Protocol version * - {target}: Request target of the request (path + query + fragment) * - {hostname}: Hostname of the machine that sent the request * - {code}: Status code of the response (if available) * - {phrase}: Reason phrase of the response (if available) * - {error}: Any error messages (if available) * - {req_header_*}: Replace `*` with the lowercased name of a request header to add to the message * - {res_header_*}: Replace `*` with the lowercased name of a response header to add to the message * - {req_headers}: Request headers * - {res_headers}: Response headers * - {req_body}: Request body * - {res_body}: Response body * * @final */ class MessageFormatter implements MessageFormatterInterface { /** * Apache Common Log Format. * * @see https://httpd.apache.org/docs/2.4/logs.html#common * * @var string */ public const CLF = '{hostname} {req_header_User-Agent} - [{date_common_log}] "{method} {target} HTTP/{version}" {code} {res_header_Content-Length}'; public const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}"; public const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}'; /** * @var string Template used to format log messages */ private $template; /** * @param string $template Log message template */ public function __construct(?string $template = self::CLF) { $this->template = $template ?: self::CLF; } /** * Returns a formatted message string. * * @param RequestInterface $request Request that was sent * @param ResponseInterface|null $response Response that was received * @param \Throwable|null $error Exception that was received */ public function format(RequestInterface $request, ?ResponseInterface $response = null, ?\Throwable $error = null): string { $cache = []; /** @var string */ return \preg_replace_callback( '/{\s*([A-Za-z_\-\.0-9]+)\s*}/', function (array $matches) use ($request, $response, $error, &$cache) { if (isset($cache[$matches[1]])) { return $cache[$matches[1]]; } $result = ''; switch ($matches[1]) { case 'request': $result = Psr7\Message::toString($request); break; case 'response': $result = $response ? Psr7\Message::toString($response) : ''; break; case 'req_headers': $result = \trim($request->getMethod() .' '.$request->getRequestTarget()) .' HTTP/'.$request->getProtocolVersion()."\r\n" .$this->headers($request); break; case 'res_headers': $result = $response ? \sprintf( 'HTTP/%s %d %s', $response->getProtocolVersion(), $response->getStatusCode(), $response->getReasonPhrase() )."\r\n".$this->headers($response) : 'NULL'; break; case 'req_body': $result = $request->getBody()->__toString(); break; case 'res_body': if (!$response instanceof ResponseInterface) { $result = 'NULL'; break; } $body = $response->getBody(); if (!$body->isSeekable()) { $result = 'RESPONSE_NOT_LOGGEABLE'; break; } $result = $response->getBody()->__toString(); break; case 'ts': case 'date_iso_8601': $result = \gmdate('c'); break; case 'date_common_log': $result = \date('d/M/Y:H:i:s O'); break; case 'method': $result = $request->getMethod(); break; case 'version': $result = $request->getProtocolVersion(); break; case 'uri': case 'url': $result = $request->getUri()->__toString(); break; case 'target': $result = $request->getRequestTarget(); break; case 'req_version': $result = $request->getProtocolVersion(); break; case 'res_version': $result = $response ? $response->getProtocolVersion() : 'NULL'; break; case 'host': $result = $request->getHeaderLine('Host'); break; case 'hostname': $result = \gethostname(); break; case 'code': $result = $response ? $response->getStatusCode() : 'NULL'; break; case 'phrase': $result = $response ? $response->getReasonPhrase() : 'NULL'; break; case 'error': $result = $error ? $error->getMessage() : 'NULL'; break; default: // handle prefixed dynamic headers if (\strpos($matches[1], 'req_header_') === 0) { $result = $request->getHeaderLine(\substr($matches[1], 11)); } elseif (\strpos($matches[1], 'res_header_') === 0) { $result = $response ? $response->getHeaderLine(\substr($matches[1], 11)) : 'NULL'; } } $cache[$matches[1]] = $result; return $result; }, $this->template ); } /** * Get headers from message as string */ private function headers(MessageInterface $message): string { $result = ''; foreach ($message->getHeaders() as $name => $values) { $result .= $name.': '.\implode(', ', $values)."\r\n"; } return \trim($result); } } PK������Zsw����$��DeepCopy/TypeMatcher/TypeMatcher.phpnu�W+A��������<?php namespace DeepCopy\TypeMatcher; class TypeMatcher { /** * @var string */ private $type; /** * @param string $type */ public function __construct($type) { $this->type = $type; } /** * @param mixed $element * * @return boolean */ public function matches($element) { return is_object($element) ? is_a($element, $this->type) : gettype($element) === $this->type; } } PK������Z 0������DeepCopy/DeepCopy.phpnu�W+A��������<?php namespace DeepCopy; use ArrayObject; use DateInterval; use DateTimeInterface; use DateTimeZone; use DeepCopy\Exception\CloneException; use DeepCopy\Filter\ChainableFilter; use DeepCopy\Filter\Filter; use DeepCopy\Matcher\Matcher; use DeepCopy\Reflection\ReflectionHelper; use DeepCopy\TypeFilter\Date\DateIntervalFilter; use DeepCopy\TypeFilter\Spl\ArrayObjectFilter; use DeepCopy\TypeFilter\Spl\SplDoublyLinkedListFilter; use DeepCopy\TypeFilter\TypeFilter; use DeepCopy\TypeMatcher\TypeMatcher; use ReflectionObject; use ReflectionProperty; use SplDoublyLinkedList; /** * @final */ class DeepCopy { /** * @var object[] List of objects copied. */ private $hashMap = []; /** * Filters to apply. * * @var array Array of ['filter' => Filter, 'matcher' => Matcher] pairs. */ private $filters = []; /** * Type Filters to apply. * * @var array Array of ['filter' => Filter, 'matcher' => Matcher] pairs. */ private $typeFilters = []; /** * @var bool */ private $skipUncloneable = false; /** * @var bool */ private $useCloneMethod; /** * @param bool $useCloneMethod If set to true, when an object implements the __clone() function, it will be used * instead of the regular deep cloning. */ public function __construct($useCloneMethod = false) { $this->useCloneMethod = $useCloneMethod; $this->addTypeFilter(new ArrayObjectFilter($this), new TypeMatcher(ArrayObject::class)); $this->addTypeFilter(new DateIntervalFilter(), new TypeMatcher(DateInterval::class)); $this->addTypeFilter(new SplDoublyLinkedListFilter($this), new TypeMatcher(SplDoublyLinkedList::class)); } /** * If enabled, will not throw an exception when coming across an uncloneable property. * * @param $skipUncloneable * * @return $this */ public function skipUncloneable($skipUncloneable = true) { $this->skipUncloneable = $skipUncloneable; return $this; } /** * Deep copies the given object. * * @param mixed $object * * @return mixed */ public function copy($object) { $this->hashMap = []; return $this->recursiveCopy($object); } public function addFilter(Filter $filter, Matcher $matcher) { $this->filters[] = [ 'matcher' => $matcher, 'filter' => $filter, ]; } public function prependFilter(Filter $filter, Matcher $matcher) { array_unshift($this->filters, [ 'matcher' => $matcher, 'filter' => $filter, ]); } public function addTypeFilter(TypeFilter $filter, TypeMatcher $matcher) { $this->typeFilters[] = [ 'matcher' => $matcher, 'filter' => $filter, ]; } private function recursiveCopy($var) { // Matches Type Filter if ($filter = $this->getFirstMatchedTypeFilter($this->typeFilters, $var)) { return $filter->apply($var); } // Resource if (is_resource($var)) { return $var; } // Array if (is_array($var)) { return $this->copyArray($var); } // Scalar if (! is_object($var)) { return $var; } // Enum if (PHP_VERSION_ID >= 80100 && enum_exists(get_class($var))) { return $var; } // Object return $this->copyObject($var); } /** * Copy an array * @param array $array * @return array */ private function copyArray(array $array) { foreach ($array as $key => $value) { $array[$key] = $this->recursiveCopy($value); } return $array; } /** * Copies an object. * * @param object $object * * @throws CloneException * * @return object */ private function copyObject($object) { $objectHash = spl_object_hash($object); if (isset($this->hashMap[$objectHash])) { return $this->hashMap[$objectHash]; } $reflectedObject = new ReflectionObject($object); $isCloneable = $reflectedObject->isCloneable(); if (false === $isCloneable) { if ($this->skipUncloneable) { $this->hashMap[$objectHash] = $object; return $object; } throw new CloneException( sprintf( 'The class "%s" is not cloneable.', $reflectedObject->getName() ) ); } $newObject = clone $object; $this->hashMap[$objectHash] = $newObject; if ($this->useCloneMethod && $reflectedObject->hasMethod('__clone')) { return $newObject; } if ($newObject instanceof DateTimeInterface || $newObject instanceof DateTimeZone) { return $newObject; } foreach (ReflectionHelper::getProperties($reflectedObject) as $property) { $this->copyObjectProperty($newObject, $property); } return $newObject; } private function copyObjectProperty($object, ReflectionProperty $property) { // Ignore static properties if ($property->isStatic()) { return; } // Apply the filters foreach ($this->filters as $item) { /** @var Matcher $matcher */ $matcher = $item['matcher']; /** @var Filter $filter */ $filter = $item['filter']; if ($matcher->matches($object, $property->getName())) { $filter->apply( $object, $property->getName(), function ($object) { return $this->recursiveCopy($object); } ); if ($filter instanceof ChainableFilter) { continue; } // If a filter matches, we stop processing this property return; } } $property->setAccessible(true); // Ignore uninitialized properties (for PHP >7.4) if (method_exists($property, 'isInitialized') && !$property->isInitialized($object)) { return; } $propertyValue = $property->getValue($object); // Copy the property $property->setValue($object, $this->recursiveCopy($propertyValue)); } /** * Returns first filter that matches variable, `null` if no such filter found. * * @param array $filterRecords Associative array with 2 members: 'filter' with value of type {@see TypeFilter} and * 'matcher' with value of type {@see TypeMatcher} * @param mixed $var * * @return TypeFilter|null */ private function getFirstMatchedTypeFilter(array $filterRecords, $var) { $matched = $this->first( $filterRecords, function (array $record) use ($var) { /* @var TypeMatcher $matcher */ $matcher = $record['matcher']; return $matcher->matches($var); } ); return isset($matched) ? $matched['filter'] : null; } /** * Returns first element that matches predicate, `null` if no such element found. * * @param array $elements Array of ['filter' => Filter, 'matcher' => Matcher] pairs. * @param callable $predicate Predicate arguments are: element. * * @return array|null Associative array with 2 members: 'filter' with value of type {@see TypeFilter} and 'matcher' * with value of type {@see TypeMatcher} or `null`. */ private function first(array $elements, callable $predicate) { foreach ($elements as $element) { if (call_user_func($predicate, $element)) { return $element; } } return null; } } PK������Z"e������DeepCopy/deep_copy.phpnu�W+A��������<?php namespace DeepCopy; use function function_exists; if (false === function_exists('DeepCopy\deep_copy')) { /** * Deep copies the given value. * * @param mixed $value * @param bool $useCloneMethod * * @return mixed */ function deep_copy($value, $useCloneMethod = false) { return (new DeepCopy($useCloneMethod))->copy($value); } } PK������Z3!*$��$��(��DeepCopy/Matcher/PropertyTypeMatcher.phpnu�W+A��������<?php namespace DeepCopy\Matcher; use DeepCopy\Reflection\ReflectionHelper; use ReflectionException; /** * Matches a property by its type. * * It is recommended to use {@see DeepCopy\TypeFilter\TypeFilter} instead, as it applies on all occurrences * of given type in copied context (eg. array elements), not just on object properties. * * @final */ class PropertyTypeMatcher implements Matcher { /** * @var string */ private $propertyType; /** * @param string $propertyType Property type */ public function __construct($propertyType) { $this->propertyType = $propertyType; } /** * {@inheritdoc} */ public function matches($object, $property) { try { $reflectionProperty = ReflectionHelper::getProperty($object, $property); } catch (ReflectionException $exception) { return false; } $reflectionProperty->setAccessible(true); // Uninitialized properties (for PHP >7.4) if (method_exists($reflectionProperty, 'isInitialized') && !$reflectionProperty->isInitialized($object)) { // null instanceof $this->propertyType return false; } return $reflectionProperty->getValue($object) instanceof $this->propertyType; } } PK������Z?Sb����$��DeepCopy/Matcher/PropertyMatcher.phpnu�W+A��������<?php namespace DeepCopy\Matcher; /** * @final */ class PropertyMatcher implements Matcher { /** * @var string */ private $class; /** * @var string */ private $property; /** * @param string $class Class name * @param string $property Property name */ public function __construct($class, $property) { $this->class = $class; $this->property = $property; } /** * Matches a specific property of a specific class. * * {@inheritdoc} */ public function matches($object, $property) { return ($object instanceof $this->class) && $property == $this->property; } } PK������ZLbh��h��2��DeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.phpnu�W+A��������<?php namespace DeepCopy\Matcher\Doctrine; use DeepCopy\Matcher\Matcher; use Doctrine\Persistence\Proxy; /** * @final */ class DoctrineProxyMatcher implements Matcher { /** * Matches a Doctrine Proxy class. * * {@inheritdoc} */ public function matches($object, $property) { return $object instanceof Proxy; } } PK������ZYx����(��DeepCopy/Matcher/PropertyNameMatcher.phpnu�W+A��������<?php namespace DeepCopy\Matcher; /** * @final */ class PropertyNameMatcher implements Matcher { /** * @var string */ private $property; /** * @param string $property Property name */ public function __construct($property) { $this->property = $property; } /** * Matches a property by its name. * * {@inheritdoc} */ public function matches($object, $property) { return $property == $this->property; } } PK������Zqe��������DeepCopy/Matcher/Matcher.phpnu�W+A��������<?php namespace DeepCopy\Matcher; interface Matcher { /** * @param object $object * @param string $property * * @return boolean */ public function matches($object, $property); } PK������Z4x���x���(��DeepCopy/Exception/PropertyException.phpnu�W+A��������<?php namespace DeepCopy\Exception; use ReflectionException; class PropertyException extends ReflectionException { } PK������ZLt������%��DeepCopy/Exception/CloneException.phpnu�W+A��������<?php namespace DeepCopy\Exception; use UnexpectedValueException; class CloneException extends UnexpectedValueException { } PK������Z:~��~��(��DeepCopy/Reflection/ReflectionHelper.phpnu�W+A��������<?php namespace DeepCopy\Reflection; use DeepCopy\Exception\PropertyException; use ReflectionClass; use ReflectionException; use ReflectionObject; use ReflectionProperty; class ReflectionHelper { /** * Retrieves all properties (including private ones), from object and all its ancestors. * * Standard \ReflectionClass->getProperties() does not return private properties from ancestor classes. * * @author muratyaman@gmail.com * @see http://php.net/manual/en/reflectionclass.getproperties.php * * @param ReflectionClass $ref * * @return ReflectionProperty[] */ public static function getProperties(ReflectionClass $ref) { $props = $ref->getProperties(); $propsArr = array(); foreach ($props as $prop) { $propertyName = $prop->getName(); $propsArr[$propertyName] = $prop; } if ($parentClass = $ref->getParentClass()) { $parentPropsArr = self::getProperties($parentClass); foreach ($propsArr as $key => $property) { $parentPropsArr[$key] = $property; } return $parentPropsArr; } return $propsArr; } /** * Retrieves property by name from object and all its ancestors. * * @param object|string $object * @param string $name * * @throws PropertyException * @throws ReflectionException * * @return ReflectionProperty */ public static function getProperty($object, $name) { $reflection = is_object($object) ? new ReflectionObject($object) : new ReflectionClass($object); if ($reflection->hasProperty($name)) { return $reflection->getProperty($name); } if ($parentClass = $reflection->getParentClass()) { return self::getProperty($parentClass->getName(), $name); } throw new PropertyException( sprintf( 'The class "%s" doesn\'t have a property with the given name: "%s".', is_object($object) ? get_class($object) : $object, $name ) ); } } PK������Z]]����!��DeepCopy/Filter/SetNullFilter.phpnu�W+A��������<?php namespace DeepCopy\Filter; use DeepCopy\Reflection\ReflectionHelper; /** * @final */ class SetNullFilter implements Filter { /** * Sets the object property to null. * * {@inheritdoc} */ public function apply($object, $property, $objectCopier) { $reflectionProperty = ReflectionHelper::getProperty($object, $property); $reflectionProperty->setAccessible(true); $reflectionProperty->setValue($object, null); } } PK������Z7����:��DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.phpnu�W+A��������<?php namespace DeepCopy\Filter\Doctrine; use DeepCopy\Filter\Filter; use DeepCopy\Reflection\ReflectionHelper; use Doctrine\Common\Collections\ArrayCollection; /** * @final */ class DoctrineEmptyCollectionFilter implements Filter { /** * Sets the object property to an empty doctrine collection. * * @param object $object * @param string $property * @param callable $objectCopier */ public function apply($object, $property, $objectCopier) { $reflectionProperty = ReflectionHelper::getProperty($object, $property); $reflectionProperty->setAccessible(true); $reflectionProperty->setValue($object, new ArrayCollection()); } } PK������Z����0��DeepCopy/Filter/Doctrine/DoctrineProxyFilter.phpnu�W+A��������<?php namespace DeepCopy\Filter\Doctrine; use DeepCopy\Filter\Filter; /** * @final */ class DoctrineProxyFilter implements Filter { /** * Triggers the magic method __load() on a Doctrine Proxy class to load the * actual entity from the database. * * {@inheritdoc} */ public function apply($object, $property, $objectCopier) { $object->__load(); } } PK������Z:D����5��DeepCopy/Filter/Doctrine/DoctrineCollectionFilter.phpnu�W+A��������<?php namespace DeepCopy\Filter\Doctrine; use DeepCopy\Filter\Filter; use DeepCopy\Reflection\ReflectionHelper; /** * @final */ class DoctrineCollectionFilter implements Filter { /** * Copies the object property doctrine collection. * * {@inheritdoc} */ public function apply($object, $property, $objectCopier) { $reflectionProperty = ReflectionHelper::getProperty($object, $property); $reflectionProperty->setAccessible(true); $oldCollection = $reflectionProperty->getValue($object); $newCollection = $oldCollection->map( function ($item) use ($objectCopier) { return $objectCopier($item); } ); $reflectionProperty->setValue($object, $newCollection); } } PK������Za˲����!��DeepCopy/Filter/ReplaceFilter.phpnu�W+A��������<?php namespace DeepCopy\Filter; use DeepCopy\Reflection\ReflectionHelper; /** * @final */ class ReplaceFilter implements Filter { /** * @var callable */ protected $callback; /** * @param callable $callable Will be called to get the new value for each property to replace */ public function __construct(callable $callable) { $this->callback = $callable; } /** * Replaces the object property by the result of the callback called with the object property. * * {@inheritdoc} */ public function apply($object, $property, $objectCopier) { $reflectionProperty = ReflectionHelper::getProperty($object, $property); $reflectionProperty->setAccessible(true); $value = call_user_func($this->callback, $reflectionProperty->getValue($object)); $reflectionProperty->setValue($object, $value); } } PK������Z,>����#��DeepCopy/Filter/ChainableFilter.phpnu�W+A��������<?php namespace DeepCopy\Filter; /** * Defines a decorator filter that will not stop the chain of filters. */ class ChainableFilter implements Filter { /** * @var Filter */ protected $filter; public function __construct(Filter $filter) { $this->filter = $filter; } public function apply($object, $property, $objectCopier) { $this->filter->apply($object, $property, $objectCopier); } } PK������Z6S\��\����DeepCopy/Filter/Filter.phpnu�W+A��������<?php namespace DeepCopy\Filter; /** * Filter to apply to a property while copying an object */ interface Filter { /** * Applies the filter to the object. * * @param object $object * @param string $property * @param callable $objectCopier */ public function apply($object, $property, $objectCopier); } PK������Z������DeepCopy/Filter/KeepFilter.phpnu�W+A��������<?php namespace DeepCopy\Filter; class KeepFilter implements Filter { /** * Keeps the value of the object property. * * {@inheritdoc} */ public function apply($object, $property, $objectCopier) { // Nothing to do } } PK������Z-h������"��DeepCopy/TypeFilter/TypeFilter.phpnu�W+A��������<?php namespace DeepCopy\TypeFilter; interface TypeFilter { /** * Applies the filter to the object. * * @param mixed $element */ public function apply($element); } PK������ZGF����/��DeepCopy/TypeFilter/Date/DateIntervalFilter.phpnu�W+A��������<?php namespace DeepCopy\TypeFilter\Date; use DateInterval; use DeepCopy\TypeFilter\TypeFilter; /** * @final * * @deprecated Will be removed in 2.0. This filter will no longer be necessary in PHP 7.1+. */ class DateIntervalFilter implements TypeFilter { /** * {@inheritdoc} * * @param DateInterval $element * * @see http://news.php.net/php.bugs/205076 */ public function apply($element) { $copy = new DateInterval('P0D'); foreach ($element as $propertyName => $propertyValue) { $copy->{$propertyName} = $propertyValue; } return $copy; } } PK������Z7 �� ��%��DeepCopy/TypeFilter/ReplaceFilter.phpnu�W+A��������<?php namespace DeepCopy\TypeFilter; /** * @final */ class ReplaceFilter implements TypeFilter { /** * @var callable */ protected $callback; /** * @param callable $callable Will be called to get the new value for each element to replace */ public function __construct(callable $callable) { $this->callback = $callable; } /** * {@inheritdoc} */ public function apply($element) { return call_user_func($this->callback, $element); } } PK������ZJ����5��DeepCopy/TypeFilter/Spl/SplDoublyLinkedListFilter.phpnu�W+A��������<?php namespace DeepCopy\TypeFilter\Spl; use Closure; use DeepCopy\DeepCopy; use DeepCopy\TypeFilter\TypeFilter; use SplDoublyLinkedList; /** * @final */ class SplDoublyLinkedListFilter implements TypeFilter { private $copier; public function __construct(DeepCopy $copier) { $this->copier = $copier; } /** * {@inheritdoc} */ public function apply($element) { $newElement = clone $element; $copy = $this->createCopyClosure(); return $copy($newElement); } private function createCopyClosure() { $copier = $this->copier; $copy = function (SplDoublyLinkedList $list) use ($copier) { // Replace each element in the list with a deep copy of itself for ($i = 1; $i <= $list->count(); $i++) { $copy = $copier->recursiveCopy($list->shift()); $list->push($copy); } return $list; }; return Closure::bind($copy, null, DeepCopy::class); } } PK������Z̰������/��DeepCopy/TypeFilter/Spl/SplDoublyLinkedList.phpnu�W+A��������<?php namespace DeepCopy\TypeFilter\Spl; /** * @deprecated Use {@see SplDoublyLinkedListFilter} instead. */ class SplDoublyLinkedList extends SplDoublyLinkedListFilter { } PK������Z0�)����-��DeepCopy/TypeFilter/Spl/ArrayObjectFilter.phpnu�W+A��������<?php namespace DeepCopy\TypeFilter\Spl; use DeepCopy\DeepCopy; use DeepCopy\TypeFilter\TypeFilter; /** * In PHP 7.4 the storage of an ArrayObject isn't returned as * ReflectionProperty. So we deep copy its array copy. */ final class ArrayObjectFilter implements TypeFilter { /** * @var DeepCopy */ private $copier; public function __construct(DeepCopy $copier) { $this->copier = $copier; } /** * {@inheritdoc} */ public function apply($arrayObject) { $clone = clone $arrayObject; foreach ($arrayObject->getArrayCopy() as $k => $v) { $clone->offsetSet($k, $this->copier->copy($v)); } return $clone; } } PK������ZZ������)��DeepCopy/TypeFilter/ShallowCopyFilter.phpnu�W+A��������<?php namespace DeepCopy\TypeFilter; /** * @final */ class ShallowCopyFilter implements TypeFilter { /** * {@inheritdoc} */ public function apply($element) { return clone $element; } } PK������ऩZ{)������CacheInterface.phpnu�W+A��������<?php namespace Psr\SimpleCache; interface CacheInterface { /** * Fetches a value from the cache. * * @param string $key The unique key of this item in the cache. * @param mixed $default Default value to return if the key does not exist. * * @return mixed The value of the item from the cache, or $default in case of cache miss. * * @throws \Psr\SimpleCache\InvalidArgumentException * MUST be thrown if the $key string is not a legal value. */ public function get(string $key, mixed $default = null): mixed; /** * Persists data in the cache, uniquely referenced by a key with an optional expiration TTL time. * * @param string $key The key of the item to store. * @param mixed $value The value of the item to store, must be serializable. * @param null|int|\DateInterval $ttl Optional. The TTL value of this item. If no value is sent and * the driver supports TTL then the library may set a default value * for it or let the driver take care of that. * * @return bool True on success and false on failure. * * @throws \Psr\SimpleCache\InvalidArgumentException * MUST be thrown if the $key string is not a legal value. */ public function set(string $key, mixed $value, null|int|\DateInterval $ttl = null): bool; /** * Delete an item from the cache by its unique key. * * @param string $key The unique cache key of the item to delete. * * @return bool True if the item was successfully removed. False if there was an error. * * @throws \Psr\SimpleCache\InvalidArgumentException * MUST be thrown if the $key string is not a legal value. */ public function delete(string $key): bool; /** * Wipes clean the entire cache's keys. * * @return bool True on success and false on failure. */ public function clear(): bool; /** * Obtains multiple cache items by their unique keys. * * @param iterable<string> $keys A list of keys that can be obtained in a single operation. * @param mixed $default Default value to return for keys that do not exist. * * @return iterable<string, mixed> A list of key => value pairs. Cache keys that do not exist or are stale will have $default as value. * * @throws \Psr\SimpleCache\InvalidArgumentException * MUST be thrown if $keys is neither an array nor a Traversable, * or if any of the $keys are not a legal value. */ public function getMultiple(iterable $keys, mixed $default = null): iterable; /** * Persists a set of key => value pairs in the cache, with an optional TTL. * * @param iterable $values A list of key => value pairs for a multiple-set operation. * @param null|int|\DateInterval $ttl Optional. The TTL value of this item. If no value is sent and * the driver supports TTL then the library may set a default value * for it or let the driver take care of that. * * @return bool True on success and false on failure. * * @throws \Psr\SimpleCache\InvalidArgumentException * MUST be thrown if $values is neither an array nor a Traversable, * or if any of the $values are not a legal value. */ public function setMultiple(iterable $values, null|int|\DateInterval $ttl = null): bool; /** * Deletes multiple cache items in a single operation. * * @param iterable<string> $keys A list of string-based keys to be deleted. * * @return bool True if the items were successfully removed. False if there was an error. * * @throws \Psr\SimpleCache\InvalidArgumentException * MUST be thrown if $keys is neither an array nor a Traversable, * or if any of the $keys are not a legal value. */ public function deleteMultiple(iterable $keys): bool; /** * Determines whether an item is present in the cache. * * NOTE: It is recommended that has() is only to be used for cache warming type purposes * and not to be used within your live applications operations for get/set, as this method * is subject to a race condition where your has() will return true and immediately after, * another script can remove it making the state of your app out of date. * * @param string $key The cache item key. * * @return bool * * @throws \Psr\SimpleCache\InvalidArgumentException * MUST be thrown if the $key string is not a legal value. */ public function has(string $key): bool; } PK������ऩZ٭q��������CacheException.phpnu�W+A��������<?php namespace Psr\SimpleCache; /** * Interface used for all types of exceptions thrown by the implementing library. */ interface CacheException extends \Throwable { } PK������ZSm������OperatingSystem.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/environment. * * (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\Environment; use const DIRECTORY_SEPARATOR; use const PHP_OS; use const PHP_OS_FAMILY; use function defined; final class OperatingSystem { /** * Returns PHP_OS_FAMILY (if defined (which it is on PHP >= 7.2)). * Returns a string (compatible with PHP_OS_FAMILY) derived from PHP_OS otherwise. */ public function getFamily(): string { if (defined('PHP_OS_FAMILY')) { return PHP_OS_FAMILY; } if (DIRECTORY_SEPARATOR === '\\') { return 'Windows'; } switch (PHP_OS) { case 'Darwin': return 'Darwin'; case 'DragonFly': case 'FreeBSD': case 'NetBSD': case 'OpenBSD': return 'BSD'; case 'Linux': return 'Linux'; case 'SunOS': return 'Solaris'; default: return 'Unknown'; } } } PK������Zb6���� ��Console.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/environment. * * (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\Environment; use const DIRECTORY_SEPARATOR; use const STDIN; use const STDOUT; use function defined; use function fclose; use function fstat; use function function_exists; use function getenv; use function is_resource; use function is_string; use function posix_isatty; use function preg_match; use function proc_close; use function proc_open; use function sapi_windows_vt100_support; use function shell_exec; use function stream_get_contents; use function stream_isatty; use function trim; final class Console { /** * @var int */ public const STDIN = 0; /** * @var int */ public const STDOUT = 1; /** * @var int */ public const STDERR = 2; /** * Returns true if STDOUT supports colorization. * * This code has been copied and adapted from * Symfony\Component\Console\Output\StreamOutput. */ public function hasColorSupport(): bool { if ('Hyper' === getenv('TERM_PROGRAM')) { return true; } if ($this->isWindows()) { // @codeCoverageIgnoreStart return (defined('STDOUT') && function_exists('sapi_windows_vt100_support') && @sapi_windows_vt100_support(STDOUT)) || false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM'); // @codeCoverageIgnoreEnd } if (!defined('STDOUT')) { // @codeCoverageIgnoreStart return false; // @codeCoverageIgnoreEnd } return $this->isInteractive(STDOUT); } /** * Returns the number of columns of the terminal. * * @codeCoverageIgnore */ public function getNumberOfColumns(): int { if (!$this->isInteractive(defined('STDIN') ? STDIN : self::STDIN)) { return 80; } if ($this->isWindows()) { return $this->getNumberOfColumnsWindows(); } return $this->getNumberOfColumnsInteractive(); } /** * Returns if the file descriptor is an interactive terminal or not. * * Normally, we want to use a resource as a parameter, yet sadly it's not always awailable, * eg when running code in interactive console (`php -a`), STDIN/STDOUT/STDERR constants are not defined. * * @param int|resource $fileDescriptor */ public function isInteractive($fileDescriptor = self::STDOUT): bool { if (is_resource($fileDescriptor)) { if (function_exists('stream_isatty') && @stream_isatty($fileDescriptor)) { return true; } if (function_exists('fstat')) { $stat = @fstat(STDOUT); return $stat && 0020000 === ($stat['mode'] & 0170000); } return false; } return function_exists('posix_isatty') && @posix_isatty($fileDescriptor); } private function isWindows(): bool { return DIRECTORY_SEPARATOR === '\\'; } /** * @codeCoverageIgnore */ private function getNumberOfColumnsInteractive(): int { if (function_exists('shell_exec') && preg_match('#\d+ (\d+)#', shell_exec('stty size') ?: '', $match) === 1) { if ((int) $match[1] > 0) { return (int) $match[1]; } } if (function_exists('shell_exec') && preg_match('#columns = (\d+);#', shell_exec('stty') ?: '', $match) === 1) { if ((int) $match[1] > 0) { return (int) $match[1]; } } return 80; } /** * @codeCoverageIgnore */ private function getNumberOfColumnsWindows(): int { $ansicon = getenv('ANSICON'); $columns = 80; if (is_string($ansicon) && preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim($ansicon), $matches)) { $columns = (int) $matches[1]; } elseif (function_exists('proc_open')) { $process = proc_open( 'mode CON', [ 1 => ['pipe', 'w'], 2 => ['pipe', 'w'], ], $pipes, null, null, ['suppress_errors' => true] ); if (is_resource($process)) { $info = stream_get_contents($pipes[1]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) { $columns = (int) $matches[2]; } } } return $columns - 1; } } PK������Zo*WO ��O �� ��Runtime.phpnu�W+A��������<?php declare(strict_types=1); /* * This file is part of sebastian/environment. * * (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\Environment; use const PHP_BINARY; use const PHP_BINDIR; use const PHP_MAJOR_VERSION; use const PHP_SAPI; use const PHP_VERSION; use function array_map; use function array_merge; use function defined; use function escapeshellarg; use function explode; use function extension_loaded; use function getenv; use function ini_get; use function is_readable; use function parse_ini_file; use function php_ini_loaded_file; use function php_ini_scanned_files; use function phpversion; use function sprintf; use function strpos; /** * Utility class for HHVM/PHP environment handling. */ final class Runtime { /** * @var string */ private static $binary; /** * Returns true when Xdebug or PCOV is available or * the runtime used is PHPDBG. */ public function canCollectCodeCoverage(): bool { return $this->hasXdebug() || $this->hasPCOV() || $this->hasPHPDBGCodeCoverage(); } /** * Returns true when Zend OPcache is loaded, enabled, * and is configured to discard comments. */ public function discardsComments(): bool { if (!$this->isOpcacheActive()) { return false; } if (ini_get('opcache.save_comments') !== '0') { return false; } return true; } /** * Returns true when Zend OPcache is loaded, enabled, * and is configured to perform just-in-time compilation. */ public function performsJustInTimeCompilation(): bool { if (PHP_MAJOR_VERSION < 8) { return false; } if (!$this->isOpcacheActive()) { return false; } if (strpos(ini_get('opcache.jit'), '0') === 0) { return false; } return true; } /** * Returns the path to the binary of the current runtime. * Appends ' --php' to the path when the runtime is HHVM. */ public function getBinary(): string { // HHVM if (self::$binary === null && $this->isHHVM()) { // @codeCoverageIgnoreStart if ((self::$binary = getenv('PHP_BINARY')) === false) { self::$binary = PHP_BINARY; } self::$binary = escapeshellarg(self::$binary) . ' --php' . ' -d hhvm.php7.all=1'; // @codeCoverageIgnoreEnd } if (self::$binary === null && PHP_BINARY !== '') { self::$binary = escapeshellarg(PHP_BINARY); } if (self::$binary === null) { // @codeCoverageIgnoreStart $possibleBinaryLocations = [ PHP_BINDIR . '/php', PHP_BINDIR . '/php-cli.exe', PHP_BINDIR . '/php.exe', ]; foreach ($possibleBinaryLocations as $binary) { if (is_readable($binary)) { self::$binary = escapeshellarg($binary); break; } } // @codeCoverageIgnoreEnd } if (self::$binary === null) { // @codeCoverageIgnoreStart self::$binary = 'php'; // @codeCoverageIgnoreEnd } return self::$binary; } public function getNameWithVersion(): string { return $this->getName() . ' ' . $this->getVersion(); } public function getNameWithVersionAndCodeCoverageDriver(): string { if (!$this->canCollectCodeCoverage() || $this->hasPHPDBGCodeCoverage()) { return $this->getNameWithVersion(); } if ($this->hasPCOV()) { return sprintf( '%s with PCOV %s', $this->getNameWithVersion(), phpversion('pcov') ); } if ($this->hasXdebug()) { return sprintf( '%s with Xdebug %s', $this->getNameWithVersion(), phpversion('xdebug') ); } } public function getName(): string { if ($this->isHHVM()) { // @codeCoverageIgnoreStart return 'HHVM'; // @codeCoverageIgnoreEnd } if ($this->isPHPDBG()) { // @codeCoverageIgnoreStart return 'PHPDBG'; // @codeCoverageIgnoreEnd } return 'PHP'; } public function getVendorUrl(): string { if ($this->isHHVM()) { // @codeCoverageIgnoreStart return 'http://hhvm.com/'; // @codeCoverageIgnoreEnd } return 'https://secure.php.net/'; } public function getVersion(): string { if ($this->isHHVM()) { // @codeCoverageIgnoreStart return HHVM_VERSION; // @codeCoverageIgnoreEnd } return PHP_VERSION; } /** * Returns true when the runtime used is PHP and Xdebug is loaded. */ public function hasXdebug(): bool { return ($this->isPHP() || $this->isHHVM()) && extension_loaded('xdebug'); } /** * Returns true when the runtime used is HHVM. */ public function isHHVM(): bool { return defined('HHVM_VERSION'); } /** * Returns true when the runtime used is PHP without the PHPDBG SAPI. */ public function isPHP(): bool { return !$this->isHHVM() && !$this->isPHPDBG(); } /** * Returns true when the runtime used is PHP with the PHPDBG SAPI. */ public function isPHPDBG(): bool { return PHP_SAPI === 'phpdbg' && !$this->isHHVM(); } /** * Returns true when the runtime used is PHP with the PHPDBG SAPI * and the phpdbg_*_oplog() functions are available (PHP >= 7.0). */ public function hasPHPDBGCodeCoverage(): bool { return $this->isPHPDBG(); } /** * Returns true when the runtime used is PHP with PCOV loaded and enabled. */ public function hasPCOV(): bool { return $this->isPHP() && extension_loaded('pcov') && ini_get('pcov.enabled'); } /** * Parses the loaded php.ini file (if any) as well as all * additional php.ini files from the additional ini dir for * a list of all configuration settings loaded from files * at startup. Then checks for each php.ini setting passed * via the `$values` parameter whether this setting has * been changed at runtime. Returns an array of strings * where each string has the format `key=value` denoting * the name of a changed php.ini setting with its new value. * * @return string[] */ public function getCurrentSettings(array $values): array { $diff = []; $files = []; if ($file = php_ini_loaded_file()) { $files[] = $file; } if ($scanned = php_ini_scanned_files()) { $files = array_merge( $files, array_map( 'trim', explode(",\n", $scanned) ) ); } foreach ($files as $ini) { $config = parse_ini_file($ini, true); foreach ($values as $value) { $set = ini_get($value); if (empty($set)) { continue; } if ((!isset($config[$value]) || ($set !== $config[$value]))) { $diff[$value] = sprintf('%s=%s', $value, $set); } } } return $diff; } private function isOpcacheActive(): bool { if (!extension_loaded('Zend OPcache')) { return false; } if ((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') && ini_get('opcache.enable_cli') === '1') { return true; } if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg' && ini_get('opcache.enable') === '1') { return true; } return false; } } PK������ֺZ������Port.phpnu�W+A��������<?php /** * Port utilities for Requests * * @package Requests\Utilities * @since 2.0.0 */ namespace WpOrg\Requests; use WpOrg\Requests\Exception; use WpOrg\Requests\Exception\InvalidArgument; /** * Find the correct port depending on the Request type. * * @package Requests\Utilities * @since 2.0.0 */ final class Port { /** * Port to use with Acap requests. * * @var int */ const ACAP = 674; /** * Port to use with Dictionary requests. * * @var int */ const DICT = 2628; /** * Port to use with HTTP requests. * * @var int */ const HTTP = 80; /** * Port to use with HTTP over SSL requests. * * @var int */ const HTTPS = 443; /** * Retrieve the port number to use. * * @param string $type Request type. * The following requests types are supported: * 'acap', 'dict', 'http' and 'https'. * * @return int * * @throws \WpOrg\Requests\Exception\InvalidArgument When a non-string input has been passed. * @throws \WpOrg\Requests\Exception When a non-supported port is requested ('portnotsupported'). */ public static function get($type) { if (!is_string($type)) { throw InvalidArgument::create(1, '$type', 'string', gettype($type)); } $type = strtoupper($type); if (!defined("self::{$type}")) { $message = sprintf('Invalid port type (%s) passed', $type); throw new Exception($message, 'portnotsupported'); } return constant("self::{$type}"); } } PK������ֺZZ �� ����Auth/Basic.phpnu�W+A��������<?php /** * Basic Authentication provider * * @package Requests\Authentication */ namespace WpOrg\Requests\Auth; use WpOrg\Requests\Auth; use WpOrg\Requests\Exception\ArgumentCount; use WpOrg\Requests\Exception\InvalidArgument; use WpOrg\Requests\Hooks; /** * Basic Authentication provider * * Provides a handler for Basic HTTP authentication via the Authorization * header. * * @package Requests\Authentication */ class Basic implements Auth { /** * Username * * @var string */ public $user; /** * Password * * @var string */ public $pass; /** * Constructor * * @since 2.0 Throws an `InvalidArgument` exception. * @since 2.0 Throws an `ArgumentCount` exception instead of the Requests base `Exception. * * @param array|null $args Array of user and password. Must have exactly two elements * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not an array or null. * @throws \WpOrg\Requests\Exception\ArgumentCount On incorrect number of array elements (`authbasicbadargs`). */ public function __construct($args = null) { if (is_array($args)) { if (count($args) !== 2) { throw ArgumentCount::create('an array with exactly two elements', count($args), 'authbasicbadargs'); } list($this->user, $this->pass) = $args; return; } if ($args !== null) { throw InvalidArgument::create(1, '$args', 'array|null', gettype($args)); } } /** * Register the necessary callbacks * * @see \WpOrg\Requests\Auth\Basic::curl_before_send() * @see \WpOrg\Requests\Auth\Basic::fsockopen_header() * @param \WpOrg\Requests\Hooks $hooks Hook system */ public function register(Hooks $hooks) { $hooks->register('curl.before_send', [$this, 'curl_before_send']); $hooks->register('fsockopen.after_headers', [$this, 'fsockopen_header']); } /** * Set cURL parameters before the data is sent * * @param resource|\CurlHandle $handle cURL handle */ public function curl_before_send(&$handle) { curl_setopt($handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); curl_setopt($handle, CURLOPT_USERPWD, $this->getAuthString()); } /** * Add extra headers to the request before sending * * @param string $out HTTP header string */ public function fsockopen_header(&$out) { $out .= sprintf("Authorization: Basic %s\r\n", base64_encode($this->getAuthString())); } /** * Get the authentication string (user:pass) * * @return string */ public function getAuthString() { return $this->user . ':' . $this->pass; } } PK������ֺZC������HookManager.phpnu�W+A��������<?php /** * Event dispatcher * * @package Requests\EventDispatcher */ namespace WpOrg\Requests; /** * Event dispatcher * * @package Requests\EventDispatcher */ interface HookManager { /** * Register a callback for a hook * * @param string $hook Hook name * @param callable $callback Function/method to call on event * @param int $priority Priority number. <0 is executed earlier, >0 is executed later */ public function register($hook, $callback, $priority = 0); /** * Dispatch a message * * @param string $hook Hook name * @param array $parameters Parameters to pass to callbacks * @return boolean Successfulness */ public function dispatch($hook, $parameters = []); } PK������ֺZ s��s����Iri.phpnu�W+A��������<?php /** * IRI parser/serialiser/normaliser * * @package Requests\Utilities */ namespace WpOrg\Requests; use WpOrg\Requests\Exception; use WpOrg\Requests\Exception\InvalidArgument; use WpOrg\Requests\Ipv6; use WpOrg\Requests\Port; use WpOrg\Requests\Utility\InputValidator; /** * IRI parser/serialiser/normaliser * * Copyright (c) 2007-2010, Geoffrey Sneddon and Steve Minutillo. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * * Neither the name of the SimplePie Team nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @package Requests\Utilities * @author Geoffrey Sneddon * @author Steve Minutillo * @copyright 2007-2009 Geoffrey Sneddon and Steve Minutillo * @license https://opensource.org/licenses/bsd-license.php * @link http://hg.gsnedders.com/iri/ * * @property string $iri IRI we're working with * @property-read string $uri IRI in URI form, {@see \WpOrg\Requests\Iri::to_uri()} * @property string $scheme Scheme part of the IRI * @property string $authority Authority part, formatted for a URI (userinfo + host + port) * @property string $iauthority Authority part of the IRI (userinfo + host + port) * @property string $userinfo Userinfo part, formatted for a URI (after '://' and before '@') * @property string $iuserinfo Userinfo part of the IRI (after '://' and before '@') * @property string $host Host part, formatted for a URI * @property string $ihost Host part of the IRI * @property string $port Port part of the IRI (after ':') * @property string $path Path part, formatted for a URI (after first '/') * @property string $ipath Path part of the IRI (after first '/') * @property string $query Query part, formatted for a URI (after '?') * @property string $iquery Query part of the IRI (after '?') * @property string $fragment Fragment, formatted for a URI (after '#') * @property string $ifragment Fragment part of the IRI (after '#') */ class Iri { /** * Scheme * * @var string|null */ protected $scheme = null; /** * User Information * * @var string|null */ protected $iuserinfo = null; /** * ihost * * @var string|null */ protected $ihost = null; /** * Port * * @var string|null */ protected $port = null; /** * ipath * * @var string */ protected $ipath = ''; /** * iquery * * @var string|null */ protected $iquery = null; /** * ifragment|null * * @var string */ protected $ifragment = null; /** * Normalization database * * Each key is the scheme, each value is an array with each key as the IRI * part and value as the default value for that part. * * @var array */ protected $normalization = array( 'acap' => array( 'port' => Port::ACAP, ), 'dict' => array( 'port' => Port::DICT, ), 'file' => array( 'ihost' => 'localhost', ), 'http' => array( 'port' => Port::HTTP, ), 'https' => array( 'port' => Port::HTTPS, ), ); /** * Return the entire IRI when you try and read the object as a string * * @return string */ public function __toString() { return $this->get_iri(); } /** * Overload __set() to provide access via properties * * @param string $name Property name * @param mixed $value Property value */ public function __set($name, $value) { if (method_exists($this, 'set_' . $name)) { call_user_func(array($this, 'set_' . $name), $value); } elseif ( $name === 'iauthority' || $name === 'iuserinfo' || $name === 'ihost' || $name === 'ipath' || $name === 'iquery' || $name === 'ifragment' ) { call_user_func(array($this, 'set_' . substr($name, 1)), $value); } } /** * Overload __get() to provide access via properties * * @param string $name Property name * @return mixed */ public function __get($name) { // isset() returns false for null, we don't want to do that // Also why we use array_key_exists below instead of isset() $props = get_object_vars($this); if ( $name === 'iri' || $name === 'uri' || $name === 'iauthority' || $name === 'authority' ) { $method = 'get_' . $name; $return = $this->$method(); } elseif (array_key_exists($name, $props)) { $return = $this->$name; } // host -> ihost elseif (($prop = 'i' . $name) && array_key_exists($prop, $props)) { $name = $prop; $return = $this->$prop; } // ischeme -> scheme elseif (($prop = substr($name, 1)) && array_key_exists($prop, $props)) { $name = $prop; $return = $this->$prop; } else { trigger_error('Undefined property: ' . get_class($this) . '::' . $name, E_USER_NOTICE); $return = null; } if ($return === null && isset($this->normalization[$this->scheme][$name])) { return $this->normalization[$this->scheme][$name]; } else { return $return; } } /** * Overload __isset() to provide access via properties * * @param string $name Property name * @return bool */ public function __isset($name) { return (method_exists($this, 'get_' . $name) || isset($this->$name)); } /** * Overload __unset() to provide access via properties * * @param string $name Property name */ public function __unset($name) { if (method_exists($this, 'set_' . $name)) { call_user_func(array($this, 'set_' . $name), ''); } } /** * Create a new IRI object, from a specified string * * @param string|Stringable|null $iri * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $iri argument is not a string, Stringable or null. */ public function __construct($iri = null) { if ($iri !== null && InputValidator::is_string_or_stringable($iri) === false) { throw InvalidArgument::create(1, '$iri', 'string|Stringable|null', gettype($iri)); } $this->set_iri($iri); } /** * Create a new IRI object by resolving a relative IRI * * Returns false if $base is not absolute, otherwise an IRI. * * @param \WpOrg\Requests\Iri|string $base (Absolute) Base IRI * @param \WpOrg\Requests\Iri|string $relative Relative IRI * @return \WpOrg\Requests\Iri|false */ public static function absolutize($base, $relative) { if (!($relative instanceof self)) { $relative = new self($relative); } if (!$relative->is_valid()) { return false; } elseif ($relative->scheme !== null) { return clone $relative; } if (!($base instanceof self)) { $base = new self($base); } if ($base->scheme === null || !$base->is_valid()) { return false; } if ($relative->get_iri() !== '') { if ($relative->iuserinfo !== null || $relative->ihost !== null || $relative->port !== null) { $target = clone $relative; $target->scheme = $base->scheme; } else { $target = new self; $target->scheme = $base->scheme; $target->iuserinfo = $base->iuserinfo; $target->ihost = $base->ihost; $target->port = $base->port; if ($relative->ipath !== '') { if ($relative->ipath[0] === '/') { $target->ipath = $relative->ipath; } elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '') { $target->ipath = '/' . $relative->ipath; } elseif (($last_segment = strrpos($base->ipath, '/')) !== false) { $target->ipath = substr($base->ipath, 0, $last_segment + 1) . $relative->ipath; } else { $target->ipath = $relative->ipath; } $target->ipath = $target->remove_dot_segments($target->ipath); $target->iquery = $relative->iquery; } else { $target->ipath = $base->ipath; if ($relative->iquery !== null) { $target->iquery = $relative->iquery; } elseif ($base->iquery !== null) { $target->iquery = $base->iquery; } } $target->ifragment = $relative->ifragment; } } else { $target = clone $base; $target->ifragment = null; } $target->scheme_normalization(); return $target; } /** * Parse an IRI into scheme/authority/path/query/fragment segments * * @param string $iri * @return array */ protected function parse_iri($iri) { $iri = trim($iri, "\x20\x09\x0A\x0C\x0D"); $has_match = preg_match('/^((?P<scheme>[^:\/?#]+):)?(\/\/(?P<authority>[^\/?#]*))?(?P<path>[^?#]*)(\?(?P<query>[^#]*))?(#(?P<fragment>.*))?$/', $iri, $match); if (!$has_match) { throw new Exception('Cannot parse supplied IRI', 'iri.cannot_parse', $iri); } if ($match[1] === '') { $match['scheme'] = null; } if (!isset($match[3]) || $match[3] === '') { $match['authority'] = null; } if (!isset($match[5])) { $match['path'] = ''; } if (!isset($match[6]) || $match[6] === '') { $match['query'] = null; } if (!isset($match[8]) || $match[8] === '') { $match['fragment'] = null; } return $match; } /** * Remove dot segments from a path * * @param string $input * @return string */ protected function remove_dot_segments($input) { $output = ''; while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..') { // A: If the input buffer begins with a prefix of "../" or "./", // then remove that prefix from the input buffer; otherwise, if (strpos($input, '../') === 0) { $input = substr($input, 3); } elseif (strpos($input, './') === 0) { $input = substr($input, 2); } // B: if the input buffer begins with a prefix of "/./" or "/.", // where "." is a complete path segment, then replace that prefix // with "/" in the input buffer; otherwise, elseif (strpos($input, '/./') === 0) { $input = substr($input, 2); } elseif ($input === '/.') { $input = '/'; } // C: if the input buffer begins with a prefix of "/../" or "/..", // where ".." is a complete path segment, then replace that prefix // with "/" in the input buffer and remove the last segment and its // preceding "/" (if any) from the output buffer; otherwise, elseif (strpos($input, '/../') === 0) { $input = substr($input, 3); $output = substr_replace($output, '', (strrpos($output, '/') ?: 0)); } elseif ($input === '/..') { $input = '/'; $output = substr_replace($output, '', (strrpos($output, '/') ?: 0)); } // D: if the input buffer consists only of "." or "..", then remove // that from the input buffer; otherwise, elseif ($input === '.' || $input === '..') { $input = ''; } // E: move the first path segment in the input buffer to the end of // the output buffer, including the initial "/" character (if any) // and any subsequent characters up to, but not including, the next // "/" character or the end of the input buffer elseif (($pos = strpos($input, '/', 1)) !== false) { $output .= substr($input, 0, $pos); $input = substr_replace($input, '', 0, $pos); } else { $output .= $input; $input = ''; } } return $output . $input; } /** * Replace invalid character with percent encoding * * @param string $text Input string * @param string $extra_chars Valid characters not in iunreserved or * iprivate (this is ASCII-only) * @param bool $iprivate Allow iprivate * @return string */ protected function replace_invalid_with_pct_encoding($text, $extra_chars, $iprivate = false) { // Normalize as many pct-encoded sections as possible $text = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array($this, 'remove_iunreserved_percent_encoded'), $text); // Replace invalid percent characters $text = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $text); // Add unreserved and % to $extra_chars (the latter is safe because all // pct-encoded sections are now valid). $extra_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%'; // Now replace any bytes that aren't allowed with their pct-encoded versions $position = 0; $strlen = strlen($text); while (($position += strspn($text, $extra_chars, $position)) < $strlen) { $value = ord($text[$position]); // Start position $start = $position; // By default we are valid $valid = true; // No one byte sequences are valid due to the while. // Two byte sequence: if (($value & 0xE0) === 0xC0) { $character = ($value & 0x1F) << 6; $length = 2; $remaining = 1; } // Three byte sequence: elseif (($value & 0xF0) === 0xE0) { $character = ($value & 0x0F) << 12; $length = 3; $remaining = 2; } // Four byte sequence: elseif (($value & 0xF8) === 0xF0) { $character = ($value & 0x07) << 18; $length = 4; $remaining = 3; } // Invalid byte: else { $valid = false; $length = 1; $remaining = 0; } if ($remaining) { if ($position + $length <= $strlen) { for ($position++; $remaining; $position++) { $value = ord($text[$position]); // Check that the byte is valid, then add it to the character: if (($value & 0xC0) === 0x80) { $character |= ($value & 0x3F) << (--$remaining * 6); } // If it is invalid, count the sequence as invalid and reprocess the current byte: else { $valid = false; $position--; break; } } } else { $position = $strlen - 1; $valid = false; } } // Percent encode anything invalid or not in ucschar if ( // Invalid sequences !$valid // Non-shortest form sequences are invalid || $length > 1 && $character <= 0x7F || $length > 2 && $character <= 0x7FF || $length > 3 && $character <= 0xFFFF // Outside of range of ucschar codepoints // Noncharacters || ($character & 0xFFFE) === 0xFFFE || $character >= 0xFDD0 && $character <= 0xFDEF || ( // Everything else not in ucschar $character > 0xD7FF && $character < 0xF900 || $character < 0xA0 || $character > 0xEFFFD ) && ( // Everything not in iprivate, if it applies !$iprivate || $character < 0xE000 || $character > 0x10FFFD ) ) { // If we were a character, pretend we weren't, but rather an error. if ($valid) { $position--; } for ($j = $start; $j <= $position; $j++) { $text = substr_replace($text, sprintf('%%%02X', ord($text[$j])), $j, 1); $j += 2; $position += 2; $strlen += 2; } } } return $text; } /** * Callback function for preg_replace_callback. * * Removes sequences of percent encoded bytes that represent UTF-8 * encoded characters in iunreserved * * @param array $regex_match PCRE match * @return string Replacement */ protected function remove_iunreserved_percent_encoded($regex_match) { // As we just have valid percent encoded sequences we can just explode // and ignore the first member of the returned array (an empty string). $bytes = explode('%', $regex_match[0]); // Initialize the new string (this is what will be returned) and that // there are no bytes remaining in the current sequence (unsurprising // at the first byte!). $string = ''; $remaining = 0; // Loop over each and every byte, and set $value to its value for ($i = 1, $len = count($bytes); $i < $len; $i++) { $value = hexdec($bytes[$i]); // If we're the first byte of sequence: if (!$remaining) { // Start position $start = $i; // By default we are valid $valid = true; // One byte sequence: if ($value <= 0x7F) { $character = $value; $length = 1; } // Two byte sequence: elseif (($value & 0xE0) === 0xC0) { $character = ($value & 0x1F) << 6; $length = 2; $remaining = 1; } // Three byte sequence: elseif (($value & 0xF0) === 0xE0) { $character = ($value & 0x0F) << 12; $length = 3; $remaining = 2; } // Four byte sequence: elseif (($value & 0xF8) === 0xF0) { $character = ($value & 0x07) << 18; $length = 4; $remaining = 3; } // Invalid byte: else { $valid = false; $remaining = 0; } } // Continuation byte: else { // Check that the byte is valid, then add it to the character: if (($value & 0xC0) === 0x80) { $remaining--; $character |= ($value & 0x3F) << ($remaining * 6); } // If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence: else { $valid = false; $remaining = 0; $i--; } } // If we've reached the end of the current byte sequence, append it to Unicode::$data if (!$remaining) { // Percent encode anything invalid or not in iunreserved if ( // Invalid sequences !$valid // Non-shortest form sequences are invalid || $length > 1 && $character <= 0x7F || $length > 2 && $character <= 0x7FF || $length > 3 && $character <= 0xFFFF // Outside of range of iunreserved codepoints || $character < 0x2D || $character > 0xEFFFD // Noncharacters || ($character & 0xFFFE) === 0xFFFE || $character >= 0xFDD0 && $character <= 0xFDEF // Everything else not in iunreserved (this is all BMP) || $character === 0x2F || $character > 0x39 && $character < 0x41 || $character > 0x5A && $character < 0x61 || $character > 0x7A && $character < 0x7E || $character > 0x7E && $character < 0xA0 || $character > 0xD7FF && $character < 0xF900 ) { for ($j = $start; $j <= $i; $j++) { $string .= '%' . strtoupper($bytes[$j]); } } else { for ($j = $start; $j <= $i; $j++) { $string .= chr(hexdec($bytes[$j])); } } } } // If we have any bytes left over they are invalid (i.e., we are // mid-way through a multi-byte sequence) if ($remaining) { for ($j = $start; $j < $len; $j++) { $string .= '%' . strtoupper($bytes[$j]); } } return $string; } protected function scheme_normalization() { if (isset($this->normalization[$this->scheme]['iuserinfo']) && $this->iuserinfo === $this->normalization[$this->scheme]['iuserinfo']) { $this->iuserinfo = null; } if (isset($this->normalization[$this->scheme]['ihost']) && $this->ihost === $this->normalization[$this->scheme]['ihost']) { $this->ihost = null; } if (isset($this->normalization[$this->scheme]['port']) && $this->port === $this->normalization[$this->scheme]['port']) { $this->port = null; } if (isset($this->normalization[$this->scheme]['ipath']) && $this->ipath === $this->normalization[$this->scheme]['ipath']) { $this->ipath = ''; } if (isset($this->ihost) && empty($this->ipath)) { $this->ipath = '/'; } if (isset($this->normalization[$this->scheme]['iquery']) && $this->iquery === $this->normalization[$this->scheme]['iquery']) { $this->iquery = null; } if (isset($this->normalization[$this->scheme]['ifragment']) && $this->ifragment === $this->normalization[$this->scheme]['ifragment']) { $this->ifragment = null; } } /** * Check if the object represents a valid IRI. This needs to be done on each * call as some things change depending on another part of the IRI. * * @return bool */ public function is_valid() { $isauthority = $this->iuserinfo !== null || $this->ihost !== null || $this->port !== null; if ($this->ipath !== '' && ( $isauthority && $this->ipath[0] !== '/' || ( $this->scheme === null && !$isauthority && strpos($this->ipath, ':') !== false && (strpos($this->ipath, '/') === false ? true : strpos($this->ipath, ':') < strpos($this->ipath, '/')) ) ) ) { return false; } return true; } public function __wakeup() { $class_props = get_class_vars( __CLASS__ ); $string_props = array( 'scheme', 'iuserinfo', 'ihost', 'port', 'ipath', 'iquery', 'ifragment' ); $array_props = array( 'normalization' ); foreach ( $class_props as $prop => $default_value ) { if ( in_array( $prop, $string_props, true ) && ! is_string( $this->$prop ) ) { throw new UnexpectedValueException(); } elseif ( in_array( $prop, $array_props, true ) && ! is_array( $this->$prop ) ) { throw new UnexpectedValueException(); } $this->$prop = null; } } /** * Set the entire IRI. Returns true on success, false on failure (if there * are any invalid characters). * * @param string $iri * @return bool */ protected function set_iri($iri) { static $cache; if (!$cache) { $cache = array(); } if ($iri === null) { return true; } $iri = (string) $iri; if (isset($cache[$iri])) { list($this->scheme, $this->iuserinfo, $this->ihost, $this->port, $this->ipath, $this->iquery, $this->ifragment, $return) = $cache[$iri]; return $return; } $parsed = $this->parse_iri($iri); $return = $this->set_scheme($parsed['scheme']) && $this->set_authority($parsed['authority']) && $this->set_path($parsed['path']) && $this->set_query($parsed['query']) && $this->set_fragment($parsed['fragment']); $cache[$iri] = array($this->scheme, $this->iuserinfo, $this->ihost, $this->port, $this->ipath, $this->iquery, $this->ifragment, $return); return $return; } /** * Set the scheme. Returns true on success, false on failure (if there are * any invalid characters). * * @param string $scheme * @return bool */ protected function set_scheme($scheme) { if ($scheme === null) { $this->scheme = null; } elseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\-.]*$/', $scheme)) { $this->scheme = null; return false; } else { $this->scheme = strtolower($scheme); } return true; } /** * Set the authority. Returns true on success, false on failure (if there are * any invalid characters). * * @param string $authority * @return bool */ protected function set_authority($authority) { static $cache; if (!$cache) { $cache = array(); } if ($authority === null) { $this->iuserinfo = null; $this->ihost = null; $this->port = null; return true; } if (isset($cache[$authority])) { list($this->iuserinfo, $this->ihost, $this->port, $return) = $cache[$authority]; return $return; } $remaining = $authority; if (($iuserinfo_end = strrpos($remaining, '@')) !== false) { $iuserinfo = substr($remaining, 0, $iuserinfo_end); $remaining = substr($remaining, $iuserinfo_end + 1); } else { $iuserinfo = null; } if (($port_start = strpos($remaining, ':', (strpos($remaining, ']') ?: 0))) !== false) { $port = substr($remaining, $port_start + 1); if ($port === false || $port === '') { $port = null; } $remaining = substr($remaining, 0, $port_start); } else { $port = null; } $return = $this->set_userinfo($iuserinfo) && $this->set_host($remaining) && $this->set_port($port); $cache[$authority] = array($this->iuserinfo, $this->ihost, $this->port, $return); return $return; } /** * Set the iuserinfo. * * @param string $iuserinfo * @return bool */ protected function set_userinfo($iuserinfo) { if ($iuserinfo === null) { $this->iuserinfo = null; } else { $this->iuserinfo = $this->replace_invalid_with_pct_encoding($iuserinfo, '!$&\'()*+,;=:'); $this->scheme_normalization(); } return true; } /** * Set the ihost. Returns true on success, false on failure (if there are * any invalid characters). * * @param string $ihost * @return bool */ protected function set_host($ihost) { if ($ihost === null) { $this->ihost = null; return true; } if (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']') { if (Ipv6::check_ipv6(substr($ihost, 1, -1))) { $this->ihost = '[' . Ipv6::compress(substr($ihost, 1, -1)) . ']'; } else { $this->ihost = null; return false; } } else { $ihost = $this->replace_invalid_with_pct_encoding($ihost, '!$&\'()*+,;='); // Lowercase, but ignore pct-encoded sections (as they should // remain uppercase). This must be done after the previous step // as that can add unescaped characters. $position = 0; $strlen = strlen($ihost); while (($position += strcspn($ihost, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ%', $position)) < $strlen) { if ($ihost[$position] === '%') { $position += 3; } else { $ihost[$position] = strtolower($ihost[$position]); $position++; } } $this->ihost = $ihost; } $this->scheme_normalization(); return true; } /** * Set the port. Returns true on success, false on failure (if there are * any invalid characters). * * @param string $port * @return bool */ protected function set_port($port) { if ($port === null) { $this->port = null; return true; } if (strspn($port, '0123456789') === strlen($port)) { $this->port = (int) $port; $this->scheme_normalization(); return true; } $this->port = null; return false; } /** * Set the ipath. * * @param string $ipath * @return bool */ protected function set_path($ipath) { static $cache; if (!$cache) { $cache = array(); } $ipath = (string) $ipath; if (isset($cache[$ipath])) { $this->ipath = $cache[$ipath][(int) ($this->scheme !== null)]; } else { $valid = $this->replace_invalid_with_pct_encoding($ipath, '!$&\'()*+,;=@:/'); $removed = $this->remove_dot_segments($valid); $cache[$ipath] = array($valid, $removed); $this->ipath = ($this->scheme !== null) ? $removed : $valid; } $this->scheme_normalization(); return true; } /** * Set the iquery. * * @param string $iquery * @return bool */ protected function set_query($iquery) { if ($iquery === null) { $this->iquery = null; } else { $this->iquery = $this->replace_invalid_with_pct_encoding($iquery, '!$&\'()*+,;=:@/?', true); $this->scheme_normalization(); } return true; } /** * Set the ifragment. * * @param string $ifragment * @return bool */ protected function set_fragment($ifragment) { if ($ifragment === null) { $this->ifragment = null; } else { $this->ifragment = $this->replace_invalid_with_pct_encoding($ifragment, '!$&\'()*+,;=:@/?'); $this->scheme_normalization(); } return true; } /** * Convert an IRI to a URI (or parts thereof) * * @param string|bool $iri IRI to convert (or false from {@see \WpOrg\Requests\Iri::get_iri()}) * @return string|false URI if IRI is valid, false otherwise. */ protected function to_uri($iri) { if (!is_string($iri)) { return false; } static $non_ascii; if (!$non_ascii) { $non_ascii = implode('', range("\x80", "\xFF")); } $position = 0; $strlen = strlen($iri); while (($position += strcspn($iri, $non_ascii, $position)) < $strlen) { $iri = substr_replace($iri, sprintf('%%%02X', ord($iri[$position])), $position, 1); $position += 3; $strlen += 2; } return $iri; } /** * Get the complete IRI * * @return string|false */ protected function get_iri() { if (!$this->is_valid()) { return false; } $iri = ''; if ($this->scheme !== null) { $iri .= $this->scheme . ':'; } if (($iauthority = $this->get_iauthority()) !== null) { $iri .= '//' . $iauthority; } $iri .= $this->ipath; if ($this->iquery !== null) { $iri .= '?' . $this->iquery; } if ($this->ifragment !== null) { $iri .= '#' . $this->ifragment; } return $iri; } /** * Get the complete URI * * @return string */ protected function get_uri() { return $this->to_uri($this->get_iri()); } /** * Get the complete iauthority * * @return string|null */ protected function get_iauthority() { if ($this->iuserinfo === null && $this->ihost === null && $this->port === null) { return null; } $iauthority = ''; if ($this->iuserinfo !== null) { $iauthority .= $this->iuserinfo . '@'; } if ($this->ihost !== null) { $iauthority .= $this->ihost; } if ($this->port !== null) { $iauthority .= ':' . $this->port; } return $iauthority; } /** * Get the complete authority * * @return string */ protected function get_authority() { $iauthority = $this->get_iauthority(); if (is_string($iauthority)) { return $this->to_uri($iauthority); } else { return $iauthority; } } } PK������ֺZ\��\����Auth.phpnu�W+A��������<?php /** * Authentication provider interface * * @package Requests\Authentication */ namespace WpOrg\Requests; use WpOrg\Requests\Hooks; /** * Authentication provider interface * * Implement this interface to act as an authentication provider. * * Parameters should be passed via the constructor where possible, as this * makes it much easier for users to use your provider. * * @see \WpOrg\Requests\Hooks * * @package Requests\Authentication */ interface Auth { /** * Register hooks as needed * * This method is called in {@see \WpOrg\Requests\Requests::request()} when the user * has set an instance as the 'auth' option. Use this callback to register all the * hooks you'll need. * * @see \WpOrg\Requests\Hooks::register() * @param \WpOrg\Requests\Hooks $hooks Hook system */ public function register(Hooks $hooks); } PK������ֺZiA��������Exception/Transport.phpnu�W+A��������<?php /** * Transport Exception * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception; use WpOrg\Requests\Exception; /** * Transport Exception * * @package Requests\Exceptions */ class Transport extends Exception {} PK������ֺZR��R����Exception/InvalidArgument.phpnu�W+A��������<?php namespace WpOrg\Requests\Exception; use InvalidArgumentException; /** * Exception for an invalid argument passed. * * @package Requests\Exceptions * @since 2.0.0 */ final class InvalidArgument extends InvalidArgumentException { /** * Create a new invalid argument exception with a standardized text. * * @param int $position The argument position in the function signature. 1-based. * @param string $name The argument name in the function signature. * @param string $expected The argument type expected as a string. * @param string $received The actual argument type received. * * @return \WpOrg\Requests\Exception\InvalidArgument */ public static function create($position, $name, $expected, $received) { // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_debug_backtrace $stack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); return new self( sprintf( '%s::%s(): Argument #%d (%s) must be of type %s, %s given', $stack[1]['class'], $stack[1]['function'], $position, $name, $expected, $received ) ); } } PK������ֺZq1������Exception/ArgumentCount.phpnu�W+A��������<?php namespace WpOrg\Requests\Exception; use WpOrg\Requests\Exception; /** * Exception for when an incorrect number of arguments are passed to a method. * * Typically, this exception is used when all arguments for a method are optional, * but certain arguments need to be passed together, i.e. a method which can be called * with no arguments or with two arguments, but not with one argument. * * Along the same lines, this exception is also used if a method expects an array * with a certain number of elements and the provided number of elements does not comply. * * @package Requests\Exceptions * @since 2.0.0 */ final class ArgumentCount extends Exception { /** * Create a new argument count exception with a standardized text. * * @param string $expected The argument count expected as a phrase. * For example: `at least 2 arguments` or `exactly 1 argument`. * @param int $received The actual argument count received. * @param string $type Exception type. * * @return \WpOrg\Requests\Exception\ArgumentCount */ public static function create($expected, $received, $type) { // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_debug_backtrace $stack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); return new self( sprintf( '%s::%s() expects %s, %d given', $stack[1]['class'], $stack[1]['function'], $expected, $received ), $type ); } } PK������ֺZ&������Exception/Http.phpnu�W+A��������<?php /** * Exception based on HTTP response * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception; use WpOrg\Requests\Exception; use WpOrg\Requests\Exception\Http\StatusUnknown; /** * Exception based on HTTP response * * @package Requests\Exceptions */ class Http extends Exception { /** * HTTP status code * * @var integer */ protected $code = 0; /** * Reason phrase * * @var string */ protected $reason = 'Unknown'; /** * Create a new exception * * There is no mechanism to pass in the status code, as this is set by the * subclass used. Reason phrases can vary, however. * * @param string|null $reason Reason phrase * @param mixed $data Associated data */ public function __construct($reason = null, $data = null) { if ($reason !== null) { $this->reason = $reason; } $message = sprintf('%d %s', $this->code, $this->reason); parent::__construct($message, 'httpresponse', $data, $this->code); } /** * Get the status message. * * @return string */ public function getReason() { return $this->reason; } /** * Get the correct exception class for a given error code * * @param int|bool $code HTTP status code, or false if unavailable * @return string Exception class name to use */ public static function get_class($code) { if (!$code) { return StatusUnknown::class; } $class = sprintf('\WpOrg\Requests\Exception\Http\Status%d', $code); if (class_exists($class)) { return $class; } return StatusUnknown::class; } } PK������ֺZ������Exception/Http/Status304.phpnu�W+A��������<?php /** * Exception for 304 Not Modified responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 304 Not Modified responses * * @package Requests\Exceptions */ final class Status304 extends Http { /** * HTTP status code * * @var integer */ protected $code = 304; /** * Reason phrase * * @var string */ protected $reason = 'Not Modified'; } PK������ֺZ(s��s����Exception/Http/Status429.phpnu�W+A��������<?php /** * Exception for 429 Too Many Requests responses * * @link https://tools.ietf.org/html/draft-nottingham-http-new-status-04 * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 429 Too Many Requests responses * * @link https://tools.ietf.org/html/draft-nottingham-http-new-status-04 * * @package Requests\Exceptions */ final class Status429 extends Http { /** * HTTP status code * * @var integer */ protected $code = 429; /** * Reason phrase * * @var string */ protected $reason = 'Too Many Requests'; } PK������ֺZ{������Exception/Http/Status402.phpnu�W+A��������<?php /** * Exception for 402 Payment Required responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 402 Payment Required responses * * @package Requests\Exceptions */ final class Status402 extends Http { /** * HTTP status code * * @var integer */ protected $code = 402; /** * Reason phrase * * @var string */ protected $reason = 'Payment Required'; } PK������ֺZkf������Exception/Http/Status504.phpnu�W+A��������<?php /** * Exception for 504 Gateway Timeout responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 504 Gateway Timeout responses * * @package Requests\Exceptions */ final class Status504 extends Http { /** * HTTP status code * * @var integer */ protected $code = 504; /** * Reason phrase * * @var string */ protected $reason = 'Gateway Timeout'; } PK������ֺZSb������Exception/Http/Status406.phpnu�W+A��������<?php /** * Exception for 406 Not Acceptable responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 406 Not Acceptable responses * * @package Requests\Exceptions */ final class Status406 extends Http { /** * HTTP status code * * @var integer */ protected $code = 406; /** * Reason phrase * * @var string */ protected $reason = 'Not Acceptable'; } PK������ֺZ4,��,����Exception/Http/Status418.phpnu�W+A��������<?php /** * Exception for 418 I'm A Teapot responses * * @link https://tools.ietf.org/html/rfc2324 * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 418 I'm A Teapot responses * * @link https://tools.ietf.org/html/rfc2324 * * @package Requests\Exceptions */ final class Status418 extends Http { /** * HTTP status code * * @var integer */ protected $code = 418; /** * Reason phrase * * @var string */ protected $reason = "I'm A Teapot"; } PK������ֺZ&Xe��e����Exception/Http/Status431.phpnu�W+A��������<?php /** * Exception for 431 Request Header Fields Too Large responses * * @link https://tools.ietf.org/html/rfc6585 * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 431 Request Header Fields Too Large responses * * @link https://tools.ietf.org/html/rfc6585 * * @package Requests\Exceptions */ final class Status431 extends Http { /** * HTTP status code * * @var integer */ protected $code = 431; /** * Reason phrase * * @var string */ protected $reason = 'Request Header Fields Too Large'; } PK������ֺZhm������Exception/Http/Status413.phpnu�W+A��������<?php /** * Exception for 413 Request Entity Too Large responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 413 Request Entity Too Large responses * * @package Requests\Exceptions */ final class Status413 extends Http { /** * HTTP status code * * @var integer */ protected $code = 413; /** * Reason phrase * * @var string */ protected $reason = 'Request Entity Too Large'; } PK������ֺZwא������Exception/Http/Status405.phpnu�W+A��������<?php /** * Exception for 405 Method Not Allowed responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 405 Method Not Allowed responses * * @package Requests\Exceptions */ final class Status405 extends Http { /** * HTTP status code * * @var integer */ protected $code = 405; /** * Reason phrase * * @var string */ protected $reason = 'Method Not Allowed'; } PK������ֺZw;������Exception/Http/Status503.phpnu�W+A��������<?php /** * Exception for 503 Service Unavailable responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 503 Service Unavailable responses * * @package Requests\Exceptions */ final class Status503 extends Http { /** * HTTP status code * * @var integer */ protected $code = 503; /** * Reason phrase * * @var string */ protected $reason = 'Service Unavailable'; } PK������ֺZh$a������Exception/Http/Status306.phpnu�W+A��������<?php /** * Exception for 306 Switch Proxy responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 306 Switch Proxy responses * * @package Requests\Exceptions */ final class Status306 extends Http { /** * HTTP status code * * @var integer */ protected $code = 306; /** * Reason phrase * * @var string */ protected $reason = 'Switch Proxy'; } PK������ֺZy������Exception/Http/Status404.phpnu�W+A��������<?php /** * Exception for 404 Not Found responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 404 Not Found responses * * @package Requests\Exceptions */ final class Status404 extends Http { /** * HTTP status code * * @var integer */ protected $code = 404; /** * Reason phrase * * @var string */ protected $reason = 'Not Found'; } PK������ֺZ*���� ��Exception/Http/StatusUnknown.phpnu�W+A��������<?php /** * Exception for unknown status responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; use WpOrg\Requests\Response; /** * Exception for unknown status responses * * @package Requests\Exceptions */ final class StatusUnknown extends Http { /** * HTTP status code * * @var integer|bool Code if available, false if an error occurred */ protected $code = 0; /** * Reason phrase * * @var string */ protected $reason = 'Unknown'; /** * Create a new exception * * If `$data` is an instance of {@see \WpOrg\Requests\Response}, uses the status * code from it. Otherwise, sets as 0 * * @param string|null $reason Reason phrase * @param mixed $data Associated data */ public function __construct($reason = null, $data = null) { if ($data instanceof Response) { $this->code = (int) $data->status_code; } parent::__construct($reason, $data); } } PK������ֺZ������Exception/Http/Status502.phpnu�W+A��������<?php /** * Exception for 502 Bad Gateway responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 502 Bad Gateway responses * * @package Requests\Exceptions */ final class Status502 extends Http { /** * HTTP status code * * @var integer */ protected $code = 502; /** * Reason phrase * * @var string */ protected $reason = 'Bad Gateway'; } PK������ֺZe��e����Exception/Http/Status511.phpnu�W+A��������<?php /** * Exception for 511 Network Authentication Required responses * * @link https://tools.ietf.org/html/rfc6585 * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 511 Network Authentication Required responses * * @link https://tools.ietf.org/html/rfc6585 * * @package Requests\Exceptions */ final class Status511 extends Http { /** * HTTP status code * * @var integer */ protected $code = 511; /** * Reason phrase * * @var string */ protected $reason = 'Network Authentication Required'; } PK������ֺZ[F������Exception/Http/Status411.phpnu�W+A��������<?php /** * Exception for 411 Length Required responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 411 Length Required responses * * @package Requests\Exceptions */ final class Status411 extends Http { /** * HTTP status code * * @var integer */ protected $code = 411; /** * Reason phrase * * @var string */ protected $reason = 'Length Required'; } PK������ֺZ������Exception/Http/Status409.phpnu�W+A��������<?php /** * Exception for 409 Conflict responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 409 Conflict responses * * @package Requests\Exceptions */ final class Status409 extends Http { /** * HTTP status code * * @var integer */ protected $code = 409; /** * Reason phrase * * @var string */ protected $reason = 'Conflict'; } PK������ֺZP������Exception/Http/Status415.phpnu�W+A��������<?php /** * Exception for 415 Unsupported Media Type responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 415 Unsupported Media Type responses * * @package Requests\Exceptions */ final class Status415 extends Http { /** * HTTP status code * * @var integer */ protected $code = 415; /** * Reason phrase * * @var string */ protected $reason = 'Unsupported Media Type'; } PK������ֺZ2d������Exception/Http/Status414.phpnu�W+A��������<?php /** * Exception for 414 Request-URI Too Large responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 414 Request-URI Too Large responses * * @package Requests\Exceptions */ final class Status414 extends Http { /** * HTTP status code * * @var integer */ protected $code = 414; /** * Reason phrase * * @var string */ protected $reason = 'Request-URI Too Large'; } PK������ֺZkT������Exception/Http/Status408.phpnu�W+A��������<?php /** * Exception for 408 Request Timeout responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 408 Request Timeout responses * * @package Requests\Exceptions */ final class Status408 extends Http { /** * HTTP status code * * @var integer */ protected $code = 408; /** * Reason phrase * * @var string */ protected $reason = 'Request Timeout'; } PK������ֺZf+������Exception/Http/Status417.phpnu�W+A��������<?php /** * Exception for 417 Expectation Failed responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 417 Expectation Failed responses * * @package Requests\Exceptions */ final class Status417 extends Http { /** * HTTP status code * * @var integer */ protected $code = 417; /** * Reason phrase * * @var string */ protected $reason = 'Expectation Failed'; } PK������ֺZ^:G��G����Exception/Http/Status428.phpnu�W+A��������<?php /** * Exception for 428 Precondition Required responses * * @link https://tools.ietf.org/html/rfc6585 * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 428 Precondition Required responses * * @link https://tools.ietf.org/html/rfc6585 * * @package Requests\Exceptions */ final class Status428 extends Http { /** * HTTP status code * * @var integer */ protected $code = 428; /** * Reason phrase * * @var string */ protected $reason = 'Precondition Required'; } PK������ֺZm������Exception/Http/Status505.phpnu�W+A��������<?php /** * Exception for 505 HTTP Version Not Supported responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 505 HTTP Version Not Supported responses * * @package Requests\Exceptions */ final class Status505 extends Http { /** * HTTP status code * * @var integer */ protected $code = 505; /** * Reason phrase * * @var string */ protected $reason = 'HTTP Version Not Supported'; } PK������ֺZ]������Exception/Http/Status407.phpnu�W+A��������<?php /** * Exception for 407 Proxy Authentication Required responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 407 Proxy Authentication Required responses * * @package Requests\Exceptions */ final class Status407 extends Http { /** * HTTP status code * * @var integer */ protected $code = 407; /** * Reason phrase * * @var string */ protected $reason = 'Proxy Authentication Required'; } PK������ֺZ`������Exception/Http/Status412.phpnu�W+A��������<?php /** * Exception for 412 Precondition Failed responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 412 Precondition Failed responses * * @package Requests\Exceptions */ final class Status412 extends Http { /** * HTTP status code * * @var integer */ protected $code = 412; /** * Reason phrase * * @var string */ protected $reason = 'Precondition Failed'; } PK������ֺZǿH7������Exception/Http/Status400.phpnu�W+A��������<?php /** * Exception for 400 Bad Request responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 400 Bad Request responses * * @package Requests\Exceptions */ final class Status400 extends Http { /** * HTTP status code * * @var integer */ protected $code = 400; /** * Reason phrase * * @var string */ protected $reason = 'Bad Request'; } PK������ֺZ ������Exception/Http/Status500.phpnu�W+A��������<?php /** * Exception for 500 Internal Server Error responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 500 Internal Server Error responses * * @package Requests\Exceptions */ final class Status500 extends Http { /** * HTTP status code * * @var integer */ protected $code = 500; /** * Reason phrase * * @var string */ protected $reason = 'Internal Server Error'; } PK������ֺZmk������Exception/Http/Status501.phpnu�W+A��������<?php /** * Exception for 501 Not Implemented responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 501 Not Implemented responses * * @package Requests\Exceptions */ final class Status501 extends Http { /** * HTTP status code * * @var integer */ protected $code = 501; /** * Reason phrase * * @var string */ protected $reason = 'Not Implemented'; } PK������ֺZη.p������Exception/Http/Status410.phpnu�W+A��������<?php /** * Exception for 410 Gone responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 410 Gone responses * * @package Requests\Exceptions */ final class Status410 extends Http { /** * HTTP status code * * @var integer */ protected $code = 410; /** * Reason phrase * * @var string */ protected $reason = 'Gone'; } PK������ֺZ�������Exception/Http/Status401.phpnu�W+A��������<?php /** * Exception for 401 Unauthorized responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 401 Unauthorized responses * * @package Requests\Exceptions */ final class Status401 extends Http { /** * HTTP status code * * @var integer */ protected $code = 401; /** * Reason phrase * * @var string */ protected $reason = 'Unauthorized'; } PK������ֺZ������Exception/Http/Status403.phpnu�W+A��������<?php /** * Exception for 403 Forbidden responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 403 Forbidden responses * * @package Requests\Exceptions */ final class Status403 extends Http { /** * HTTP status code * * @var integer */ protected $code = 403; /** * Reason phrase * * @var string */ protected $reason = 'Forbidden'; } PK������ֺZ������Exception/Http/Status305.phpnu�W+A��������<?php /** * Exception for 305 Use Proxy responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 305 Use Proxy responses * * @package Requests\Exceptions */ final class Status305 extends Http { /** * HTTP status code * * @var integer */ protected $code = 305; /** * Reason phrase * * @var string */ protected $reason = 'Use Proxy'; } PK������ֺZ������Exception/Http/Status416.phpnu�W+A��������<?php /** * Exception for 416 Requested Range Not Satisfiable responses * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Http; use WpOrg\Requests\Exception\Http; /** * Exception for 416 Requested Range Not Satisfiable responses * * @package Requests\Exceptions */ final class Status416 extends Http { /** * HTTP status code * * @var integer */ protected $code = 416; /** * Reason phrase * * @var string */ protected $reason = 'Requested Range Not Satisfiable'; } PK������ֺZ*u��u����Exception/Transport/Curl.phpnu�W+A��������<?php /** * CURL Transport Exception. * * @package Requests\Exceptions */ namespace WpOrg\Requests\Exception\Transport; use WpOrg\Requests\Exception\Transport; /** * CURL Transport Exception. * * @package Requests\Exceptions */ final class Curl extends Transport { const EASY = 'cURLEasy'; const MULTI = 'cURLMulti'; const SHARE = 'cURLShare'; /** * cURL error code * * @var integer */ protected $code = -1; /** * Which type of cURL error * * EASY|MULTI|SHARE * * @var string */ protected $type = 'Unknown'; /** * Clear text error message * * @var string */ protected $reason = 'Unknown'; /** * Create a new exception. * * @param string $message Exception message. * @param string $type Exception type. * @param mixed $data Associated data, if applicable. * @param int $code Exception numerical code, if applicable. */ public function __construct($message, $type, $data = null, $code = 0) { if ($type !== null) { $this->type = $type; } if ($code !== null) { $this->code = (int) $code; } if ($message !== null) { $this->reason = $message; } $message = sprintf('%d %s', $this->code, $this->reason); parent::__construct($message, $this->type, $data, $this->code); } /** * Get the error message. * * @return string */ public function getReason() { return $this->reason; } } PK������ֺZJM<��<�� ��Cookie.phpnu�W+A��������<?php /** * Cookie storage object * * @package Requests\Cookies */ namespace WpOrg\Requests; use WpOrg\Requests\Exception\InvalidArgument; use WpOrg\Requests\Iri; use WpOrg\Requests\Response\Headers; use WpOrg\Requests\Utility\CaseInsensitiveDictionary; use WpOrg\Requests\Utility\InputValidator; /** * Cookie storage object * * @package Requests\Cookies */ class Cookie { /** * Cookie name. * * @var string */ public $name; /** * Cookie value. * * @var string */ public $value; /** * Cookie attributes * * Valid keys are `'path'`, `'domain'`, `'expires'`, `'max-age'`, `'secure'` and * `'httponly'`. * * @var \WpOrg\Requests\Utility\CaseInsensitiveDictionary|array Array-like object */ public $attributes = []; /** * Cookie flags * * Valid keys are `'creation'`, `'last-access'`, `'persistent'` and `'host-only'`. * * @var array */ public $flags = []; /** * Reference time for relative calculations * * This is used in place of `time()` when calculating Max-Age expiration and * checking time validity. * * @var int */ public $reference_time = 0; /** * Create a new cookie object * * @param string $name The name of the cookie. * @param string $value The value for the cookie. * @param array|\WpOrg\Requests\Utility\CaseInsensitiveDictionary $attributes Associative array of attribute data * @param array $flags The flags for the cookie. * Valid keys are `'creation'`, `'last-access'`, * `'persistent'` and `'host-only'`. * @param int|null $reference_time Reference time for relative calculations. * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $name argument is not a string. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $value argument is not a string. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $attributes argument is not an array or iterable object with array access. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $flags argument is not an array. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $reference_time argument is not an integer or null. */ public function __construct($name, $value, $attributes = [], $flags = [], $reference_time = null) { if (is_string($name) === false) { throw InvalidArgument::create(1, '$name', 'string', gettype($name)); } if (is_string($value) === false) { throw InvalidArgument::create(2, '$value', 'string', gettype($value)); } if (InputValidator::has_array_access($attributes) === false || InputValidator::is_iterable($attributes) === false) { throw InvalidArgument::create(3, '$attributes', 'array|ArrayAccess&Traversable', gettype($attributes)); } if (is_array($flags) === false) { throw InvalidArgument::create(4, '$flags', 'array', gettype($flags)); } if ($reference_time !== null && is_int($reference_time) === false) { throw InvalidArgument::create(5, '$reference_time', 'integer|null', gettype($reference_time)); } $this->name = $name; $this->value = $value; $this->attributes = $attributes; $default_flags = [ 'creation' => time(), 'last-access' => time(), 'persistent' => false, 'host-only' => true, ]; $this->flags = array_merge($default_flags, $flags); $this->reference_time = time(); if ($reference_time !== null) { $this->reference_time = $reference_time; } $this->normalize(); } /** * Get the cookie value * * Attributes and other data can be accessed via methods. */ public function __toString() { return $this->value; } /** * Check if a cookie is expired. * * Checks the age against $this->reference_time to determine if the cookie * is expired. * * @return boolean True if expired, false if time is valid. */ public function is_expired() { // RFC6265, s. 4.1.2.2: // If a cookie has both the Max-Age and the Expires attribute, the Max- // Age attribute has precedence and controls the expiration date of the // cookie. if (isset($this->attributes['max-age'])) { $max_age = $this->attributes['max-age']; return $max_age < $this->reference_time; } if (isset($this->attributes['expires'])) { $expires = $this->attributes['expires']; return $expires < $this->reference_time; } return false; } /** * Check if a cookie is valid for a given URI * * @param \WpOrg\Requests\Iri $uri URI to check * @return boolean Whether the cookie is valid for the given URI */ public function uri_matches(Iri $uri) { if (!$this->domain_matches($uri->host)) { return false; } if (!$this->path_matches($uri->path)) { return false; } return empty($this->attributes['secure']) || $uri->scheme === 'https'; } /** * Check if a cookie is valid for a given domain * * @param string $domain Domain to check * @return boolean Whether the cookie is valid for the given domain */ public function domain_matches($domain) { if (is_string($domain) === false) { return false; } if (!isset($this->attributes['domain'])) { // Cookies created manually; cookies created by Requests will set // the domain to the requested domain return true; } $cookie_domain = $this->attributes['domain']; if ($cookie_domain === $domain) { // The cookie domain and the passed domain are identical. return true; } // If the cookie is marked as host-only and we don't have an exact // match, reject the cookie if ($this->flags['host-only'] === true) { return false; } if (strlen($domain) <= strlen($cookie_domain)) { // For obvious reasons, the cookie domain cannot be a suffix if the passed domain // is shorter than the cookie domain return false; } if (substr($domain, -1 * strlen($cookie_domain)) !== $cookie_domain) { // The cookie domain should be a suffix of the passed domain. return false; } $prefix = substr($domain, 0, strlen($domain) - strlen($cookie_domain)); if (substr($prefix, -1) !== '.') { // The last character of the passed domain that is not included in the // domain string should be a %x2E (".") character. return false; } // The passed domain should be a host name (i.e., not an IP address). return !preg_match('#^(.+\.)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$#', $domain); } /** * Check if a cookie is valid for a given path * * From the path-match check in RFC 6265 section 5.1.4 * * @param string $request_path Path to check * @return boolean Whether the cookie is valid for the given path */ public function path_matches($request_path) { if (empty($request_path)) { // Normalize empty path to root $request_path = '/'; } if (!isset($this->attributes['path'])) { // Cookies created manually; cookies created by Requests will set // the path to the requested path return true; } if (is_scalar($request_path) === false) { return false; } $cookie_path = $this->attributes['path']; if ($cookie_path === $request_path) { // The cookie-path and the request-path are identical. return true; } if (strlen($request_path) > strlen($cookie_path) && substr($request_path, 0, strlen($cookie_path)) === $cookie_path) { if (substr($cookie_path, -1) === '/') { // The cookie-path is a prefix of the request-path, and the last // character of the cookie-path is %x2F ("/"). return true; } if (substr($request_path, strlen($cookie_path), 1) === '/') { // The cookie-path is a prefix of the request-path, and the // first character of the request-path that is not included in // the cookie-path is a %x2F ("/") character. return true; } } return false; } /** * Normalize cookie and attributes * * @return boolean Whether the cookie was successfully normalized */ public function normalize() { foreach ($this->attributes as $key => $value) { $orig_value = $value; if (is_string($key)) { $value = $this->normalize_attribute($key, $value); } if ($value === null) { unset($this->attributes[$key]); continue; } if ($value !== $orig_value) { $this->attributes[$key] = $value; } } return true; } /** * Parse an individual cookie attribute * * Handles parsing individual attributes from the cookie values. * * @param string $name Attribute name * @param string|int|bool $value Attribute value (string/integer value, or true if empty/flag) * @return mixed Value if available, or null if the attribute value is invalid (and should be skipped) */ protected function normalize_attribute($name, $value) { switch (strtolower($name)) { case 'expires': // Expiration parsing, as per RFC 6265 section 5.2.1 if (is_int($value)) { return $value; } $expiry_time = strtotime($value); if ($expiry_time === false) { return null; } return $expiry_time; case 'max-age': // Expiration parsing, as per RFC 6265 section 5.2.2 if (is_int($value)) { return $value; } // Check that we have a valid age if (!preg_match('/^-?\d+$/', $value)) { return null; } $delta_seconds = (int) $value; if ($delta_seconds <= 0) { $expiry_time = 0; } else { $expiry_time = $this->reference_time + $delta_seconds; } return $expiry_time; case 'domain': // Domains are not required as per RFC 6265 section 5.2.3 if (empty($value)) { return null; } // Domain normalization, as per RFC 6265 section 5.2.3 if ($value[0] === '.') { $value = substr($value, 1); } return $value; default: return $value; } } /** * Format a cookie for a Cookie header * * This is used when sending cookies to a server. * * @return string Cookie formatted for Cookie header */ public function format_for_header() { return sprintf('%s=%s', $this->name, $this->value); } /** * Format a cookie for a Set-Cookie header * * This is used when sending cookies to clients. This isn't really * applicable to client-side usage, but might be handy for debugging. * * @return string Cookie formatted for Set-Cookie header */ public function format_for_set_cookie() { $header_value = $this->format_for_header(); if (!empty($this->attributes)) { $parts = []; foreach ($this->attributes as $key => $value) { // Ignore non-associative attributes if (is_numeric($key)) { $parts[] = $value; } else { $parts[] = sprintf('%s=%s', $key, $value); } } $header_value .= '; ' . implode('; ', $parts); } return $header_value; } /** * Parse a cookie string into a cookie object * * Based on Mozilla's parsing code in Firefox and related projects, which * is an intentional deviation from RFC 2109 and RFC 2616. RFC 6265 * specifies some of this handling, but not in a thorough manner. * * @param string $cookie_header Cookie header value (from a Set-Cookie header) * @param string $name * @param int|null $reference_time * @return \WpOrg\Requests\Cookie Parsed cookie object * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $cookie_header argument is not a string. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $name argument is not a string. */ public static function parse($cookie_header, $name = '', $reference_time = null) { if (is_string($cookie_header) === false) { throw InvalidArgument::create(1, '$cookie_header', 'string', gettype($cookie_header)); } if (is_string($name) === false) { throw InvalidArgument::create(2, '$name', 'string', gettype($name)); } $parts = explode(';', $cookie_header); $kvparts = array_shift($parts); if (!empty($name)) { $value = $cookie_header; } elseif (strpos($kvparts, '=') === false) { // Some sites might only have a value without the equals separator. // Deviate from RFC 6265 and pretend it was actually a blank name // (`=foo`) // // https://bugzilla.mozilla.org/show_bug.cgi?id=169091 $name = ''; $value = $kvparts; } else { list($name, $value) = explode('=', $kvparts, 2); } $name = trim($name); $value = trim($value); // Attribute keys are handled case-insensitively $attributes = new CaseInsensitiveDictionary(); if (!empty($parts)) { foreach ($parts as $part) { if (strpos($part, '=') === false) { $part_key = $part; $part_value = true; } else { list($part_key, $part_value) = explode('=', $part, 2); $part_value = trim($part_value); } $part_key = trim($part_key); $attributes[$part_key] = $part_value; } } return new static($name, $value, $attributes, [], $reference_time); } /** * Parse all Set-Cookie headers from request headers * * @param \WpOrg\Requests\Response\Headers $headers Headers to parse from * @param \WpOrg\Requests\Iri|null $origin URI for comparing cookie origins * @param int|null $time Reference time for expiration calculation * @return array * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $origin argument is not null or an instance of the Iri class. */ public static function parse_from_headers(Headers $headers, $origin = null, $time = null) { $cookie_headers = $headers->getValues('Set-Cookie'); if (empty($cookie_headers)) { return []; } if ($origin !== null && !($origin instanceof Iri)) { throw InvalidArgument::create(2, '$origin', Iri::class . ' or null', gettype($origin)); } $cookies = []; foreach ($cookie_headers as $header) { $parsed = self::parse($header, '', $time); // Default domain/path attributes if (empty($parsed->attributes['domain']) && !empty($origin)) { $parsed->attributes['domain'] = $origin->host; $parsed->flags['host-only'] = true; } else { $parsed->flags['host-only'] = false; } $path_is_valid = (!empty($parsed->attributes['path']) && $parsed->attributes['path'][0] === '/'); if (!$path_is_valid && !empty($origin)) { $path = $origin->path; // Default path normalization as per RFC 6265 section 5.1.4 if (substr($path, 0, 1) !== '/') { // If the uri-path is empty or if the first character of // the uri-path is not a %x2F ("/") character, output // %x2F ("/") and skip the remaining steps. $path = '/'; } elseif (substr_count($path, '/') === 1) { // If the uri-path contains no more than one %x2F ("/") // character, output %x2F ("/") and skip the remaining // step. $path = '/'; } else { // Output the characters of the uri-path from the first // character up to, but not including, the right-most // %x2F ("/"). $path = substr($path, 0, strrpos($path, '/')); } $parsed->attributes['path'] = $path; } // Reject invalid cookie domains if (!empty($origin) && !$parsed->domain_matches($origin->host)) { continue; } $cookies[$parsed->name] = $parsed; } return $cookies; } } PK������ֺZ @9ф��ф�� ��Requests.phpnu�W+A��������<?php /** * Requests for PHP * * Inspired by Requests for Python. * * Based on concepts from SimplePie_File, RequestCore and WP_Http. * * @package Requests */ namespace WpOrg\Requests; use WpOrg\Requests\Auth\Basic; use WpOrg\Requests\Capability; use WpOrg\Requests\Cookie\Jar; use WpOrg\Requests\Exception; use WpOrg\Requests\Exception\InvalidArgument; use WpOrg\Requests\Hooks; use WpOrg\Requests\IdnaEncoder; use WpOrg\Requests\Iri; use WpOrg\Requests\Proxy\Http; use WpOrg\Requests\Response; use WpOrg\Requests\Transport\Curl; use WpOrg\Requests\Transport\Fsockopen; use WpOrg\Requests\Utility\InputValidator; /** * Requests for PHP * * Inspired by Requests for Python. * * Based on concepts from SimplePie_File, RequestCore and WP_Http. * * @package Requests */ class Requests { /** * POST method * * @var string */ const POST = 'POST'; /** * PUT method * * @var string */ const PUT = 'PUT'; /** * GET method * * @var string */ const GET = 'GET'; /** * HEAD method * * @var string */ const HEAD = 'HEAD'; /** * DELETE method * * @var string */ const DELETE = 'DELETE'; /** * OPTIONS method * * @var string */ const OPTIONS = 'OPTIONS'; /** * TRACE method * * @var string */ const TRACE = 'TRACE'; /** * PATCH method * * @link https://tools.ietf.org/html/rfc5789 * @var string */ const PATCH = 'PATCH'; /** * Default size of buffer size to read streams * * @var integer */ const BUFFER_SIZE = 1160; /** * Option defaults. * * @see \WpOrg\Requests\Requests::get_default_options() * @see \WpOrg\Requests\Requests::request() for values returned by this method * * @since 2.0.0 * * @var array */ const OPTION_DEFAULTS = [ 'timeout' => 10, 'connect_timeout' => 10, 'useragent' => 'php-requests/' . self::VERSION, 'protocol_version' => 1.1, 'redirected' => 0, 'redirects' => 10, 'follow_redirects' => true, 'blocking' => true, 'type' => self::GET, 'filename' => false, 'auth' => false, 'proxy' => false, 'cookies' => false, 'max_bytes' => false, 'idn' => true, 'hooks' => null, 'transport' => null, 'verify' => null, 'verifyname' => true, ]; /** * Default supported Transport classes. * * @since 2.0.0 * * @var array */ const DEFAULT_TRANSPORTS = [ Curl::class => Curl::class, Fsockopen::class => Fsockopen::class, ]; /** * Current version of Requests * * @var string */ const VERSION = '2.0.11'; /** * Selected transport name * * Use {@see \WpOrg\Requests\Requests::get_transport()} instead * * @var array */ public static $transport = []; /** * Registered transport classes * * @var array */ protected static $transports = []; /** * Default certificate path. * * @see \WpOrg\Requests\Requests::get_certificate_path() * @see \WpOrg\Requests\Requests::set_certificate_path() * * @var string */ protected static $certificate_path = __DIR__ . '/../certificates/cacert.pem'; /** * All (known) valid deflate, gzip header magic markers. * * These markers relate to different compression levels. * * @link https://stackoverflow.com/a/43170354/482864 Marker source. * * @since 2.0.0 * * @var array */ private static $magic_compression_headers = [ "\x1f\x8b" => true, // Gzip marker. "\x78\x01" => true, // Zlib marker - level 1. "\x78\x5e" => true, // Zlib marker - level 2 to 5. "\x78\x9c" => true, // Zlib marker - level 6. "\x78\xda" => true, // Zlib marker - level 7 to 9. ]; /** * This is a static class, do not instantiate it * * @codeCoverageIgnore */ private function __construct() {} /** * Register a transport * * @param string $transport Transport class to add, must support the \WpOrg\Requests\Transport interface */ public static function add_transport($transport) { if (empty(self::$transports)) { self::$transports = self::DEFAULT_TRANSPORTS; } self::$transports[$transport] = $transport; } /** * Get the fully qualified class name (FQCN) for a working transport. * * @param array<string, bool> $capabilities Optional. Associative array of capabilities to test against, i.e. `['<capability>' => true]`. * @return string FQCN of the transport to use, or an empty string if no transport was * found which provided the requested capabilities. */ protected static function get_transport_class(array $capabilities = []) { // Caching code, don't bother testing coverage. // @codeCoverageIgnoreStart // Array of capabilities as a string to be used as an array key. ksort($capabilities); $cap_string = serialize($capabilities); // Don't search for a transport if it's already been done for these $capabilities. if (isset(self::$transport[$cap_string])) { return self::$transport[$cap_string]; } // Ensure we will not run this same check again later on. self::$transport[$cap_string] = ''; // @codeCoverageIgnoreEnd if (empty(self::$transports)) { self::$transports = self::DEFAULT_TRANSPORTS; } // Find us a working transport. foreach (self::$transports as $class) { if (!class_exists($class)) { continue; } $result = $class::test($capabilities); if ($result === true) { self::$transport[$cap_string] = $class; break; } } return self::$transport[$cap_string]; } /** * Get a working transport. * * @param array<string, bool> $capabilities Optional. Associative array of capabilities to test against, i.e. `['<capability>' => true]`. * @return \WpOrg\Requests\Transport * @throws \WpOrg\Requests\Exception If no valid transport is found (`notransport`). */ protected static function get_transport(array $capabilities = []) { $class = self::get_transport_class($capabilities); if ($class === '') { throw new Exception('No working transports found', 'notransport', self::$transports); } return new $class(); } /** * Checks to see if we have a transport for the capabilities requested. * * Supported capabilities can be found in the {@see \WpOrg\Requests\Capability} * interface as constants. * * Example usage: * `Requests::has_capabilities([Capability::SSL => true])`. * * @param array<string, bool> $capabilities Optional. Associative array of capabilities to test against, i.e. `['<capability>' => true]`. * @return bool Whether the transport has the requested capabilities. */ public static function has_capabilities(array $capabilities = []) { return self::get_transport_class($capabilities) !== ''; } /**#@+ * @see \WpOrg\Requests\Requests::request() * @param string $url * @param array $headers * @param array $options * @return \WpOrg\Requests\Response */ /** * Send a GET request */ public static function get($url, $headers = [], $options = []) { return self::request($url, $headers, null, self::GET, $options); } /** * Send a HEAD request */ public static function head($url, $headers = [], $options = []) { return self::request($url, $headers, null, self::HEAD, $options); } /** * Send a DELETE request */ public static function delete($url, $headers = [], $options = []) { return self::request($url, $headers, null, self::DELETE, $options); } /** * Send a TRACE request */ public static function trace($url, $headers = [], $options = []) { return self::request($url, $headers, null, self::TRACE, $options); } /**#@-*/ /**#@+ * @see \WpOrg\Requests\Requests::request() * @param string $url * @param array $headers * @param array $data * @param array $options * @return \WpOrg\Requests\Response */ /** * Send a POST request */ public static function post($url, $headers = [], $data = [], $options = []) { return self::request($url, $headers, $data, self::POST, $options); } /** * Send a PUT request */ public static function put($url, $headers = [], $data = [], $options = []) { return self::request($url, $headers, $data, self::PUT, $options); } /** * Send an OPTIONS request */ public static function options($url, $headers = [], $data = [], $options = []) { return self::request($url, $headers, $data, self::OPTIONS, $options); } /** * Send a PATCH request * * Note: Unlike {@see \WpOrg\Requests\Requests::post()} and {@see \WpOrg\Requests\Requests::put()}, * `$headers` is required, as the specification recommends that should send an ETag * * @link https://tools.ietf.org/html/rfc5789 */ public static function patch($url, $headers, $data = [], $options = []) { return self::request($url, $headers, $data, self::PATCH, $options); } /**#@-*/ /** * Main interface for HTTP requests * * This method initiates a request and sends it via a transport before * parsing. * * The `$options` parameter takes an associative array with the following * options: * * - `timeout`: How long should we wait for a response? * Note: for cURL, a minimum of 1 second applies, as DNS resolution * operates at second-resolution only. * (float, seconds with a millisecond precision, default: 10, example: 0.01) * - `connect_timeout`: How long should we wait while trying to connect? * (float, seconds with a millisecond precision, default: 10, example: 0.01) * - `useragent`: Useragent to send to the server * (string, default: php-requests/$version) * - `follow_redirects`: Should we follow 3xx redirects? * (boolean, default: true) * - `redirects`: How many times should we redirect before erroring? * (integer, default: 10) * - `blocking`: Should we block processing on this request? * (boolean, default: true) * - `filename`: File to stream the body to instead. * (string|boolean, default: false) * - `auth`: Authentication handler or array of user/password details to use * for Basic authentication * (\WpOrg\Requests\Auth|array|boolean, default: false) * - `proxy`: Proxy details to use for proxy by-passing and authentication * (\WpOrg\Requests\Proxy|array|string|boolean, default: false) * - `max_bytes`: Limit for the response body size. * (integer|boolean, default: false) * - `idn`: Enable IDN parsing * (boolean, default: true) * - `transport`: Custom transport. Either a class name, or a * transport object. Defaults to the first working transport from * {@see \WpOrg\Requests\Requests::getTransport()} * (string|\WpOrg\Requests\Transport, default: {@see \WpOrg\Requests\Requests::getTransport()}) * - `hooks`: Hooks handler. * (\WpOrg\Requests\HookManager, default: new WpOrg\Requests\Hooks()) * - `verify`: Should we verify SSL certificates? Allows passing in a custom * certificate file as a string. (Using true uses the system-wide root * certificate store instead, but this may have different behaviour * across transports.) * (string|boolean, default: certificates/cacert.pem) * - `verifyname`: Should we verify the common name in the SSL certificate? * (boolean, default: true) * - `data_format`: How should we send the `$data` parameter? * (string, one of 'query' or 'body', default: 'query' for * HEAD/GET/DELETE, 'body' for POST/PUT/OPTIONS/PATCH) * * @param string|Stringable $url URL to request * @param array $headers Extra headers to send with the request * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests * @param string $type HTTP request type (use Requests constants) * @param array $options Options for the request (see description for more information) * @return \WpOrg\Requests\Response * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $url argument is not a string or Stringable. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $type argument is not a string. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. * @throws \WpOrg\Requests\Exception On invalid URLs (`nonhttp`) */ public static function request($url, $headers = [], $data = [], $type = self::GET, $options = []) { if (InputValidator::is_string_or_stringable($url) === false) { throw InvalidArgument::create(1, '$url', 'string|Stringable', gettype($url)); } if (is_string($type) === false) { throw InvalidArgument::create(4, '$type', 'string', gettype($type)); } if (is_array($options) === false) { throw InvalidArgument::create(5, '$options', 'array', gettype($options)); } if (empty($options['type'])) { $options['type'] = $type; } $options = array_merge(self::get_default_options(), $options); self::set_defaults($url, $headers, $data, $type, $options); $options['hooks']->dispatch('requests.before_request', [&$url, &$headers, &$data, &$type, &$options]); if (!empty($options['transport'])) { $transport = $options['transport']; if (is_string($options['transport'])) { $transport = new $transport(); } } else { $need_ssl = (stripos($url, 'https://') === 0); $capabilities = [Capability::SSL => $need_ssl]; $transport = self::get_transport($capabilities); } $response = $transport->request($url, $headers, $data, $options); $options['hooks']->dispatch('requests.before_parse', [&$response, $url, $headers, $data, $type, $options]); return self::parse_response($response, $url, $headers, $data, $options); } /** * Send multiple HTTP requests simultaneously * * The `$requests` parameter takes an associative or indexed array of * request fields. The key of each request can be used to match up the * request with the returned data, or with the request passed into your * `multiple.request.complete` callback. * * The request fields value is an associative array with the following keys: * * - `url`: Request URL Same as the `$url` parameter to * {@see \WpOrg\Requests\Requests::request()} * (string, required) * - `headers`: Associative array of header fields. Same as the `$headers` * parameter to {@see \WpOrg\Requests\Requests::request()} * (array, default: `array()`) * - `data`: Associative array of data fields or a string. Same as the * `$data` parameter to {@see \WpOrg\Requests\Requests::request()} * (array|string, default: `array()`) * - `type`: HTTP request type (use \WpOrg\Requests\Requests constants). Same as the `$type` * parameter to {@see \WpOrg\Requests\Requests::request()} * (string, default: `\WpOrg\Requests\Requests::GET`) * - `cookies`: Associative array of cookie name to value, or cookie jar. * (array|\WpOrg\Requests\Cookie\Jar) * * If the `$options` parameter is specified, individual requests will * inherit options from it. This can be used to use a single hooking system, * or set all the types to `\WpOrg\Requests\Requests::POST`, for example. * * In addition, the `$options` parameter takes the following global options: * * - `complete`: A callback for when a request is complete. Takes two * parameters, a \WpOrg\Requests\Response/\WpOrg\Requests\Exception reference, and the * ID from the request array (Note: this can also be overridden on a * per-request basis, although that's a little silly) * (callback) * * @param array $requests Requests data (see description for more information) * @param array $options Global and default options (see {@see \WpOrg\Requests\Requests::request()}) * @return array Responses (either \WpOrg\Requests\Response or a \WpOrg\Requests\Exception object) * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $requests argument is not an array or iterable object with array access. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. */ public static function request_multiple($requests, $options = []) { if (InputValidator::has_array_access($requests) === false || InputValidator::is_iterable($requests) === false) { throw InvalidArgument::create(1, '$requests', 'array|ArrayAccess&Traversable', gettype($requests)); } if (is_array($options) === false) { throw InvalidArgument::create(2, '$options', 'array', gettype($options)); } $options = array_merge(self::get_default_options(true), $options); if (!empty($options['hooks'])) { $options['hooks']->register('transport.internal.parse_response', [static::class, 'parse_multiple']); if (!empty($options['complete'])) { $options['hooks']->register('multiple.request.complete', $options['complete']); } } foreach ($requests as $id => &$request) { if (!isset($request['headers'])) { $request['headers'] = []; } if (!isset($request['data'])) { $request['data'] = []; } if (!isset($request['type'])) { $request['type'] = self::GET; } if (!isset($request['options'])) { $request['options'] = $options; $request['options']['type'] = $request['type']; } else { if (empty($request['options']['type'])) { $request['options']['type'] = $request['type']; } $request['options'] = array_merge($options, $request['options']); } self::set_defaults($request['url'], $request['headers'], $request['data'], $request['type'], $request['options']); // Ensure we only hook in once if ($request['options']['hooks'] !== $options['hooks']) { $request['options']['hooks']->register('transport.internal.parse_response', [static::class, 'parse_multiple']); if (!empty($request['options']['complete'])) { $request['options']['hooks']->register('multiple.request.complete', $request['options']['complete']); } } } unset($request); if (!empty($options['transport'])) { $transport = $options['transport']; if (is_string($options['transport'])) { $transport = new $transport(); } } else { $transport = self::get_transport(); } $responses = $transport->request_multiple($requests, $options); foreach ($responses as $id => &$response) { // If our hook got messed with somehow, ensure we end up with the // correct response if (is_string($response)) { $request = $requests[$id]; self::parse_multiple($response, $request); $request['options']['hooks']->dispatch('multiple.request.complete', [&$response, $id]); } } return $responses; } /** * Get the default options * * @see \WpOrg\Requests\Requests::request() for values returned by this method * @param boolean $multirequest Is this a multirequest? * @return array Default option values */ protected static function get_default_options($multirequest = false) { $defaults = static::OPTION_DEFAULTS; $defaults['verify'] = self::$certificate_path; if ($multirequest !== false) { $defaults['complete'] = null; } return $defaults; } /** * Get default certificate path. * * @return string Default certificate path. */ public static function get_certificate_path() { return self::$certificate_path; } /** * Set default certificate path. * * @param string|Stringable|bool $path Certificate path, pointing to a PEM file. * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $url argument is not a string, Stringable or boolean. */ public static function set_certificate_path($path) { if (InputValidator::is_string_or_stringable($path) === false && is_bool($path) === false) { throw InvalidArgument::create(1, '$path', 'string|Stringable|bool', gettype($path)); } self::$certificate_path = $path; } /** * Set the default values * * The $options parameter is updated with the results. * * @param string $url URL to request * @param array $headers Extra headers to send with the request * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests * @param string $type HTTP request type * @param array $options Options for the request * @return void * * @throws \WpOrg\Requests\Exception When the $url is not an http(s) URL. */ protected static function set_defaults(&$url, &$headers, &$data, &$type, &$options) { if (!preg_match('/^http(s)?:\/\//i', $url, $matches)) { throw new Exception('Only HTTP(S) requests are handled.', 'nonhttp', $url); } if (empty($options['hooks'])) { $options['hooks'] = new Hooks(); } if (is_array($options['auth'])) { $options['auth'] = new Basic($options['auth']); } if ($options['auth'] !== false) { $options['auth']->register($options['hooks']); } if (is_string($options['proxy']) || is_array($options['proxy'])) { $options['proxy'] = new Http($options['proxy']); } if ($options['proxy'] !== false) { $options['proxy']->register($options['hooks']); } if (is_array($options['cookies'])) { $options['cookies'] = new Jar($options['cookies']); } elseif (empty($options['cookies'])) { $options['cookies'] = new Jar(); } if ($options['cookies'] !== false) { $options['cookies']->register($options['hooks']); } if ($options['idn'] !== false) { $iri = new Iri($url); $iri->host = IdnaEncoder::encode($iri->ihost); $url = $iri->uri; } // Massage the type to ensure we support it. $type = strtoupper($type); if (!isset($options['data_format'])) { if (in_array($type, [self::HEAD, self::GET, self::DELETE], true)) { $options['data_format'] = 'query'; } else { $options['data_format'] = 'body'; } } } /** * HTTP response parser * * @param string $headers Full response text including headers and body * @param string $url Original request URL * @param array $req_headers Original $headers array passed to {@link request()}, in case we need to follow redirects * @param array $req_data Original $data array passed to {@link request()}, in case we need to follow redirects * @param array $options Original $options array passed to {@link request()}, in case we need to follow redirects * @return \WpOrg\Requests\Response * * @throws \WpOrg\Requests\Exception On missing head/body separator (`requests.no_crlf_separator`) * @throws \WpOrg\Requests\Exception On missing head/body separator (`noversion`) * @throws \WpOrg\Requests\Exception On missing head/body separator (`toomanyredirects`) */ protected static function parse_response($headers, $url, $req_headers, $req_data, $options) { $return = new Response(); if (!$options['blocking']) { return $return; } $return->raw = $headers; $return->url = (string) $url; $return->body = ''; if (!$options['filename']) { $pos = strpos($headers, "\r\n\r\n"); if ($pos === false) { // Crap! throw new Exception('Missing header/body separator', 'requests.no_crlf_separator'); } $headers = substr($return->raw, 0, $pos); // Headers will always be separated from the body by two new lines - `\n\r\n\r`. $body = substr($return->raw, $pos + 4); if (!empty($body)) { $return->body = $body; } } // Pretend CRLF = LF for compatibility (RFC 2616, section 19.3) $headers = str_replace("\r\n", "\n", $headers); // Unfold headers (replace [CRLF] 1*( SP | HT ) with SP) as per RFC 2616 (section 2.2) $headers = preg_replace('/\n[ \t]/', ' ', $headers); $headers = explode("\n", $headers); preg_match('#^HTTP/(1\.\d)[ \t]+(\d+)#i', array_shift($headers), $matches); if (empty($matches)) { throw new Exception('Response could not be parsed', 'noversion', $headers); } $return->protocol_version = (float) $matches[1]; $return->status_code = (int) $matches[2]; if ($return->status_code >= 200 && $return->status_code < 300) { $return->success = true; } foreach ($headers as $header) { list($key, $value) = explode(':', $header, 2); $value = trim($value); preg_replace('#(\s+)#i', ' ', $value); $return->headers[$key] = $value; } if (isset($return->headers['transfer-encoding'])) { $return->body = self::decode_chunked($return->body); unset($return->headers['transfer-encoding']); } if (isset($return->headers['content-encoding'])) { $return->body = self::decompress($return->body); } //fsockopen and cURL compatibility if (isset($return->headers['connection'])) { unset($return->headers['connection']); } $options['hooks']->dispatch('requests.before_redirect_check', [&$return, $req_headers, $req_data, $options]); if ($return->is_redirect() && $options['follow_redirects'] === true) { if (isset($return->headers['location']) && $options['redirected'] < $options['redirects']) { if ($return->status_code === 303) { $options['type'] = self::GET; } $options['redirected']++; $location = $return->headers['location']; if (strpos($location, 'http://') !== 0 && strpos($location, 'https://') !== 0) { // relative redirect, for compatibility make it absolute $location = Iri::absolutize($url, $location); $location = $location->uri; } $hook_args = [ &$location, &$req_headers, &$req_data, &$options, $return, ]; $options['hooks']->dispatch('requests.before_redirect', $hook_args); $redirected = self::request($location, $req_headers, $req_data, $options['type'], $options); $redirected->history[] = $return; return $redirected; } elseif ($options['redirected'] >= $options['redirects']) { throw new Exception('Too many redirects', 'toomanyredirects', $return); } } $return->redirects = $options['redirected']; $options['hooks']->dispatch('requests.after_request', [&$return, $req_headers, $req_data, $options]); return $return; } /** * Callback for `transport.internal.parse_response` * * Internal use only. Converts a raw HTTP response to a \WpOrg\Requests\Response * while still executing a multiple request. * * `$response` is either set to a \WpOrg\Requests\Response instance, or a \WpOrg\Requests\Exception object * * @param string $response Full response text including headers and body (will be overwritten with Response instance) * @param array $request Request data as passed into {@see \WpOrg\Requests\Requests::request_multiple()} * @return void */ public static function parse_multiple(&$response, $request) { try { $url = $request['url']; $headers = $request['headers']; $data = $request['data']; $options = $request['options']; $response = self::parse_response($response, $url, $headers, $data, $options); } catch (Exception $e) { $response = $e; } } /** * Decoded a chunked body as per RFC 2616 * * @link https://tools.ietf.org/html/rfc2616#section-3.6.1 * @param string $data Chunked body * @return string Decoded body */ protected static function decode_chunked($data) { if (!preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', trim($data))) { return $data; } $decoded = ''; $encoded = $data; while (true) { $is_chunked = (bool) preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', $encoded, $matches); if (!$is_chunked) { // Looks like it's not chunked after all return $data; } $length = hexdec(trim($matches[1])); if ($length === 0) { // Ignore trailer headers return $decoded; } $chunk_length = strlen($matches[0]); $decoded .= substr($encoded, $chunk_length, $length); $encoded = substr($encoded, $chunk_length + $length + 2); if (trim($encoded) === '0' || empty($encoded)) { return $decoded; } } // We'll never actually get down here // @codeCoverageIgnoreStart } // @codeCoverageIgnoreEnd /** * Convert a key => value array to a 'key: value' array for headers * * @param iterable $dictionary Dictionary of header values * @return array List of headers * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not iterable. */ public static function flatten($dictionary) { if (InputValidator::is_iterable($dictionary) === false) { throw InvalidArgument::create(1, '$dictionary', 'iterable', gettype($dictionary)); } $return = []; foreach ($dictionary as $key => $value) { $return[] = sprintf('%s: %s', $key, $value); } return $return; } /** * Decompress an encoded body * * Implements gzip, compress and deflate. Guesses which it is by attempting * to decode. * * @param string $data Compressed data in one of the above formats * @return string Decompressed string * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string. */ public static function decompress($data) { if (is_string($data) === false) { throw InvalidArgument::create(1, '$data', 'string', gettype($data)); } if (trim($data) === '') { // Empty body does not need further processing. return $data; } $marker = substr($data, 0, 2); if (!isset(self::$magic_compression_headers[$marker])) { // Not actually compressed. Probably cURL ruining this for us. return $data; } if (function_exists('gzdecode')) { $decoded = @gzdecode($data); if ($decoded !== false) { return $decoded; } } if (function_exists('gzinflate')) { $decoded = @gzinflate($data); if ($decoded !== false) { return $decoded; } } $decoded = self::compatible_gzinflate($data); if ($decoded !== false) { return $decoded; } if (function_exists('gzuncompress')) { $decoded = @gzuncompress($data); if ($decoded !== false) { return $decoded; } } return $data; } /** * Decompression of deflated string while staying compatible with the majority of servers. * * Certain Servers will return deflated data with headers which PHP's gzinflate() * function cannot handle out of the box. The following function has been created from * various snippets on the gzinflate() PHP documentation. * * Warning: Magic numbers within. Due to the potential different formats that the compressed * data may be returned in, some "magic offsets" are needed to ensure proper decompression * takes place. For a simple progmatic way to determine the magic offset in use, see: * https://core.trac.wordpress.org/ticket/18273 * * @since 1.6.0 * @link https://core.trac.wordpress.org/ticket/18273 * @link https://www.php.net/gzinflate#70875 * @link https://www.php.net/gzinflate#77336 * * @param string $gz_data String to decompress. * @return string|bool False on failure. * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string. */ public static function compatible_gzinflate($gz_data) { if (is_string($gz_data) === false) { throw InvalidArgument::create(1, '$gz_data', 'string', gettype($gz_data)); } if (trim($gz_data) === '') { return false; } // Compressed data might contain a full zlib header, if so strip it for // gzinflate() if (substr($gz_data, 0, 3) === "\x1f\x8b\x08") { $i = 10; $flg = ord(substr($gz_data, 3, 1)); if ($flg > 0) { if ($flg & 4) { list($xlen) = unpack('v', substr($gz_data, $i, 2)); $i += 2 + $xlen; } if ($flg & 8) { $i = strpos($gz_data, "\0", $i) + 1; } if ($flg & 16) { $i = strpos($gz_data, "\0", $i) + 1; } if ($flg & 2) { $i += 2; } } $decompressed = self::compatible_gzinflate(substr($gz_data, $i)); if ($decompressed !== false) { return $decompressed; } } // If the data is Huffman Encoded, we must first strip the leading 2 // byte Huffman marker for gzinflate() // The response is Huffman coded by many compressors such as // java.util.zip.Deflater, Ruby's Zlib::Deflate, and .NET's // System.IO.Compression.DeflateStream. // // See https://decompres.blogspot.com/ for a quick explanation of this // data type $huffman_encoded = false; // low nibble of first byte should be 0x08 list(, $first_nibble) = unpack('h', $gz_data); // First 2 bytes should be divisible by 0x1F list(, $first_two_bytes) = unpack('n', $gz_data); if ($first_nibble === 0x08 && ($first_two_bytes % 0x1F) === 0) { $huffman_encoded = true; } if ($huffman_encoded) { $decompressed = @gzinflate(substr($gz_data, 2)); if ($decompressed !== false) { return $decompressed; } } if (substr($gz_data, 0, 4) === "\x50\x4b\x03\x04") { // ZIP file format header // Offset 6: 2 bytes, General-purpose field // Offset 26: 2 bytes, filename length // Offset 28: 2 bytes, optional field length // Offset 30: Filename field, followed by optional field, followed // immediately by data list(, $general_purpose_flag) = unpack('v', substr($gz_data, 6, 2)); // If the file has been compressed on the fly, 0x08 bit is set of // the general purpose field. We can use this to differentiate // between a compressed document, and a ZIP file $zip_compressed_on_the_fly = ((0x08 & $general_purpose_flag) === 0x08); if (!$zip_compressed_on_the_fly) { // Don't attempt to decode a compressed zip file return $gz_data; } // Determine the first byte of data, based on the above ZIP header // offsets: $first_file_start = array_sum(unpack('v2', substr($gz_data, 26, 4))); $decompressed = @gzinflate(substr($gz_data, 30 + $first_file_start)); if ($decompressed !== false) { return $decompressed; } return false; } // Finally fall back to straight gzinflate $decompressed = @gzinflate($gz_data); if ($decompressed !== false) { return $decompressed; } // Fallback for all above failing, not expected, but included for // debugging and preventing regressions and to track stats $decompressed = @gzinflate(substr($gz_data, 2)); if ($decompressed !== false) { return $decompressed; } return false; } } PK������ֺZ;������Ipv6.phpnu�W+A��������<?php /** * Class to validate and to work with IPv6 addresses * * @package Requests\Utilities */ namespace WpOrg\Requests; use WpOrg\Requests\Exception\InvalidArgument; use WpOrg\Requests\Utility\InputValidator; /** * Class to validate and to work with IPv6 addresses * * This was originally based on the PEAR class of the same name, but has been * entirely rewritten. * * @package Requests\Utilities */ final class Ipv6 { /** * Uncompresses an IPv6 address * * RFC 4291 allows you to compress consecutive zero pieces in an address to * '::'. This method expects a valid IPv6 address and expands the '::' to * the required number of zero pieces. * * Example: FF01::101 -> FF01:0:0:0:0:0:0:101 * ::1 -> 0:0:0:0:0:0:0:1 * * @author Alexander Merz <alexander.merz@web.de> * @author elfrink at introweb dot nl * @author Josh Peck <jmp at joshpeck dot org> * @copyright 2003-2005 The PHP Group * @license https://opensource.org/licenses/bsd-license.php * * @param string|Stringable $ip An IPv6 address * @return string The uncompressed IPv6 address * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string or a stringable object. */ public static function uncompress($ip) { if (InputValidator::is_string_or_stringable($ip) === false) { throw InvalidArgument::create(1, '$ip', 'string|Stringable', gettype($ip)); } $ip = (string) $ip; if (substr_count($ip, '::') !== 1) { return $ip; } list($ip1, $ip2) = explode('::', $ip); $c1 = ($ip1 === '') ? -1 : substr_count($ip1, ':'); $c2 = ($ip2 === '') ? -1 : substr_count($ip2, ':'); if (strpos($ip2, '.') !== false) { $c2++; } if ($c1 === -1 && $c2 === -1) { // :: $ip = '0:0:0:0:0:0:0:0'; } elseif ($c1 === -1) { // ::xxx $fill = str_repeat('0:', 7 - $c2); $ip = str_replace('::', $fill, $ip); } elseif ($c2 === -1) { // xxx:: $fill = str_repeat(':0', 7 - $c1); $ip = str_replace('::', $fill, $ip); } else { // xxx::xxx $fill = ':' . str_repeat('0:', 6 - $c2 - $c1); $ip = str_replace('::', $fill, $ip); } return $ip; } /** * Compresses an IPv6 address * * RFC 4291 allows you to compress consecutive zero pieces in an address to * '::'. This method expects a valid IPv6 address and compresses consecutive * zero pieces to '::'. * * Example: FF01:0:0:0:0:0:0:101 -> FF01::101 * 0:0:0:0:0:0:0:1 -> ::1 * * @see \WpOrg\Requests\Ipv6::uncompress() * * @param string $ip An IPv6 address * @return string The compressed IPv6 address */ public static function compress($ip) { // Prepare the IP to be compressed. // Note: Input validation is handled in the `uncompress()` method, which is the first call made in this method. $ip = self::uncompress($ip); $ip_parts = self::split_v6_v4($ip); // Replace all leading zeros $ip_parts[0] = preg_replace('/(^|:)0+([0-9])/', '\1\2', $ip_parts[0]); // Find bunches of zeros if (preg_match_all('/(?:^|:)(?:0(?::|$))+/', $ip_parts[0], $matches, PREG_OFFSET_CAPTURE)) { $max = 0; $pos = null; foreach ($matches[0] as $match) { if (strlen($match[0]) > $max) { $max = strlen($match[0]); $pos = $match[1]; } } $ip_parts[0] = substr_replace($ip_parts[0], '::', $pos, $max); } if ($ip_parts[1] !== '') { return implode(':', $ip_parts); } else { return $ip_parts[0]; } } /** * Splits an IPv6 address into the IPv6 and IPv4 representation parts * * RFC 4291 allows you to represent the last two parts of an IPv6 address * using the standard IPv4 representation * * Example: 0:0:0:0:0:0:13.1.68.3 * 0:0:0:0:0:FFFF:129.144.52.38 * * @param string $ip An IPv6 address * @return string[] [0] contains the IPv6 represented part, and [1] the IPv4 represented part */ private static function split_v6_v4($ip) { if (strpos($ip, '.') !== false) { $pos = strrpos($ip, ':'); $ipv6_part = substr($ip, 0, $pos); $ipv4_part = substr($ip, $pos + 1); return [$ipv6_part, $ipv4_part]; } else { return [$ip, '']; } } /** * Checks an IPv6 address * * Checks if the given IP is a valid IPv6 address * * @param string $ip An IPv6 address * @return bool true if $ip is a valid IPv6 address */ public static function check_ipv6($ip) { // Note: Input validation is handled in the `uncompress()` method, which is the first call made in this method. $ip = self::uncompress($ip); list($ipv6, $ipv4) = self::split_v6_v4($ip); $ipv6 = explode(':', $ipv6); $ipv4 = explode('.', $ipv4); if (count($ipv6) === 8 && count($ipv4) === 1 || count($ipv6) === 6 && count($ipv4) === 4) { foreach ($ipv6 as $ipv6_part) { // The section can't be empty if ($ipv6_part === '') { return false; } // Nor can it be over four characters if (strlen($ipv6_part) > 4) { return false; } // Remove leading zeros (this is safe because of the above) $ipv6_part = ltrim($ipv6_part, '0'); if ($ipv6_part === '') { $ipv6_part = '0'; } // Check the value is valid $value = hexdec($ipv6_part); if (dechex($value) !== strtolower($ipv6_part) || $value < 0 || $value > 0xFFFF) { return false; } } if (count($ipv4) === 4) { foreach ($ipv4 as $ipv4_part) { $value = (int) $ipv4_part; if ((string) $value !== $ipv4_part || $value < 0 || $value > 0xFF) { return false; } } } return true; } else { return false; } } } PK������ֺZy �� �� ��Hooks.phpnu�W+A��������<?php /** * Handles adding and dispatching events * * @package Requests\EventDispatcher */ namespace WpOrg\Requests; use WpOrg\Requests\Exception\InvalidArgument; use WpOrg\Requests\HookManager; use WpOrg\Requests\Utility\InputValidator; /** * Handles adding and dispatching events * * @package Requests\EventDispatcher */ class Hooks implements HookManager { /** * Registered callbacks for each hook * * @var array */ protected $hooks = []; /** * Register a callback for a hook * * @param string $hook Hook name * @param callable $callback Function/method to call on event * @param int $priority Priority number. <0 is executed earlier, >0 is executed later * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $hook argument is not a string. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $callback argument is not callable. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $priority argument is not an integer. */ public function register($hook, $callback, $priority = 0) { if (is_string($hook) === false) { throw InvalidArgument::create(1, '$hook', 'string', gettype($hook)); } if (is_callable($callback) === false) { throw InvalidArgument::create(2, '$callback', 'callable', gettype($callback)); } if (InputValidator::is_numeric_array_key($priority) === false) { throw InvalidArgument::create(3, '$priority', 'integer', gettype($priority)); } if (!isset($this->hooks[$hook])) { $this->hooks[$hook] = [ $priority => [], ]; } elseif (!isset($this->hooks[$hook][$priority])) { $this->hooks[$hook][$priority] = []; } $this->hooks[$hook][$priority][] = $callback; } /** * Dispatch a message * * @param string $hook Hook name * @param array $parameters Parameters to pass to callbacks * @return boolean Successfulness * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $hook argument is not a string. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $parameters argument is not an array. */ public function dispatch($hook, $parameters = []) { if (is_string($hook) === false) { throw InvalidArgument::create(1, '$hook', 'string', gettype($hook)); } // Check strictly against array, as Array* objects don't work in combination with `call_user_func_array()`. if (is_array($parameters) === false) { throw InvalidArgument::create(2, '$parameters', 'array', gettype($parameters)); } if (empty($this->hooks[$hook])) { return false; } if (!empty($parameters)) { // Strip potential keys from the array to prevent them being interpreted as parameter names in PHP 8.0. $parameters = array_values($parameters); } ksort($this->hooks[$hook]); foreach ($this->hooks[$hook] as $priority => $hooked) { foreach ($hooked as $callback) { $callback(...$parameters); } } return true; } public function __wakeup() { throw new \LogicException( __CLASS__ . ' should never be unserialized' ); } } PK������ֺZrw$��w$�� ��Autoload.phpnu�W+A��������<?php /** * Autoloader for Requests for PHP. * * Include this file if you'd like to avoid having to create your own autoloader. * * @package Requests * @since 2.0.0 * * @codeCoverageIgnore */ namespace WpOrg\Requests; /* * Ensure the autoloader is only declared once. * This safeguard is in place as this is the typical entry point for this library * and this file being required unconditionally could easily cause * fatal "Class already declared" errors. */ if (class_exists('WpOrg\Requests\Autoload') === false) { /** * Autoloader for Requests for PHP. * * This autoloader supports the PSR-4 based Requests 2.0.0 classes in a case-sensitive manner * as the most common server OS-es are case-sensitive and the file names are in mixed case. * * For the PSR-0 Requests 1.x BC-layer, requested classes will be treated case-insensitively. * * @package Requests */ final class Autoload { /** * List of the old PSR-0 class names in lowercase as keys with their PSR-4 case-sensitive name as a value. * * @var array */ private static $deprecated_classes = [ // Interfaces. 'requests_auth' => '\WpOrg\Requests\Auth', 'requests_hooker' => '\WpOrg\Requests\HookManager', 'requests_proxy' => '\WpOrg\Requests\Proxy', 'requests_transport' => '\WpOrg\Requests\Transport', // Classes. 'requests_cookie' => '\WpOrg\Requests\Cookie', 'requests_exception' => '\WpOrg\Requests\Exception', 'requests_hooks' => '\WpOrg\Requests\Hooks', 'requests_idnaencoder' => '\WpOrg\Requests\IdnaEncoder', 'requests_ipv6' => '\WpOrg\Requests\Ipv6', 'requests_iri' => '\WpOrg\Requests\Iri', 'requests_response' => '\WpOrg\Requests\Response', 'requests_session' => '\WpOrg\Requests\Session', 'requests_ssl' => '\WpOrg\Requests\Ssl', 'requests_auth_basic' => '\WpOrg\Requests\Auth\Basic', 'requests_cookie_jar' => '\WpOrg\Requests\Cookie\Jar', 'requests_proxy_http' => '\WpOrg\Requests\Proxy\Http', 'requests_response_headers' => '\WpOrg\Requests\Response\Headers', 'requests_transport_curl' => '\WpOrg\Requests\Transport\Curl', 'requests_transport_fsockopen' => '\WpOrg\Requests\Transport\Fsockopen', 'requests_utility_caseinsensitivedictionary' => '\WpOrg\Requests\Utility\CaseInsensitiveDictionary', 'requests_utility_filterediterator' => '\WpOrg\Requests\Utility\FilteredIterator', 'requests_exception_http' => '\WpOrg\Requests\Exception\Http', 'requests_exception_transport' => '\WpOrg\Requests\Exception\Transport', 'requests_exception_transport_curl' => '\WpOrg\Requests\Exception\Transport\Curl', 'requests_exception_http_304' => '\WpOrg\Requests\Exception\Http\Status304', 'requests_exception_http_305' => '\WpOrg\Requests\Exception\Http\Status305', 'requests_exception_http_306' => '\WpOrg\Requests\Exception\Http\Status306', 'requests_exception_http_400' => '\WpOrg\Requests\Exception\Http\Status400', 'requests_exception_http_401' => '\WpOrg\Requests\Exception\Http\Status401', 'requests_exception_http_402' => '\WpOrg\Requests\Exception\Http\Status402', 'requests_exception_http_403' => '\WpOrg\Requests\Exception\Http\Status403', 'requests_exception_http_404' => '\WpOrg\Requests\Exception\Http\Status404', 'requests_exception_http_405' => '\WpOrg\Requests\Exception\Http\Status405', 'requests_exception_http_406' => '\WpOrg\Requests\Exception\Http\Status406', 'requests_exception_http_407' => '\WpOrg\Requests\Exception\Http\Status407', 'requests_exception_http_408' => '\WpOrg\Requests\Exception\Http\Status408', 'requests_exception_http_409' => '\WpOrg\Requests\Exception\Http\Status409', 'requests_exception_http_410' => '\WpOrg\Requests\Exception\Http\Status410', 'requests_exception_http_411' => '\WpOrg\Requests\Exception\Http\Status411', 'requests_exception_http_412' => '\WpOrg\Requests\Exception\Http\Status412', 'requests_exception_http_413' => '\WpOrg\Requests\Exception\Http\Status413', 'requests_exception_http_414' => '\WpOrg\Requests\Exception\Http\Status414', 'requests_exception_http_415' => '\WpOrg\Requests\Exception\Http\Status415', 'requests_exception_http_416' => '\WpOrg\Requests\Exception\Http\Status416', 'requests_exception_http_417' => '\WpOrg\Requests\Exception\Http\Status417', 'requests_exception_http_418' => '\WpOrg\Requests\Exception\Http\Status418', 'requests_exception_http_428' => '\WpOrg\Requests\Exception\Http\Status428', 'requests_exception_http_429' => '\WpOrg\Requests\Exception\Http\Status429', 'requests_exception_http_431' => '\WpOrg\Requests\Exception\Http\Status431', 'requests_exception_http_500' => '\WpOrg\Requests\Exception\Http\Status500', 'requests_exception_http_501' => '\WpOrg\Requests\Exception\Http\Status501', 'requests_exception_http_502' => '\WpOrg\Requests\Exception\Http\Status502', 'requests_exception_http_503' => '\WpOrg\Requests\Exception\Http\Status503', 'requests_exception_http_504' => '\WpOrg\Requests\Exception\Http\Status504', 'requests_exception_http_505' => '\WpOrg\Requests\Exception\Http\Status505', 'requests_exception_http_511' => '\WpOrg\Requests\Exception\Http\Status511', 'requests_exception_http_unknown' => '\WpOrg\Requests\Exception\Http\StatusUnknown', ]; /** * Register the autoloader. * * Note: the autoloader is *prepended* in the autoload queue. * This is done to ensure that the Requests 2.0 autoloader takes precedence * over a potentially (dependency-registered) Requests 1.x autoloader. * * @internal This method contains a safeguard against the autoloader being * registered multiple times. This safeguard uses a global constant to * (hopefully/in most cases) still function correctly, even if the * class would be renamed. * * @return void */ public static function register() { if (defined('REQUESTS_AUTOLOAD_REGISTERED') === false) { spl_autoload_register([self::class, 'load'], true); define('REQUESTS_AUTOLOAD_REGISTERED', true); } } /** * Autoloader. * * @param string $class_name Name of the class name to load. * * @return bool Whether a class was loaded or not. */ public static function load($class_name) { // Check that the class starts with "Requests" (PSR-0) or "WpOrg\Requests" (PSR-4). $psr_4_prefix_pos = strpos($class_name, 'WpOrg\\Requests\\'); if (stripos($class_name, 'Requests') !== 0 && $psr_4_prefix_pos !== 0) { return false; } $class_lower = strtolower($class_name); if ($class_lower === 'requests') { // Reference to the original PSR-0 Requests class. $file = dirname(__DIR__) . '/library/Requests.php'; } elseif ($psr_4_prefix_pos === 0) { // PSR-4 classname. $file = __DIR__ . '/' . strtr(substr($class_name, 15), '\\', '/') . '.php'; } if (isset($file) && file_exists($file)) { include $file; return true; } /* * Okay, so the class starts with "Requests", but we couldn't find the file. * If this is one of the deprecated/renamed PSR-0 classes being requested, * let's alias it to the new name and throw a deprecation notice. */ if (isset(self::$deprecated_classes[$class_lower])) { /* * Integrators who cannot yet upgrade to the PSR-4 class names can silence deprecations * by defining a `REQUESTS_SILENCE_PSR0_DEPRECATIONS` constant and setting it to `true`. * The constant needs to be defined before the first deprecated class is requested * via this autoloader. */ if (!defined('REQUESTS_SILENCE_PSR0_DEPRECATIONS') || REQUESTS_SILENCE_PSR0_DEPRECATIONS !== true) { // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error trigger_error( 'The PSR-0 `Requests_...` class names in the Requests library are deprecated.' . ' Switch to the PSR-4 `WpOrg\Requests\...` class names at your earliest convenience.', E_USER_DEPRECATED ); // Prevent the deprecation notice from being thrown twice. if (!defined('REQUESTS_SILENCE_PSR0_DEPRECATIONS')) { define('REQUESTS_SILENCE_PSR0_DEPRECATIONS', true); } } // Create an alias and let the autoloader recursively kick in to load the PSR-4 class. return class_alias(self::$deprecated_classes[$class_lower], $class_name, true); } return false; } } } PK������ֺZՄec��c�� ��Proxy.phpnu�W+A��������<?php /** * Proxy connection interface * * @package Requests\Proxy * @since 1.6 */ namespace WpOrg\Requests; use WpOrg\Requests\Hooks; /** * Proxy connection interface * * Implement this interface to handle proxy settings and authentication * * Parameters should be passed via the constructor where possible, as this * makes it much easier for users to use your provider. * * @see \WpOrg\Requests\Hooks * * @package Requests\Proxy * @since 1.6 */ interface Proxy { /** * Register hooks as needed * * This method is called in {@see \WpOrg\Requests\Requests::request()} when the user * has set an instance as the 'auth' option. Use this callback to register all the * hooks you'll need. * * @see \WpOrg\Requests\Hooks::register() * @param \WpOrg\Requests\Hooks $hooks Hook system */ public function register(Hooks $hooks); } PK������ֺZ,S���� ��Transport.phpnu�W+A��������<?php /** * Base HTTP transport * * @package Requests\Transport */ namespace WpOrg\Requests; /** * Base HTTP transport * * @package Requests\Transport */ interface Transport { /** * Perform a request * * @param string $url URL to request * @param array $headers Associative array of request headers * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD * @param array $options Request options, see {@see \WpOrg\Requests\Requests::response()} for documentation * @return string Raw HTTP result */ public function request($url, $headers = [], $data = [], $options = []); /** * Send multiple requests simultaneously * * @param array $requests Request data (array of 'url', 'headers', 'data', 'options') as per {@see \WpOrg\Requests\Transport::request()} * @param array $options Global options, see {@see \WpOrg\Requests\Requests::response()} for documentation * @return array Array of \WpOrg\Requests\Response objects (may contain \WpOrg\Requests\Exception or string responses as well) */ public function request_multiple($requests, $options); /** * Self-test whether the transport can be used. * * The available capabilities to test for can be found in {@see \WpOrg\Requests\Capability}. * * @param array<string, bool> $capabilities Optional. Associative array of capabilities to test against, i.e. `['<capability>' => true]`. * @return bool Whether the transport can be used. */ public static function test($capabilities = []); } PK������ֺZ84 �� ����Cookie/Jar.phpnu�W+A��������<?php /** * Cookie holder object * * @package Requests\Cookies */ namespace WpOrg\Requests\Cookie; use ArrayAccess; use ArrayIterator; use IteratorAggregate; use ReturnTypeWillChange; use WpOrg\Requests\Cookie; use WpOrg\Requests\Exception; use WpOrg\Requests\Exception\InvalidArgument; use WpOrg\Requests\HookManager; use WpOrg\Requests\Iri; use WpOrg\Requests\Response; /** * Cookie holder object * * @package Requests\Cookies */ class Jar implements ArrayAccess, IteratorAggregate { /** * Actual item data * * @var array */ protected $cookies = []; /** * Create a new jar * * @param array $cookies Existing cookie values * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not an array. */ public function __construct($cookies = []) { if (is_array($cookies) === false) { throw InvalidArgument::create(1, '$cookies', 'array', gettype($cookies)); } $this->cookies = $cookies; } /** * Normalise cookie data into a \WpOrg\Requests\Cookie * * @param string|\WpOrg\Requests\Cookie $cookie Cookie header value, possibly pre-parsed (object). * @param string $key Optional. The name for this cookie. * @return \WpOrg\Requests\Cookie */ public function normalize_cookie($cookie, $key = '') { if ($cookie instanceof Cookie) { return $cookie; } return Cookie::parse($cookie, $key); } /** * Check if the given item exists * * @param string $offset Item key * @return boolean Does the item exist? */ #[ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->cookies[$offset]); } /** * Get the value for the item * * @param string $offset Item key * @return string|null Item value (null if offsetExists is false) */ #[ReturnTypeWillChange] public function offsetGet($offset) { if (!isset($this->cookies[$offset])) { return null; } return $this->cookies[$offset]; } /** * Set the given item * * @param string $offset Item name * @param string $value Item value * * @throws \WpOrg\Requests\Exception On attempting to use dictionary as list (`invalidset`) */ #[ReturnTypeWillChange] public function offsetSet($offset, $value) { if ($offset === null) { throw new Exception('Object is a dictionary, not a list', 'invalidset'); } $this->cookies[$offset] = $value; } /** * Unset the given header * * @param string $offset The key for the item to unset. */ #[ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->cookies[$offset]); } /** * Get an iterator for the data * * @return \ArrayIterator */ #[ReturnTypeWillChange] public function getIterator() { return new ArrayIterator($this->cookies); } /** * Register the cookie handler with the request's hooking system * * @param \WpOrg\Requests\HookManager $hooks Hooking system */ public function register(HookManager $hooks) { $hooks->register('requests.before_request', [$this, 'before_request']); $hooks->register('requests.before_redirect_check', [$this, 'before_redirect_check']); } /** * Add Cookie header to a request if we have any * * As per RFC 6265, cookies are separated by '; ' * * @param string $url * @param array $headers * @param array $data * @param string $type * @param array $options */ public function before_request($url, &$headers, &$data, &$type, &$options) { if (!$url instanceof Iri) { $url = new Iri($url); } if (!empty($this->cookies)) { $cookies = []; foreach ($this->cookies as $key => $cookie) { $cookie = $this->normalize_cookie($cookie, $key); // Skip expired cookies if ($cookie->is_expired()) { continue; } if ($cookie->domain_matches($url->host)) { $cookies[] = $cookie->format_for_header(); } } $headers['Cookie'] = implode('; ', $cookies); } } /** * Parse all cookies from a response and attach them to the response * * @param \WpOrg\Requests\Response $response Response as received. */ public function before_redirect_check(Response $response) { $url = $response->url; if (!$url instanceof Iri) { $url = new Iri($url); } $cookies = Cookie::parse_from_headers($response->headers, $url); $this->cookies = array_merge($this->cookies, $cookies); $response->cookies = $this; } } PK������ֺZ/yQ#��#�� ��Session.phpnu�W+A��������<?php /** * Session handler for persistent requests and default parameters * * @package Requests\SessionHandler */ namespace WpOrg\Requests; use WpOrg\Requests\Cookie\Jar; use WpOrg\Requests\Exception\InvalidArgument; use WpOrg\Requests\Iri; use WpOrg\Requests\Requests; use WpOrg\Requests\Utility\InputValidator; /** * Session handler for persistent requests and default parameters * * Allows various options to be set as default values, and merges both the * options and URL properties together. A base URL can be set for all requests, * with all subrequests resolved from this. Base options can be set (including * a shared cookie jar), then overridden for individual requests. * * @package Requests\SessionHandler */ class Session { /** * Base URL for requests * * URLs will be made absolute using this as the base * * @var string|null */ public $url = null; /** * Base headers for requests * * @var array */ public $headers = []; /** * Base data for requests * * If both the base data and the per-request data are arrays, the data will * be merged before sending the request. * * @var array */ public $data = []; /** * Base options for requests * * The base options are merged with the per-request data for each request. * The only default option is a shared cookie jar between requests. * * Values here can also be set directly via properties on the Session * object, e.g. `$session->useragent = 'X';` * * @var array */ public $options = []; /** * Create a new session * * @param string|Stringable|null $url Base URL for requests * @param array $headers Default headers for requests * @param array $data Default data for requests * @param array $options Default options for requests * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $url argument is not a string, Stringable or null. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $headers argument is not an array. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $data argument is not an array. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. */ public function __construct($url = null, $headers = [], $data = [], $options = []) { if ($url !== null && InputValidator::is_string_or_stringable($url) === false) { throw InvalidArgument::create(1, '$url', 'string|Stringable|null', gettype($url)); } if (is_array($headers) === false) { throw InvalidArgument::create(2, '$headers', 'array', gettype($headers)); } if (is_array($data) === false) { throw InvalidArgument::create(3, '$data', 'array', gettype($data)); } if (is_array($options) === false) { throw InvalidArgument::create(4, '$options', 'array', gettype($options)); } $this->url = $url; $this->headers = $headers; $this->data = $data; $this->options = $options; if (empty($this->options['cookies'])) { $this->options['cookies'] = new Jar(); } } /** * Get a property's value * * @param string $name Property name. * @return mixed|null Property value, null if none found */ public function __get($name) { if (isset($this->options[$name])) { return $this->options[$name]; } return null; } /** * Set a property's value * * @param string $name Property name. * @param mixed $value Property value */ public function __set($name, $value) { $this->options[$name] = $value; } /** * Remove a property's value * * @param string $name Property name. */ public function __isset($name) { return isset($this->options[$name]); } /** * Remove a property's value * * @param string $name Property name. */ public function __unset($name) { unset($this->options[$name]); } /**#@+ * @see \WpOrg\Requests\Session::request() * @param string $url * @param array $headers * @param array $options * @return \WpOrg\Requests\Response */ /** * Send a GET request */ public function get($url, $headers = [], $options = []) { return $this->request($url, $headers, null, Requests::GET, $options); } /** * Send a HEAD request */ public function head($url, $headers = [], $options = []) { return $this->request($url, $headers, null, Requests::HEAD, $options); } /** * Send a DELETE request */ public function delete($url, $headers = [], $options = []) { return $this->request($url, $headers, null, Requests::DELETE, $options); } /**#@-*/ /**#@+ * @see \WpOrg\Requests\Session::request() * @param string $url * @param array $headers * @param array $data * @param array $options * @return \WpOrg\Requests\Response */ /** * Send a POST request */ public function post($url, $headers = [], $data = [], $options = []) { return $this->request($url, $headers, $data, Requests::POST, $options); } /** * Send a PUT request */ public function put($url, $headers = [], $data = [], $options = []) { return $this->request($url, $headers, $data, Requests::PUT, $options); } /** * Send a PATCH request * * Note: Unlike {@see \WpOrg\Requests\Session::post()} and {@see \WpOrg\Requests\Session::put()}, * `$headers` is required, as the specification recommends that should send an ETag * * @link https://tools.ietf.org/html/rfc5789 */ public function patch($url, $headers, $data = [], $options = []) { return $this->request($url, $headers, $data, Requests::PATCH, $options); } /**#@-*/ /** * Main interface for HTTP requests * * This method initiates a request and sends it via a transport before * parsing. * * @see \WpOrg\Requests\Requests::request() * * @param string $url URL to request * @param array $headers Extra headers to send with the request * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests * @param string $type HTTP request type (use \WpOrg\Requests\Requests constants) * @param array $options Options for the request (see {@see \WpOrg\Requests\Requests::request()}) * @return \WpOrg\Requests\Response * * @throws \WpOrg\Requests\Exception On invalid URLs (`nonhttp`) */ public function request($url, $headers = [], $data = [], $type = Requests::GET, $options = []) { $request = $this->merge_request(compact('url', 'headers', 'data', 'options')); return Requests::request($request['url'], $request['headers'], $request['data'], $type, $request['options']); } /** * Send multiple HTTP requests simultaneously * * @see \WpOrg\Requests\Requests::request_multiple() * * @param array $requests Requests data (see {@see \WpOrg\Requests\Requests::request_multiple()}) * @param array $options Global and default options (see {@see \WpOrg\Requests\Requests::request()}) * @return array Responses (either \WpOrg\Requests\Response or a \WpOrg\Requests\Exception object) * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $requests argument is not an array or iterable object with array access. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. */ public function request_multiple($requests, $options = []) { if (InputValidator::has_array_access($requests) === false || InputValidator::is_iterable($requests) === false) { throw InvalidArgument::create(1, '$requests', 'array|ArrayAccess&Traversable', gettype($requests)); } if (is_array($options) === false) { throw InvalidArgument::create(2, '$options', 'array', gettype($options)); } foreach ($requests as $key => $request) { $requests[$key] = $this->merge_request($request, false); } $options = array_merge($this->options, $options); // Disallow forcing the type, as that's a per request setting unset($options['type']); return Requests::request_multiple($requests, $options); } public function __wakeup() { throw new \LogicException( __CLASS__ . ' should never be unserialized' ); } /** * Merge a request's data with the default data * * @param array $request Request data (same form as {@see \WpOrg\Requests\Session::request_multiple()}) * @param boolean $merge_options Should we merge options as well? * @return array Request data */ protected function merge_request($request, $merge_options = true) { if ($this->url !== null) { $request['url'] = Iri::absolutize($this->url, $request['url']); $request['url'] = $request['url']->uri; } if (empty($request['headers'])) { $request['headers'] = []; } $request['headers'] = array_merge($this->headers, $request['headers']); if (empty($request['data'])) { if (is_array($this->data)) { $request['data'] = $this->data; } } elseif (is_array($request['data']) && is_array($this->data)) { $request['data'] = array_merge($this->data, $request['data']); } if ($merge_options === true) { $request['options'] = array_merge($this->options, $request['options']); // Disallow forcing the type, as that's a per request setting unset($request['options']['type']); } return $request; } } PK������ֺZ5 L �� ��%��Utility/CaseInsensitiveDictionary.phpnu�W+A��������<?php /** * Case-insensitive dictionary, suitable for HTTP headers * * @package Requests\Utilities */ namespace WpOrg\Requests\Utility; use ArrayAccess; use ArrayIterator; use IteratorAggregate; use ReturnTypeWillChange; use WpOrg\Requests\Exception; /** * Case-insensitive dictionary, suitable for HTTP headers * * @package Requests\Utilities */ class CaseInsensitiveDictionary implements ArrayAccess, IteratorAggregate { /** * Actual item data * * @var array */ protected $data = []; /** * Creates a case insensitive dictionary. * * @param array $data Dictionary/map to convert to case-insensitive */ public function __construct(array $data = []) { foreach ($data as $offset => $value) { $this->offsetSet($offset, $value); } } /** * Check if the given item exists * * @param string $offset Item key * @return boolean Does the item exist? */ #[ReturnTypeWillChange] public function offsetExists($offset) { if (is_string($offset)) { $offset = strtolower($offset); } return isset($this->data[$offset]); } /** * Get the value for the item * * @param string $offset Item key * @return string|null Item value (null if the item key doesn't exist) */ #[ReturnTypeWillChange] public function offsetGet($offset) { if (is_string($offset)) { $offset = strtolower($offset); } if (!isset($this->data[$offset])) { return null; } return $this->data[$offset]; } /** * Set the given item * * @param string $offset Item name * @param string $value Item value * * @throws \WpOrg\Requests\Exception On attempting to use dictionary as list (`invalidset`) */ #[ReturnTypeWillChange] public function offsetSet($offset, $value) { if ($offset === null) { throw new Exception('Object is a dictionary, not a list', 'invalidset'); } if (is_string($offset)) { $offset = strtolower($offset); } $this->data[$offset] = $value; } /** * Unset the given header * * @param string $offset The key for the item to unset. */ #[ReturnTypeWillChange] public function offsetUnset($offset) { if (is_string($offset)) { $offset = strtolower($offset); } unset($this->data[$offset]); } /** * Get an iterator for the data * * @return \ArrayIterator */ #[ReturnTypeWillChange] public function getIterator() { return new ArrayIterator($this->data); } /** * Get the headers as an array * * @return array Header data */ public function getAll() { return $this->data; } } PK������ֺZm��m����Utility/FilteredIterator.phpnu�W+A��������<?php /** * Iterator for arrays requiring filtered values * * @package Requests\Utilities */ namespace WpOrg\Requests\Utility; use ArrayIterator; use ReturnTypeWillChange; use WpOrg\Requests\Exception\InvalidArgument; use WpOrg\Requests\Utility\InputValidator; /** * Iterator for arrays requiring filtered values * * @package Requests\Utilities */ final class FilteredIterator extends ArrayIterator { /** * Callback to run as a filter * * @var callable */ private $callback; /** * Create a new iterator * * @param array $data The array or object to be iterated on. * @param callable $callback Callback to be called on each value * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $data argument is not iterable. */ public function __construct($data, $callback) { if (InputValidator::is_iterable($data) === false) { throw InvalidArgument::create(1, '$data', 'iterable', gettype($data)); } parent::__construct($data); if (is_callable($callback)) { $this->callback = $callback; } } /** * Prevent unserialization of the object for security reasons. * * @phpcs:disable PHPCompatibility.FunctionNameRestrictions.NewMagicMethods.__unserializeFound * * @param array $data Restored array of data originally serialized. * * @return void */ #[ReturnTypeWillChange] public function __unserialize($data) {} // phpcs:enable /** * Perform reinitialization tasks. * * Prevents a callback from being injected during unserialization of an object. * * @return void */ public function __wakeup() { unset($this->callback); } /** * Get the current item's value after filtering * * @return string */ #[ReturnTypeWillChange] public function current() { $value = parent::current(); if (is_callable($this->callback)) { $value = call_user_func($this->callback, $value); } return $value; } /** * Prevent creating a PHP value from a stored representation of the object for security reasons. * * @param string $data The serialized string. * * @return void */ #[ReturnTypeWillChange] public function unserialize($data) {} } PK������ֺZ^ �� ����Utility/InputValidator.phpnu�W+A��������<?php /** * Input validation utilities. * * @package Requests\Utilities */ namespace WpOrg\Requests\Utility; use ArrayAccess; use CurlHandle; use Traversable; /** * Input validation utilities. * * @package Requests\Utilities */ final class InputValidator { /** * Verify that a received input parameter is of type string or is "stringable". * * @param mixed $input Input parameter to verify. * * @return bool */ public static function is_string_or_stringable($input) { return is_string($input) || self::is_stringable_object($input); } /** * Verify whether a received input parameter is usable as an integer array key. * * @param mixed $input Input parameter to verify. * * @return bool */ public static function is_numeric_array_key($input) { if (is_int($input)) { return true; } if (!is_string($input)) { return false; } return (bool) preg_match('`^-?[0-9]+$`', $input); } /** * Verify whether a received input parameter is "stringable". * * @param mixed $input Input parameter to verify. * * @return bool */ public static function is_stringable_object($input) { return is_object($input) && method_exists($input, '__toString'); } /** * Verify whether a received input parameter is _accessible as if it were an array_. * * @param mixed $input Input parameter to verify. * * @return bool */ public static function has_array_access($input) { return is_array($input) || $input instanceof ArrayAccess; } /** * Verify whether a received input parameter is "iterable". * * @internal The PHP native `is_iterable()` function was only introduced in PHP 7.1 * and this library still supports PHP 5.6. * * @param mixed $input Input parameter to verify. * * @return bool */ public static function is_iterable($input) { return is_array($input) || $input instanceof Traversable; } /** * Verify whether a received input parameter is a Curl handle. * * The PHP Curl extension worked with resources prior to PHP 8.0 and with * an instance of the `CurlHandle` class since PHP 8.0. * {@link https://www.php.net/manual/en/migration80.incompatible.php#migration80.incompatible.resource2object} * * @param mixed $input Input parameter to verify. * * @return bool */ public static function is_curl_handle($input) { if (is_resource($input)) { return get_resource_type($input) === 'curl'; } if (is_object($input)) { return $input instanceof CurlHandle; } return false; } } PK������ֺZM0��0����IdnaEncoder.phpnu�W+A��������<?php namespace WpOrg\Requests; use WpOrg\Requests\Exception; use WpOrg\Requests\Exception\InvalidArgument; use WpOrg\Requests\Utility\InputValidator; /** * IDNA URL encoder * * Note: Not fully compliant, as nameprep does nothing yet. * * @package Requests\Utilities * * @link https://tools.ietf.org/html/rfc3490 IDNA specification * @link https://tools.ietf.org/html/rfc3492 Punycode/Bootstrap specification */ class IdnaEncoder { /** * ACE prefix used for IDNA * * @link https://tools.ietf.org/html/rfc3490#section-5 * @var string */ const ACE_PREFIX = 'xn--'; /** * Maximum length of a IDNA URL in ASCII. * * @see \WpOrg\Requests\IdnaEncoder::to_ascii() * * @since 2.0.0 * * @var int */ const MAX_LENGTH = 64; /**#@+ * Bootstrap constant for Punycode * * @link https://tools.ietf.org/html/rfc3492#section-5 * @var int */ const BOOTSTRAP_BASE = 36; const BOOTSTRAP_TMIN = 1; const BOOTSTRAP_TMAX = 26; const BOOTSTRAP_SKEW = 38; const BOOTSTRAP_DAMP = 700; const BOOTSTRAP_INITIAL_BIAS = 72; const BOOTSTRAP_INITIAL_N = 128; /**#@-*/ /** * Encode a hostname using Punycode * * @param string|Stringable $hostname Hostname * @return string Punycode-encoded hostname * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string or a stringable object. */ public static function encode($hostname) { if (InputValidator::is_string_or_stringable($hostname) === false) { throw InvalidArgument::create(1, '$hostname', 'string|Stringable', gettype($hostname)); } $parts = explode('.', $hostname); foreach ($parts as &$part) { $part = self::to_ascii($part); } return implode('.', $parts); } /** * Convert a UTF-8 text string to an ASCII string using Punycode * * @param string $text ASCII or UTF-8 string (max length 64 characters) * @return string ASCII string * * @throws \WpOrg\Requests\Exception Provided string longer than 64 ASCII characters (`idna.provided_too_long`) * @throws \WpOrg\Requests\Exception Prepared string longer than 64 ASCII characters (`idna.prepared_too_long`) * @throws \WpOrg\Requests\Exception Provided string already begins with xn-- (`idna.provided_is_prefixed`) * @throws \WpOrg\Requests\Exception Encoded string longer than 64 ASCII characters (`idna.encoded_too_long`) */ public static function to_ascii($text) { // Step 1: Check if the text is already ASCII if (self::is_ascii($text)) { // Skip to step 7 if (strlen($text) < self::MAX_LENGTH) { return $text; } throw new Exception('Provided string is too long', 'idna.provided_too_long', $text); } // Step 2: nameprep $text = self::nameprep($text); // Step 3: UseSTD3ASCIIRules is false, continue // Step 4: Check if it's ASCII now if (self::is_ascii($text)) { // Skip to step 7 /* * As the `nameprep()` method returns the original string, this code will never be reached until * that method is properly implemented. */ // @codeCoverageIgnoreStart if (strlen($text) < self::MAX_LENGTH) { return $text; } throw new Exception('Prepared string is too long', 'idna.prepared_too_long', $text); // @codeCoverageIgnoreEnd } // Step 5: Check ACE prefix if (strpos($text, self::ACE_PREFIX) === 0) { throw new Exception('Provided string begins with ACE prefix', 'idna.provided_is_prefixed', $text); } // Step 6: Encode with Punycode $text = self::punycode_encode($text); // Step 7: Prepend ACE prefix $text = self::ACE_PREFIX . $text; // Step 8: Check size if (strlen($text) < self::MAX_LENGTH) { return $text; } throw new Exception('Encoded string is too long', 'idna.encoded_too_long', $text); } /** * Check whether a given text string contains only ASCII characters * * @internal (Testing found regex was the fastest implementation) * * @param string $text Text to examine. * @return bool Is the text string ASCII-only? */ protected static function is_ascii($text) { return (preg_match('/(?:[^\x00-\x7F])/', $text) !== 1); } /** * Prepare a text string for use as an IDNA name * * @todo Implement this based on RFC 3491 and the newer 5891 * @param string $text Text to prepare. * @return string Prepared string */ protected static function nameprep($text) { return $text; } /** * Convert a UTF-8 string to a UCS-4 codepoint array * * Based on \WpOrg\Requests\Iri::replace_invalid_with_pct_encoding() * * @param string $input Text to convert. * @return array Unicode code points * * @throws \WpOrg\Requests\Exception Invalid UTF-8 codepoint (`idna.invalidcodepoint`) */ protected static function utf8_to_codepoints($input) { $codepoints = []; // Get number of bytes $strlen = strlen($input); // phpcs:ignore Generic.CodeAnalysis.JumbledIncrementer -- This is a deliberate choice. for ($position = 0; $position < $strlen; $position++) { $value = ord($input[$position]); if ((~$value & 0x80) === 0x80) { // One byte sequence: $character = $value; $length = 1; $remaining = 0; } elseif (($value & 0xE0) === 0xC0) { // Two byte sequence: $character = ($value & 0x1F) << 6; $length = 2; $remaining = 1; } elseif (($value & 0xF0) === 0xE0) { // Three byte sequence: $character = ($value & 0x0F) << 12; $length = 3; $remaining = 2; } elseif (($value & 0xF8) === 0xF0) { // Four byte sequence: $character = ($value & 0x07) << 18; $length = 4; $remaining = 3; } else { // Invalid byte: throw new Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $value); } if ($remaining > 0) { if ($position + $length > $strlen) { throw new Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character); } for ($position++; $remaining > 0; $position++) { $value = ord($input[$position]); // If it is invalid, count the sequence as invalid and reprocess the current byte: if (($value & 0xC0) !== 0x80) { throw new Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character); } --$remaining; $character |= ($value & 0x3F) << ($remaining * 6); } $position--; } if (// Non-shortest form sequences are invalid $length > 1 && $character <= 0x7F || $length > 2 && $character <= 0x7FF || $length > 3 && $character <= 0xFFFF // Outside of range of ucschar codepoints // Noncharacters || ($character & 0xFFFE) === 0xFFFE || $character >= 0xFDD0 && $character <= 0xFDEF || ( // Everything else not in ucschar $character > 0xD7FF && $character < 0xF900 || $character < 0x20 || $character > 0x7E && $character < 0xA0 || $character > 0xEFFFD ) ) { throw new Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character); } $codepoints[] = $character; } return $codepoints; } /** * RFC3492-compliant encoder * * @internal Pseudo-code from Section 6.3 is commented with "#" next to relevant code * * @param string $input UTF-8 encoded string to encode * @return string Punycode-encoded string * * @throws \WpOrg\Requests\Exception On character outside of the domain (never happens with Punycode) (`idna.character_outside_domain`) */ public static function punycode_encode($input) { $output = ''; // let n = initial_n $n = self::BOOTSTRAP_INITIAL_N; // let delta = 0 $delta = 0; // let bias = initial_bias $bias = self::BOOTSTRAP_INITIAL_BIAS; // let h = b = the number of basic code points in the input $h = 0; $b = 0; // see loop // copy them to the output in order $codepoints = self::utf8_to_codepoints($input); $extended = []; foreach ($codepoints as $char) { if ($char < 128) { // Character is valid ASCII // TODO: this should also check if it's valid for a URL $output .= chr($char); $h++; // Check if the character is non-ASCII, but below initial n // This never occurs for Punycode, so ignore in coverage // @codeCoverageIgnoreStart } elseif ($char < $n) { throw new Exception('Invalid character', 'idna.character_outside_domain', $char); // @codeCoverageIgnoreEnd } else { $extended[$char] = true; } } $extended = array_keys($extended); sort($extended); $b = $h; // [copy them] followed by a delimiter if b > 0 if (strlen($output) > 0) { $output .= '-'; } // {if the input contains a non-basic code point < n then fail} // while h < length(input) do begin $codepointcount = count($codepoints); while ($h < $codepointcount) { // let m = the minimum code point >= n in the input $m = array_shift($extended); //printf('next code point to insert is %s' . PHP_EOL, dechex($m)); // let delta = delta + (m - n) * (h + 1), fail on overflow $delta += ($m - $n) * ($h + 1); // let n = m $n = $m; // for each code point c in the input (in order) do begin for ($num = 0; $num < $codepointcount; $num++) { $c = $codepoints[$num]; // if c < n then increment delta, fail on overflow if ($c < $n) { $delta++; } elseif ($c === $n) { // if c == n then begin // let q = delta $q = $delta; // for k = base to infinity in steps of base do begin for ($k = self::BOOTSTRAP_BASE; ; $k += self::BOOTSTRAP_BASE) { // let t = tmin if k <= bias {+ tmin}, or // tmax if k >= bias + tmax, or k - bias otherwise if ($k <= ($bias + self::BOOTSTRAP_TMIN)) { $t = self::BOOTSTRAP_TMIN; } elseif ($k >= ($bias + self::BOOTSTRAP_TMAX)) { $t = self::BOOTSTRAP_TMAX; } else { $t = $k - $bias; } // if q < t then break if ($q < $t) { break; } // output the code point for digit t + ((q - t) mod (base - t)) $digit = (int) ($t + (($q - $t) % (self::BOOTSTRAP_BASE - $t))); $output .= self::digit_to_char($digit); // let q = (q - t) div (base - t) $q = (int) floor(($q - $t) / (self::BOOTSTRAP_BASE - $t)); } // end // output the code point for digit q $output .= self::digit_to_char($q); // let bias = adapt(delta, h + 1, test h equals b?) $bias = self::adapt($delta, $h + 1, $h === $b); // let delta = 0 $delta = 0; // increment h $h++; } // end } // end // increment delta and n $delta++; $n++; } // end return $output; } /** * Convert a digit to its respective character * * @link https://tools.ietf.org/html/rfc3492#section-5 * * @param int $digit Digit in the range 0-35 * @return string Single character corresponding to digit * * @throws \WpOrg\Requests\Exception On invalid digit (`idna.invalid_digit`) */ protected static function digit_to_char($digit) { // @codeCoverageIgnoreStart // As far as I know, this never happens, but still good to be sure. if ($digit < 0 || $digit > 35) { throw new Exception(sprintf('Invalid digit %d', $digit), 'idna.invalid_digit', $digit); } // @codeCoverageIgnoreEnd $digits = 'abcdefghijklmnopqrstuvwxyz0123456789'; return substr($digits, $digit, 1); } /** * Adapt the bias * * @link https://tools.ietf.org/html/rfc3492#section-6.1 * @param int $delta * @param int $numpoints * @param bool $firsttime * @return int|float New bias * * function adapt(delta,numpoints,firsttime): */ protected static function adapt($delta, $numpoints, $firsttime) { // if firsttime then let delta = delta div damp if ($firsttime) { $delta = floor($delta / self::BOOTSTRAP_DAMP); } else { // else let delta = delta div 2 $delta = floor($delta / 2); } // let delta = delta + (delta div numpoints) $delta += floor($delta / $numpoints); // let k = 0 $k = 0; // while delta > ((base - tmin) * tmax) div 2 do begin $max = floor(((self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN) * self::BOOTSTRAP_TMAX) / 2); while ($delta > $max) { // let delta = delta div (base - tmin) $delta = floor($delta / (self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN)); // let k = k + base $k += self::BOOTSTRAP_BASE; } // end // return k + (((base - tmin + 1) * delta) div (delta + skew)) return $k + floor(((self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN + 1) * $delta) / ($delta + self::BOOTSTRAP_SKEW)); } } PK������ֺZg^y��y����Proxy/Http.phpnu�W+A��������<?php /** * HTTP Proxy connection interface * * @package Requests\Proxy * @since 1.6 */ namespace WpOrg\Requests\Proxy; use WpOrg\Requests\Exception\ArgumentCount; use WpOrg\Requests\Exception\InvalidArgument; use WpOrg\Requests\Hooks; use WpOrg\Requests\Proxy; /** * HTTP Proxy connection interface * * Provides a handler for connection via an HTTP proxy * * @package Requests\Proxy * @since 1.6 */ final class Http implements Proxy { /** * Proxy host and port * * Notation: "host:port" (eg 127.0.0.1:8080 or someproxy.com:3128) * * @var string */ public $proxy; /** * Username * * @var string */ public $user; /** * Password * * @var string */ public $pass; /** * Do we need to authenticate? (ie username & password have been provided) * * @var boolean */ public $use_authentication; /** * Constructor * * @since 1.6 * * @param array|string|null $args Proxy as a string or an array of proxy, user and password. * When passed as an array, must have exactly one (proxy) * or three elements (proxy, user, password). * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not an array, a string or null. * @throws \WpOrg\Requests\Exception\ArgumentCount On incorrect number of arguments (`proxyhttpbadargs`) */ public function __construct($args = null) { if (is_string($args)) { $this->proxy = $args; } elseif (is_array($args)) { if (count($args) === 1) { list($this->proxy) = $args; } elseif (count($args) === 3) { list($this->proxy, $this->user, $this->pass) = $args; $this->use_authentication = true; } else { throw ArgumentCount::create( 'an array with exactly one element or exactly three elements', count($args), 'proxyhttpbadargs' ); } } elseif ($args !== null) { throw InvalidArgument::create(1, '$args', 'array|string|null', gettype($args)); } } /** * Register the necessary callbacks * * @since 1.6 * @see \WpOrg\Requests\Proxy\Http::curl_before_send() * @see \WpOrg\Requests\Proxy\Http::fsockopen_remote_socket() * @see \WpOrg\Requests\Proxy\Http::fsockopen_remote_host_path() * @see \WpOrg\Requests\Proxy\Http::fsockopen_header() * @param \WpOrg\Requests\Hooks $hooks Hook system */ public function register(Hooks $hooks) { $hooks->register('curl.before_send', [$this, 'curl_before_send']); $hooks->register('fsockopen.remote_socket', [$this, 'fsockopen_remote_socket']); $hooks->register('fsockopen.remote_host_path', [$this, 'fsockopen_remote_host_path']); if ($this->use_authentication) { $hooks->register('fsockopen.after_headers', [$this, 'fsockopen_header']); } } /** * Set cURL parameters before the data is sent * * @since 1.6 * @param resource|\CurlHandle $handle cURL handle */ public function curl_before_send(&$handle) { curl_setopt($handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); curl_setopt($handle, CURLOPT_PROXY, $this->proxy); if ($this->use_authentication) { curl_setopt($handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY); curl_setopt($handle, CURLOPT_PROXYUSERPWD, $this->get_auth_string()); } } /** * Alter remote socket information before opening socket connection * * @since 1.6 * @param string $remote_socket Socket connection string */ public function fsockopen_remote_socket(&$remote_socket) { $remote_socket = $this->proxy; } /** * Alter remote path before getting stream data * * @since 1.6 * @param string $path Path to send in HTTP request string ("GET ...") * @param string $url Full URL we're requesting */ public function fsockopen_remote_host_path(&$path, $url) { $path = $url; } /** * Add extra headers to the request before sending * * @since 1.6 * @param string $out HTTP header string */ public function fsockopen_header(&$out) { $out .= sprintf("Proxy-Authorization: Basic %s\r\n", base64_encode($this->get_auth_string())); } /** * Get the authentication string (user:pass) * * @since 1.6 * @return string */ public function get_auth_string() { return $this->user . ':' . $this->pass; } } PK������ֺZ^ �� ����Response/Headers.phpnu�W+A��������<?php /** * Case-insensitive dictionary, suitable for HTTP headers * * @package Requests */ namespace WpOrg\Requests\Response; use WpOrg\Requests\Exception; use WpOrg\Requests\Exception\InvalidArgument; use WpOrg\Requests\Utility\CaseInsensitiveDictionary; use WpOrg\Requests\Utility\FilteredIterator; /** * Case-insensitive dictionary, suitable for HTTP headers * * @package Requests */ class Headers extends CaseInsensitiveDictionary { /** * Get the given header * * Unlike {@see \WpOrg\Requests\Response\Headers::getValues()}, this returns a string. If there are * multiple values, it concatenates them with a comma as per RFC2616. * * Avoid using this where commas may be used unquoted in values, such as * Set-Cookie headers. * * @param string $offset Name of the header to retrieve. * @return string|null Header value */ public function offsetGet($offset) { if (is_string($offset)) { $offset = strtolower($offset); } if (!isset($this->data[$offset])) { return null; } return $this->flatten($this->data[$offset]); } /** * Set the given item * * @param string $offset Item name * @param string $value Item value * * @throws \WpOrg\Requests\Exception On attempting to use dictionary as list (`invalidset`) */ public function offsetSet($offset, $value) { if ($offset === null) { throw new Exception('Object is a dictionary, not a list', 'invalidset'); } if (is_string($offset)) { $offset = strtolower($offset); } if (!isset($this->data[$offset])) { $this->data[$offset] = []; } $this->data[$offset][] = $value; } /** * Get all values for a given header * * @param string $offset Name of the header to retrieve. * @return array|null Header values * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not valid as an array key. */ public function getValues($offset) { if (!is_string($offset) && !is_int($offset)) { throw InvalidArgument::create(1, '$offset', 'string|int', gettype($offset)); } if (is_string($offset)) { $offset = strtolower($offset); } if (!isset($this->data[$offset])) { return null; } return $this->data[$offset]; } /** * Flattens a value into a string * * Converts an array into a string by imploding values with a comma, as per * RFC2616's rules for folding headers. * * @param string|array $value Value to flatten * @return string Flattened value * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string or an array. */ public function flatten($value) { if (is_string($value)) { return $value; } if (is_array($value)) { return implode(',', $value); } throw InvalidArgument::create(1, '$value', 'string|array', gettype($value)); } /** * Get an iterator for the data * * Converts the internally stored values to a comma-separated string if there is more * than one value for a key. * * @return \ArrayIterator */ public function getIterator() { return new FilteredIterator($this->data, [$this, 'flatten']); } } PK������ֺZޣ@������Capability.phpnu�W+A��������<?php /** * Capability interface declaring the known capabilities. * * @package Requests\Utilities */ namespace WpOrg\Requests; /** * Capability interface declaring the known capabilities. * * This is used as the authoritative source for which capabilities can be queried. * * @package Requests\Utilities */ interface Capability { /** * Support for SSL. * * @var string */ const SSL = 'ssl'; /** * Collection of all capabilities supported in Requests. * * Note: this does not automatically mean that the capability will be supported for your chosen transport! * * @var string[] */ const ALL = [ self::SSL, ]; } PK������ֺZw ׺1��1����Ssl.phpnu�W+A��������<?php /** * SSL utilities for Requests * * @package Requests\Utilities */ namespace WpOrg\Requests; use WpOrg\Requests\Exception\InvalidArgument; use WpOrg\Requests\Utility\InputValidator; /** * SSL utilities for Requests * * Collection of utilities for working with and verifying SSL certificates. * * @package Requests\Utilities */ final class Ssl { /** * Verify the certificate against common name and subject alternative names * * Unfortunately, PHP doesn't check the certificate against the alternative * names, leading things like 'https://www.github.com/' to be invalid. * * @link https://tools.ietf.org/html/rfc2818#section-3.1 RFC2818, Section 3.1 * * @param string|Stringable $host Host name to verify against * @param array $cert Certificate data from openssl_x509_parse() * @return bool * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $host argument is not a string or a stringable object. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $cert argument is not an array or array accessible. */ public static function verify_certificate($host, $cert) { if (InputValidator::is_string_or_stringable($host) === false) { throw InvalidArgument::create(1, '$host', 'string|Stringable', gettype($host)); } if (InputValidator::has_array_access($cert) === false) { throw InvalidArgument::create(2, '$cert', 'array|ArrayAccess', gettype($cert)); } $has_dns_alt = false; // Check the subjectAltName if (!empty($cert['extensions']['subjectAltName'])) { $altnames = explode(',', $cert['extensions']['subjectAltName']); foreach ($altnames as $altname) { $altname = trim($altname); if (strpos($altname, 'DNS:') !== 0) { continue; } $has_dns_alt = true; // Strip the 'DNS:' prefix and trim whitespace $altname = trim(substr($altname, 4)); // Check for a match if (self::match_domain($host, $altname) === true) { return true; } } if ($has_dns_alt === true) { return false; } } // Fall back to checking the common name if we didn't get any dNSName // alt names, as per RFC2818 if (!empty($cert['subject']['CN'])) { // Check for a match return (self::match_domain($host, $cert['subject']['CN']) === true); } return false; } /** * Verify that a reference name is valid * * Verifies a dNSName for HTTPS usage, (almost) as per Firefox's rules: * - Wildcards can only occur in a name with more than 3 components * - Wildcards can only occur as the last character in the first * component * - Wildcards may be preceded by additional characters * * We modify these rules to be a bit stricter and only allow the wildcard * character to be the full first component; that is, with the exclusion of * the third rule. * * @param string|Stringable $reference Reference dNSName * @return boolean Is the name valid? * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string or a stringable object. */ public static function verify_reference_name($reference) { if (InputValidator::is_string_or_stringable($reference) === false) { throw InvalidArgument::create(1, '$reference', 'string|Stringable', gettype($reference)); } if ($reference === '') { return false; } if (preg_match('`\s`', $reference) > 0) { // Whitespace detected. This can never be a dNSName. return false; } $parts = explode('.', $reference); if ($parts !== array_filter($parts)) { // DNSName cannot contain two dots next to each other. return false; } // Check the first part of the name $first = array_shift($parts); if (strpos($first, '*') !== false) { // Check that the wildcard is the full part if ($first !== '*') { return false; } // Check that we have at least 3 components (including first) if (count($parts) < 2) { return false; } } // Check the remaining parts foreach ($parts as $part) { if (strpos($part, '*') !== false) { return false; } } // Nothing found, verified! return true; } /** * Match a hostname against a dNSName reference * * @param string|Stringable $host Requested host * @param string|Stringable $reference dNSName to match against * @return boolean Does the domain match? * @throws \WpOrg\Requests\Exception\InvalidArgument When either of the passed arguments is not a string or a stringable object. */ public static function match_domain($host, $reference) { if (InputValidator::is_string_or_stringable($host) === false) { throw InvalidArgument::create(1, '$host', 'string|Stringable', gettype($host)); } // Check if the reference is blocklisted first if (self::verify_reference_name($reference) !== true) { return false; } // Check for a direct match if ((string) $host === (string) $reference) { return true; } // Calculate the valid wildcard match if the host is not an IP address // Also validates that the host has 3 parts or more, as per Firefox's ruleset, // as a wildcard reference is only allowed with 3 parts or more, so the // comparison will never match if host doesn't contain 3 parts or more as well. if (ip2long($host) === false) { $parts = explode('.', $host); $parts[0] = '*'; $wildcard = implode('.', $parts); if ($wildcard === (string) $reference) { return true; } } return false; } } PK������ֺZYP>��>����Transport/Fsockopen.phpnu�W+A��������<?php /** * fsockopen HTTP transport * * @package Requests\Transport */ namespace WpOrg\Requests\Transport; use WpOrg\Requests\Capability; use WpOrg\Requests\Exception; use WpOrg\Requests\Exception\InvalidArgument; use WpOrg\Requests\Port; use WpOrg\Requests\Requests; use WpOrg\Requests\Ssl; use WpOrg\Requests\Transport; use WpOrg\Requests\Utility\CaseInsensitiveDictionary; use WpOrg\Requests\Utility\InputValidator; /** * fsockopen HTTP transport * * @package Requests\Transport */ final class Fsockopen implements Transport { /** * Second to microsecond conversion * * @var integer */ const SECOND_IN_MICROSECONDS = 1000000; /** * Raw HTTP data * * @var string */ public $headers = ''; /** * Stream metadata * * @var array Associative array of properties, see {@link https://www.php.net/stream_get_meta_data} */ public $info; /** * What's the maximum number of bytes we should keep? * * @var int|bool Byte count, or false if no limit. */ private $max_bytes = false; /** * Cache for received connection errors. * * @var string */ private $connect_error = ''; /** * Perform a request * * @param string|Stringable $url URL to request * @param array $headers Associative array of request headers * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD * @param array $options Request options, see {@see \WpOrg\Requests\Requests::response()} for documentation * @return string Raw HTTP result * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $url argument is not a string or Stringable. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $headers argument is not an array. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $data parameter is not an array or string. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. * @throws \WpOrg\Requests\Exception On failure to connect to socket (`fsockopenerror`) * @throws \WpOrg\Requests\Exception On socket timeout (`timeout`) */ public function request($url, $headers = [], $data = [], $options = []) { if (InputValidator::is_string_or_stringable($url) === false) { throw InvalidArgument::create(1, '$url', 'string|Stringable', gettype($url)); } if (is_array($headers) === false) { throw InvalidArgument::create(2, '$headers', 'array', gettype($headers)); } if (!is_array($data) && !is_string($data)) { if ($data === null) { $data = ''; } else { throw InvalidArgument::create(3, '$data', 'array|string', gettype($data)); } } if (is_array($options) === false) { throw InvalidArgument::create(4, '$options', 'array', gettype($options)); } $options['hooks']->dispatch('fsockopen.before_request'); $url_parts = parse_url($url); if (empty($url_parts)) { throw new Exception('Invalid URL.', 'invalidurl', $url); } $host = $url_parts['host']; $context = stream_context_create(); $verifyname = false; $case_insensitive_headers = new CaseInsensitiveDictionary($headers); // HTTPS support if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https') { $remote_socket = 'ssl://' . $host; if (!isset($url_parts['port'])) { $url_parts['port'] = Port::HTTPS; } $context_options = [ 'verify_peer' => true, 'capture_peer_cert' => true, ]; $verifyname = true; // SNI, if enabled (OpenSSL >=0.9.8j) // phpcs:ignore PHPCompatibility.Constants.NewConstants.openssl_tlsext_server_nameFound if (defined('OPENSSL_TLSEXT_SERVER_NAME') && OPENSSL_TLSEXT_SERVER_NAME) { $context_options['SNI_enabled'] = true; if (isset($options['verifyname']) && $options['verifyname'] === false) { $context_options['SNI_enabled'] = false; } } if (isset($options['verify'])) { if ($options['verify'] === false) { $context_options['verify_peer'] = false; $context_options['verify_peer_name'] = false; $verifyname = false; } elseif (is_string($options['verify'])) { $context_options['cafile'] = $options['verify']; } } if (isset($options['verifyname']) && $options['verifyname'] === false) { $context_options['verify_peer_name'] = false; $verifyname = false; } // Handle the PHP 8.4 deprecation (PHP 9.0 removal) of the function signature we use for stream_context_set_option(). // Ref: https://wiki.php.net/rfc/deprecate_functions_with_overloaded_signatures#stream_context_set_option if (function_exists('stream_context_set_options')) { // PHP 8.3+. stream_context_set_options($context, ['ssl' => $context_options]); } else { // PHP < 8.3. stream_context_set_option($context, ['ssl' => $context_options]); } } else { $remote_socket = 'tcp://' . $host; } $this->max_bytes = $options['max_bytes']; if (!isset($url_parts['port'])) { $url_parts['port'] = Port::HTTP; } $remote_socket .= ':' . $url_parts['port']; // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_set_error_handler set_error_handler([$this, 'connect_error_handler'], E_WARNING | E_NOTICE); $options['hooks']->dispatch('fsockopen.remote_socket', [&$remote_socket]); $socket = stream_socket_client($remote_socket, $errno, $errstr, ceil($options['connect_timeout']), STREAM_CLIENT_CONNECT, $context); restore_error_handler(); if ($verifyname && !$this->verify_certificate_from_context($host, $context)) { throw new Exception('SSL certificate did not match the requested domain name', 'ssl.no_match'); } if (!$socket) { if ($errno === 0) { // Connection issue throw new Exception(rtrim($this->connect_error), 'fsockopen.connect_error'); } throw new Exception($errstr, 'fsockopenerror', null, $errno); } $data_format = $options['data_format']; if ($data_format === 'query') { $path = self::format_get($url_parts, $data); $data = ''; } else { $path = self::format_get($url_parts, []); } $options['hooks']->dispatch('fsockopen.remote_host_path', [&$path, $url]); $request_body = ''; $out = sprintf("%s %s HTTP/%.1F\r\n", $options['type'], $path, $options['protocol_version']); if ($options['type'] !== Requests::TRACE) { if (is_array($data)) { $request_body = http_build_query($data, '', '&'); } else { $request_body = $data; } // Always include Content-length on POST requests to prevent // 411 errors from some servers when the body is empty. if (!empty($data) || $options['type'] === Requests::POST) { if (!isset($case_insensitive_headers['Content-Length'])) { $headers['Content-Length'] = strlen($request_body); } if (!isset($case_insensitive_headers['Content-Type'])) { $headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'; } } } if (!isset($case_insensitive_headers['Host'])) { $out .= sprintf('Host: %s', $url_parts['host']); $scheme_lower = strtolower($url_parts['scheme']); if (($scheme_lower === 'http' && $url_parts['port'] !== Port::HTTP) || ($scheme_lower === 'https' && $url_parts['port'] !== Port::HTTPS)) { $out .= ':' . $url_parts['port']; } $out .= "\r\n"; } if (!isset($case_insensitive_headers['User-Agent'])) { $out .= sprintf("User-Agent: %s\r\n", $options['useragent']); } $accept_encoding = $this->accept_encoding(); if (!isset($case_insensitive_headers['Accept-Encoding']) && !empty($accept_encoding)) { $out .= sprintf("Accept-Encoding: %s\r\n", $accept_encoding); } $headers = Requests::flatten($headers); if (!empty($headers)) { $out .= implode("\r\n", $headers) . "\r\n"; } $options['hooks']->dispatch('fsockopen.after_headers', [&$out]); if (substr($out, -2) !== "\r\n") { $out .= "\r\n"; } if (!isset($case_insensitive_headers['Connection'])) { $out .= "Connection: Close\r\n"; } $out .= "\r\n" . $request_body; $options['hooks']->dispatch('fsockopen.before_send', [&$out]); fwrite($socket, $out); $options['hooks']->dispatch('fsockopen.after_send', [$out]); if (!$options['blocking']) { fclose($socket); $fake_headers = ''; $options['hooks']->dispatch('fsockopen.after_request', [&$fake_headers]); return ''; } $timeout_sec = (int) floor($options['timeout']); if ($timeout_sec === $options['timeout']) { $timeout_msec = 0; } else { $timeout_msec = self::SECOND_IN_MICROSECONDS * $options['timeout'] % self::SECOND_IN_MICROSECONDS; } stream_set_timeout($socket, $timeout_sec, $timeout_msec); $response = ''; $body = ''; $headers = ''; $this->info = stream_get_meta_data($socket); $size = 0; $doingbody = false; $download = false; if ($options['filename']) { // phpcs:ignore WordPress.PHP.NoSilencedErrors -- Silenced the PHP native warning in favour of throwing an exception. $download = @fopen($options['filename'], 'wb'); if ($download === false) { $error = error_get_last(); throw new Exception($error['message'], 'fopen'); } } while (!feof($socket)) { $this->info = stream_get_meta_data($socket); if ($this->info['timed_out']) { throw new Exception('fsocket timed out', 'timeout'); } $block = fread($socket, Requests::BUFFER_SIZE); if (!$doingbody) { $response .= $block; if (strpos($response, "\r\n\r\n")) { list($headers, $block) = explode("\r\n\r\n", $response, 2); $doingbody = true; } } // Are we in body mode now? if ($doingbody) { $options['hooks']->dispatch('request.progress', [$block, $size, $this->max_bytes]); $data_length = strlen($block); if ($this->max_bytes) { // Have we already hit a limit? if ($size === $this->max_bytes) { continue; } if (($size + $data_length) > $this->max_bytes) { // Limit the length $limited_length = ($this->max_bytes - $size); $block = substr($block, 0, $limited_length); } } $size += strlen($block); if ($download) { fwrite($download, $block); } else { $body .= $block; } } } $this->headers = $headers; if ($download) { fclose($download); } else { $this->headers .= "\r\n\r\n" . $body; } fclose($socket); $options['hooks']->dispatch('fsockopen.after_request', [&$this->headers, &$this->info]); return $this->headers; } /** * Send multiple requests simultaneously * * @param array $requests Request data (array of 'url', 'headers', 'data', 'options') as per {@see \WpOrg\Requests\Transport::request()} * @param array $options Global options, see {@see \WpOrg\Requests\Requests::response()} for documentation * @return array Array of \WpOrg\Requests\Response objects (may contain \WpOrg\Requests\Exception or string responses as well) * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $requests argument is not an array or iterable object with array access. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. */ public function request_multiple($requests, $options) { // If you're not requesting, we can't get any responses ¯\_(ツ)_/¯ if (empty($requests)) { return []; } if (InputValidator::has_array_access($requests) === false || InputValidator::is_iterable($requests) === false) { throw InvalidArgument::create(1, '$requests', 'array|ArrayAccess&Traversable', gettype($requests)); } if (is_array($options) === false) { throw InvalidArgument::create(2, '$options', 'array', gettype($options)); } $responses = []; $class = get_class($this); foreach ($requests as $id => $request) { try { $handler = new $class(); $responses[$id] = $handler->request($request['url'], $request['headers'], $request['data'], $request['options']); $request['options']['hooks']->dispatch('transport.internal.parse_response', [&$responses[$id], $request]); } catch (Exception $e) { $responses[$id] = $e; } if (!is_string($responses[$id])) { $request['options']['hooks']->dispatch('multiple.request.complete', [&$responses[$id], $id]); } } return $responses; } /** * Retrieve the encodings we can accept * * @return string Accept-Encoding header value */ private static function accept_encoding() { $type = []; if (function_exists('gzinflate')) { $type[] = 'deflate;q=1.0'; } if (function_exists('gzuncompress')) { $type[] = 'compress;q=0.5'; } $type[] = 'gzip;q=0.5'; return implode(', ', $type); } /** * Format a URL given GET data * * @param array $url_parts Array of URL parts as received from {@link https://www.php.net/parse_url} * @param array|object $data Data to build query using, see {@link https://www.php.net/http_build_query} * @return string URL with data */ private static function format_get($url_parts, $data) { if (!empty($data)) { if (empty($url_parts['query'])) { $url_parts['query'] = ''; } $url_parts['query'] .= '&' . http_build_query($data, '', '&'); $url_parts['query'] = trim($url_parts['query'], '&'); } if (isset($url_parts['path'])) { if (isset($url_parts['query'])) { $get = $url_parts['path'] . '?' . $url_parts['query']; } else { $get = $url_parts['path']; } } else { $get = '/'; } return $get; } /** * Error handler for stream_socket_client() * * @param int $errno Error number (e.g. E_WARNING) * @param string $errstr Error message */ public function connect_error_handler($errno, $errstr) { // Double-check we can handle it if (($errno & E_WARNING) === 0 && ($errno & E_NOTICE) === 0) { // Return false to indicate the default error handler should engage return false; } $this->connect_error .= $errstr . "\n"; return true; } /** * Verify the certificate against common name and subject alternative names * * Unfortunately, PHP doesn't check the certificate against the alternative * names, leading things like 'https://www.github.com/' to be invalid. * Instead * * @link https://tools.ietf.org/html/rfc2818#section-3.1 RFC2818, Section 3.1 * * @param string $host Host name to verify against * @param resource $context Stream context * @return bool * * @throws \WpOrg\Requests\Exception On failure to connect via TLS (`fsockopen.ssl.connect_error`) * @throws \WpOrg\Requests\Exception On not obtaining a match for the host (`fsockopen.ssl.no_match`) */ public function verify_certificate_from_context($host, $context) { $meta = stream_context_get_options($context); // If we don't have SSL options, then we couldn't make the connection at // all if (empty($meta) || empty($meta['ssl']) || empty($meta['ssl']['peer_certificate'])) { throw new Exception(rtrim($this->connect_error), 'ssl.connect_error'); } $cert = openssl_x509_parse($meta['ssl']['peer_certificate']); return Ssl::verify_certificate($host, $cert); } /** * Self-test whether the transport can be used. * * The available capabilities to test for can be found in {@see \WpOrg\Requests\Capability}. * * @codeCoverageIgnore * @param array<string, bool> $capabilities Optional. Associative array of capabilities to test against, i.e. `['<capability>' => true]`. * @return bool Whether the transport can be used. */ public static function test($capabilities = []) { if (!function_exists('fsockopen')) { return false; } // If needed, check that streams support SSL if (isset($capabilities[Capability::SSL]) && $capabilities[Capability::SSL]) { if (!extension_loaded('openssl') || !function_exists('openssl_x509_parse')) { return false; } } return true; } } PK������ֺZj;sL��sL����Transport/Curl.phpnu�W+A��������<?php /** * cURL HTTP transport * * @package Requests\Transport */ namespace WpOrg\Requests\Transport; use RecursiveArrayIterator; use RecursiveIteratorIterator; use WpOrg\Requests\Capability; use WpOrg\Requests\Exception; use WpOrg\Requests\Exception\InvalidArgument; use WpOrg\Requests\Exception\Transport\Curl as CurlException; use WpOrg\Requests\Requests; use WpOrg\Requests\Transport; use WpOrg\Requests\Utility\InputValidator; /** * cURL HTTP transport * * @package Requests\Transport */ final class Curl implements Transport { const CURL_7_10_5 = 0x070A05; const CURL_7_16_2 = 0x071002; /** * Raw HTTP data * * @var string */ public $headers = ''; /** * Raw body data * * @var string */ public $response_data = ''; /** * Information on the current request * * @var array cURL information array, see {@link https://www.php.net/curl_getinfo} */ public $info; /** * cURL version number * * @var int */ public $version; /** * cURL handle * * @var resource|\CurlHandle Resource in PHP < 8.0, Instance of CurlHandle in PHP >= 8.0. */ private $handle; /** * Hook dispatcher instance * * @var \WpOrg\Requests\Hooks */ private $hooks; /** * Have we finished the headers yet? * * @var boolean */ private $done_headers = false; /** * If streaming to a file, keep the file pointer * * @var resource */ private $stream_handle; /** * How many bytes are in the response body? * * @var int */ private $response_bytes; /** * What's the maximum number of bytes we should keep? * * @var int|bool Byte count, or false if no limit. */ private $response_byte_limit; /** * Constructor */ public function __construct() { $curl = curl_version(); $this->version = $curl['version_number']; $this->handle = curl_init(); curl_setopt($this->handle, CURLOPT_HEADER, false); curl_setopt($this->handle, CURLOPT_RETURNTRANSFER, 1); if ($this->version >= self::CURL_7_10_5) { curl_setopt($this->handle, CURLOPT_ENCODING, ''); } if (defined('CURLOPT_PROTOCOLS')) { // phpcs:ignore PHPCompatibility.Constants.NewConstants.curlopt_protocolsFound curl_setopt($this->handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); } if (defined('CURLOPT_REDIR_PROTOCOLS')) { // phpcs:ignore PHPCompatibility.Constants.NewConstants.curlopt_redir_protocolsFound curl_setopt($this->handle, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); } } /** * Destructor */ public function __destruct() { if (is_resource($this->handle)) { curl_close($this->handle); } } /** * Perform a request * * @param string|Stringable $url URL to request * @param array $headers Associative array of request headers * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD * @param array $options Request options, see {@see \WpOrg\Requests\Requests::response()} for documentation * @return string Raw HTTP result * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $url argument is not a string or Stringable. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $headers argument is not an array. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $data parameter is not an array or string. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. * @throws \WpOrg\Requests\Exception On a cURL error (`curlerror`) */ public function request($url, $headers = [], $data = [], $options = []) { if (InputValidator::is_string_or_stringable($url) === false) { throw InvalidArgument::create(1, '$url', 'string|Stringable', gettype($url)); } if (is_array($headers) === false) { throw InvalidArgument::create(2, '$headers', 'array', gettype($headers)); } if (!is_array($data) && !is_string($data)) { if ($data === null) { $data = ''; } else { throw InvalidArgument::create(3, '$data', 'array|string', gettype($data)); } } if (is_array($options) === false) { throw InvalidArgument::create(4, '$options', 'array', gettype($options)); } $this->hooks = $options['hooks']; $this->setup_handle($url, $headers, $data, $options); $options['hooks']->dispatch('curl.before_send', [&$this->handle]); if ($options['filename'] !== false) { // phpcs:ignore WordPress.PHP.NoSilencedErrors -- Silenced the PHP native warning in favour of throwing an exception. $this->stream_handle = @fopen($options['filename'], 'wb'); if ($this->stream_handle === false) { $error = error_get_last(); throw new Exception($error['message'], 'fopen'); } } $this->response_data = ''; $this->response_bytes = 0; $this->response_byte_limit = false; if ($options['max_bytes'] !== false) { $this->response_byte_limit = $options['max_bytes']; } if (isset($options['verify'])) { if ($options['verify'] === false) { curl_setopt($this->handle, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($this->handle, CURLOPT_SSL_VERIFYPEER, 0); } elseif (is_string($options['verify'])) { curl_setopt($this->handle, CURLOPT_CAINFO, $options['verify']); } } if (isset($options['verifyname']) && $options['verifyname'] === false) { curl_setopt($this->handle, CURLOPT_SSL_VERIFYHOST, 0); } curl_exec($this->handle); $response = $this->response_data; $options['hooks']->dispatch('curl.after_send', []); if (curl_errno($this->handle) === CURLE_WRITE_ERROR || curl_errno($this->handle) === CURLE_BAD_CONTENT_ENCODING) { // Reset encoding and try again curl_setopt($this->handle, CURLOPT_ENCODING, 'none'); $this->response_data = ''; $this->response_bytes = 0; curl_exec($this->handle); $response = $this->response_data; } $this->process_response($response, $options); // Need to remove the $this reference from the curl handle. // Otherwise \WpOrg\Requests\Transport\Curl won't be garbage collected and the curl_close() will never be called. curl_setopt($this->handle, CURLOPT_HEADERFUNCTION, null); curl_setopt($this->handle, CURLOPT_WRITEFUNCTION, null); return $this->headers; } /** * Send multiple requests simultaneously * * @param array $requests Request data * @param array $options Global options * @return array Array of \WpOrg\Requests\Response objects (may contain \WpOrg\Requests\Exception or string responses as well) * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $requests argument is not an array or iterable object with array access. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. */ public function request_multiple($requests, $options) { // If you're not requesting, we can't get any responses ¯\_(ツ)_/¯ if (empty($requests)) { return []; } if (InputValidator::has_array_access($requests) === false || InputValidator::is_iterable($requests) === false) { throw InvalidArgument::create(1, '$requests', 'array|ArrayAccess&Traversable', gettype($requests)); } if (is_array($options) === false) { throw InvalidArgument::create(2, '$options', 'array', gettype($options)); } $multihandle = curl_multi_init(); $subrequests = []; $subhandles = []; $class = get_class($this); foreach ($requests as $id => $request) { $subrequests[$id] = new $class(); $subhandles[$id] = $subrequests[$id]->get_subrequest_handle($request['url'], $request['headers'], $request['data'], $request['options']); $request['options']['hooks']->dispatch('curl.before_multi_add', [&$subhandles[$id]]); curl_multi_add_handle($multihandle, $subhandles[$id]); } $completed = 0; $responses = []; $subrequestcount = count($subrequests); $request['options']['hooks']->dispatch('curl.before_multi_exec', [&$multihandle]); do { $active = 0; do { $status = curl_multi_exec($multihandle, $active); } while ($status === CURLM_CALL_MULTI_PERFORM); $to_process = []; // Read the information as needed while ($done = curl_multi_info_read($multihandle)) { $key = array_search($done['handle'], $subhandles, true); if (!isset($to_process[$key])) { $to_process[$key] = $done; } } // Parse the finished requests before we start getting the new ones foreach ($to_process as $key => $done) { $options = $requests[$key]['options']; if ($done['result'] !== CURLE_OK) { //get error string for handle. $reason = curl_error($done['handle']); $exception = new CurlException( $reason, CurlException::EASY, $done['handle'], $done['result'] ); $responses[$key] = $exception; $options['hooks']->dispatch('transport.internal.parse_error', [&$responses[$key], $requests[$key]]); } else { $responses[$key] = $subrequests[$key]->process_response($subrequests[$key]->response_data, $options); $options['hooks']->dispatch('transport.internal.parse_response', [&$responses[$key], $requests[$key]]); } curl_multi_remove_handle($multihandle, $done['handle']); curl_close($done['handle']); if (!is_string($responses[$key])) { $options['hooks']->dispatch('multiple.request.complete', [&$responses[$key], $key]); } $completed++; } } while ($active || $completed < $subrequestcount); $request['options']['hooks']->dispatch('curl.after_multi_exec', [&$multihandle]); curl_multi_close($multihandle); return $responses; } /** * Get the cURL handle for use in a multi-request * * @param string $url URL to request * @param array $headers Associative array of request headers * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD * @param array $options Request options, see {@see \WpOrg\Requests\Requests::response()} for documentation * @return resource|\CurlHandle Subrequest's cURL handle */ public function &get_subrequest_handle($url, $headers, $data, $options) { $this->setup_handle($url, $headers, $data, $options); if ($options['filename'] !== false) { $this->stream_handle = fopen($options['filename'], 'wb'); } $this->response_data = ''; $this->response_bytes = 0; $this->response_byte_limit = false; if ($options['max_bytes'] !== false) { $this->response_byte_limit = $options['max_bytes']; } $this->hooks = $options['hooks']; return $this->handle; } /** * Setup the cURL handle for the given data * * @param string $url URL to request * @param array $headers Associative array of request headers * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD * @param array $options Request options, see {@see \WpOrg\Requests\Requests::response()} for documentation */ private function setup_handle($url, $headers, $data, $options) { $options['hooks']->dispatch('curl.before_request', [&$this->handle]); // Force closing the connection for old versions of cURL (<7.22). if (!isset($headers['Connection'])) { $headers['Connection'] = 'close'; } /** * Add "Expect" header. * * By default, cURL adds a "Expect: 100-Continue" to most requests. This header can * add as much as a second to the time it takes for cURL to perform a request. To * prevent this, we need to set an empty "Expect" header. To match the behaviour of * Guzzle, we'll add the empty header to requests that are smaller than 1 MB and use * HTTP/1.1. * * https://curl.se/mail/lib-2017-07/0013.html */ if (!isset($headers['Expect']) && $options['protocol_version'] === 1.1) { $headers['Expect'] = $this->get_expect_header($data); } $headers = Requests::flatten($headers); if (!empty($data)) { $data_format = $options['data_format']; if ($data_format === 'query') { $url = self::format_get($url, $data); $data = ''; } elseif (!is_string($data)) { $data = http_build_query($data, '', '&'); } } switch ($options['type']) { case Requests::POST: curl_setopt($this->handle, CURLOPT_POST, true); curl_setopt($this->handle, CURLOPT_POSTFIELDS, $data); break; case Requests::HEAD: curl_setopt($this->handle, CURLOPT_CUSTOMREQUEST, $options['type']); curl_setopt($this->handle, CURLOPT_NOBODY, true); break; case Requests::TRACE: curl_setopt($this->handle, CURLOPT_CUSTOMREQUEST, $options['type']); break; case Requests::PATCH: case Requests::PUT: case Requests::DELETE: case Requests::OPTIONS: default: curl_setopt($this->handle, CURLOPT_CUSTOMREQUEST, $options['type']); if (!empty($data)) { curl_setopt($this->handle, CURLOPT_POSTFIELDS, $data); } } // cURL requires a minimum timeout of 1 second when using the system // DNS resolver, as it uses `alarm()`, which is second resolution only. // There's no way to detect which DNS resolver is being used from our // end, so we need to round up regardless of the supplied timeout. // // https://github.com/curl/curl/blob/4f45240bc84a9aa648c8f7243be7b79e9f9323a5/lib/hostip.c#L606-L609 $timeout = max($options['timeout'], 1); if (is_int($timeout) || $this->version < self::CURL_7_16_2) { curl_setopt($this->handle, CURLOPT_TIMEOUT, ceil($timeout)); } else { // phpcs:ignore PHPCompatibility.Constants.NewConstants.curlopt_timeout_msFound curl_setopt($this->handle, CURLOPT_TIMEOUT_MS, round($timeout * 1000)); } if (is_int($options['connect_timeout']) || $this->version < self::CURL_7_16_2) { curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT, ceil($options['connect_timeout'])); } else { // phpcs:ignore PHPCompatibility.Constants.NewConstants.curlopt_connecttimeout_msFound curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT_MS, round($options['connect_timeout'] * 1000)); } curl_setopt($this->handle, CURLOPT_URL, $url); curl_setopt($this->handle, CURLOPT_USERAGENT, $options['useragent']); if (!empty($headers)) { curl_setopt($this->handle, CURLOPT_HTTPHEADER, $headers); } if ($options['protocol_version'] === 1.1) { curl_setopt($this->handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); } else { curl_setopt($this->handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); } if ($options['blocking'] === true) { curl_setopt($this->handle, CURLOPT_HEADERFUNCTION, [$this, 'stream_headers']); curl_setopt($this->handle, CURLOPT_WRITEFUNCTION, [$this, 'stream_body']); curl_setopt($this->handle, CURLOPT_BUFFERSIZE, Requests::BUFFER_SIZE); } } /** * Process a response * * @param string $response Response data from the body * @param array $options Request options * @return string|false HTTP response data including headers. False if non-blocking. * @throws \WpOrg\Requests\Exception If the request resulted in a cURL error. */ public function process_response($response, $options) { if ($options['blocking'] === false) { $fake_headers = ''; $options['hooks']->dispatch('curl.after_request', [&$fake_headers]); return false; } if ($options['filename'] !== false && $this->stream_handle) { fclose($this->stream_handle); $this->headers = trim($this->headers); } else { $this->headers .= $response; } if (curl_errno($this->handle)) { $error = sprintf( 'cURL error %s: %s', curl_errno($this->handle), curl_error($this->handle) ); throw new Exception($error, 'curlerror', $this->handle); } $this->info = curl_getinfo($this->handle); $options['hooks']->dispatch('curl.after_request', [&$this->headers, &$this->info]); return $this->headers; } /** * Collect the headers as they are received * * @param resource|\CurlHandle $handle cURL handle * @param string $headers Header string * @return integer Length of provided header */ public function stream_headers($handle, $headers) { // Why do we do this? cURL will send both the final response and any // interim responses, such as a 100 Continue. We don't need that. // (We may want to keep this somewhere just in case) if ($this->done_headers) { $this->headers = ''; $this->done_headers = false; } $this->headers .= $headers; if ($headers === "\r\n") { $this->done_headers = true; } return strlen($headers); } /** * Collect data as it's received * * @since 1.6.1 * * @param resource|\CurlHandle $handle cURL handle * @param string $data Body data * @return integer Length of provided data */ public function stream_body($handle, $data) { $this->hooks->dispatch('request.progress', [$data, $this->response_bytes, $this->response_byte_limit]); $data_length = strlen($data); // Are we limiting the response size? if ($this->response_byte_limit) { if ($this->response_bytes === $this->response_byte_limit) { // Already at maximum, move on return $data_length; } if (($this->response_bytes + $data_length) > $this->response_byte_limit) { // Limit the length $limited_length = ($this->response_byte_limit - $this->response_bytes); $data = substr($data, 0, $limited_length); } } if ($this->stream_handle) { fwrite($this->stream_handle, $data); } else { $this->response_data .= $data; } $this->response_bytes += strlen($data); return $data_length; } /** * Format a URL given GET data * * @param string $url Original URL. * @param array|object $data Data to build query using, see {@link https://www.php.net/http_build_query} * @return string URL with data */ private static function format_get($url, $data) { if (!empty($data)) { $query = ''; $url_parts = parse_url($url); if (empty($url_parts['query'])) { $url_parts['query'] = ''; } else { $query = $url_parts['query']; } $query .= '&' . http_build_query($data, '', '&'); $query = trim($query, '&'); if (empty($url_parts['query'])) { $url .= '?' . $query; } else { $url = str_replace($url_parts['query'], $query, $url); } } return $url; } /** * Self-test whether the transport can be used. * * The available capabilities to test for can be found in {@see \WpOrg\Requests\Capability}. * * @codeCoverageIgnore * @param array<string, bool> $capabilities Optional. Associative array of capabilities to test against, i.e. `['<capability>' => true]`. * @return bool Whether the transport can be used. */ public static function test($capabilities = []) { if (!function_exists('curl_init') || !function_exists('curl_exec')) { return false; } // If needed, check that our installed curl version supports SSL if (isset($capabilities[Capability::SSL]) && $capabilities[Capability::SSL]) { $curl_version = curl_version(); if (!(CURL_VERSION_SSL & $curl_version['features'])) { return false; } } return true; } /** * Get the correct "Expect" header for the given request data. * * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD. * @return string The "Expect" header. */ private function get_expect_header($data) { if (!is_array($data)) { return strlen((string) $data) >= 1048576 ? '100-Continue' : ''; } $bytesize = 0; $iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($data)); foreach ($iterator as $datum) { $bytesize += strlen((string) $datum); if ($bytesize >= 1048576) { return '100-Continue'; } } return ''; } } PK�������Z+o��o����AbstractLexer.phpnu�W+A��������<?php declare(strict_types=1); namespace Doctrine\Common\Lexer; use ReflectionClass; use UnitEnum; use function implode; use function preg_split; use function sprintf; use function substr; use const PREG_SPLIT_DELIM_CAPTURE; use const PREG_SPLIT_NO_EMPTY; use const PREG_SPLIT_OFFSET_CAPTURE; /** * Base class for writing simple lexers, i.e. for creating small DSLs. * * @template T of UnitEnum|string|int * @template V of string|int */ abstract class AbstractLexer { /** * Lexer original input string. */ private string $input; /** * Array of scanned tokens. * * @var list<Token<T, V>> */ private array $tokens = []; /** * Current lexer position in input string. */ private int $position = 0; /** * Current peek of current lexer position. */ private int $peek = 0; /** * The next token in the input. * * @var mixed[]|null * @psalm-var Token<T, V>|null */ public Token|null $lookahead; /** * The last matched/seen token. * * @var mixed[]|null * @psalm-var Token<T, V>|null */ public Token|null $token; /** * Composed regex for input parsing. */ private string|null $regex = null; /** * Sets the input data to be tokenized. * * The Lexer is immediately reset and the new input tokenized. * Any unprocessed tokens from any previous input are lost. * * @param string $input The input to be tokenized. * * @return void */ public function setInput(string $input) { $this->input = $input; $this->tokens = []; $this->reset(); $this->scan($input); } /** * Resets the lexer. * * @return void */ public function reset() { $this->lookahead = null; $this->token = null; $this->peek = 0; $this->position = 0; } /** * Resets the peek pointer to 0. * * @return void */ public function resetPeek() { $this->peek = 0; } /** * Resets the lexer position on the input to the given position. * * @param int $position Position to place the lexical scanner. * * @return void */ public function resetPosition(int $position = 0) { $this->position = $position; } /** * Retrieve the original lexer's input until a given position. * * @return string */ public function getInputUntilPosition(int $position) { return substr($this->input, 0, $position); } /** * Checks whether a given token matches the current lookahead. * * @param T $type * * @return bool * * @psalm-assert-if-true !=null $this->lookahead */ public function isNextToken(int|string|UnitEnum $type) { return $this->lookahead !== null && $this->lookahead->isA($type); } /** * Checks whether any of the given tokens matches the current lookahead. * * @param list<T> $types * * @return bool * * @psalm-assert-if-true !=null $this->lookahead */ public function isNextTokenAny(array $types) { return $this->lookahead !== null && $this->lookahead->isA(...$types); } /** * Moves to the next token in the input string. * * @return bool * * @psalm-assert-if-true !null $this->lookahead */ public function moveNext() { $this->peek = 0; $this->token = $this->lookahead; $this->lookahead = isset($this->tokens[$this->position]) ? $this->tokens[$this->position++] : null; return $this->lookahead !== null; } /** * Tells the lexer to skip input tokens until it sees a token with the given value. * * @param T $type The token type to skip until. * * @return void */ public function skipUntil(int|string|UnitEnum $type) { while ($this->lookahead !== null && ! $this->lookahead->isA($type)) { $this->moveNext(); } } /** * Checks if given value is identical to the given token. * * @return bool */ public function isA(string $value, int|string|UnitEnum $token) { return $this->getType($value) === $token; } /** * Moves the lookahead token forward. * * @return mixed[]|null The next token or NULL if there are no more tokens ahead. * @psalm-return Token<T, V>|null */ public function peek() { if (isset($this->tokens[$this->position + $this->peek])) { return $this->tokens[$this->position + $this->peek++]; } return null; } /** * Peeks at the next token, returns it and immediately resets the peek. * * @return mixed[]|null The next token or NULL if there are no more tokens ahead. * @psalm-return Token<T, V>|null */ public function glimpse() { $peek = $this->peek(); $this->peek = 0; return $peek; } /** * Scans the input string for tokens. * * @param string $input A query string. * * @return void */ protected function scan(string $input) { if (! isset($this->regex)) { $this->regex = sprintf( '/(%s)|%s/%s', implode(')|(', $this->getCatchablePatterns()), implode('|', $this->getNonCatchablePatterns()), $this->getModifiers(), ); } $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE; $matches = preg_split($this->regex, $input, -1, $flags); if ($matches === false) { // Work around https://bugs.php.net/78122 $matches = [[$input, 0]]; } foreach ($matches as $match) { // Must remain before 'value' assignment since it can change content $firstMatch = $match[0]; $type = $this->getType($firstMatch); $this->tokens[] = new Token( $firstMatch, $type, $match[1], ); } } /** * Gets the literal for a given token. * * @param T $token * * @return int|string */ public function getLiteral(int|string|UnitEnum $token) { if ($token instanceof UnitEnum) { return $token::class . '::' . $token->name; } $className = static::class; $reflClass = new ReflectionClass($className); $constants = $reflClass->getConstants(); foreach ($constants as $name => $value) { if ($value === $token) { return $className . '::' . $name; } } return $token; } /** * Regex modifiers * * @return string */ protected function getModifiers() { return 'iu'; } /** * Lexical catchable patterns. * * @return string[] */ abstract protected function getCatchablePatterns(); /** * Lexical non-catchable patterns. * * @return string[] */ abstract protected function getNonCatchablePatterns(); /** * Retrieve token type. Also processes the token value if necessary. * * @return T|null * * @param-out V $value */ abstract protected function getType(string &$value); } PK�������Z(���� ��Token.phpnu�W+A��������<?php declare(strict_types=1); namespace Doctrine\Common\Lexer; use UnitEnum; use function in_array; /** * @template T of UnitEnum|string|int * @template V of string|int */ final class Token { /** * The string value of the token in the input string * * @readonly * @var V */ public string|int $value; /** * The type of the token (identifier, numeric, string, input parameter, none) * * @readonly * @var T|null */ public $type; /** * The position of the token in the input string * * @readonly */ public int $position; /** * @param V $value * @param T|null $type */ public function __construct(string|int $value, $type, int $position) { $this->value = $value; $this->type = $type; $this->position = $position; } /** @param T ...$types */ public function isA(...$types): bool { return in_array($this->type, $types, true); } } PK������Z G������View.phpnu�W+A��������<?php namespace Spatie\FlareClient; use Symfony\Component\VarDumper\Cloner\VarCloner; use Symfony\Component\VarDumper\Dumper\HtmlDumper; class View { protected string $file; /** @var array<string, mixed> */ protected array $data = []; /** * @param string $file * @param array<string, mixed> $data */ public function __construct(string $file, array $data = []) { $this->file = $file; $this->data = $data; } /** * @param string $file * @param array<string, mixed> $data * * @return self */ public static function create(string $file, array $data = []): self { return new self($file, $data); } protected function dumpViewData(mixed $variable): string { $cloner = new VarCloner(); $dumper = new HtmlDumper(); $dumper->setDumpHeader(''); $output = fopen('php://memory', 'r+b'); if (! $output) { return ''; } $dumper->dump($cloner->cloneVar($variable)->withMaxDepth(1), $output, [ 'maxDepth' => 1, 'maxStringLength' => 160, ]); return (string)stream_get_contents($output, -1, 0); } /** @return array<string, mixed> */ public function toArray(): array { return [ 'file' => $this->file, 'data' => array_map([$this, 'dumpViewData'], $this->data), ]; } } PK������Z(������Glows/Glow.phpnu�W+A��������<?php namespace Spatie\FlareClient\Glows; use Spatie\FlareClient\Concerns\UsesTime; use Spatie\FlareClient\Enums\MessageLevels; class Glow { use UsesTime; protected string $name; /** @var array<int, mixed> */ protected array $metaData = []; protected string $messageLevel; protected float $microtime; /** * @param string $name * @param string $messageLevel * @param array<int, mixed> $metaData * @param float|null $microtime */ public function __construct( string $name, string $messageLevel = MessageLevels::INFO, array $metaData = [], ?float $microtime = null ) { $this->name = $name; $this->messageLevel = $messageLevel; $this->metaData = $metaData; $this->microtime = $microtime ?? microtime(true); } /** * @return array{time: int, name: string, message_level: string, meta_data: array, microtime: float} */ public function toArray(): array { return [ 'time' => $this->getCurrentTime(), 'name' => $this->name, 'message_level' => $this->messageLevel, 'meta_data' => $this->metaData, 'microtime' => $this->microtime, ]; } } PK������ZD >������Glows/GlowRecorder.phpnu�W+A��������<?php namespace Spatie\FlareClient\Glows; class GlowRecorder { const GLOW_LIMIT = 30; /** @var array<int, Glow> */ protected array $glows = []; public function record(Glow $glow): void { $this->glows[] = $glow; $this->glows = array_slice($this->glows, static::GLOW_LIMIT * -1, static::GLOW_LIMIT); } /** @return array<int, Glow> */ public function glows(): array { return $this->glows; } public function reset(): void { $this->glows = []; } } PK������Z7������Concerns/UsesTime.phpnu�W+A��������<?php namespace Spatie\FlareClient\Concerns; use Spatie\FlareClient\Time\SystemTime; use Spatie\FlareClient\Time\Time; trait UsesTime { public static Time $time; public static function useTime(Time $time): void { self::$time = $time; } public function getCurrentTime(): int { $time = self::$time ?? new SystemTime(); return $time->getCurrentTime(); } } PK������ZC~A��A����Concerns/HasContext.phpnu�W+A��������<?php namespace Spatie\FlareClient\Concerns; trait HasContext { protected ?string $messageLevel = null; protected ?string $stage = null; /** * @var array<string, mixed> */ protected array $userProvidedContext = []; public function stage(?string $stage): self { $this->stage = $stage; return $this; } public function messageLevel(?string $messageLevel): self { $this->messageLevel = $messageLevel; return $this; } /** * @param string $groupName * @param mixed $default * * @return array<int, mixed> */ public function getGroup(string $groupName = 'context', $default = []): array { return $this->userProvidedContext[$groupName] ?? $default; } public function context(string $key, mixed $value): self { return $this->group('context', [$key => $value]); } /** * @param string $groupName * @param array<string, mixed> $properties * * @return $this */ public function group(string $groupName, array $properties): self { $group = $this->userProvidedContext[$groupName] ?? []; $this->userProvidedContext[$groupName] = array_merge_recursive_distinct( $group, $properties ); return $this; } } PK������Z Li���i��� ��Time/Time.phpnu�W+A��������<?php namespace Spatie\FlareClient\Time; interface Time { public function getCurrentTime(): int; } PK������Z'��������Time/SystemTime.phpnu�W+A��������<?php namespace Spatie\FlareClient\Time; use DateTimeImmutable; class SystemTime implements Time { public function getCurrentTime(): int { return (new DateTimeImmutable())->getTimestamp(); } } PK������Z!/qF��F����Api.phpnu�W+A��������<?php namespace Spatie\FlareClient; use Exception; use Spatie\FlareClient\Http\Client; use Spatie\FlareClient\Truncation\ReportTrimmer; class Api { protected Client $client; protected bool $sendReportsImmediately = false; /** @var array<int, Report> */ protected array $queue = []; public function __construct(Client $client) { $this->client = $client; register_shutdown_function([$this, 'sendQueuedReports']); } public function sendReportsImmediately(): self { $this->sendReportsImmediately = true; return $this; } public function report(Report $report): void { try { $this->sendReportsImmediately ? $this->sendReportToApi($report) : $this->addReportToQueue($report); } catch (Exception $e) { // } } public function sendTestReport(Report $report): self { $this->sendReportToApi($report); return $this; } protected function addReportToQueue(Report $report): self { $this->queue[] = $report; return $this; } public function sendQueuedReports(): void { try { foreach ($this->queue as $report) { $this->sendReportToApi($report); } } catch (Exception $e) { // } finally { $this->queue = []; } } protected function sendReportToApi(Report $report): void { $payload = $this->truncateReport($report->toArray()); $this->client->post('reports', $payload); } /** * @param array<int|string, mixed> $payload * * @return array<int|string, mixed> */ protected function truncateReport(array $payload): array { return (new ReportTrimmer())->trim($payload); } } PK������ZT?+��+�� ��Flare.phpnu�W+A��������<?php namespace Spatie\FlareClient; use Closure; use Error; use ErrorException; use Exception; use Illuminate\Contracts\Container\Container; use Illuminate\Pipeline\Pipeline; use Spatie\FlareClient\Concerns\HasContext; use Spatie\FlareClient\Context\BaseContextProviderDetector; use Spatie\FlareClient\Context\ContextProviderDetector; use Spatie\FlareClient\Enums\MessageLevels; use Spatie\FlareClient\FlareMiddleware\AddEnvironmentInformation; use Spatie\FlareClient\FlareMiddleware\AddGlows; use Spatie\FlareClient\FlareMiddleware\CensorRequestBodyFields; use Spatie\FlareClient\FlareMiddleware\FlareMiddleware; use Spatie\FlareClient\FlareMiddleware\RemoveRequestIp; use Spatie\FlareClient\Glows\Glow; use Spatie\FlareClient\Glows\GlowRecorder; use Spatie\FlareClient\Http\Client; use Throwable; class Flare { use HasContext; protected Client $client; protected Api $api; /** @var array<int, FlareMiddleware|class-string<FlareMiddleware>> */ protected array $middleware = []; protected GlowRecorder $recorder; protected ?string $applicationPath = null; protected ContextProviderDetector $contextDetector; protected ?Closure $previousExceptionHandler = null; /** @var null|callable */ protected $previousErrorHandler = null; /** @var null|callable */ protected $determineVersionCallable = null; protected ?int $reportErrorLevels = null; /** @var null|callable */ protected $filterExceptionsCallable = null; /** @var null|callable */ protected $filterReportsCallable = null; protected ?string $stage = null; protected ?string $requestId = null; protected ?Container $container = null; public static function make( string $apiKey = null, ContextProviderDetector $contextDetector = null ): self { $client = new Client($apiKey); return new self($client, $contextDetector); } public function setApiToken(string $apiToken): self { $this->client->setApiToken($apiToken); return $this; } public function apiTokenSet(): bool { return $this->client->apiTokenSet(); } public function setBaseUrl(string $baseUrl): self { $this->client->setBaseUrl($baseUrl); return $this; } public function setStage(?string $stage): self { $this->stage = $stage; return $this; } public function sendReportsImmediately(): self { $this->api->sendReportsImmediately(); return $this; } public function determineVersionUsing(callable $determineVersionCallable): self { $this->determineVersionCallable = $determineVersionCallable; return $this; } public function reportErrorLevels(int $reportErrorLevels): self { $this->reportErrorLevels = $reportErrorLevels; return $this; } public function filterExceptionsUsing(callable $filterExceptionsCallable): self { $this->filterExceptionsCallable = $filterExceptionsCallable; return $this; } public function filterReportsUsing(callable $filterReportsCallable): self { $this->filterReportsCallable = $filterReportsCallable; return $this; } public function version(): ?string { if (! $this->determineVersionCallable) { return null; } return ($this->determineVersionCallable)(); } /** * @param \Spatie\FlareClient\Http\Client $client * @param \Spatie\FlareClient\Context\ContextProviderDetector|null $contextDetector * @param array<int, FlareMiddleware> $middleware */ public function __construct( Client $client, ContextProviderDetector $contextDetector = null, array $middleware = [] ) { $this->client = $client; $this->recorder = new GlowRecorder(); $this->contextDetector = $contextDetector ?? new BaseContextProviderDetector(); $this->middleware = $middleware; $this->api = new Api($this->client); $this->registerDefaultMiddleware(); } /** @return array<int, FlareMiddleware|class-string<FlareMiddleware>> */ public function getMiddleware(): array { return $this->middleware; } public function setContextProviderDetector(ContextProviderDetector $contextDetector): self { $this->contextDetector = $contextDetector; return $this; } public function setContainer(Container $container): self { $this->container = $container; return $this; } public function registerFlareHandlers(): self { $this->registerExceptionHandler(); $this->registerErrorHandler(); return $this; } public function registerExceptionHandler(): self { /** @phpstan-ignore-next-line */ $this->previousExceptionHandler = set_exception_handler([$this, 'handleException']); return $this; } public function registerErrorHandler(): self { $this->previousErrorHandler = set_error_handler([$this, 'handleError']); return $this; } protected function registerDefaultMiddleware(): self { return $this->registerMiddleware([ new AddGlows($this->recorder), new AddEnvironmentInformation(), ]); } /** * @param FlareMiddleware|array<FlareMiddleware>|class-string<FlareMiddleware>|callable $middleware * * @return $this */ public function registerMiddleware($middleware): self { if (! is_array($middleware)) { $middleware = [$middleware]; } $this->middleware = array_merge($this->middleware, $middleware); return $this; } /** * @return array<int,FlareMiddleware|class-string<FlareMiddleware>> */ public function getMiddlewares(): array { return $this->middleware; } /** * @param string $name * @param string $messageLevel * @param array<int, mixed> $metaData * * @return $this */ public function glow( string $name, string $messageLevel = MessageLevels::INFO, array $metaData = [] ): self { $this->recorder->record(new Glow($name, $messageLevel, $metaData)); return $this; } public function handleException(Throwable $throwable): void { $this->report($throwable); if ($this->previousExceptionHandler) { call_user_func($this->previousExceptionHandler, $throwable); } } /** * @return mixed */ public function handleError(mixed $code, string $message, string $file = '', int $line = 0) { $exception = new ErrorException($message, 0, $code, $file, $line); $this->report($exception); if ($this->previousErrorHandler) { return call_user_func( $this->previousErrorHandler, $message, $code, $file, $line ); } } public function applicationPath(string $applicationPath): self { $this->applicationPath = $applicationPath; return $this; } public function report(Throwable $throwable, callable $callback = null, Report $report = null): ?Report { if (! $this->shouldSendReport($throwable)) { return null; } $report ??= $this->createReport($throwable); if (! is_null($callback)) { call_user_func($callback, $report); } $this->recorder->reset(); $this->sendReportToApi($report); return $report; } protected function shouldSendReport(Throwable $throwable): bool { if (isset($this->reportErrorLevels) && $throwable instanceof Error) { return (bool)($this->reportErrorLevels & $throwable->getCode()); } if (isset($this->reportErrorLevels) && $throwable instanceof ErrorException) { return (bool)($this->reportErrorLevels & $throwable->getSeverity()); } if ($this->filterExceptionsCallable && $throwable instanceof Exception) { return (bool)(call_user_func($this->filterExceptionsCallable, $throwable)); } return true; } public function reportMessage(string $message, string $logLevel, callable $callback = null): void { $report = $this->createReportFromMessage($message, $logLevel); if (! is_null($callback)) { call_user_func($callback, $report); } $this->sendReportToApi($report); } public function sendTestReport(Throwable $throwable): void { $this->api->sendTestReport($this->createReport($throwable)); } protected function sendReportToApi(Report $report): void { if ($this->filterReportsCallable) { if (! call_user_func($this->filterReportsCallable, $report)) { return; } } try { $this->api->report($report); } catch (Exception $exception) { } } public function reset(): void { $this->api->sendQueuedReports(); $this->userProvidedContext = []; $this->recorder->reset(); } protected function applyAdditionalParameters(Report $report): void { $report ->stage($this->stage) ->messageLevel($this->messageLevel) ->setApplicationPath($this->applicationPath) ->userProvidedContext($this->userProvidedContext); } public function anonymizeIp(): self { $this->registerMiddleware(new RemoveRequestIp()); return $this; } /** * @param array<int, string> $fieldNames * * @return $this */ public function censorRequestBodyFields(array $fieldNames): self { $this->registerMiddleware(new CensorRequestBodyFields($fieldNames)); return $this; } public function createReport(Throwable $throwable): Report { $report = Report::createForThrowable( $throwable, $this->contextDetector->detectCurrentContext(), $this->applicationPath, $this->version() ); return $this->applyMiddlewareToReport($report); } public function createReportFromMessage(string $message, string $logLevel): Report { $report = Report::createForMessage( $message, $logLevel, $this->contextDetector->detectCurrentContext(), $this->applicationPath ); return $this->applyMiddlewareToReport($report); } protected function applyMiddlewareToReport(Report $report): Report { $this->applyAdditionalParameters($report); $middleware = array_map(function ($singleMiddleware) { return is_string($singleMiddleware) ? new $singleMiddleware : $singleMiddleware; }, $this->middleware); $report = (new Pipeline()) ->send($report) ->through($middleware) ->then(fn ($report) => $report); return $report; } } PK������ZaR���� ��helpers.phpnu�W+A��������<?php if (! function_exists('array_merge_recursive_distinct')) { /** * @param array<int|string, mixed> $array1 * @param array<int|string, mixed> $array2 * * @return array<int|string, mixed> */ function array_merge_recursive_distinct(array &$array1, array &$array2): array { $merged = $array1; foreach ($array2 as $key => &$value) { if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) { $merged[$key] = array_merge_recursive_distinct($merged[$key], $value); } else { $merged[$key] = $value; } } return $merged; } } PK������Zs^����(��FlareMiddleware/CensorRequestHeaders.phpnu�W+A��������<?php namespace Spatie\FlareClient\FlareMiddleware; use Spatie\FlareClient\Report; class CensorRequestHeaders implements FlareMiddleware { protected array $headers = []; public function __construct(array $headers) { $this->headers = $headers; } public function handle(Report $report, $next) { $context = $report->allContext(); foreach ($this->headers as $header) { $header = strtolower($header); if (isset($context['headers'][$header])) { $context['headers'][$header] = '<CENSORED>'; } } $report->userProvidedContext($context); return $next($report); } } PK������Z]ՆG��G����FlareMiddleware/AddGlows.phpnu�W+A��������<?php namespace Spatie\FlareClient\FlareMiddleware; namespace Spatie\FlareClient\FlareMiddleware; use Closure; use Spatie\FlareClient\Glows\GlowRecorder; use Spatie\FlareClient\Report; class AddGlows implements FlareMiddleware { protected GlowRecorder $recorder; public function __construct(GlowRecorder $recorder) { $this->recorder = $recorder; } public function handle(Report $report, Closure $next) { foreach ($this->recorder->glows() as $glow) { $report->addGlow($glow); } return $next($report); } } PK������Zjf\������#��FlareMiddleware/FlareMiddleware.phpnu�W+A��������<?php namespace Spatie\FlareClient\FlareMiddleware; use Closure; use Spatie\FlareClient\Report; interface FlareMiddleware { public function handle(Report $report, Closure $next); } PK������ZL_o��o��#��FlareMiddleware/RemoveRequestIp.phpnu�W+A��������<?php namespace Spatie\FlareClient\FlareMiddleware; use Spatie\FlareClient\Report; class RemoveRequestIp implements FlareMiddleware { public function handle(Report $report, $next) { $context = $report->allContext(); $context['request']['ip'] = null; $report->userProvidedContext($context); return $next($report); } } PK������Z<0C��C��)��FlareMiddleware/AddDocumentationLinks.phpnu�W+A��������<?php namespace Spatie\FlareClient\FlareMiddleware; use ArrayObject; use Closure; use Spatie\FlareClient\Report; class AddDocumentationLinks implements FlareMiddleware { protected ArrayObject $documentationLinkResolvers; public function __construct(ArrayObject $documentationLinkResolvers) { $this->documentationLinkResolvers = $documentationLinkResolvers; } public function handle(Report $report, Closure $next) { if (! $throwable = $report->getThrowable()) { return $next($report); } $links = $this->getLinks($throwable); if (count($links)) { $report->addDocumentationLinks($links); } return $next($report); } /** @return array<int, string> */ protected function getLinks(\Throwable $throwable): array { $allLinks = []; foreach ($this->documentationLinkResolvers as $resolver) { $resolvedLinks = $resolver($throwable); if (is_null($resolvedLinks)) { continue; } if (is_string($resolvedLinks)) { $resolvedLinks = [$resolvedLinks]; } foreach ($resolvedLinks as $link) { $allLinks[] = $link; } } return array_values(array_unique($allLinks)); } } PK������ZL����+��FlareMiddleware/CensorRequestBodyFields.phpnu�W+A��������<?php namespace Spatie\FlareClient\FlareMiddleware; use Spatie\FlareClient\Report; class CensorRequestBodyFields implements FlareMiddleware { protected array $fieldNames = []; public function __construct(array $fieldNames) { $this->fieldNames = $fieldNames; } public function handle(Report $report, $next) { $context = $report->allContext(); foreach ($this->fieldNames as $fieldName) { if (isset($context['request_data']['body'][$fieldName])) { $context['request_data']['body'][$fieldName] = '<CENSORED>'; } } $report->userProvidedContext($context); return $next($report); } } PK������ZA;��;��%��FlareMiddleware/AddGitInformation.phpnu�W+A��������<?php namespace Spatie\FlareClient\FlareMiddleware; use Closure; use Spatie\FlareClient\Report; use Symfony\Component\Process\Process; use Throwable; class AddGitInformation { protected ?string $baseDir = null; public function handle(Report $report, Closure $next) { try { $this->baseDir = $this->getGitBaseDirectory(); if (! $this->baseDir) { return $next($report); } $report->group('git', [ 'hash' => $this->hash(), 'message' => $this->message(), 'tag' => $this->tag(), 'remote' => $this->remote(), 'isDirty' => ! $this->isClean(), ]); } catch (Throwable) { } return $next($report); } protected function hash(): ?string { return $this->command("git log --pretty=format:'%H' -n 1") ?: null; } protected function message(): ?string { return $this->command("git log --pretty=format:'%s' -n 1") ?: null; } protected function tag(): ?string { return $this->command('git describe --tags --abbrev=0') ?: null; } protected function remote(): ?string { return $this->command('git config --get remote.origin.url') ?: null; } protected function isClean(): bool { return empty($this->command('git status -s')); } protected function getGitBaseDirectory(): ?string { /** @var Process $process */ $process = Process::fromShellCommandline("echo $(git rev-parse --show-toplevel)")->setTimeout(1); $process->run(); if (! $process->isSuccessful()) { return null; } $directory = trim($process->getOutput()); if (! file_exists($directory)) { return null; } return $directory; } protected function command($command) { $process = Process::fromShellCommandline($command, $this->baseDir)->setTimeout(1); $process->run(); return trim($process->getOutput()); } } PK������ZT_��_��-��FlareMiddleware/AddEnvironmentInformation.phpnu�W+A��������<?php namespace Spatie\FlareClient\FlareMiddleware; use Closure; use Spatie\FlareClient\Report; class AddEnvironmentInformation implements FlareMiddleware { public function handle(Report $report, Closure $next) { $report->group('env', [ 'php_version' => phpversion(), ]); return $next($report); } } PK������Z>Q��Q��#��FlareMiddleware/AddNotifierName.phpnu�W+A��������<?php namespace Spatie\FlareClient\FlareMiddleware; use Spatie\FlareClient\Report; class AddNotifierName implements FlareMiddleware { public const NOTIFIER_NAME = 'Flare Client'; public function handle(Report $report, $next) { $report->notifierName(static::NOTIFIER_NAME); return $next($report); } } PK������Zfد:��:�� ��FlareMiddleware/AddSolutions.phpnu�W+A��������<?php namespace Spatie\FlareClient\FlareMiddleware; use Closure; use Spatie\FlareClient\Report; use Spatie\Ignition\Contracts\SolutionProviderRepository; class AddSolutions implements FlareMiddleware { protected SolutionProviderRepository $solutionProviderRepository; public function __construct(SolutionProviderRepository $solutionProviderRepository) { $this->solutionProviderRepository = $solutionProviderRepository; } public function handle(Report $report, Closure $next) { if ($throwable = $report->getThrowable()) { $solutions = $this->solutionProviderRepository->getSolutionsForThrowable($throwable); foreach ($solutions as $solution) { $report->addSolution($solution); } } return $next($report); } } PK������Z&v����'��Context/BaseContextProviderDetector.phpnu�W+A��������<?php namespace Spatie\FlareClient\Context; class BaseContextProviderDetector implements ContextProviderDetector { public function detectCurrentContext(): ContextProvider { if ($this->runningInConsole()) { return new ConsoleContextProvider($_SERVER['argv'] ?? []); } return new RequestContextProvider(); } protected function runningInConsole(): bool { if (isset($_ENV['APP_RUNNING_IN_CONSOLE'])) { return $_ENV['APP_RUNNING_IN_CONSOLE'] === 'true'; } if (isset($_ENV['FLARE_FAKE_WEB_REQUEST'])) { return false; } return in_array(php_sapi_name(), ['cli', 'phpdb']); } } PK������ZV������#��Context/ContextProviderDetector.phpnu�W+A��������<?php namespace Spatie\FlareClient\Context; interface ContextProviderDetector { public function detectCurrentContext(): ContextProvider; } PK������Z#hª��������Context/ContextProvider.phpnu�W+A��������<?php namespace Spatie\FlareClient\Context; interface ContextProvider { /** * @return array<int, string|mixed> */ public function toArray(): array; } PK������Z[����"��Context/RequestContextProvider.phpnu�W+A��������<?php namespace Spatie\FlareClient\Context; use RuntimeException; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Mime\Exception\InvalidArgumentException; use Throwable; class RequestContextProvider implements ContextProvider { protected ?Request $request; public function __construct(Request $request = null) { $this->request = $request ?? Request::createFromGlobals(); } /** * @return array<string, mixed> */ public function getRequest(): array { return [ 'url' => $this->request->getUri(), 'ip' => $this->request->getClientIp(), 'method' => $this->request->getMethod(), 'useragent' => $this->request->headers->get('User-Agent'), ]; } /** * @return array<int, mixed> */ protected function getFiles(): array { if (is_null($this->request->files)) { return []; } return $this->mapFiles($this->request->files->all()); } /** * @param array<int, mixed> $files * * @return array<string, string> */ protected function mapFiles(array $files): array { return array_map(function ($file) { if (is_array($file)) { return $this->mapFiles($file); } if (! $file instanceof UploadedFile) { return; } try { $fileSize = $file->getSize(); } catch (RuntimeException $e) { $fileSize = 0; } try { $mimeType = $file->getMimeType(); } catch (InvalidArgumentException $e) { $mimeType = 'undefined'; } return [ 'pathname' => $file->getPathname(), 'size' => $fileSize, 'mimeType' => $mimeType, ]; }, $files); } /** * @return array<string, mixed> */ public function getSession(): array { try { $session = $this->request->getSession(); } catch (Throwable $exception) { $session = []; } return $session ? $this->getValidSessionData($session) : []; } protected function getValidSessionData($session): array { if (! method_exists($session, 'all')) { return []; } try { json_encode($session->all()); } catch (Throwable $e) { return []; } return $session->all(); } /** * @return array<int|string, mixed */ public function getCookies(): array { return $this->request->cookies->all(); } /** * @return array<string, mixed> */ public function getHeaders(): array { /** @var array<string, list<string|null>> $headers */ $headers = $this->request->headers->all(); return array_filter( array_map( fn (array $header) => $header[0], $headers ) ); } /** * @return array<string, mixed> */ public function getRequestData(): array { return [ 'queryString' => $this->request->query->all(), 'body' => $this->request->request->all(), 'files' => $this->getFiles(), ]; } /** @return array<string, mixed> */ public function toArray(): array { return [ 'request' => $this->getRequest(), 'request_data' => $this->getRequestData(), 'headers' => $this->getHeaders(), 'cookies' => $this->getCookies(), 'session' => $this->getSession(), ]; } } PK������Z{tf����"��Context/ConsoleContextProvider.phpnu�W+A��������<?php namespace Spatie\FlareClient\Context; class ConsoleContextProvider implements ContextProvider { /** * @var array<string, mixed> */ protected array $arguments = []; /** * @param array<string, mixed> $arguments */ public function __construct(array $arguments = []) { $this->arguments = $arguments; } /** * @return array<int|string, mixed> */ public function toArray(): array { return [ 'arguments' => $this->arguments, ]; } } PK������Z v��������Enums/MessageLevels.phpnu�W+A��������<?php namespace Spatie\FlareClient\Enums; class MessageLevels { const INFO = 'info'; const DEBUG = 'debug'; const WARNING = 'warning'; const ERROR = 'error'; const CRITICAL = 'critical'; } PK������ZϬ������"��Contracts/ProvidesFlareContext.phpnu�W+A��������<?php namespace Spatie\FlareClient\Contracts; interface ProvidesFlareContext { /** * @return array<int|string, mixed> */ public function context(): array; } PK������Z =\������Solutions/ReportSolution.phpnu�W+A��������<?php namespace Spatie\FlareClient\Solutions; use Spatie\Ignition\Contracts\RunnableSolution; use Spatie\Ignition\Contracts\Solution as SolutionContract; class ReportSolution { protected SolutionContract $solution; public function __construct(SolutionContract $solution) { $this->solution = $solution; } public static function fromSolution(SolutionContract $solution): self { return new self($solution); } /** * @return array<string, mixed> */ public function toArray(): array { $isRunnable = ($this->solution instanceof RunnableSolution); return [ 'class' => get_class($this->solution), 'title' => $this->solution->getSolutionTitle(), 'description' => $this->solution->getSolutionDescription(), 'links' => $this->solution->getDocumentationLinks(), /** @phpstan-ignore-next-line */ 'action_description' => $isRunnable ? $this->solution->getSolutionActionDescription() : null, 'is_runnable' => $isRunnable, 'ai_generated' => $this->solution->aiGenerated ?? false, ]; } } PK������Z]]��]����Http/Response.phpnu�W+A��������<?php namespace Spatie\FlareClient\Http; class Response { protected mixed $headers; protected mixed $body; protected mixed $error; public function __construct(mixed $headers, mixed $body, mixed $error) { $this->headers = $headers; $this->body = $body; $this->error = $error; } public function getHeaders(): mixed { return $this->headers; } public function getBody(): mixed { return $this->body; } public function hasBody(): bool { return $this->body != false; } public function getError(): mixed { return $this->error; } public function getHttpResponseCode(): ?int { if (! isset($this->headers['http_code'])) { return null; } return (int) $this->headers['http_code']; } } PK������ZH˵������Http/Client.phpnu�W+A��������<?php namespace Spatie\FlareClient\Http; use Spatie\FlareClient\Http\Exceptions\BadResponseCode; use Spatie\FlareClient\Http\Exceptions\InvalidData; use Spatie\FlareClient\Http\Exceptions\MissingParameter; use Spatie\FlareClient\Http\Exceptions\NotFound; class Client { protected ?string $apiToken; protected ?string $baseUrl; protected int $timeout; protected $lastRequest = null; public function __construct( ?string $apiToken = null, string $baseUrl = 'https://reporting.flareapp.io/api', int $timeout = 10 ) { $this->apiToken = $apiToken; if (! $baseUrl) { throw MissingParameter::create('baseUrl'); } $this->baseUrl = $baseUrl; if (! $timeout) { throw MissingParameter::create('timeout'); } $this->timeout = $timeout; } public function setApiToken(string $apiToken): self { $this->apiToken = $apiToken; return $this; } public function apiTokenSet(): bool { return ! empty($this->apiToken); } public function setBaseUrl(string $baseUrl): self { $this->baseUrl = $baseUrl; return $this; } /** * @param string $url * @param array $arguments * * @return array|false */ public function get(string $url, array $arguments = []) { return $this->makeRequest('get', $url, $arguments); } /** * @param string $url * @param array $arguments * * @return array|false */ public function post(string $url, array $arguments = []) { return $this->makeRequest('post', $url, $arguments); } /** * @param string $url * @param array $arguments * * @return array|false */ public function patch(string $url, array $arguments = []) { return $this->makeRequest('patch', $url, $arguments); } /** * @param string $url * @param array $arguments * * @return array|false */ public function put(string $url, array $arguments = []) { return $this->makeRequest('put', $url, $arguments); } /** * @param string $method * @param array $arguments * * @return array|false */ public function delete(string $method, array $arguments = []) { return $this->makeRequest('delete', $method, $arguments); } /** * @param string $httpVerb * @param string $url * @param array $arguments * * @return array */ protected function makeRequest(string $httpVerb, string $url, array $arguments = []) { $queryString = http_build_query([ 'key' => $this->apiToken, ]); $fullUrl = "{$this->baseUrl}/{$url}?{$queryString}"; $headers = [ 'x-api-token: '.$this->apiToken, ]; $response = $this->makeCurlRequest($httpVerb, $fullUrl, $headers, $arguments); if ($response->getHttpResponseCode() === 422) { throw InvalidData::createForResponse($response); } if ($response->getHttpResponseCode() === 404) { throw NotFound::createForResponse($response); } if ($response->getHttpResponseCode() !== 200 && $response->getHttpResponseCode() !== 204) { throw BadResponseCode::createForResponse($response); } return $response->getBody(); } public function makeCurlRequest(string $httpVerb, string $fullUrl, array $headers = [], array $arguments = []): Response { $curlHandle = $this->getCurlHandle($fullUrl, $headers); switch ($httpVerb) { case 'post': curl_setopt($curlHandle, CURLOPT_POST, true); $this->attachRequestPayload($curlHandle, $arguments); break; case 'get': curl_setopt($curlHandle, CURLOPT_URL, $fullUrl.'&'.http_build_query($arguments)); break; case 'delete': curl_setopt($curlHandle, CURLOPT_CUSTOMREQUEST, 'DELETE'); break; case 'patch': curl_setopt($curlHandle, CURLOPT_CUSTOMREQUEST, 'PATCH'); $this->attachRequestPayload($curlHandle, $arguments); break; case 'put': curl_setopt($curlHandle, CURLOPT_CUSTOMREQUEST, 'PUT'); $this->attachRequestPayload($curlHandle, $arguments); break; } $body = json_decode(curl_exec($curlHandle), true); $headers = curl_getinfo($curlHandle); $error = curl_error($curlHandle); return new Response($headers, $body, $error); } protected function attachRequestPayload(&$curlHandle, array $data) { $encoded = json_encode($data); $this->lastRequest['body'] = $encoded; curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $encoded); } /** * @param string $fullUrl * @param array $headers * * @return resource */ protected function getCurlHandle(string $fullUrl, array $headers = []) { $curlHandle = curl_init(); curl_setopt($curlHandle, CURLOPT_URL, $fullUrl); curl_setopt($curlHandle, CURLOPT_HTTPHEADER, array_merge([ 'Accept: application/json', 'Content-Type: application/json', ], $headers)); curl_setopt($curlHandle, CURLOPT_USERAGENT, 'Laravel/Flare API 1.0'); curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true); curl_setopt($curlHandle, CURLOPT_TIMEOUT, $this->timeout); curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($curlHandle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); curl_setopt($curlHandle, CURLOPT_ENCODING, ''); curl_setopt($curlHandle, CURLINFO_HEADER_OUT, true); curl_setopt($curlHandle, CURLOPT_FOLLOWLOCATION, true); curl_setopt($curlHandle, CURLOPT_MAXREDIRS, 1); return $curlHandle; } } PK������Z_L������Http/Exceptions/BadResponse.phpnu�W+A��������<?php namespace Spatie\FlareClient\Http\Exceptions; use Exception; use Spatie\FlareClient\Http\Response; class BadResponse extends Exception { public Response $response; public static function createForResponse(Response $response): self { $exception = new self("Could not perform request because: {$response->getError()}"); $exception->response = $response; return $exception; } } PK������Z$ͬ��������Http/Exceptions/NotFound.phpnu�W+A��������<?php namespace Spatie\FlareClient\Http\Exceptions; use Spatie\FlareClient\Http\Response; class NotFound extends BadResponseCode { public static function getMessageForResponse(Response $response): string { return 'Not found'; } } PK������Z����$��Http/Exceptions/MissingParameter.phpnu�W+A��������<?php namespace Spatie\FlareClient\Http\Exceptions; use Exception; class MissingParameter extends Exception { public static function create(string $parameterName): self { return new self("`$parameterName` is a required parameter"); } } PK������ZH����#��Http/Exceptions/BadResponseCode.phpnu�W+A��������<?php namespace Spatie\FlareClient\Http\Exceptions; use Exception; use Spatie\FlareClient\Http\Response; class BadResponseCode extends Exception { public Response $response; /** * @var array<int, mixed> */ public array $errors = []; public static function createForResponse(Response $response): self { $exception = new self(static::getMessageForResponse($response)); $exception->response = $response; $bodyErrors = isset($response->getBody()['errors']) ? $response->getBody()['errors'] : []; $exception->errors = $bodyErrors; return $exception; } public static function getMessageForResponse(Response $response): string { return "Response code {$response->getHttpResponseCode()} returned"; } } PK������Z8r �� ����Http/Exceptions/InvalidData.phpnu�W+A��������<?php namespace Spatie\FlareClient\Http\Exceptions; use Spatie\FlareClient\Http\Response; class InvalidData extends BadResponseCode { public static function getMessageForResponse(Response $response): string { return 'Invalid data found'; } } PK������Z?U����"��Truncation/TrimStringsStrategy.phpnu�W+A��������<?php namespace Spatie\FlareClient\Truncation; class TrimStringsStrategy extends AbstractTruncationStrategy { /** * @return array<int, int> */ public static function thresholds(): array { return [1024, 512, 256]; } /** * @param array<int|string, mixed> $payload * * @return array<int|string, mixed> */ public function execute(array $payload): array { foreach (static::thresholds() as $threshold) { if (! $this->reportTrimmer->needsToBeTrimmed($payload)) { break; } $payload = $this->trimPayloadString($payload, $threshold); } return $payload; } /** * @param array<int|string, mixed> $payload * @param int $threshold * * @return array<int|string, mixed> */ protected function trimPayloadString(array $payload, int $threshold): array { array_walk_recursive($payload, function (&$value) use ($threshold) { if (is_string($value) && strlen($value) > $threshold) { $value = substr($value, 0, $threshold); } }); return $payload; } } PK������Z0T����'��Truncation/TrimContextItemsStrategy.phpnu�W+A��������<?php namespace Spatie\FlareClient\Truncation; class TrimContextItemsStrategy extends AbstractTruncationStrategy { /** * @return array<int, int> */ public static function thresholds(): array { return [100, 50, 25, 10]; } /** * @param array<int|string, mixed> $payload * * @return array<int|string, mixed> */ public function execute(array $payload): array { foreach (static::thresholds() as $threshold) { if (! $this->reportTrimmer->needsToBeTrimmed($payload)) { break; } $payload['context'] = $this->iterateContextItems($payload['context'], $threshold); } return $payload; } /** * @param array<int|string, mixed> $contextItems * @param int $threshold * * @return array<int|string, mixed> */ protected function iterateContextItems(array $contextItems, int $threshold): array { array_walk($contextItems, [$this, 'trimContextItems'], $threshold); return $contextItems; } protected function trimContextItems(mixed &$value, mixed $key, int $threshold): mixed { if (is_array($value)) { if (count($value) > $threshold) { $value = array_slice($value, $threshold * -1, $threshold); } array_walk($value, [$this, 'trimContextItems'], $threshold); } return $value; } } PK������Z^E|.#��#��)��Truncation/AbstractTruncationStrategy.phpnu�W+A��������<?php namespace Spatie\FlareClient\Truncation; abstract class AbstractTruncationStrategy implements TruncationStrategy { protected ReportTrimmer $reportTrimmer; public function __construct(ReportTrimmer $reportTrimmer) { $this->reportTrimmer = $reportTrimmer; } } PK������Z@,������!��Truncation/TruncationStrategy.phpnu�W+A��������<?php namespace Spatie\FlareClient\Truncation; interface TruncationStrategy { /** * @param array<int|string, mixed> $payload * * @return array<int|string, mixed> */ public function execute(array $payload): array; } PK������Z 6������Truncation/ReportTrimmer.phpnu�W+A��������<?php namespace Spatie\FlareClient\Truncation; class ReportTrimmer { protected static int $maxPayloadSize = 524288; /** @var array<int, class-string<\Spatie\FlareClient\Truncation\TruncationStrategy>> */ protected array $strategies = [ TrimStringsStrategy::class, TrimContextItemsStrategy::class, ]; /** * @param array<int|string, mixed> $payload * * @return array<int|string, mixed> */ public function trim(array $payload): array { foreach ($this->strategies as $strategy) { if (! $this->needsToBeTrimmed($payload)) { break; } $payload = (new $strategy($this))->execute($payload); } return $payload; } /** * @param array<int|string, mixed> $payload * * @return bool */ public function needsToBeTrimmed(array $payload): bool { return strlen((string)json_encode($payload)) > self::getMaxPayloadSize(); } public static function getMaxPayloadSize(): int { return self::$maxPayloadSize; } public static function setMaxPayloadSize(int $maxPayloadSize): void { self::$maxPayloadSize = $maxPayloadSize; } } PK������Z[ݺ#��#�� ��Report.phpnu�W+A��������<?php namespace Spatie\FlareClient; use Spatie\Backtrace\Backtrace; use Spatie\Backtrace\Frame as SpatieFrame; use Spatie\FlareClient\Concerns\HasContext; use Spatie\FlareClient\Concerns\UsesTime; use Spatie\FlareClient\Context\ContextProvider; use Spatie\FlareClient\Contracts\ProvidesFlareContext; use Spatie\FlareClient\Glows\Glow; use Spatie\FlareClient\Solutions\ReportSolution; use Spatie\Ignition\Contracts\Solution; use Spatie\LaravelIgnition\Exceptions\ViewException; use Throwable; class Report { use UsesTime; use HasContext; protected Backtrace $stacktrace; protected string $exceptionClass = ''; protected string $message = ''; /** @var array<int, array{time: int, name: string, message_level: string, meta_data: array, microtime: float}> */ protected array $glows = []; /** @var array<int, array<int|string, mixed>> */ protected array $solutions = []; /** @var array<int, string> */ public array $documentationLinks = []; protected ContextProvider $context; protected ?string $applicationPath = null; protected ?string $applicationVersion = null; /** @var array<int|string, mixed> */ protected array $userProvidedContext = []; /** @var array<int|string, mixed> */ protected array $exceptionContext = []; protected ?Throwable $throwable = null; protected string $notifierName = 'Flare Client'; protected ?string $languageVersion = null; protected ?string $frameworkVersion = null; protected ?int $openFrameIndex = null; protected string $trackingUuid; protected ?View $view; public static ?string $fakeTrackingUuid = null; public static function createForThrowable( Throwable $throwable, ContextProvider $context, ?string $applicationPath = null, ?string $version = null ): self { return (new self()) ->setApplicationPath($applicationPath) ->throwable($throwable) ->useContext($context) ->exceptionClass(self::getClassForThrowable($throwable)) ->message($throwable->getMessage()) ->stackTrace(Backtrace::createForThrowable($throwable)->applicationPath($applicationPath ?? '')) ->exceptionContext($throwable) ->setApplicationVersion($version); } protected static function getClassForThrowable(Throwable $throwable): string { /** @phpstan-ignore-next-line */ if ($throwable::class === ViewException::class) { /** @phpstan-ignore-next-line */ if ($previous = $throwable->getPrevious()) { return get_class($previous); } } return get_class($throwable); } public static function createForMessage( string $message, string $logLevel, ContextProvider $context, ?string $applicationPath = null ): self { $stacktrace = Backtrace::create()->applicationPath($applicationPath ?? ''); return (new self()) ->setApplicationPath($applicationPath) ->message($message) ->useContext($context) ->exceptionClass($logLevel) ->stacktrace($stacktrace) ->openFrameIndex($stacktrace->firstApplicationFrameIndex()); } public function __construct() { $this->trackingUuid = self::$fakeTrackingUuid ?? $this->generateUuid(); } public function trackingUuid(): string { return $this->trackingUuid; } public function exceptionClass(string $exceptionClass): self { $this->exceptionClass = $exceptionClass; return $this; } public function getExceptionClass(): string { return $this->exceptionClass; } public function throwable(Throwable $throwable): self { $this->throwable = $throwable; return $this; } public function getThrowable(): ?Throwable { return $this->throwable; } public function message(string $message): self { $this->message = $message; return $this; } public function getMessage(): string { return $this->message; } public function stacktrace(Backtrace $stacktrace): self { $this->stacktrace = $stacktrace; return $this; } public function getStacktrace(): Backtrace { return $this->stacktrace; } public function notifierName(string $notifierName): self { $this->notifierName = $notifierName; return $this; } public function languageVersion(string $languageVersion): self { $this->languageVersion = $languageVersion; return $this; } public function frameworkVersion(string $frameworkVersion): self { $this->frameworkVersion = $frameworkVersion; return $this; } public function useContext(ContextProvider $request): self { $this->context = $request; return $this; } public function openFrameIndex(?int $index): self { $this->openFrameIndex = $index; return $this; } public function setApplicationPath(?string $applicationPath): self { $this->applicationPath = $applicationPath; return $this; } public function getApplicationPath(): ?string { return $this->applicationPath; } public function setApplicationVersion(?string $applicationVersion): self { $this->applicationVersion = $applicationVersion; return $this; } public function getApplicationVersion(): ?string { return $this->applicationVersion; } public function view(?View $view): self { $this->view = $view; return $this; } public function addGlow(Glow $glow): self { $this->glows[] = $glow->toArray(); return $this; } public function addSolution(Solution $solution): self { $this->solutions[] = ReportSolution::fromSolution($solution)->toArray(); return $this; } /** * @param array<int, string> $documentationLinks * * @return $this */ public function addDocumentationLinks(array $documentationLinks): self { $this->documentationLinks = $documentationLinks; return $this; } /** * @param array<int|string, mixed> $userProvidedContext * * @return $this */ public function userProvidedContext(array $userProvidedContext): self { $this->userProvidedContext = $userProvidedContext; return $this; } /** * @return array<int|string, mixed> */ public function allContext(): array { $context = $this->context->toArray(); $context = array_merge_recursive_distinct($context, $this->exceptionContext); return array_merge_recursive_distinct($context, $this->userProvidedContext); } protected function exceptionContext(Throwable $throwable): self { if ($throwable instanceof ProvidesFlareContext) { $this->exceptionContext = $throwable->context(); } return $this; } /** * @return array<int|string, mixed> */ protected function stracktraceAsArray(): array { return array_map( fn (SpatieFrame $frame) => Frame::fromSpatieFrame($frame)->toArray(), $this->stacktrace->frames(), ); } /** * @return array<string, mixed> */ public function toArray(): array { return [ 'notifier' => $this->notifierName ?? 'Flare Client', 'language' => 'PHP', 'framework_version' => $this->frameworkVersion, 'language_version' => $this->languageVersion ?? phpversion(), 'exception_class' => $this->exceptionClass, 'seen_at' => $this->getCurrentTime(), 'message' => $this->message, 'glows' => $this->glows, 'solutions' => $this->solutions, 'documentation_links' => $this->documentationLinks, 'stacktrace' => $this->stracktraceAsArray(), 'context' => $this->allContext(), 'stage' => $this->stage, 'message_level' => $this->messageLevel, 'open_frame_index' => $this->openFrameIndex, 'application_path' => $this->applicationPath, 'application_version' => $this->applicationVersion, 'tracking_uuid' => $this->trackingUuid, ]; } /* * Found on https://stackoverflow.com/questions/2040240/php-function-to-generate-v4-uuid/15875555#15875555 */ protected function generateUuid(): string { // Generate 16 bytes (128 bits) of random data or use the data passed into the function. $data = random_bytes(16); // Set version to 0100 $data[6] = chr(ord($data[6]) & 0x0f | 0x40); // Set bits 6-7 to 10 $data[8] = chr(ord($data[8]) & 0x3f | 0x80); // Output the 36 character UUID. return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)); } } PK������y Z Y������Illuminate/Testing/TestView.phpnu�W+A��������<?php namespace Illuminate\Testing; use Closure; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; use Illuminate\Support\Traits\Macroable; use Illuminate\Testing\Assert as PHPUnit; use Illuminate\Testing\Constraints\SeeInOrder; use Illuminate\View\View; class TestView { use Macroable; /** * The original view. * * @var \Illuminate\View\View */ protected $view; /** * The rendered view contents. * * @var string */ protected $rendered; /** * Create a new test view instance. * * @param \Illuminate\View\View $view * @return void */ public function __construct(View $view) { $this->view = $view; $this->rendered = $view->render(); } /** * Assert that the response view has a given piece of bound data. * * @param string|array $key * @param mixed $value * @return $this */ public function assertViewHas($key, $value = null) { if (is_array($key)) { return $this->assertViewHasAll($key); } if (is_null($value)) { PHPUnit::assertTrue(Arr::has($this->view->gatherData(), $key)); } elseif ($value instanceof Closure) { PHPUnit::assertTrue($value(Arr::get($this->view->gatherData(), $key))); } elseif ($value instanceof Model) { PHPUnit::assertTrue($value->is(Arr::get($this->view->gatherData(), $key))); } elseif ($value instanceof Collection) { $actual = Arr::get($this->view->gatherData(), $key); PHPUnit::assertInstanceOf(Collection::class, $actual); PHPUnit::assertSameSize($value, $actual); $value->each(fn ($item, $index) => PHPUnit::assertTrue($actual->get($index)->is($item))); } else { PHPUnit::assertEquals($value, Arr::get($this->view->gatherData(), $key)); } return $this; } /** * Assert that the response view has a given list of bound data. * * @param array $bindings * @return $this */ public function assertViewHasAll(array $bindings) { foreach ($bindings as $key => $value) { if (is_int($key)) { $this->assertViewHas($value); } else { $this->assertViewHas($key, $value); } } return $this; } /** * Assert that the response view is missing a piece of bound data. * * @param string $key * @return $this */ public function assertViewMissing($key) { PHPUnit::assertFalse(Arr::has($this->view->gatherData(), $key)); return $this; } /** * Assert that the given string is contained within the view. * * @param string $value * @param bool $escape * @return $this */ public function assertSee($value, $escape = true) { $value = $escape ? e($value) : $value; PHPUnit::assertStringContainsString((string) $value, $this->rendered); return $this; } /** * Assert that the given strings are contained in order within the view. * * @param array $values * @param bool $escape * @return $this */ public function assertSeeInOrder(array $values, $escape = true) { $values = $escape ? array_map('e', $values) : $values; PHPUnit::assertThat($values, new SeeInOrder($this->rendered)); return $this; } /** * Assert that the given string is contained within the view text. * * @param string $value * @param bool $escape * @return $this */ public function assertSeeText($value, $escape = true) { $value = $escape ? e($value) : $value; PHPUnit::assertStringContainsString((string) $value, strip_tags($this->rendered)); return $this; } /** * Assert that the given strings are contained in order within the view text. * * @param array $values * @param bool $escape * @return $this */ public function assertSeeTextInOrder(array $values, $escape = true) { $values = $escape ? array_map('e', $values) : $values; PHPUnit::assertThat($values, new SeeInOrder(strip_tags($this->rendered))); return $this; } /** * Assert that the given string is not contained within the view. * * @param string $value * @param bool $escape * @return $this */ public function assertDontSee($value, $escape = true) { $value = $escape ? e($value) : $value; PHPUnit::assertStringNotContainsString((string) $value, $this->rendered); return $this; } /** * Assert that the given string is not contained within the view text. * * @param string $value * @param bool $escape * @return $this */ public function assertDontSeeText($value, $escape = true) { $value = $escape ? e($value) : $value; PHPUnit::assertStringNotContainsString((string) $value, strip_tags($this->rendered)); return $this; } /** * Get the string contents of the rendered view. * * @return string */ public function __toString() { return $this->rendered; } } PK������y Zc�u��u��,��Illuminate/Testing/ParallelConsoleOutput.phpnu�W+A��������<?php namespace Illuminate\Testing; use Illuminate\Support\Str; use Symfony\Component\Console\Output\ConsoleOutput; class ParallelConsoleOutput extends ConsoleOutput { /** * The original output instance. * * @var \Symfony\Component\Console\Output\OutputInterface */ protected $output; /** * The output that should be ignored. * * @var array */ protected $ignore = [ 'Running phpunit in', 'Configuration read from', ]; /** * Create a new Parallel ConsoleOutput instance. * * @param \Symfony\Component\Console\Output\OutputInterface $output * @return void */ public function __construct($output) { parent::__construct( $output->getVerbosity(), $output->isDecorated(), $output->getFormatter(), ); $this->output = $output; } /** * Writes a message to the output. * * @param string|iterable $messages * @param bool $newline * @param int $options * @return void */ public function write($messages, bool $newline = false, int $options = 0) { $messages = collect($messages)->filter(function ($message) { return ! Str::contains($message, $this->ignore); }); $this->output->write($messages->toArray(), $newline, $options); } } PK������y ZG��G��-��Illuminate/Testing/Concerns/TestDatabases.phpnu�W+A��������<?php namespace Illuminate\Testing\Concerns; use Illuminate\Database\QueryException; use Illuminate\Foundation\Testing; use Illuminate\Support\Arr; use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\ParallelTesting; use Illuminate\Support\Facades\Schema; trait TestDatabases { /** * Indicates if the test database schema is up to date. * * @var bool */ protected static $schemaIsUpToDate = false; /** * Boot a test database. * * @return void */ protected function bootTestDatabase() { ParallelTesting::setUpProcess(function () { $this->whenNotUsingInMemoryDatabase(function ($database) { if (ParallelTesting::option('recreate_databases')) { Schema::dropDatabaseIfExists( $this->testDatabase($database) ); } }); }); ParallelTesting::setUpTestCase(function ($testCase) { $uses = array_flip(class_uses_recursive(get_class($testCase))); $databaseTraits = [ Testing\DatabaseMigrations::class, Testing\DatabaseTransactions::class, Testing\DatabaseTruncation::class, Testing\RefreshDatabase::class, ]; if (Arr::hasAny($uses, $databaseTraits) && ! ParallelTesting::option('without_databases')) { $this->whenNotUsingInMemoryDatabase(function ($database) use ($uses) { [$testDatabase, $created] = $this->ensureTestDatabaseExists($database); $this->switchToDatabase($testDatabase); if (isset($uses[Testing\DatabaseTransactions::class])) { $this->ensureSchemaIsUpToDate(); } if ($created) { ParallelTesting::callSetUpTestDatabaseCallbacks($testDatabase); } }); } }); ParallelTesting::tearDownProcess(function () { $this->whenNotUsingInMemoryDatabase(function ($database) { if (ParallelTesting::option('drop_databases')) { Schema::dropDatabaseIfExists( $this->testDatabase($database) ); } }); }); } /** * Ensure a test database exists and returns its name. * * @param string $database * @return array */ protected function ensureTestDatabaseExists($database) { $testDatabase = $this->testDatabase($database); try { $this->usingDatabase($testDatabase, function () { Schema::hasTable('dummy'); }); } catch (QueryException $e) { $this->usingDatabase($database, function () use ($testDatabase) { Schema::dropDatabaseIfExists($testDatabase); Schema::createDatabase($testDatabase); }); return [$testDatabase, true]; } return [$testDatabase, false]; } /** * Ensure the current database test schema is up to date. * * @return void */ protected function ensureSchemaIsUpToDate() { if (! static::$schemaIsUpToDate) { Artisan::call('migrate'); static::$schemaIsUpToDate = true; } } /** * Runs the given callable using the given database. * * @param string $database * @param callable $callable * @return void */ protected function usingDatabase($database, $callable) { $original = DB::getConfig('database'); try { $this->switchToDatabase($database); $callable(); } finally { $this->switchToDatabase($original); } } /** * Apply the given callback when tests are not using in memory database. * * @param callable $callback * @return void */ protected function whenNotUsingInMemoryDatabase($callback) { $database = DB::getConfig('database'); if ($database !== ':memory:') { $callback($database); } } /** * Switch to the given database. * * @param string $database * @return void */ protected function switchToDatabase($database) { DB::purge(); $default = config('database.default'); $url = config("database.connections.{$default}.url"); if ($url) { config()->set( "database.connections.{$default}.url", preg_replace('/^(.*)(\/[\w-]*)(\??.*)$/', "$1/{$database}$3", $url), ); } else { config()->set( "database.connections.{$default}.database", $database, ); } } /** * Returns the test database name. * * @return string */ protected function testDatabase($database) { $token = ParallelTesting::token(); return "{$database}_test_{$token}"; } } PK������y ZfY;[ ��[ ��2��Illuminate/Testing/Concerns/AssertsStatusCodes.phpnu�W+A��������<?php namespace Illuminate\Testing\Concerns; use Illuminate\Testing\Assert as PHPUnit; trait AssertsStatusCodes { /** * Assert that the response has a 200 "OK" status code. * * @return $this */ public function assertOk() { return $this->assertStatus(200); } /** * Assert that the response has a 201 "Created" status code. * * @return $this */ public function assertCreated() { return $this->assertStatus(201); } /** * Assert that the response has a 202 "Accepted" status code. * * @return $this */ public function assertAccepted() { return $this->assertStatus(202); } /** * Assert that the response has the given status code and no content. * * @param int $status * @return $this */ public function assertNoContent($status = 204) { $this->assertStatus($status); PHPUnit::assertEmpty($this->getContent(), 'Response content is not empty.'); return $this; } /** * Assert that the response has a 301 "Moved Permanently" status code. * * @param int $status * @return $this */ public function assertMovedPermanently() { return $this->assertStatus(301); } /** * Assert that the response has a 302 "Found" status code. * * @param int $status * @return $this */ public function assertFound() { return $this->assertStatus(302); } /** * Assert that the response has a 400 "Bad Request" status code. * * @return $this */ public function assertBadRequest() { return $this->assertStatus(400); } /** * Assert that the response has a 401 "Unauthorized" status code. * * @return $this */ public function assertUnauthorized() { return $this->assertStatus(401); } /** * Assert that the response has a 402 "Payment Required" status code. * * @return $this */ public function assertPaymentRequired() { return $this->assertStatus(402); } /** * Assert that the response has a 403 "Forbidden" status code. * * @return $this */ public function assertForbidden() { return $this->assertStatus(403); } /** * Assert that the response has a 404 "Not Found" status code. * * @return $this */ public function assertNotFound() { return $this->assertStatus(404); } /** * Assert that the response has a 408 "Request Timeout" status code. * * @return $this */ public function assertRequestTimeout() { return $this->assertStatus(408); } /** * Assert that the response has a 409 "Conflict" status code. * * @return $this */ public function assertConflict() { return $this->assertStatus(409); } /** * Assert that the response has a 422 "Unprocessable Entity" status code. * * @return $this */ public function assertUnprocessable() { return $this->assertStatus(422); } /** * Assert that the response has a 429 "Too Many Requests" status code. * * @return $this */ public function assertTooManyRequests() { return $this->assertStatus(429); } } PK������y Zα3��3����Illuminate/Testing/LICENSE.mdnu�W+A��������The MIT License (MIT) Copyright (c) Taylor Otwell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PK������y ZO <����$��Illuminate/Testing/TestComponent.phpnu�W+A��������<?php namespace Illuminate\Testing; use Illuminate\Testing\Assert as PHPUnit; use Illuminate\Testing\Constraints\SeeInOrder; class TestComponent { /** * The original component. * * @var \Illuminate\View\Component */ public $component; /** * The rendered component contents. * * @var string */ protected $rendered; /** * Create a new test component instance. * * @param \Illuminate\View\Component $component * @param \Illuminate\View\View $view * @return void */ public function __construct($component, $view) { $this->component = $component; $this->rendered = $view->render(); } /** * Assert that the given string is contained within the rendered component. * * @param string $value * @param bool $escape * @return $this */ public function assertSee($value, $escape = true) { $value = $escape ? e($value) : $value; PHPUnit::assertStringContainsString((string) $value, $this->rendered); return $this; } /** * Assert that the given strings are contained in order within the rendered component. * * @param array $values * @param bool $escape * @return $this */ public function assertSeeInOrder(array $values, $escape = true) { $values = $escape ? array_map('e', $values) : $values; PHPUnit::assertThat($values, new SeeInOrder($this->rendered)); return $this; } /** * Assert that the given string is contained within the rendered component text. * * @param string $value * @param bool $escape * @return $this */ public function assertSeeText($value, $escape = true) { $value = $escape ? e($value) : $value; PHPUnit::assertStringContainsString((string) $value, strip_tags($this->rendered)); return $this; } /** * Assert that the given strings are contained in order within the rendered component text. * * @param array $values * @param bool $escape * @return $this */ public function assertSeeTextInOrder(array $values, $escape = true) { $values = $escape ? array_map('e', $values) : $values; PHPUnit::assertThat($values, new SeeInOrder(strip_tags($this->rendered))); return $this; } /** * Assert that the given string is not contained within the rendered component. * * @param string $value * @param bool $escape * @return $this */ public function assertDontSee($value, $escape = true) { $value = $escape ? e($value) : $value; PHPUnit::assertStringNotContainsString((string) $value, $this->rendered); return $this; } /** * Assert that the given string is not contained within the rendered component text. * * @param string $value * @param bool $escape * @return $this */ public function assertDontSeeText($value, $escape = true) { $value = $escape ? e($value) : $value; PHPUnit::assertStringNotContainsString((string) $value, strip_tags($this->rendered)); return $this; } /** * Get the string contents of the rendered component. * * @return string */ public function __toString() { return $this->rendered; } /** * Dynamically access properties on the underlying component. * * @param string $attribute * @return mixed */ public function __get($attribute) { return $this->component->{$attribute}; } /** * Dynamically call methods on the underlying component. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { return $this->component->{$method}(...$parameters); } } PK������y Zy83��3��%��Illuminate/Testing/PendingCommand.phpnu�W+A��������<?php namespace Illuminate\Testing; use Illuminate\Console\OutputStyle; use Illuminate\Contracts\Console\Kernel; use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Support\Arr; use Mockery; use Mockery\Exception\NoMatchingExpectationException; use PHPUnit\Framework\TestCase as PHPUnitTestCase; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\BufferedOutput; class PendingCommand { /** * The test being run. * * @var \Illuminate\Foundation\Testing\TestCase */ public $test; /** * The application instance. * * @var \Illuminate\Contracts\Container\Container */ protected $app; /** * The command to run. * * @var string */ protected $command; /** * The parameters to pass to the command. * * @var array */ protected $parameters; /** * The expected exit code. * * @var int */ protected $expectedExitCode; /** * The unexpected exit code. * * @var int */ protected $unexpectedExitCode; /** * Determine if the command has executed. * * @var bool */ protected $hasExecuted = false; /** * Create a new pending console command run. * * @param \PHPUnit\Framework\TestCase $test * @param \Illuminate\Contracts\Container\Container $app * @param string $command * @param array $parameters * @return void */ public function __construct(PHPUnitTestCase $test, Container $app, $command, $parameters) { $this->app = $app; $this->test = $test; $this->command = $command; $this->parameters = $parameters; } /** * Specify an expected question that will be asked when the command runs. * * @param string $question * @param string|bool $answer * @return $this */ public function expectsQuestion($question, $answer) { $this->test->expectedQuestions[] = [$question, $answer]; return $this; } /** * Specify an expected confirmation question that will be asked when the command runs. * * @param string $question * @param string $answer * @return $this */ public function expectsConfirmation($question, $answer = 'no') { return $this->expectsQuestion($question, strtolower($answer) === 'yes'); } /** * Specify an expected choice question with expected answers that will be asked/shown when the command runs. * * @param string $question * @param string|array $answer * @param array $answers * @param bool $strict * @return $this */ public function expectsChoice($question, $answer, $answers, $strict = false) { $this->test->expectedChoices[$question] = [ 'expected' => $answers, 'strict' => $strict, ]; return $this->expectsQuestion($question, $answer); } /** * Specify output that should be printed when the command runs. * * @param string $output * @return $this */ public function expectsOutput($output) { $this->test->expectedOutput[] = $output; return $this; } /** * Specify output that should never be printed when the command runs. * * @param string $output * @return $this */ public function doesntExpectOutput($output) { $this->test->unexpectedOutput[$output] = false; return $this; } /** * Specify that the given string should be contained in the command output. * * @param string $string * @return $this */ public function expectsOutputToContain($string) { $this->test->expectedOutputSubstrings[] = $string; return $this; } /** * Specify that the given string shouldn't be contained in the command output. * * @param string $string * @return $this */ public function doesntExpectOutputToContain($string) { $this->test->unexpectedOutputSubstrings[$string] = false; return $this; } /** * Specify a table that should be printed when the command runs. * * @param array $headers * @param \Illuminate\Contracts\Support\Arrayable|array $rows * @param string $tableStyle * @param array $columnStyles * @return $this */ public function expectsTable($headers, $rows, $tableStyle = 'default', array $columnStyles = []) { $table = (new Table($output = new BufferedOutput)) ->setHeaders((array) $headers) ->setRows($rows instanceof Arrayable ? $rows->toArray() : $rows) ->setStyle($tableStyle); foreach ($columnStyles as $columnIndex => $columnStyle) { $table->setColumnStyle($columnIndex, $columnStyle); } $table->render(); $lines = array_filter( explode(PHP_EOL, $output->fetch()) ); foreach ($lines as $line) { $this->expectsOutput($line); } return $this; } /** * Assert that the command has the given exit code. * * @param int $exitCode * @return $this */ public function assertExitCode($exitCode) { $this->expectedExitCode = $exitCode; return $this; } /** * Assert that the command does not have the given exit code. * * @param int $exitCode * @return $this */ public function assertNotExitCode($exitCode) { $this->unexpectedExitCode = $exitCode; return $this; } /** * Assert that the command has the success exit code. * * @return $this */ public function assertSuccessful() { return $this->assertExitCode(Command::SUCCESS); } /** * Assert that the command has the success exit code. * * @return $this */ public function assertOk() { return $this->assertSuccessful(); } /** * Assert that the command does not have the success exit code. * * @return $this */ public function assertFailed() { return $this->assertNotExitCode(Command::SUCCESS); } /** * Execute the command. * * @return int */ public function execute() { return $this->run(); } /** * Execute the command. * * @return int * * @throws \Mockery\Exception\NoMatchingExpectationException */ public function run() { $this->hasExecuted = true; $mock = $this->mockConsoleOutput(); try { $exitCode = $this->app->make(Kernel::class)->call($this->command, $this->parameters, $mock); } catch (NoMatchingExpectationException $e) { if ($e->getMethodName() === 'askQuestion') { $this->test->fail('Unexpected question "'.$e->getActualArguments()[0]->getQuestion().'" was asked.'); } throw $e; } if ($this->expectedExitCode !== null) { $this->test->assertEquals( $this->expectedExitCode, $exitCode, "Expected status code {$this->expectedExitCode} but received {$exitCode}." ); } elseif (! is_null($this->unexpectedExitCode)) { $this->test->assertNotEquals( $this->unexpectedExitCode, $exitCode, "Unexpected status code {$this->unexpectedExitCode} was received." ); } $this->verifyExpectations(); $this->flushExpectations(); return $exitCode; } /** * Determine if expected questions / choices / outputs are fulfilled. * * @return void */ protected function verifyExpectations() { if (count($this->test->expectedQuestions)) { $this->test->fail('Question "'.Arr::first($this->test->expectedQuestions)[0].'" was not asked.'); } if (count($this->test->expectedChoices) > 0) { foreach ($this->test->expectedChoices as $question => $answers) { $assertion = $answers['strict'] ? 'assertEquals' : 'assertEqualsCanonicalizing'; $this->test->{$assertion}( $answers['expected'], $answers['actual'], 'Question "'.$question.'" has different options.' ); } } if (count($this->test->expectedOutput)) { $this->test->fail('Output "'.Arr::first($this->test->expectedOutput).'" was not printed.'); } if (count($this->test->expectedOutputSubstrings)) { $this->test->fail('Output does not contain "'.Arr::first($this->test->expectedOutputSubstrings).'".'); } if ($output = array_search(true, $this->test->unexpectedOutput)) { $this->test->fail('Output "'.$output.'" was printed.'); } if ($output = array_search(true, $this->test->unexpectedOutputSubstrings)) { $this->test->fail('Output "'.$output.'" was printed.'); } } /** * Mock the application's console output. * * @return \Mockery\MockInterface */ protected function mockConsoleOutput() { $mock = Mockery::mock(OutputStyle::class.'[askQuestion]', [ new ArrayInput($this->parameters), $this->createABufferedOutputMock(), ]); foreach ($this->test->expectedQuestions as $i => $question) { $mock->shouldReceive('askQuestion') ->once() ->ordered() ->with(Mockery::on(function ($argument) use ($question) { if (isset($this->test->expectedChoices[$question[0]])) { $this->test->expectedChoices[$question[0]]['actual'] = $argument->getAutocompleterValues(); } return $argument->getQuestion() == $question[0]; })) ->andReturnUsing(function () use ($question, $i) { unset($this->test->expectedQuestions[$i]); return $question[1]; }); } $this->app->bind(OutputStyle::class, function () use ($mock) { return $mock; }); return $mock; } /** * Create a mock for the buffered output. * * @return \Mockery\MockInterface */ private function createABufferedOutputMock() { $mock = Mockery::mock(BufferedOutput::class.'[doWrite]') ->shouldAllowMockingProtectedMethods() ->shouldIgnoreMissing(); foreach ($this->test->expectedOutput as $i => $output) { $mock->shouldReceive('doWrite') ->once() ->ordered() ->with($output, Mockery::any()) ->andReturnUsing(function () use ($i) { unset($this->test->expectedOutput[$i]); }); } foreach ($this->test->expectedOutputSubstrings as $i => $text) { $mock->shouldReceive('doWrite') ->atLeast() ->times(0) ->withArgs(fn ($output) => str_contains($output, $text)) ->andReturnUsing(function () use ($i) { unset($this->test->expectedOutputSubstrings[$i]); }); } foreach ($this->test->unexpectedOutput as $output => $displayed) { $mock->shouldReceive('doWrite') ->atLeast() ->times(0) ->ordered() ->with($output, Mockery::any()) ->andReturnUsing(function () use ($output) { $this->test->unexpectedOutput[$output] = true; }); } foreach ($this->test->unexpectedOutputSubstrings as $text => $displayed) { $mock->shouldReceive('doWrite') ->atLeast() ->times(0) ->withArgs(fn ($output) => str_contains($output, $text)) ->andReturnUsing(function () use ($text) { $this->test->unexpectedOutputSubstrings[$text] = true; }); } return $mock; } /** * Flush the expectations from the test case. * * @return void */ protected function flushExpectations() { $this->test->expectedOutput = []; $this->test->expectedOutputSubstrings = []; $this->test->unexpectedOutput = []; $this->test->unexpectedOutputSubstrings = []; $this->test->expectedTables = []; $this->test->expectedQuestions = []; $this->test->expectedChoices = []; } /** * Handle the object's destruction. * * @return void */ public function __destruct() { if ($this->hasExecuted) { return; } $this->run(); } } PK������y ZD������0��Illuminate/Testing/LoggedExceptionCollection.phpnu�W+A��������<?php namespace Illuminate\Testing; use Illuminate\Support\Collection; class LoggedExceptionCollection extends Collection { // } PK������y Zl|LQ��Q��5��Illuminate/Testing/ParallelTestingServiceProvider.phpnu�W+A��������<?php namespace Illuminate\Testing; use Illuminate\Contracts\Support\DeferrableProvider; use Illuminate\Support\ServiceProvider; use Illuminate\Testing\Concerns\TestDatabases; class ParallelTestingServiceProvider extends ServiceProvider implements DeferrableProvider { use TestDatabases; /** * Boot the application's service providers. * * @return void */ public function boot() { if ($this->app->runningInConsole()) { $this->bootTestDatabase(); } } /** * Register the service provider. * * @return void */ public function register() { if ($this->app->runningInConsole()) { $this->app->singleton(ParallelTesting::class, function () { return new ParallelTesting($this->app); }); } } } PK������y Z|����-��Illuminate/Testing/Constraints/SeeInOrder.phpnu�W+A��������<?php namespace Illuminate\Testing\Constraints; use PHPUnit\Framework\Constraint\Constraint; use ReflectionClass; class SeeInOrder extends Constraint { /** * The string under validation. * * @var string */ protected $content; /** * The last value that failed to pass validation. * * @var string */ protected $failedValue; /** * Create a new constraint instance. * * @param string $content * @return void */ public function __construct($content) { $this->content = $content; } /** * Determine if the rule passes validation. * * @param array $values * @return bool */ public function matches($values): bool { $position = 0; foreach ($values as $value) { if (empty($value)) { continue; } $valuePosition = mb_strpos($this->content, $value, $position); if ($valuePosition === false || $valuePosition < $position) { $this->failedValue = $value; return false; } $position = $valuePosition + mb_strlen($value); } return true; } /** * Get the description of the failure. * * @param array $values * @return string */ public function failureDescription($values): string { return sprintf( 'Failed asserting that \'%s\' contains "%s" in specified order.', $this->content, $this->failedValue ); } /** * Get a string representation of the object. * * @return string */ public function toString(): string { return (new ReflectionClass($this))->name; } } PK������y Z q ��q ��0��Illuminate/Testing/Constraints/HasInDatabase.phpnu�W+A��������<?php namespace Illuminate\Testing\Constraints; use Illuminate\Database\Connection; use Illuminate\Database\Query\Expression; use PHPUnit\Framework\Constraint\Constraint; class HasInDatabase extends Constraint { /** * Number of records that will be shown in the console in case of failure. * * @var int */ protected $show = 3; /** * The database connection. * * @var \Illuminate\Database\Connection */ protected $database; /** * The data that will be used to narrow the search in the database table. * * @var array */ protected $data; /** * Create a new constraint instance. * * @param \Illuminate\Database\Connection $database * @param array $data * @return void */ public function __construct(Connection $database, array $data) { $this->data = $data; $this->database = $database; } /** * Check if the data is found in the given table. * * @param string $table * @return bool */ public function matches($table): bool { return $this->database->table($table)->where($this->data)->count() > 0; } /** * Get the description of the failure. * * @param string $table * @return string */ public function failureDescription($table): string { return sprintf( "a row in the table [%s] matches the attributes %s.\n\n%s", $table, $this->toString(JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), $this->getAdditionalInfo($table) ); } /** * Get additional info about the records found in the database table. * * @param string $table * @return string */ protected function getAdditionalInfo($table) { $query = $this->database->table($table); $similarResults = $query->where( array_key_first($this->data), $this->data[array_key_first($this->data)] )->select(array_keys($this->data))->limit($this->show)->get(); if ($similarResults->isNotEmpty()) { $description = 'Found similar results: '.json_encode($similarResults, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); } else { $query = $this->database->table($table); $results = $query->select(array_keys($this->data))->limit($this->show)->get(); if ($results->isEmpty()) { return 'The table is empty'; } $description = 'Found: '.json_encode($results, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); } if ($query->count() > $this->show) { $description .= sprintf(' and %s others', $query->count() - $this->show); } return $description; } /** * Get a string representation of the object. * * @param int $options * @return string */ public function toString($options = 0): string { foreach ($this->data as $key => $data) { $output[$key] = $data instanceof Expression ? (string) $data : $data; } return json_encode($output ?? [], $options); } } PK������y Z\̱ �� ��;��Illuminate/Testing/Constraints/NotSoftDeletedInDatabase.phpnu�W+A��������<?php namespace Illuminate\Testing\Constraints; use Illuminate\Database\Connection; use PHPUnit\Framework\Constraint\Constraint; class NotSoftDeletedInDatabase extends Constraint { /** * Number of records that will be shown in the console in case of failure. * * @var int */ protected $show = 3; /** * The database connection. * * @var \Illuminate\Database\Connection */ protected $database; /** * The data that will be used to narrow the search in the database table. * * @var array */ protected $data; /** * The name of the column that indicates soft deletion has occurred. * * @var string */ protected $deletedAtColumn; /** * Create a new constraint instance. * * @param \Illuminate\Database\Connection $database * @param array $data * @param string $deletedAtColumn * @return void */ public function __construct(Connection $database, array $data, string $deletedAtColumn) { $this->database = $database; $this->data = $data; $this->deletedAtColumn = $deletedAtColumn; } /** * Check if the data is found in the given table. * * @param string $table * @return bool */ public function matches($table): bool { return $this->database->table($table) ->where($this->data) ->whereNull($this->deletedAtColumn) ->count() > 0; } /** * Get the description of the failure. * * @param string $table * @return string */ public function failureDescription($table): string { return sprintf( "any existing row in the table [%s] matches the attributes %s.\n\n%s", $table, $this->toString(), $this->getAdditionalInfo($table) ); } /** * Get additional info about the records found in the database table. * * @param string $table * @return string */ protected function getAdditionalInfo($table) { $query = $this->database->table($table); $results = $query->limit($this->show)->get(); if ($results->isEmpty()) { return 'The table is empty'; } $description = 'Found: '.json_encode($results, JSON_PRETTY_PRINT); if ($query->count() > $this->show) { $description .= sprintf(' and %s others', $query->count() - $this->show); } return $description; } /** * Get a string representation of the object. * * @return string */ public function toString(): string { return json_encode($this->data); } } PK������y Z,;!��;!��.��Illuminate/Testing/Constraints/ArraySubset.phpnu�W+A��������<?php namespace Illuminate\Testing\Constraints; use ArrayObject; use PHPUnit\Framework\Constraint\Constraint; use PHPUnit\Runner\Version; use SebastianBergmann\Comparator\ComparisonFailure; use Traversable; if (class_exists(Version::class) && (int) Version::series()[0] >= 9) { /** * @internal This class is not meant to be used or overwritten outside the framework itself. */ final class ArraySubset extends Constraint { /** * @var iterable */ private $subset; /** * @var bool */ private $strict; /** * Create a new array subset constraint instance. * * @param iterable $subset * @param bool $strict * @return void */ public function __construct(iterable $subset, bool $strict = false) { $this->strict = $strict; $this->subset = $subset; } /** * Evaluates the constraint for parameter $other. * * If $returnResult is set to false (the default), an exception is thrown * in case of a failure. null is returned otherwise. * * If $returnResult is true, the result of the evaluation is returned as * a boolean value instead: true in case of success, false in case of a * failure. * * @param mixed $other * @param string $description * @param bool $returnResult * @return bool|null * * @throws \PHPUnit\Framework\ExpectationFailedException * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException */ public function evaluate($other, string $description = '', bool $returnResult = false): ?bool { // type cast $other & $this->subset as an array to allow // support in standard array functions. $other = $this->toArray($other); $this->subset = $this->toArray($this->subset); $patched = array_replace_recursive($other, $this->subset); if ($this->strict) { $result = $other === $patched; } else { $result = $other == $patched; } if ($returnResult) { return $result; } if (! $result) { $f = new ComparisonFailure( $patched, $other, var_export($patched, true), var_export($other, true) ); $this->fail($other, $description, $f); } return null; } /** * Returns a string representation of the constraint. * * @return string * * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException */ public function toString(): string { return 'has the subset '.$this->exporter()->export($this->subset); } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. * * @param mixed $other * @return string * * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException */ protected function failureDescription($other): string { return 'an array '.$this->toString(); } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. * * @param iterable $other * @return array */ private function toArray(iterable $other): array { if (is_array($other)) { return $other; } if ($other instanceof ArrayObject) { return $other->getArrayCopy(); } if ($other instanceof Traversable) { return iterator_to_array($other); } // Keep BC even if we know that array would not be the expected one return (array) $other; } } } else { /** * @internal This class is not meant to be used or overwritten outside the framework itself. */ final class ArraySubset extends Constraint { /** * @var iterable */ private $subset; /** * @var bool */ private $strict; /** * Create a new array subset constraint instance. * * @param iterable $subset * @param bool $strict * @return void */ public function __construct(iterable $subset, bool $strict = false) { $this->strict = $strict; $this->subset = $subset; } /** * Evaluates the constraint for parameter $other. * * If $returnResult is set to false (the default), an exception is thrown * in case of a failure. null is returned otherwise. * * If $returnResult is true, the result of the evaluation is returned as * a boolean value instead: true in case of success, false in case of a * failure. * * @param mixed $other * @param string $description * @param bool $returnResult * @return bool|null * * @throws \PHPUnit\Framework\ExpectationFailedException * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException */ public function evaluate($other, string $description = '', bool $returnResult = false) { // type cast $other & $this->subset as an array to allow // support in standard array functions. $other = $this->toArray($other); $this->subset = $this->toArray($this->subset); $patched = array_replace_recursive($other, $this->subset); if ($this->strict) { $result = $other === $patched; } else { $result = $other == $patched; } if ($returnResult) { return $result; } if (! $result) { $f = new ComparisonFailure( $patched, $other, var_export($patched, true), var_export($other, true) ); $this->fail($other, $description, $f); } } /** * Returns a string representation of the constraint. * * @return string * * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException */ public function toString(): string { return 'has the subset '.$this->exporter()->export($this->subset); } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. * * @param mixed $other * @return string * * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException */ protected function failureDescription($other): string { return 'an array '.$this->toString(); } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. * * @param iterable $other * @return array */ private function toArray(iterable $other): array { if (is_array($other)) { return $other; } if ($other instanceof ArrayObject) { return $other->getArrayCopy(); } if ($other instanceof Traversable) { return iterator_to_array($other); } // Keep BC even if we know that array would not be the expected one return (array) $other; } } } PK������y Z6"#q��q��2��Illuminate/Testing/Constraints/CountInDatabase.phpnu�W+A��������<?php namespace Illuminate\Testing\Constraints; use Illuminate\Database\Connection; use PHPUnit\Framework\Constraint\Constraint; use ReflectionClass; class CountInDatabase extends Constraint { /** * The database connection. * * @var \Illuminate\Database\Connection */ protected $database; /** * The expected table entries count that will be checked against the actual count. * * @var int */ protected $expectedCount; /** * The actual table entries count that will be checked against the expected count. * * @var int */ protected $actualCount; /** * Create a new constraint instance. * * @param \Illuminate\Database\Connection $database * @param int $expectedCount * @return void */ public function __construct(Connection $database, int $expectedCount) { $this->expectedCount = $expectedCount; $this->database = $database; } /** * Check if the expected and actual count are equal. * * @param string $table * @return bool */ public function matches($table): bool { $this->actualCount = $this->database->table($table)->count(); return $this->actualCount === $this->expectedCount; } /** * Get the description of the failure. * * @param string $table * @return string */ public function failureDescription($table): string { return sprintf( "table [%s] matches expected entries count of %s. Entries found: %s.\n", $table, $this->expectedCount, $this->actualCount ); } /** * Get a string representation of the object. * * @param int $options * @return string */ public function toString($options = 0): string { return (new ReflectionClass($this))->name; } } PK������y Z? �� ��8��Illuminate/Testing/Constraints/SoftDeletedInDatabase.phpnu�W+A��������<?php namespace Illuminate\Testing\Constraints; use Illuminate\Database\Connection; use PHPUnit\Framework\Constraint\Constraint; class SoftDeletedInDatabase extends Constraint { /** * Number of records that will be shown in the console in case of failure. * * @var int */ protected $show = 3; /** * The database connection. * * @var \Illuminate\Database\Connection */ protected $database; /** * The data that will be used to narrow the search in the database table. * * @var array */ protected $data; /** * The name of the column that indicates soft deletion has occurred. * * @var string */ protected $deletedAtColumn; /** * Create a new constraint instance. * * @param \Illuminate\Database\Connection $database * @param array $data * @param string $deletedAtColumn * @return void */ public function __construct(Connection $database, array $data, string $deletedAtColumn) { $this->data = $data; $this->database = $database; $this->deletedAtColumn = $deletedAtColumn; } /** * Check if the data is found in the given table. * * @param string $table * @return bool */ public function matches($table): bool { return $this->database->table($table) ->where($this->data) ->whereNotNull($this->deletedAtColumn) ->count() > 0; } /** * Get the description of the failure. * * @param string $table * @return string */ public function failureDescription($table): string { return sprintf( "any soft deleted row in the table [%s] matches the attributes %s.\n\n%s", $table, $this->toString(), $this->getAdditionalInfo($table) ); } /** * Get additional info about the records found in the database table. * * @param string $table * @return string */ protected function getAdditionalInfo($table) { $query = $this->database->table($table); $results = $query->limit($this->show)->get(); if ($results->isEmpty()) { return 'The table is empty'; } $description = 'Found: '.json_encode($results, JSON_PRETTY_PRINT); if ($query->count() > $this->show) { $description .= sprintf(' and %s others', $query->count() - $this->show); } return $description; } /** * Get a string representation of the object. * * @return string */ public function toString(): string { return json_encode($this->data); } } PK������y Z;k �� ����Illuminate/Testing/Assert.phpnu�W+A��������<?php namespace Illuminate\Testing; use ArrayAccess; use Illuminate\Testing\Constraints\ArraySubset; use PHPUnit\Framework\Assert as PHPUnit; use PHPUnit\Framework\Constraint\DirectoryExists; use PHPUnit\Framework\Constraint\FileExists; use PHPUnit\Framework\Constraint\LogicalNot; use PHPUnit\Framework\Constraint\RegularExpression; use PHPUnit\Framework\InvalidArgumentException; /** * @internal This class is not meant to be used or overwritten outside the framework itself. */ abstract class Assert extends PHPUnit { /** * Asserts that an array has a specified subset. * * @param \ArrayAccess|array $subset * @param \ArrayAccess|array $array * @param bool $checkForIdentity * @param string $msg * @return void */ public static function assertArraySubset($subset, $array, bool $checkForIdentity = false, string $msg = ''): void { if (! (is_array($subset) || $subset instanceof ArrayAccess)) { throw InvalidArgumentException::create(1, 'array or ArrayAccess'); } if (! (is_array($array) || $array instanceof ArrayAccess)) { throw InvalidArgumentException::create(2, 'array or ArrayAccess'); } $constraint = new ArraySubset($subset, $checkForIdentity); PHPUnit::assertThat($array, $constraint, $msg); } /** * Asserts that a file does not exist. * * @param string $filename * @param string $message * @return void */ public static function assertFileDoesNotExist(string $filename, string $message = ''): void { static::assertThat($filename, new LogicalNot(new FileExists), $message); } /** * Asserts that a directory does not exist. * * @param string $directory * @param string $message * @return void */ public static function assertDirectoryDoesNotExist(string $directory, string $message = ''): void { static::assertThat($directory, new LogicalNot(new DirectoryExists), $message); } /** * Asserts that a string matches a given regular expression. * * @param string $pattern * @param string $string * @param string $message * @return void */ public static function assertMatchesRegularExpression(string $pattern, string $string, string $message = ''): void { static::assertThat($string, new RegularExpression($pattern), $message); } } PK������y ZjE)��)��+��Illuminate/Testing/AssertableJsonString.phpnu�W+A��������<?php namespace Illuminate\Testing; use ArrayAccess; use Closure; use Countable; use Illuminate\Contracts\Support\Jsonable; use Illuminate\Support\Arr; use Illuminate\Support\Str; use Illuminate\Testing\Assert as PHPUnit; use JsonSerializable; class AssertableJsonString implements ArrayAccess, Countable { /** * The original encoded json. * * @var \Illuminate\Contracts\Support\Jsonable|\JsonSerializable|array|string */ public $json; /** * The decoded json contents. * * @var array|null */ protected $decoded; /** * Create a new assertable JSON string instance. * * @param \Illuminate\Contracts\Support\Jsonable|\JsonSerializable|array|string $jsonable * @return void */ public function __construct($jsonable) { $this->json = $jsonable; if ($jsonable instanceof JsonSerializable) { $this->decoded = $jsonable->jsonSerialize(); } elseif ($jsonable instanceof Jsonable) { $this->decoded = json_decode($jsonable->toJson(), true); } elseif (is_array($jsonable)) { $this->decoded = $jsonable; } else { $this->decoded = json_decode($jsonable, true); } } /** * Validate and return the decoded response JSON. * * @param string|null $key * @return mixed */ public function json($key = null) { return data_get($this->decoded, $key); } /** * Assert that the response JSON has the expected count of items at the given key. * * @param int $count * @param string|null $key * @return $this */ public function assertCount(int $count, $key = null) { if (! is_null($key)) { PHPUnit::assertCount( $count, data_get($this->decoded, $key), "Failed to assert that the response count matched the expected {$count}" ); return $this; } PHPUnit::assertCount($count, $this->decoded, "Failed to assert that the response count matched the expected {$count}" ); return $this; } /** * Assert that the response has the exact given JSON. * * @param array $data * @return $this */ public function assertExact(array $data) { $actual = $this->reorderAssocKeys((array) $this->decoded); $expected = $this->reorderAssocKeys($data); PHPUnit::assertEquals( json_encode($expected, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES), json_encode($actual, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) ); return $this; } /** * Assert that the response has the similar JSON as given. * * @param array $data * @return $this */ public function assertSimilar(array $data) { $actual = json_encode( Arr::sortRecursive((array) $this->decoded), JSON_UNESCAPED_UNICODE ); PHPUnit::assertEquals(json_encode(Arr::sortRecursive($data), JSON_UNESCAPED_UNICODE), $actual); return $this; } /** * Assert that the response contains the given JSON fragment. * * @param array $data * @return $this */ public function assertFragment(array $data) { $actual = json_encode( Arr::sortRecursive((array) $this->decoded), JSON_UNESCAPED_UNICODE ); foreach (Arr::sortRecursive($data) as $key => $value) { $expected = $this->jsonSearchStrings($key, $value); PHPUnit::assertTrue( Str::contains($actual, $expected), 'Unable to find JSON fragment: '.PHP_EOL.PHP_EOL. '['.json_encode([$key => $value], JSON_UNESCAPED_UNICODE).']'.PHP_EOL.PHP_EOL. 'within'.PHP_EOL.PHP_EOL. "[{$actual}]." ); } return $this; } /** * Assert that the response does not contain the given JSON fragment. * * @param array $data * @param bool $exact * @return $this */ public function assertMissing(array $data, $exact = false) { if ($exact) { return $this->assertMissingExact($data); } $actual = json_encode( Arr::sortRecursive((array) $this->decoded), JSON_UNESCAPED_UNICODE ); foreach (Arr::sortRecursive($data) as $key => $value) { $unexpected = $this->jsonSearchStrings($key, $value); PHPUnit::assertFalse( Str::contains($actual, $unexpected), 'Found unexpected JSON fragment: '.PHP_EOL.PHP_EOL. '['.json_encode([$key => $value], JSON_UNESCAPED_UNICODE).']'.PHP_EOL.PHP_EOL. 'within'.PHP_EOL.PHP_EOL. "[{$actual}]." ); } return $this; } /** * Assert that the response does not contain the exact JSON fragment. * * @param array $data * @return $this */ public function assertMissingExact(array $data) { $actual = json_encode( Arr::sortRecursive((array) $this->decoded), JSON_UNESCAPED_UNICODE ); foreach (Arr::sortRecursive($data) as $key => $value) { $unexpected = $this->jsonSearchStrings($key, $value); if (! Str::contains($actual, $unexpected)) { return $this; } } PHPUnit::fail( 'Found unexpected JSON fragment: '.PHP_EOL.PHP_EOL. '['.json_encode($data, JSON_UNESCAPED_UNICODE).']'.PHP_EOL.PHP_EOL. 'within'.PHP_EOL.PHP_EOL. "[{$actual}]." ); return $this; } /** * Assert that the response does not contain the given path. * * @param string $path * @return $this */ public function assertMissingPath($path) { PHPUnit::assertFalse(Arr::has($this->json(), $path)); return $this; } /** * Assert that the expected value and type exists at the given path in the response. * * @param string $path * @param mixed $expect * @return $this */ public function assertPath($path, $expect) { if ($expect instanceof Closure) { PHPUnit::assertTrue($expect($this->json($path))); } else { PHPUnit::assertSame($expect, $this->json($path)); } return $this; } /** * Assert that the response has a given JSON structure. * * @param array|null $structure * @param array|null $responseData * @return $this */ public function assertStructure(array $structure = null, $responseData = null) { if (is_null($structure)) { return $this->assertSimilar($this->decoded); } if (! is_null($responseData)) { return (new static($responseData))->assertStructure($structure); } foreach ($structure as $key => $value) { if (is_array($value) && $key === '*') { PHPUnit::assertIsArray($this->decoded); foreach ($this->decoded as $responseDataItem) { $this->assertStructure($structure['*'], $responseDataItem); } } elseif (is_array($value)) { PHPUnit::assertArrayHasKey($key, $this->decoded); $this->assertStructure($structure[$key], $this->decoded[$key]); } else { PHPUnit::assertArrayHasKey($value, $this->decoded); } } return $this; } /** * Assert that the response is a superset of the given JSON. * * @param array $data * @param bool $strict * @return $this */ public function assertSubset(array $data, $strict = false) { PHPUnit::assertArraySubset( $data, $this->decoded, $strict, $this->assertJsonMessage($data) ); return $this; } /** * Reorder associative array keys to make it easy to compare arrays. * * @param array $data * @return array */ protected function reorderAssocKeys(array $data) { $data = Arr::dot($data); ksort($data); $result = []; foreach ($data as $key => $value) { Arr::set($result, $key, $value); } return $result; } /** * Get the assertion message for assertJson. * * @param array $data * @return string */ protected function assertJsonMessage(array $data) { $expected = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); $actual = json_encode($this->decoded, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); return 'Unable to find JSON: '.PHP_EOL.PHP_EOL. "[{$expected}]".PHP_EOL.PHP_EOL. 'within response JSON:'.PHP_EOL.PHP_EOL. "[{$actual}].".PHP_EOL.PHP_EOL; } /** * Get the strings we need to search for when examining the JSON. * * @param string $key * @param string $value * @return array */ protected function jsonSearchStrings($key, $value) { $needle = Str::substr(json_encode([$key => $value], JSON_UNESCAPED_UNICODE), 1, -1); return [ $needle.']', $needle.'}', $needle.',', ]; } /** * Get the total number of items in the underlying JSON array. * * @return int */ public function count(): int { return count($this->decoded); } /** * Determine whether an offset exists. * * @param mixed $offset * @return bool */ public function offsetExists($offset): bool { return isset($this->decoded[$offset]); } /** * Get the value at the given offset. * * @param string $offset * @return mixed */ public function offsetGet($offset): mixed { return $this->decoded[$offset]; } /** * Set the value at the given offset. * * @param string $offset * @param mixed $value * @return void */ public function offsetSet($offset, $value): void { $this->decoded[$offset] = $value; } /** * Unset the value at the given offset. * * @param string $offset * @return void */ public function offsetUnset($offset): void { unset($this->decoded[$offset]); } } PK������y ZSÿ����%��Illuminate/Testing/ParallelRunner.phpnu�W+A��������<?php namespace Illuminate\Testing; use Illuminate\Contracts\Console\Kernel; use Illuminate\Support\Facades\ParallelTesting; use ParaTest\Runners\PHPUnit\Options; use ParaTest\Runners\PHPUnit\RunnerInterface; use ParaTest\Runners\PHPUnit\WrapperRunner; use PHPUnit\TextUI\XmlConfiguration\PhpHandler; use RuntimeException; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\OutputInterface; class ParallelRunner implements RunnerInterface { /** * The application resolver callback. * * @var \Closure|null */ protected static $applicationResolver; /** * The runner resolver callback. * * @var \Closure|null */ protected static $runnerResolver; /** * The original test runner options. * * @var \ParaTest\Runners\PHPUnit\Options */ protected $options; /** * The output instance. * * @var \Symfony\Component\Console\Output\OutputInterface */ protected $output; /** * The original test runner. * * @var \ParaTest\Runners\PHPUnit\RunnerInterface */ protected $runner; /** * Creates a new test runner instance. * * @param \ParaTest\Runners\PHPUnit\Options $options * @param \Symfony\Component\Console\Output\OutputInterface $output * @return void */ public function __construct(Options $options, OutputInterface $output) { $this->options = $options; if ($output instanceof ConsoleOutput) { $output = new ParallelConsoleOutput($output); } $runnerResolver = static::$runnerResolver ?: function (Options $options, OutputInterface $output) { return new WrapperRunner($options, $output); }; $this->runner = $runnerResolver($options, $output); } /** * Set the application resolver callback. * * @param \Closure|null $resolver * @return void */ public static function resolveApplicationUsing($resolver) { static::$applicationResolver = $resolver; } /** * Set the runner resolver callback. * * @param \Closure|null $resolver * @return void */ public static function resolveRunnerUsing($resolver) { static::$runnerResolver = $resolver; } /** * Runs the test suite. * * @return void */ public function run(): void { (new PhpHandler)->handle($this->options->configuration()->php()); $this->forEachProcess(function () { ParallelTesting::callSetUpProcessCallbacks(); }); try { $this->runner->run(); } finally { $this->forEachProcess(function () { ParallelTesting::callTearDownProcessCallbacks(); }); } } /** * Returns the highest exit code encountered throughout the course of test execution. * * @return int */ public function getExitCode(): int { return $this->runner->getExitCode(); } /** * Apply the given callback for each process. * * @param callable $callback * @return void */ protected function forEachProcess($callback) { collect(range(1, $this->options->processes()))->each(function ($token) use ($callback) { tap($this->createApplication(), function ($app) use ($callback, $token) { ParallelTesting::resolveTokenUsing(fn () => $token); $callback($app); })->flush(); }); } /** * Creates the application. * * @return \Illuminate\Contracts\Foundation\Application * * @throws \RuntimeException */ protected function createApplication() { $applicationResolver = static::$applicationResolver ?: function () { if (trait_exists(\Tests\CreatesApplication::class)) { $applicationCreator = new class { use \Tests\CreatesApplication; }; return $applicationCreator->createApplication(); } elseif (file_exists(getcwd().'/bootstrap/app.php')) { $app = require getcwd().'/bootstrap/app.php'; $app->make(Kernel::class)->bootstrap(); return $app; } throw new RuntimeException('Parallel Runner unable to resolve application.'); }; return $applicationResolver(); } } PK������y Zʶl��l�� ��Illuminate/Testing/composer.jsonnu�W+A��������{ "name": "illuminate/testing", "description": "The Illuminate Testing package.", "license": "MIT", "homepage": "https://laravel.com", "support": { "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, "authors": [ { "name": "Taylor Otwell", "email": "taylor@laravel.com" } ], "require": { "php": "^8.0.2", "ext-mbstring": "*", "illuminate/collections": "^9.0", "illuminate/contracts": "^9.0", "illuminate/macroable": "^9.0", "illuminate/support": "^9.0" }, "autoload": { "psr-4": { "Illuminate\\Testing\\": "" } }, "extra": { "branch-alias": { "dev-master": "9.x-dev" } }, "suggest": { "brianium/paratest": "Required to run tests in parallel (^6.0).", "illuminate/console": "Required to assert console commands (^9.0).", "illuminate/database": "Required to assert databases (^9.0).", "illuminate/http": "Required to assert responses (^9.0).", "mockery/mockery": "Required to use mocking (^1.5.1).", "phpunit/phpunit": "Required to use assertions and run tests (^9.5.8)." }, "config": { "sort-packages": true }, "minimum-stability": "dev" } PK������y ZU��U��/��Illuminate/Testing/Fluent/Concerns/Matching.phpnu�W+A��������<?php namespace Illuminate\Testing\Fluent\Concerns; use Closure; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Support\Collection; use PHPUnit\Framework\Assert as PHPUnit; trait Matching { /** * Asserts that the property matches the expected value. * * @param string $key * @param mixed|\Closure $expected * @return $this */ public function where(string $key, $expected): self { $this->has($key); $actual = $this->prop($key); if ($expected instanceof Closure) { PHPUnit::assertTrue( $expected(is_array($actual) ? Collection::make($actual) : $actual), sprintf('Property [%s] was marked as invalid using a closure.', $this->dotPath($key)) ); return $this; } if ($expected instanceof Arrayable) { $expected = $expected->toArray(); } $this->ensureSorted($expected); $this->ensureSorted($actual); PHPUnit::assertSame( $expected, $actual, sprintf('Property [%s] does not match the expected value.', $this->dotPath($key)) ); return $this; } /** * Asserts that the property does not match the expected value. * * @param string $key * @param mixed|\Closure $expected * @return $this */ public function whereNot(string $key, $expected): self { $this->has($key); $actual = $this->prop($key); if ($expected instanceof Closure) { PHPUnit::assertFalse( $expected(is_array($actual) ? Collection::make($actual) : $actual), sprintf('Property [%s] was marked as invalid using a closure.', $this->dotPath($key)) ); return $this; } if ($expected instanceof Arrayable) { $expected = $expected->toArray(); } $this->ensureSorted($expected); $this->ensureSorted($actual); PHPUnit::assertNotSame( $expected, $actual, sprintf( 'Property [%s] contains a value that should be missing: [%s, %s]', $this->dotPath($key), $key, $expected ) ); return $this; } /** * Asserts that all properties match their expected values. * * @param array $bindings * @return $this */ public function whereAll(array $bindings): self { foreach ($bindings as $key => $value) { $this->where($key, $value); } return $this; } /** * Asserts that the property is of the expected type. * * @param string $key * @param string|array $expected * @return $this */ public function whereType(string $key, $expected): self { $this->has($key); $actual = $this->prop($key); if (! is_array($expected)) { $expected = explode('|', $expected); } PHPUnit::assertContains( strtolower(gettype($actual)), $expected, sprintf('Property [%s] is not of expected type [%s].', $this->dotPath($key), implode('|', $expected)) ); return $this; } /** * Asserts that all properties are of their expected types. * * @param array $bindings * @return $this */ public function whereAllType(array $bindings): self { foreach ($bindings as $key => $value) { $this->whereType($key, $value); } return $this; } /** * Asserts that the property contains the expected values. * * @param string $key * @param mixed $expected * @return $this */ public function whereContains(string $key, $expected) { $actual = Collection::make( $this->prop($key) ?? $this->prop() ); $missing = Collection::make($expected)->reject(function ($search) use ($key, $actual) { if ($actual->containsStrict($key, $search)) { return true; } return $actual->containsStrict($search); }); if ($missing->whereInstanceOf('Closure')->isNotEmpty()) { PHPUnit::assertEmpty( $missing->toArray(), sprintf( 'Property [%s] does not contain a value that passes the truth test within the given closure.', $key, ) ); } else { PHPUnit::assertEmpty( $missing->toArray(), sprintf( 'Property [%s] does not contain [%s].', $key, implode(', ', array_values($missing->toArray())) ) ); } return $this; } /** * Ensures that all properties are sorted the same way, recursively. * * @param mixed $value * @return void */ protected function ensureSorted(&$value): void { if (! is_array($value)) { return; } foreach ($value as &$arg) { $this->ensureSorted($arg); } ksort($value); } /** * Compose the absolute "dot" path to the given key. * * @param string $key * @return string */ abstract protected function dotPath(string $key = ''): string; /** * Ensure that the given prop exists. * * @param string $key * @param null $value * @param \Closure|null $scope * @return $this */ abstract public function has(string $key, $value = null, Closure $scope = null); /** * Retrieve a prop within the current scope using "dot" notation. * * @param string|null $key * @return mixed */ abstract protected function prop(string $key = null); } PK������y Zj����2��Illuminate/Testing/Fluent/Concerns/Interaction.phpnu�W+A��������<?php namespace Illuminate\Testing\Fluent\Concerns; use Illuminate\Support\Str; use PHPUnit\Framework\Assert as PHPUnit; trait Interaction { /** * The list of interacted properties. * * @var array */ protected $interacted = []; /** * Marks the property as interacted. * * @param string $key * @return void */ protected function interactsWith(string $key): void { $prop = Str::before($key, '.'); if (! in_array($prop, $this->interacted, true)) { $this->interacted[] = $prop; } } /** * Asserts that all properties have been interacted with. * * @return void */ public function interacted(): void { PHPUnit::assertSame( [], array_diff(array_keys($this->prop()), $this->interacted), $this->path ? sprintf('Unexpected properties were found in scope [%s].', $this->path) : 'Unexpected properties were found on the root level.' ); } /** * Disables the interaction check. * * @return $this */ public function etc(): self { $this->interacted = array_keys($this->prop()); return $this; } /** * Retrieve a prop within the current scope using "dot" notation. * * @param string|null $key * @return mixed */ abstract protected function prop(string $key = null); } PK������y Z-����*��Illuminate/Testing/Fluent/Concerns/Has.phpnu�W+A��������<?php namespace Illuminate\Testing\Fluent\Concerns; use Closure; use Illuminate\Support\Arr; use PHPUnit\Framework\Assert as PHPUnit; trait Has { /** * Assert that the prop is of the expected size. * * @param string|int $key * @param int|null $length * @return $this */ public function count($key, int $length = null): self { if (is_null($length)) { $path = $this->dotPath(); PHPUnit::assertCount( $key, $this->prop(), $path ? sprintf('Property [%s] does not have the expected size.', $path) : sprintf('Root level does not have the expected size.') ); return $this; } PHPUnit::assertCount( $length, $this->prop($key), sprintf('Property [%s] does not have the expected size.', $this->dotPath($key)) ); return $this; } /** * Ensure that the given prop exists. * * @param string|int $key * @param int|\Closure|null $length * @param \Closure|null $callback * @return $this */ public function has($key, $length = null, Closure $callback = null): self { $prop = $this->prop(); if (is_int($key) && is_null($length)) { return $this->count($key); } PHPUnit::assertTrue( Arr::has($prop, $key), sprintf('Property [%s] does not exist.', $this->dotPath($key)) ); $this->interactsWith($key); if (! is_null($callback)) { return $this->has($key, function (self $scope) use ($length, $callback) { return $scope ->tap(function (self $scope) use ($length) { if (! is_null($length)) { $scope->count($length); } }) ->first($callback) ->etc(); }); } if (is_callable($length)) { return $this->scope($key, $length); } if (! is_null($length)) { return $this->count($key, $length); } return $this; } /** * Assert that all of the given props exist. * * @param array|string $key * @return $this */ public function hasAll($key): self { $keys = is_array($key) ? $key : func_get_args(); foreach ($keys as $prop => $count) { if (is_int($prop)) { $this->has($count); } else { $this->has($prop, $count); } } return $this; } /** * Assert that at least one of the given props exists. * * @param array|string $key * @return $this */ public function hasAny($key): self { $keys = is_array($key) ? $key : func_get_args(); PHPUnit::assertTrue( Arr::hasAny($this->prop(), $keys), sprintf('None of properties [%s] exist.', implode(', ', $keys)) ); foreach ($keys as $key) { $this->interactsWith($key); } return $this; } /** * Assert that none of the given props exist. * * @param array|string $key * @return $this */ public function missingAll($key): self { $keys = is_array($key) ? $key : func_get_args(); foreach ($keys as $prop) { $this->missing($prop); } return $this; } /** * Assert that the given prop does not exist. * * @param string $key * @return $this */ public function missing(string $key): self { PHPUnit::assertNotTrue( Arr::has($this->prop(), $key), sprintf('Property [%s] was found while it was expected to be missing.', $this->dotPath($key)) ); return $this; } /** * Compose the absolute "dot" path to the given key. * * @param string $key * @return string */ abstract protected function dotPath(string $key = ''): string; /** * Marks the property as interacted. * * @param string $key * @return void */ abstract protected function interactsWith(string $key): void; /** * Retrieve a prop within the current scope using "dot" notation. * * @param string|null $key * @return mixed */ abstract protected function prop(string $key = null); /** * Instantiate a new "scope" at the path of the given key. * * @param string $key * @param \Closure $callback * @return $this */ abstract protected function scope(string $key, Closure $callback); /** * Disables the interaction check. * * @return $this */ abstract public function etc(); /** * Instantiate a new "scope" on the first element. * * @param \Closure $callback * @return $this */ abstract public function first(Closure $callback); } PK������y Z,����0��Illuminate/Testing/Fluent/Concerns/Debugging.phpnu�W+A��������<?php namespace Illuminate\Testing\Fluent\Concerns; trait Debugging { /** * Dumps the given props. * * @param string|null $prop * @return $this */ public function dump(string $prop = null): self { dump($this->prop($prop)); return $this; } /** * Dumps the given props and exits. * * @param string|null $prop * @return never */ public function dd(string $prop = null): void { dd($this->prop($prop)); } /** * Retrieve a prop within the current scope using "dot" notation. * * @param string|null $key * @return mixed */ abstract protected function prop(string $key = null); } PK������y Z0k��k��,��Illuminate/Testing/Fluent/AssertableJson.phpnu�W+A��������<?php namespace Illuminate\Testing\Fluent; use Closure; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Support\Arr; use Illuminate\Support\Traits\Macroable; use Illuminate\Support\Traits\Tappable; use Illuminate\Testing\AssertableJsonString; use PHPUnit\Framework\Assert as PHPUnit; class AssertableJson implements Arrayable { use Concerns\Has, Concerns\Matching, Concerns\Debugging, Concerns\Interaction, Macroable, Tappable; /** * The properties in the current scope. * * @var array */ private $props; /** * The "dot" path to the current scope. * * @var string|null */ private $path; /** * Create a new fluent, assertable JSON data instance. * * @param array $props * @param string|null $path * @return void */ protected function __construct(array $props, string $path = null) { $this->path = $path; $this->props = $props; } /** * Compose the absolute "dot" path to the given key. * * @param string $key * @return string */ protected function dotPath(string $key = ''): string { if (is_null($this->path)) { return $key; } return rtrim(implode('.', [$this->path, $key]), '.'); } /** * Retrieve a prop within the current scope using "dot" notation. * * @param string|null $key * @return mixed */ protected function prop(string $key = null) { return Arr::get($this->props, $key); } /** * Instantiate a new "scope" at the path of the given key. * * @param string $key * @param \Closure $callback * @return $this */ protected function scope(string $key, Closure $callback): self { $props = $this->prop($key); $path = $this->dotPath($key); PHPUnit::assertIsArray($props, sprintf('Property [%s] is not scopeable.', $path)); $scope = new static($props, $path); $callback($scope); $scope->interacted(); return $this; } /** * Instantiate a new "scope" on the first child element. * * @param \Closure $callback * @return $this */ public function first(Closure $callback): self { $props = $this->prop(); $path = $this->dotPath(); PHPUnit::assertNotEmpty($props, $path === '' ? 'Cannot scope directly onto the first element of the root level because it is empty.' : sprintf('Cannot scope directly onto the first element of property [%s] because it is empty.', $path) ); $key = array_keys($props)[0]; $this->interactsWith($key); return $this->scope($key, $callback); } /** * Instantiate a new "scope" on each child element. * * @param \Closure $callback * @return $this */ public function each(Closure $callback): self { $props = $this->prop(); $path = $this->dotPath(); PHPUnit::assertNotEmpty($props, $path === '' ? 'Cannot scope directly onto each element of the root level because it is empty.' : sprintf('Cannot scope directly onto each element of property [%s] because it is empty.', $path) ); foreach (array_keys($props) as $key) { $this->interactsWith($key); $this->scope($key, $callback); } return $this; } /** * Create a new instance from an array. * * @param array $data * @return static */ public static function fromArray(array $data): self { return new static($data); } /** * Create a new instance from an AssertableJsonString. * * @param \Illuminate\Testing\AssertableJsonString $json * @return static */ public static function fromAssertableJsonString(AssertableJsonString $json): self { return static::fromArray($json->json()); } /** * Get the instance as an array. * * @return array */ public function toArray() { return $this->props; } } PK������y ZX������&��Illuminate/Testing/ParallelTesting.phpnu�W+A��������<?php namespace Illuminate\Testing; use Illuminate\Contracts\Container\Container; use Illuminate\Support\Str; class ParallelTesting { /** * The container instance. * * @var \Illuminate\Contracts\Container\Container */ protected $container; /** * The options resolver callback. * * @var \Closure|null */ protected $optionsResolver; /** * The token resolver callback. * * @var \Closure|null */ protected $tokenResolver; /** * All of the registered "setUp" process callbacks. * * @var array */ protected $setUpProcessCallbacks = []; /** * All of the registered "setUp" test case callbacks. * * @var array */ protected $setUpTestCaseCallbacks = []; /** * All of the registered "setUp" test database callbacks. * * @var array */ protected $setUpTestDatabaseCallbacks = []; /** * All of the registered "tearDown" process callbacks. * * @var array */ protected $tearDownProcessCallbacks = []; /** * All of the registered "tearDown" test case callbacks. * * @var array */ protected $tearDownTestCaseCallbacks = []; /** * Create a new parallel testing instance. * * @param \Illuminate\Contracts\Container\Container $container * @return void */ public function __construct(Container $container) { $this->container = $container; } /** * Set a callback that should be used when resolving options. * * @param \Closure|null $resolver * @return void */ public function resolveOptionsUsing($resolver) { $this->optionsResolver = $resolver; } /** * Set a callback that should be used when resolving the unique process token. * * @param \Closure|null $resolver * @return void */ public function resolveTokenUsing($resolver) { $this->tokenResolver = $resolver; } /** * Register a "setUp" process callback. * * @param callable $callback * @return void */ public function setUpProcess($callback) { $this->setUpProcessCallbacks[] = $callback; } /** * Register a "setUp" test case callback. * * @param callable $callback * @return void */ public function setUpTestCase($callback) { $this->setUpTestCaseCallbacks[] = $callback; } /** * Register a "setUp" test database callback. * * @param callable $callback * @return void */ public function setUpTestDatabase($callback) { $this->setUpTestDatabaseCallbacks[] = $callback; } /** * Register a "tearDown" process callback. * * @param callable $callback * @return void */ public function tearDownProcess($callback) { $this->tearDownProcessCallbacks[] = $callback; } /** * Register a "tearDown" test case callback. * * @param callable $callback * @return void */ public function tearDownTestCase($callback) { $this->tearDownTestCaseCallbacks[] = $callback; } /** * Call all of the "setUp" process callbacks. * * @return void */ public function callSetUpProcessCallbacks() { $this->whenRunningInParallel(function () { foreach ($this->setUpProcessCallbacks as $callback) { $this->container->call($callback, [ 'token' => $this->token(), ]); } }); } /** * Call all of the "setUp" test case callbacks. * * @param \Illuminate\Foundation\Testing\TestCase $testCase * @return void */ public function callSetUpTestCaseCallbacks($testCase) { $this->whenRunningInParallel(function () use ($testCase) { foreach ($this->setUpTestCaseCallbacks as $callback) { $this->container->call($callback, [ 'testCase' => $testCase, 'token' => $this->token(), ]); } }); } /** * Call all of the "setUp" test database callbacks. * * @param string $database * @return void */ public function callSetUpTestDatabaseCallbacks($database) { $this->whenRunningInParallel(function () use ($database) { foreach ($this->setUpTestDatabaseCallbacks as $callback) { $this->container->call($callback, [ 'database' => $database, 'token' => $this->token(), ]); } }); } /** * Call all of the "tearDown" process callbacks. * * @return void */ public function callTearDownProcessCallbacks() { $this->whenRunningInParallel(function () { foreach ($this->tearDownProcessCallbacks as $callback) { $this->container->call($callback, [ 'token' => $this->token(), ]); } }); } /** * Call all of the "tearDown" test case callbacks. * * @param \Illuminate\Foundation\Testing\TestCase $testCase * @return void */ public function callTearDownTestCaseCallbacks($testCase) { $this->whenRunningInParallel(function () use ($testCase) { foreach ($this->tearDownTestCaseCallbacks as $callback) { $this->container->call($callback, [ 'testCase' => $testCase, 'token' => $this->token(), ]); } }); } /** * Get a parallel testing option. * * @param string $option * @return mixed */ public function option($option) { $optionsResolver = $this->optionsResolver ?: function ($option) { $option = 'LARAVEL_PARALLEL_TESTING_'.Str::upper($option); return $_SERVER[$option] ?? false; }; return $optionsResolver($option); } /** * Gets a unique test token. * * @return string|false */ public function token() { return $this->tokenResolver ? call_user_func($this->tokenResolver) : ($_SERVER['TEST_TOKEN'] ?? false); } /** * Apply the callback if tests are running in parallel. * * @param callable $callback * @return void */ protected function whenRunningInParallel($callback) { if ($this->inParallel()) { $callback(); } } /** * Indicates if the current tests are been run in parallel. * * @return bool */ protected function inParallel() { return ! empty($_SERVER['LARAVEL_PARALLEL_TESTING']) && $this->token(); } } PK������y ZOu����#��Illuminate/Testing/TestResponse.phpnu�W+A��������<?php namespace Illuminate\Testing; use ArrayAccess; use Closure; use Illuminate\Contracts\Support\MessageBag; use Illuminate\Contracts\View\View; use Illuminate\Cookie\CookieValuePrefix; use Illuminate\Database\Eloquent\Collection as EloquentCollection; use Illuminate\Database\Eloquent\Model; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Arr; use Illuminate\Support\Carbon; use Illuminate\Support\Collection; use Illuminate\Support\Str; use Illuminate\Support\Traits\Macroable; use Illuminate\Support\Traits\Tappable; use Illuminate\Support\ViewErrorBag; use Illuminate\Testing\Assert as PHPUnit; use Illuminate\Testing\Constraints\SeeInOrder; use Illuminate\Testing\Fluent\AssertableJson; use LogicException; use PHPUnit\Framework\ExpectationFailedException; use ReflectionProperty; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\StreamedResponse; /** * @mixin \Illuminate\Http\Response */ class TestResponse implements ArrayAccess { use Concerns\AssertsStatusCodes, Tappable, Macroable { __call as macroCall; } /** * The response to delegate to. * * @var \Illuminate\Http\Response */ public $baseResponse; /** * The collection of logged exceptions for the request. * * @var \Illuminate\Support\Collection */ public $exceptions; /** * The streamed content of the response. * * @var string */ protected $streamedContent; /** * Create a new test response instance. * * @param \Illuminate\Http\Response $response * @return void */ public function __construct($response) { $this->baseResponse = $response; $this->exceptions = new Collection; } /** * Create a new TestResponse from another response. * * @param \Illuminate\Http\Response $response * @return static */ public static function fromBaseResponse($response) { return new static($response); } /** * Assert that the response has a successful status code. * * @return $this */ public function assertSuccessful() { PHPUnit::assertTrue( $this->isSuccessful(), $this->statusMessageWithDetails('>=200, <300', $this->getStatusCode()) ); return $this; } /** * Assert that the response is a server error. * * @return $this */ public function assertServerError() { PHPUnit::assertTrue( $this->isServerError(), $this->statusMessageWithDetails('>=500, < 600', $this->getStatusCode()) ); return $this; } /** * Assert that the response has the given status code. * * @param int $status * @return $this */ public function assertStatus($status) { $message = $this->statusMessageWithDetails($status, $actual = $this->getStatusCode()); PHPUnit::assertSame($actual, $status, $message); return $this; } /** * Get an assertion message for a status assertion containing extra details when available. * * @param string|int $expected * @param string|int $actual * @return string */ protected function statusMessageWithDetails($expected, $actual) { return "Expected response status code [{$expected}] but received {$actual}."; } /** * Assert whether the response is redirecting to a given URI. * * @param string|null $uri * @return $this */ public function assertRedirect($uri = null) { PHPUnit::assertTrue( $this->isRedirect(), $this->statusMessageWithDetails('201, 301, 302, 303, 307, 308', $this->getStatusCode()), ); if (! is_null($uri)) { $this->assertLocation($uri); } return $this; } /** * Assert whether the response is redirecting to a URI that contains the given URI. * * @param string $uri * @return $this */ public function assertRedirectContains($uri) { PHPUnit::assertTrue( $this->isRedirect(), $this->statusMessageWithDetails('201, 301, 302, 303, 307, 308', $this->getStatusCode()), ); PHPUnit::assertTrue( Str::contains($this->headers->get('Location'), $uri), 'Redirect location ['.$this->headers->get('Location').'] does not contain ['.$uri.'].' ); return $this; } /** * Assert whether the response is redirecting to a given route. * * @param string $name * @param mixed $parameters * @return $this */ public function assertRedirectToRoute($name, $parameters = []) { $uri = route($name, $parameters); PHPUnit::assertTrue( $this->isRedirect(), $this->statusMessageWithDetails('201, 301, 302, 303, 307, 308', $this->getStatusCode()), ); $request = Request::create($this->headers->get('Location')); PHPUnit::assertEquals( app('url')->to($uri), $request->fullUrl() ); return $this; } /** * Assert whether the response is redirecting to a given signed route. * * @param string|null $name * @param mixed $parameters * @return $this */ public function assertRedirectToSignedRoute($name = null, $parameters = []) { if (! is_null($name)) { $uri = route($name, $parameters); } PHPUnit::assertTrue( $this->isRedirect(), $this->statusMessageWithDetails('201, 301, 302, 303, 307, 308', $this->getStatusCode()), ); $request = Request::create($this->headers->get('Location')); PHPUnit::assertTrue( $request->hasValidSignature(), 'The response is not a redirect to a signed route.' ); if (! is_null($name)) { $expectedUri = rtrim($request->fullUrlWithQuery([ 'signature' => null, 'expires' => null, ]), '?'); PHPUnit::assertEquals( app('url')->to($uri), $expectedUri ); } return $this; } /** * Asserts that the response contains the given header and equals the optional value. * * @param string $headerName * @param mixed $value * @return $this */ public function assertHeader($headerName, $value = null) { PHPUnit::assertTrue( $this->headers->has($headerName), "Header [{$headerName}] not present on response." ); $actual = $this->headers->get($headerName); if (! is_null($value)) { PHPUnit::assertEquals( $value, $this->headers->get($headerName), "Header [{$headerName}] was found, but value [{$actual}] does not match [{$value}]." ); } return $this; } /** * Asserts that the response does not contain the given header. * * @param string $headerName * @return $this */ public function assertHeaderMissing($headerName) { PHPUnit::assertFalse( $this->headers->has($headerName), "Unexpected header [{$headerName}] is present on response." ); return $this; } /** * Assert that the current location header matches the given URI. * * @param string $uri * @return $this */ public function assertLocation($uri) { PHPUnit::assertEquals( app('url')->to($uri), app('url')->to($this->headers->get('Location')) ); return $this; } /** * Assert that the response offers a file download. * * @param string|null $filename * @return $this */ public function assertDownload($filename = null) { $contentDisposition = explode(';', $this->headers->get('content-disposition')); if (trim($contentDisposition[0]) !== 'attachment') { PHPUnit::fail( 'Response does not offer a file download.'.PHP_EOL. 'Disposition ['.trim($contentDisposition[0]).'] found in header, [attachment] expected.' ); } if (! is_null($filename)) { if (isset($contentDisposition[1]) && trim(explode('=', $contentDisposition[1])[0]) !== 'filename') { PHPUnit::fail( 'Unsupported Content-Disposition header provided.'.PHP_EOL. 'Disposition ['.trim(explode('=', $contentDisposition[1])[0]).'] found in header, [filename] expected.' ); } $message = "Expected file [{$filename}] is not present in Content-Disposition header."; if (! isset($contentDisposition[1])) { PHPUnit::fail($message); } else { PHPUnit::assertSame( $filename, isset(explode('=', $contentDisposition[1])[1]) ? trim(explode('=', $contentDisposition[1])[1], " \"'") : '', $message ); return $this; } } else { PHPUnit::assertTrue(true); return $this; } } /** * Asserts that the response contains the given cookie and equals the optional value. * * @param string $cookieName * @param mixed $value * @return $this */ public function assertPlainCookie($cookieName, $value = null) { $this->assertCookie($cookieName, $value, false); return $this; } /** * Asserts that the response contains the given cookie and equals the optional value. * * @param string $cookieName * @param mixed $value * @param bool $encrypted * @param bool $unserialize * @return $this */ public function assertCookie($cookieName, $value = null, $encrypted = true, $unserialize = false) { PHPUnit::assertNotNull( $cookie = $this->getCookie($cookieName, $encrypted && ! is_null($value), $unserialize), "Cookie [{$cookieName}] not present on response." ); if (! $cookie || is_null($value)) { return $this; } $cookieValue = $cookie->getValue(); PHPUnit::assertEquals( $value, $cookieValue, "Cookie [{$cookieName}] was found, but value [{$cookieValue}] does not match [{$value}]." ); return $this; } /** * Asserts that the response contains the given cookie and is expired. * * @param string $cookieName * @return $this */ public function assertCookieExpired($cookieName) { PHPUnit::assertNotNull( $cookie = $this->getCookie($cookieName, false), "Cookie [{$cookieName}] not present on response." ); $expiresAt = Carbon::createFromTimestamp($cookie->getExpiresTime()); PHPUnit::assertTrue( $cookie->getExpiresTime() !== 0 && $expiresAt->lessThan(Carbon::now()), "Cookie [{$cookieName}] is not expired, it expires at [{$expiresAt}]." ); return $this; } /** * Asserts that the response contains the given cookie and is not expired. * * @param string $cookieName * @return $this */ public function assertCookieNotExpired($cookieName) { PHPUnit::assertNotNull( $cookie = $this->getCookie($cookieName, false), "Cookie [{$cookieName}] not present on response." ); $expiresAt = Carbon::createFromTimestamp($cookie->getExpiresTime()); PHPUnit::assertTrue( $cookie->getExpiresTime() === 0 || $expiresAt->greaterThan(Carbon::now()), "Cookie [{$cookieName}] is expired, it expired at [{$expiresAt}]." ); return $this; } /** * Asserts that the response does not contain the given cookie. * * @param string $cookieName * @return $this */ public function assertCookieMissing($cookieName) { PHPUnit::assertNull( $this->getCookie($cookieName, false), "Cookie [{$cookieName}] is present on response." ); return $this; } /** * Get the given cookie from the response. * * @param string $cookieName * @param bool $decrypt * @param bool $unserialize * @return \Symfony\Component\HttpFoundation\Cookie|null */ public function getCookie($cookieName, $decrypt = true, $unserialize = false) { foreach ($this->headers->getCookies() as $cookie) { if ($cookie->getName() === $cookieName) { if (! $decrypt) { return $cookie; } $decryptedValue = CookieValuePrefix::remove( app('encrypter')->decrypt($cookie->getValue(), $unserialize) ); return new Cookie( $cookie->getName(), $decryptedValue, $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly(), $cookie->isRaw(), $cookie->getSameSite() ); } } } /** * Assert that the given string matches the response content. * * @param string $value * @return $this */ public function assertContent($value) { PHPUnit::assertSame($value, $this->content()); return $this; } /** * Assert that the given string matches the streamed response content. * * @param string $value * @return $this */ public function assertStreamedContent($value) { PHPUnit::assertSame($value, $this->streamedContent()); return $this; } /** * Assert that the given string or array of strings are contained within the response. * * @param string|array $value * @param bool $escape * @return $this */ public function assertSee($value, $escape = true) { $value = Arr::wrap($value); $values = $escape ? array_map('e', $value) : $value; foreach ($values as $value) { PHPUnit::assertStringContainsString((string) $value, $this->getContent()); } return $this; } /** * Assert that the given strings are contained in order within the response. * * @param array $values * @param bool $escape * @return $this */ public function assertSeeInOrder(array $values, $escape = true) { $values = $escape ? array_map('e', $values) : $values; PHPUnit::assertThat($values, new SeeInOrder($this->getContent())); return $this; } /** * Assert that the given string or array of strings are contained within the response text. * * @param string|array $value * @param bool $escape * @return $this */ public function assertSeeText($value, $escape = true) { $value = Arr::wrap($value); $values = $escape ? array_map('e', $value) : $value; $content = strip_tags($this->getContent()); foreach ($values as $value) { PHPUnit::assertStringContainsString((string) $value, $content); } return $this; } /** * Assert that the given strings are contained in order within the response text. * * @param array $values * @param bool $escape * @return $this */ public function assertSeeTextInOrder(array $values, $escape = true) { $values = $escape ? array_map('e', $values) : $values; PHPUnit::assertThat($values, new SeeInOrder(strip_tags($this->getContent()))); return $this; } /** * Assert that the given string or array of strings are not contained within the response. * * @param string|array $value * @param bool $escape * @return $this */ public function assertDontSee($value, $escape = true) { $value = Arr::wrap($value); $values = $escape ? array_map('e', $value) : $value; foreach ($values as $value) { PHPUnit::assertStringNotContainsString((string) $value, $this->getContent()); } return $this; } /** * Assert that the given string or array of strings are not contained within the response text. * * @param string|array $value * @param bool $escape * @return $this */ public function assertDontSeeText($value, $escape = true) { $value = Arr::wrap($value); $values = $escape ? array_map('e', $value) : $value; $content = strip_tags($this->getContent()); foreach ($values as $value) { PHPUnit::assertStringNotContainsString((string) $value, $content); } return $this; } /** * Assert that the response is a superset of the given JSON. * * @param array|callable $value * @param bool $strict * @return $this */ public function assertJson($value, $strict = false) { $json = $this->decodeResponseJson(); if (is_array($value)) { $json->assertSubset($value, $strict); } else { $assert = AssertableJson::fromAssertableJsonString($json); $value($assert); if (Arr::isAssoc($assert->toArray())) { $assert->interacted(); } } return $this; } /** * Assert that the expected value and type exists at the given path in the response. * * @param string $path * @param mixed $expect * @return $this */ public function assertJsonPath($path, $expect) { $this->decodeResponseJson()->assertPath($path, $expect); return $this; } /** * Assert that the response has the exact given JSON. * * @param array $data * @return $this */ public function assertExactJson(array $data) { $this->decodeResponseJson()->assertExact($data); return $this; } /** * Assert that the response has the similar JSON as given. * * @param array $data * @return $this */ public function assertSimilarJson(array $data) { $this->decodeResponseJson()->assertSimilar($data); return $this; } /** * Assert that the response contains the given JSON fragment. * * @param array $data * @return $this */ public function assertJsonFragment(array $data) { $this->decodeResponseJson()->assertFragment($data); return $this; } /** * Assert that the response does not contain the given JSON fragment. * * @param array $data * @param bool $exact * @return $this */ public function assertJsonMissing(array $data, $exact = false) { $this->decodeResponseJson()->assertMissing($data, $exact); return $this; } /** * Assert that the response does not contain the exact JSON fragment. * * @param array $data * @return $this */ public function assertJsonMissingExact(array $data) { $this->decodeResponseJson()->assertMissingExact($data); return $this; } /** * Assert that the response does not contain the given path. * * @param string $path * @return $this */ public function assertJsonMissingPath(string $path) { $this->decodeResponseJson()->assertMissingPath($path); return $this; } /** * Assert that the response has a given JSON structure. * * @param array|null $structure * @param array|null $responseData * @return $this */ public function assertJsonStructure(array $structure = null, $responseData = null) { $this->decodeResponseJson()->assertStructure($structure, $responseData); return $this; } /** * Assert that the response JSON has the expected count of items at the given key. * * @param int $count * @param string|null $key * @return $this */ public function assertJsonCount(int $count, $key = null) { $this->decodeResponseJson()->assertCount($count, $key); return $this; } /** * Assert that the response has the given JSON validation errors. * * @param string|array $errors * @param string $responseKey * @return $this */ public function assertJsonValidationErrors($errors, $responseKey = 'errors') { $errors = Arr::wrap($errors); PHPUnit::assertNotEmpty($errors, 'No validation errors were provided.'); $jsonErrors = Arr::get($this->json(), $responseKey) ?? []; $errorMessage = $jsonErrors ? 'Response has the following JSON validation errors:'. PHP_EOL.PHP_EOL.json_encode($jsonErrors, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE).PHP_EOL : 'Response does not have JSON validation errors.'; foreach ($errors as $key => $value) { if (is_int($key)) { $this->assertJsonValidationErrorFor($value, $responseKey); continue; } $this->assertJsonValidationErrorFor($key, $responseKey); foreach (Arr::wrap($value) as $expectedMessage) { $errorMissing = true; foreach (Arr::wrap($jsonErrors[$key]) as $jsonErrorMessage) { if (Str::contains($jsonErrorMessage, $expectedMessage)) { $errorMissing = false; break; } } } if ($errorMissing) { PHPUnit::fail( "Failed to find a validation error in the response for key and message: '$key' => '$expectedMessage'".PHP_EOL.PHP_EOL.$errorMessage ); } } return $this; } /** * Assert the response has any JSON validation errors for the given key. * * @param string $key * @param string $responseKey * @return $this */ public function assertJsonValidationErrorFor($key, $responseKey = 'errors') { $jsonErrors = Arr::get($this->json(), $responseKey) ?? []; $errorMessage = $jsonErrors ? 'Response has the following JSON validation errors:'. PHP_EOL.PHP_EOL.json_encode($jsonErrors, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE).PHP_EOL : 'Response does not have JSON validation errors.'; PHPUnit::assertArrayHasKey( $key, $jsonErrors, "Failed to find a validation error in the response for key: '{$key}'".PHP_EOL.PHP_EOL.$errorMessage ); return $this; } /** * Assert that the response has no JSON validation errors for the given keys. * * @param string|array|null $keys * @param string $responseKey * @return $this */ public function assertJsonMissingValidationErrors($keys = null, $responseKey = 'errors') { if ($this->getContent() === '') { PHPUnit::assertTrue(true); return $this; } $json = $this->json(); if (! Arr::has($json, $responseKey)) { PHPUnit::assertTrue(true); return $this; } $errors = Arr::get($json, $responseKey, []); if (is_null($keys) && count($errors) > 0) { PHPUnit::fail( 'Response has unexpected validation errors: '.PHP_EOL.PHP_EOL. json_encode($errors, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) ); } foreach (Arr::wrap($keys) as $key) { PHPUnit::assertFalse( isset($errors[$key]), "Found unexpected validation error for key: '{$key}'" ); } return $this; } /** * Assert that the given key is a JSON array. * * @param $key * @return $this */ public function assertJsonIsArray($key = null) { $data = $this->json($key); $encodedData = json_encode($data); PHPUnit::assertTrue( is_array($data) && str_starts_with($encodedData, '[') && str_ends_with($encodedData, ']') ); return $this; } /** * Assert that the given key is a JSON object. * * @param $key * @return $this */ public function assertJsonIsObject($key = null) { $data = $this->json($key); $encodedData = json_encode($data); PHPUnit::assertTrue( is_array($data) && str_starts_with($encodedData, '{') && str_ends_with($encodedData, '}') ); return $this; } /** * Validate and return the decoded response JSON. * * @return \Illuminate\Testing\AssertableJsonString * * @throws \Throwable */ public function decodeResponseJson() { $testJson = new AssertableJsonString($this->getContent()); $decodedResponse = $testJson->json(); if (is_null($decodedResponse) || $decodedResponse === false) { if ($this->exception) { throw $this->exception; } else { PHPUnit::fail('Invalid JSON was returned from the route.'); } } return $testJson; } /** * Validate and return the decoded response JSON. * * @param string|null $key * @return mixed */ public function json($key = null) { return $this->decodeResponseJson()->json($key); } /** * Get the JSON decoded body of the response as a collection. * * @param string|null $key * @return \Illuminate\Support\Collection */ public function collect($key = null) { return Collection::make($this->json($key)); } /** * Assert that the response view equals the given value. * * @param string $value * @return $this */ public function assertViewIs($value) { $this->ensureResponseHasView(); PHPUnit::assertEquals($value, $this->original->name()); return $this; } /** * Assert that the response view has a given piece of bound data. * * @param string|array $key * @param mixed $value * @return $this */ public function assertViewHas($key, $value = null) { if (is_array($key)) { return $this->assertViewHasAll($key); } $this->ensureResponseHasView(); if (is_null($value)) { PHPUnit::assertTrue(Arr::has($this->original->gatherData(), $key)); } elseif ($value instanceof Closure) { PHPUnit::assertTrue($value(Arr::get($this->original->gatherData(), $key))); } elseif ($value instanceof Model) { PHPUnit::assertTrue($value->is(Arr::get($this->original->gatherData(), $key))); } elseif ($value instanceof EloquentCollection) { $actual = Arr::get($this->original->gatherData(), $key); PHPUnit::assertInstanceOf(EloquentCollection::class, $actual); PHPUnit::assertSameSize($value, $actual); $value->each(fn ($item, $index) => PHPUnit::assertTrue($actual->get($index)->is($item))); } else { PHPUnit::assertEquals($value, Arr::get($this->original->gatherData(), $key)); } return $this; } /** * Assert that the response view has a given list of bound data. * * @param array $bindings * @return $this */ public function assertViewHasAll(array $bindings) { foreach ($bindings as $key => $value) { if (is_int($key)) { $this->assertViewHas($value); } else { $this->assertViewHas($key, $value); } } return $this; } /** * Get a piece of data from the original view. * * @param string $key * @return mixed */ public function viewData($key) { $this->ensureResponseHasView(); return $this->original->gatherData()[$key]; } /** * Assert that the response view is missing a piece of bound data. * * @param string $key * @return $this */ public function assertViewMissing($key) { $this->ensureResponseHasView(); PHPUnit::assertFalse(Arr::has($this->original->gatherData(), $key)); return $this; } /** * Ensure that the response has a view as its original content. * * @return $this */ protected function ensureResponseHasView() { if (! $this->responseHasView()) { return PHPUnit::fail('The response is not a view.'); } return $this; } /** * Determine if the original response is a view. * * @return bool */ protected function responseHasView() { return isset($this->original) && $this->original instanceof View; } /** * Assert that the given keys do not have validation errors. * * @param string|array|null $keys * @param string $errorBag * @param string $responseKey * @return $this */ public function assertValid($keys = null, $errorBag = 'default', $responseKey = 'errors') { if ($this->baseResponse->headers->get('Content-Type') === 'application/json') { return $this->assertJsonMissingValidationErrors($keys, $responseKey); } if ($this->session()->get('errors')) { $errors = $this->session()->get('errors')->getBag($errorBag)->getMessages(); } else { $errors = []; } if (empty($errors)) { PHPUnit::assertTrue(true); return $this; } if (is_null($keys) && count($errors) > 0) { PHPUnit::fail( 'Response has unexpected validation errors: '.PHP_EOL.PHP_EOL. json_encode($errors, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) ); } foreach (Arr::wrap($keys) as $key) { PHPUnit::assertFalse( isset($errors[$key]), "Found unexpected validation error for key: '{$key}'" ); } return $this; } /** * Assert that the response has the given validation errors. * * @param string|array|null $errors * @param string $errorBag * @param string $responseKey * @return $this */ public function assertInvalid($errors = null, $errorBag = 'default', $responseKey = 'errors') { if ($this->baseResponse->headers->get('Content-Type') === 'application/json') { return $this->assertJsonValidationErrors($errors, $responseKey); } $this->assertSessionHas('errors'); $sessionErrors = $this->session()->get('errors')->getBag($errorBag)->getMessages(); $errorMessage = $sessionErrors ? 'Response has the following validation errors in the session:'. PHP_EOL.PHP_EOL.json_encode($sessionErrors, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE).PHP_EOL : 'Response does not have validation errors in the session.'; foreach (Arr::wrap($errors) as $key => $value) { PHPUnit::assertArrayHasKey( (is_int($key)) ? $value : $key, $sessionErrors, "Failed to find a validation error in session for key: '{$value}'".PHP_EOL.PHP_EOL.$errorMessage ); if (! is_int($key)) { $hasError = false; foreach (Arr::wrap($sessionErrors[$key]) as $sessionErrorMessage) { if (Str::contains($sessionErrorMessage, $value)) { $hasError = true; break; } } if (! $hasError) { PHPUnit::fail( "Failed to find a validation error for key and message: '$key' => '$value'".PHP_EOL.PHP_EOL.$errorMessage ); } } } return $this; } /** * Assert that the session has a given value. * * @param string|array $key * @param mixed $value * @return $this */ public function assertSessionHas($key, $value = null) { if (is_array($key)) { return $this->assertSessionHasAll($key); } if (is_null($value)) { PHPUnit::assertTrue( $this->session()->has($key), "Session is missing expected key [{$key}]." ); } elseif ($value instanceof Closure) { PHPUnit::assertTrue($value($this->session()->get($key))); } else { PHPUnit::assertEquals($value, $this->session()->get($key)); } return $this; } /** * Assert that the session has a given list of values. * * @param array $bindings * @return $this */ public function assertSessionHasAll(array $bindings) { foreach ($bindings as $key => $value) { if (is_int($key)) { $this->assertSessionHas($value); } else { $this->assertSessionHas($key, $value); } } return $this; } /** * Assert that the session has a given value in the flashed input array. * * @param string|array $key * @param mixed $value * @return $this */ public function assertSessionHasInput($key, $value = null) { if (is_array($key)) { foreach ($key as $k => $v) { if (is_int($k)) { $this->assertSessionHasInput($v); } else { $this->assertSessionHasInput($k, $v); } } return $this; } if (is_null($value)) { PHPUnit::assertTrue( $this->session()->hasOldInput($key), "Session is missing expected key [{$key}]." ); } elseif ($value instanceof Closure) { PHPUnit::assertTrue($value($this->session()->getOldInput($key))); } else { PHPUnit::assertEquals($value, $this->session()->getOldInput($key)); } return $this; } /** * Assert that the session has the given errors. * * @param string|array $keys * @param mixed $format * @param string $errorBag * @return $this */ public function assertSessionHasErrors($keys = [], $format = null, $errorBag = 'default') { $this->assertSessionHas('errors'); $keys = (array) $keys; $errors = $this->session()->get('errors')->getBag($errorBag); foreach ($keys as $key => $value) { if (is_int($key)) { PHPUnit::assertTrue($errors->has($value), "Session missing error: $value"); } else { PHPUnit::assertContains(is_bool($value) ? (string) $value : $value, $errors->get($key, $format)); } } return $this; } /** * Assert that the session is missing the given errors. * * @param string|array $keys * @param string|null $format * @param string $errorBag * @return $this */ public function assertSessionDoesntHaveErrors($keys = [], $format = null, $errorBag = 'default') { $keys = (array) $keys; if (empty($keys)) { return $this->assertSessionHasNoErrors(); } if (is_null($this->session()->get('errors'))) { PHPUnit::assertTrue(true); return $this; } $errors = $this->session()->get('errors')->getBag($errorBag); foreach ($keys as $key => $value) { if (is_int($key)) { PHPUnit::assertFalse($errors->has($value), "Session has unexpected error: $value"); } else { PHPUnit::assertNotContains($value, $errors->get($key, $format)); } } return $this; } /** * Assert that the session has no errors. * * @return $this */ public function assertSessionHasNoErrors() { $hasErrors = $this->session()->has('errors'); PHPUnit::assertFalse( $hasErrors, 'Session has unexpected errors: '.PHP_EOL.PHP_EOL. json_encode((function () use ($hasErrors) { $errors = []; $sessionErrors = $this->session()->get('errors'); if ($hasErrors && is_a($sessionErrors, ViewErrorBag::class)) { foreach ($sessionErrors->getBags() as $bag => $messages) { if (is_a($messages, MessageBag::class)) { $errors[$bag] = $messages->all(); } } } return $errors; })(), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), ); return $this; } /** * Assert that the session has the given errors. * * @param string $errorBag * @param string|array $keys * @param mixed $format * @return $this */ public function assertSessionHasErrorsIn($errorBag, $keys = [], $format = null) { return $this->assertSessionHasErrors($keys, $format, $errorBag); } /** * Assert that the session does not have a given key. * * @param string|array $key * @return $this */ public function assertSessionMissing($key) { if (is_array($key)) { foreach ($key as $value) { $this->assertSessionMissing($value); } } else { PHPUnit::assertFalse( $this->session()->has($key), "Session has unexpected key [{$key}]." ); } return $this; } /** * Get the current session store. * * @return \Illuminate\Session\Store */ protected function session() { $session = app('session.store'); if (! $session->isStarted()) { $session->start(); } return $session; } /** * Dump the content from the response and end the script. * * @return never */ public function dd() { $this->dump(); exit(1); } /** * Dump the headers from the response and end the script. * * @return never */ public function ddHeaders() { $this->dumpHeaders(); exit(1); } /** * Dump the session from the response and end the script. * * @param string|array $keys * @return never */ public function ddSession($keys = []) { $this->dumpSession($keys); exit(1); } /** * Dump the content from the response. * * @param string|null $key * @return $this */ public function dump($key = null) { $content = $this->getContent(); $json = json_decode($content); if (json_last_error() === JSON_ERROR_NONE) { $content = $json; } if (! is_null($key)) { dump(data_get($content, $key)); } else { dump($content); } return $this; } /** * Dump the headers from the response. * * @return $this */ public function dumpHeaders() { dump($this->headers->all()); return $this; } /** * Dump the session from the response. * * @param string|array $keys * @return $this */ public function dumpSession($keys = []) { $keys = (array) $keys; if (empty($keys)) { dump($this->session()->all()); } else { dump($this->session()->only($keys)); } return $this; } /** * Get the streamed content from the response. * * @return string */ public function streamedContent() { if (! is_null($this->streamedContent)) { return $this->streamedContent; } if (! $this->baseResponse instanceof StreamedResponse) { PHPUnit::fail('The response is not a streamed response.'); } ob_start(function (string $buffer): string { $this->streamedContent .= $buffer; return ''; }); $this->sendContent(); ob_end_clean(); return $this->streamedContent; } /** * Set the previous exceptions on the response. * * @param \Illuminate\Support\Collection $exceptions * @return $this */ public function withExceptions(Collection $exceptions) { $this->exceptions = $exceptions; return $this; } /** * This method is called when test method did not execute successfully. * * @param \Throwable $exception * @return \Throwable */ public function transformNotSuccessfulException($exception) { if (! $exception instanceof ExpectationFailedException) { return $exception; } if ($lastException = $this->exceptions->last()) { return $this->appendExceptionToException($lastException, $exception); } if ($this->baseResponse instanceof RedirectResponse) { $session = $this->baseResponse->getSession(); if (! is_null($session) && $session->has('errors')) { return $this->appendErrorsToException($session->get('errors')->all(), $exception); } } if ($this->baseResponse->headers->get('Content-Type') === 'application/json') { $testJson = new AssertableJsonString($this->getContent()); if (isset($testJson['errors'])) { return $this->appendErrorsToException($testJson->json(), $exception, true); } } return $exception; } /** * Append an exception to the message of another exception. * * @param \Throwable $exceptionToAppend * @param \Throwable $exception * @return \Throwable */ protected function appendExceptionToException($exceptionToAppend, $exception) { $exceptionMessage = $exceptionToAppend->getMessage(); $exceptionToAppend = (string) $exceptionToAppend; $message = <<<"EOF" The following exception occurred during the last request: $exceptionToAppend ---------------------------------------------------------------------------------- $exceptionMessage EOF; return $this->appendMessageToException($message, $exception); } /** * Append errors to an exception message. * * @param array $errors * @param \Throwable $exception * @param bool $json * @return \Throwable */ protected function appendErrorsToException($errors, $exception, $json = false) { $errors = $json ? json_encode($errors, JSON_PRETTY_PRINT) : implode(PHP_EOL, Arr::flatten($errors)); // JSON error messages may already contain the errors, so we shouldn't duplicate them... if (str_contains($exception->getMessage(), $errors)) { return $exception; } $message = <<<"EOF" The following errors occurred during the last request: $errors EOF; return $this->appendMessageToException($message, $exception); } /** * Append a message to an exception. * * @param string $message * @param \Throwable $exception * @return \Throwable */ protected function appendMessageToException($message, $exception) { $property = new ReflectionProperty($exception, 'message'); $property->setAccessible(true); $property->setValue( $exception, $exception->getMessage().PHP_EOL.PHP_EOL.$message.PHP_EOL ); return $exception; } /** * Dynamically access base response parameters. * * @param string $key * @return mixed */ public function __get($key) { return $this->baseResponse->{$key}; } /** * Proxy isset() checks to the underlying base response. * * @param string $key * @return bool */ public function __isset($key) { return isset($this->baseResponse->{$key}); } /** * Determine if the given offset exists. * * @param string $offset * @return bool */ public function offsetExists($offset): bool { return $this->responseHasView() ? isset($this->original->gatherData()[$offset]) : isset($this->json()[$offset]); } /** * Get the value for a given offset. * * @param string $offset * @return mixed */ public function offsetGet($offset): mixed { return $this->responseHasView() ? $this->viewData($offset) : $this->json()[$offset]; } /** * Set the value at the given offset. * * @param string $offset * @param mixed $value * @return void * * @throws \LogicException */ public function offsetSet($offset, $value): void { throw new LogicException('Response data may not be mutated using array access.'); } /** * Unset the value at the given offset. * * @param string $offset * @return void * * @throws \LogicException */ public function offsetUnset($offset): void { throw new LogicException('Response data may not be mutated using array access.'); } /** * Handle dynamic calls into macros or pass missing methods to the base response. * * @param string $method * @param array $args * @return mixed */ public function __call($method, $args) { if (static::hasMacro($method)) { return $this->macroCall($method, $args); } return $this->baseResponse->{$method}(...$args); } } PK������y Z(,��(,��+��Illuminate/Filesystem/FilesystemManager.phpnu�W+A��������<?php namespace Illuminate\Filesystem; use Aws\S3\S3Client; use Closure; use Illuminate\Contracts\Filesystem\Factory as FactoryContract; use Illuminate\Support\Arr; use InvalidArgumentException; use League\Flysystem\AwsS3V3\AwsS3V3Adapter as S3Adapter; use League\Flysystem\AwsS3V3\PortableVisibilityConverter as AwsS3PortableVisibilityConverter; use League\Flysystem\Filesystem as Flysystem; use League\Flysystem\FilesystemAdapter as FlysystemAdapter; use League\Flysystem\Ftp\FtpAdapter; use League\Flysystem\Ftp\FtpConnectionOptions; use League\Flysystem\Local\LocalFilesystemAdapter as LocalAdapter; use League\Flysystem\PathPrefixing\PathPrefixedAdapter; use League\Flysystem\PhpseclibV3\SftpAdapter; use League\Flysystem\PhpseclibV3\SftpConnectionProvider; use League\Flysystem\ReadOnly\ReadOnlyFilesystemAdapter; use League\Flysystem\UnixVisibility\PortableVisibilityConverter; use League\Flysystem\Visibility; /** * @mixin \Illuminate\Contracts\Filesystem\Filesystem * @mixin \Illuminate\Filesystem\FilesystemAdapter */ class FilesystemManager implements FactoryContract { /** * The application instance. * * @var \Illuminate\Contracts\Foundation\Application */ protected $app; /** * The array of resolved filesystem drivers. * * @var array */ protected $disks = []; /** * The registered custom driver creators. * * @var array */ protected $customCreators = []; /** * Create a new filesystem manager instance. * * @param \Illuminate\Contracts\Foundation\Application $app * @return void */ public function __construct($app) { $this->app = $app; } /** * Get a filesystem instance. * * @param string|null $name * @return \Illuminate\Contracts\Filesystem\Filesystem */ public function drive($name = null) { return $this->disk($name); } /** * Get a filesystem instance. * * @param string|null $name * @return \Illuminate\Contracts\Filesystem\Filesystem */ public function disk($name = null) { $name = $name ?: $this->getDefaultDriver(); return $this->disks[$name] = $this->get($name); } /** * Get a default cloud filesystem instance. * * @return \Illuminate\Contracts\Filesystem\Filesystem */ public function cloud() { $name = $this->getDefaultCloudDriver(); return $this->disks[$name] = $this->get($name); } /** * Build an on-demand disk. * * @param string|array $config * @return \Illuminate\Contracts\Filesystem\Filesystem */ public function build($config) { return $this->resolve('ondemand', is_array($config) ? $config : [ 'driver' => 'local', 'root' => $config, ]); } /** * Attempt to get the disk from the local cache. * * @param string $name * @return \Illuminate\Contracts\Filesystem\Filesystem */ protected function get($name) { return $this->disks[$name] ?? $this->resolve($name); } /** * Resolve the given disk. * * @param string $name * @param array|null $config * @return \Illuminate\Contracts\Filesystem\Filesystem * * @throws \InvalidArgumentException */ protected function resolve($name, $config = null) { $config ??= $this->getConfig($name); if (empty($config['driver'])) { throw new InvalidArgumentException("Disk [{$name}] does not have a configured driver."); } $name = $config['driver']; if (isset($this->customCreators[$name])) { return $this->callCustomCreator($config); } $driverMethod = 'create'.ucfirst($name).'Driver'; if (! method_exists($this, $driverMethod)) { throw new InvalidArgumentException("Driver [{$name}] is not supported."); } return $this->{$driverMethod}($config); } /** * Call a custom driver creator. * * @param array $config * @return \Illuminate\Contracts\Filesystem\Filesystem */ protected function callCustomCreator(array $config) { return $this->customCreators[$config['driver']]($this->app, $config); } /** * Create an instance of the local driver. * * @param array $config * @return \Illuminate\Contracts\Filesystem\Filesystem */ public function createLocalDriver(array $config) { $visibility = PortableVisibilityConverter::fromArray( $config['permissions'] ?? [], $config['directory_visibility'] ?? $config['visibility'] ?? Visibility::PRIVATE ); $links = ($config['links'] ?? null) === 'skip' ? LocalAdapter::SKIP_LINKS : LocalAdapter::DISALLOW_LINKS; $adapter = new LocalAdapter( $config['root'], $visibility, $config['lock'] ?? LOCK_EX, $links ); return new FilesystemAdapter($this->createFlysystem($adapter, $config), $adapter, $config); } /** * Create an instance of the ftp driver. * * @param array $config * @return \Illuminate\Contracts\Filesystem\Filesystem */ public function createFtpDriver(array $config) { if (! isset($config['root'])) { $config['root'] = ''; } $adapter = new FtpAdapter(FtpConnectionOptions::fromArray($config)); return new FilesystemAdapter($this->createFlysystem($adapter, $config), $adapter, $config); } /** * Create an instance of the sftp driver. * * @param array $config * @return \Illuminate\Contracts\Filesystem\Filesystem */ public function createSftpDriver(array $config) { $provider = SftpConnectionProvider::fromArray($config); $root = $config['root'] ?? '/'; $visibility = PortableVisibilityConverter::fromArray( $config['permissions'] ?? [] ); $adapter = new SftpAdapter($provider, $root, $visibility); return new FilesystemAdapter($this->createFlysystem($adapter, $config), $adapter, $config); } /** * Create an instance of the Amazon S3 driver. * * @param array $config * @return \Illuminate\Contracts\Filesystem\Cloud */ public function createS3Driver(array $config) { $s3Config = $this->formatS3Config($config); $root = (string) ($s3Config['root'] ?? ''); $visibility = new AwsS3PortableVisibilityConverter( $config['visibility'] ?? Visibility::PUBLIC ); $streamReads = $s3Config['stream_reads'] ?? false; $client = new S3Client($s3Config); $adapter = new S3Adapter($client, $s3Config['bucket'], $root, $visibility, null, $config['options'] ?? [], $streamReads); return new AwsS3V3Adapter( $this->createFlysystem($adapter, $config), $adapter, $s3Config, $client ); } /** * Format the given S3 configuration with the default options. * * @param array $config * @return array */ protected function formatS3Config(array $config) { $config += ['version' => 'latest']; if (! empty($config['key']) && ! empty($config['secret'])) { $config['credentials'] = Arr::only($config, ['key', 'secret', 'token']); } return Arr::except($config, ['token']); } /** * Create a scoped driver. * * @param array $config * @return \Illuminate\Contracts\Filesystem\Filesystem */ public function createScopedDriver(array $config) { if (empty($config['disk'])) { throw new InvalidArgumentException('Scoped disk is missing "disk" configuration option.'); } elseif (empty($config['prefix'])) { throw new InvalidArgumentException('Scoped disk is missing "prefix" configuration option.'); } return $this->build(tap( $this->getConfig($config['disk']), fn (&$parent) => $parent['prefix'] = $config['prefix'] )); } /** * Create a Flysystem instance with the given adapter. * * @param \League\Flysystem\FilesystemAdapter $adapter * @param array $config * @return \League\Flysystem\FilesystemOperator */ protected function createFlysystem(FlysystemAdapter $adapter, array $config) { if ($config['read-only'] ?? false === true) { $adapter = new ReadOnlyFilesystemAdapter($adapter); } if (! empty($config['prefix'])) { $adapter = new PathPrefixedAdapter($adapter, $config['prefix']); } return new Flysystem($adapter, Arr::only($config, [ 'directory_visibility', 'disable_asserts', 'temporary_url', 'url', 'visibility', ])); } /** * Set the given disk instance. * * @param string $name * @param mixed $disk * @return $this */ public function set($name, $disk) { $this->disks[$name] = $disk; return $this; } /** * Get the filesystem connection configuration. * * @param string $name * @return array */ protected function getConfig($name) { return $this->app['config']["filesystems.disks.{$name}"] ?: []; } /** * Get the default driver name. * * @return string */ public function getDefaultDriver() { return $this->app['config']['filesystems.default']; } /** * Get the default cloud driver name. * * @return string */ public function getDefaultCloudDriver() { return $this->app['config']['filesystems.cloud'] ?? 's3'; } /** * Unset the given disk instances. * * @param array|string $disk * @return $this */ public function forgetDisk($disk) { foreach ((array) $disk as $diskName) { unset($this->disks[$diskName]); } return $this; } /** * Disconnect the given disk and remove from local cache. * * @param string|null $name * @return void */ public function purge($name = null) { $name ??= $this->getDefaultDriver(); unset($this->disks[$name]); } /** * Register a custom driver creator Closure. * * @param string $driver * @param \Closure $callback * @return $this */ public function extend($driver, Closure $callback) { $this->customCreators[$driver] = $callback; return $this; } /** * Set the application instance used by the manager. * * @param \Illuminate\Contracts\Foundation\Application $app * @return $this */ public function setApplication($app) { $this->app = $app; return $this; } /** * Dynamically call the default driver instance. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { return $this->disk()->$method(...$parameters); } } PK������y Zα3��3�� ��Illuminate/Filesystem/LICENSE.mdnu�W+A��������The MIT License (MIT) Copyright (c) Taylor Otwell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PK������y Z20*����(��Illuminate/Filesystem/AwsS3V3Adapter.phpnu�W+A��������<?php namespace Illuminate\Filesystem; use Aws\S3\S3Client; use Illuminate\Support\Traits\Conditionable; use League\Flysystem\AwsS3V3\AwsS3V3Adapter as S3Adapter; use League\Flysystem\FilesystemOperator; class AwsS3V3Adapter extends FilesystemAdapter { use Conditionable; /** * The AWS S3 client. * * @var \Aws\S3\S3Client */ protected $client; /** * Create a new AwsS3V3FilesystemAdapter instance. * * @param \League\Flysystem\FilesystemOperator $driver * @param \League\Flysystem\AwsS3V3\AwsS3V3Adapter $adapter * @param array $config * @param \Aws\S3\S3Client $client * @return void */ public function __construct(FilesystemOperator $driver, S3Adapter $adapter, array $config, S3Client $client) { parent::__construct($driver, $adapter, $config); $this->client = $client; } /** * Get the URL for the file at the given path. * * @param string $path * @return string * * @throws \RuntimeException */ public function url($path) { // If an explicit base URL has been set on the disk configuration then we will use // it as the base URL instead of the default path. This allows the developer to // have full control over the base path for this filesystem's generated URLs. if (isset($this->config['url'])) { return $this->concatPathToUrl($this->config['url'], $this->prefixer->prefixPath($path)); } return $this->client->getObjectUrl( $this->config['bucket'], $this->prefixer->prefixPath($path) ); } /** * Determine if temporary URLs can be generated. * * @return bool */ public function providesTemporaryUrls() { return true; } /** * Get a temporary URL for the file at the given path. * * @param string $path * @param \DateTimeInterface $expiration * @param array $options * @return string */ public function temporaryUrl($path, $expiration, array $options = []) { $command = $this->client->getCommand('GetObject', array_merge([ 'Bucket' => $this->config['bucket'], 'Key' => $this->prefixer->prefixPath($path), ], $options)); $uri = $this->client->createPresignedRequest( $command, $expiration, $options )->getUri(); // If an explicit base URL has been set on the disk configuration then we will use // it as the base URL instead of the default path. This allows the developer to // have full control over the base path for this filesystem's generated URLs. if (isset($this->config['temporary_url'])) { $uri = $this->replaceBaseUrl($uri, $this->config['temporary_url']); } return (string) $uri; } /** * Get a temporary upload URL for the file at the given path. * * @param string $path * @param \DateTimeInterface $expiration * @param array $options * @return array */ public function temporaryUploadUrl($path, $expiration, array $options = []) { $command = $this->client->getCommand('PutObject', array_merge([ 'Bucket' => $this->config['bucket'], 'Key' => $this->prefixer->prefixPath($path), ], $options)); $signedRequest = $this->client->createPresignedRequest( $command, $expiration, $options ); $uri = $signedRequest->getUri(); // If an explicit base URL has been set on the disk configuration then we will use // it as the base URL instead of the default path. This allows the developer to // have full control over the base path for this filesystem's generated URLs. if (isset($this->config['temporary_url'])) { $uri = $this->replaceBaseUrl($uri, $this->config['temporary_url']); } return [ 'url' => (string) $uri, 'headers' => $signedRequest->getHeaders(), ]; } /** * Get the underlying S3 client. * * @return \Aws\S3\S3Client */ public function getClient() { return $this->client; } } PK������y Z�{aK��K��$��Illuminate/Filesystem/Filesystem.phpnu�W+A��������<?php namespace Illuminate\Filesystem; use ErrorException; use FilesystemIterator; use Illuminate\Contracts\Filesystem\FileNotFoundException; use Illuminate\Support\LazyCollection; use Illuminate\Support\Traits\Conditionable; use Illuminate\Support\Traits\Macroable; use RuntimeException; use SplFileObject; use Symfony\Component\Filesystem\Filesystem as SymfonyFilesystem; use Symfony\Component\Finder\Finder; use Symfony\Component\Mime\MimeTypes; class Filesystem { use Conditionable; use Macroable; /** * Determine if a file or directory exists. * * @param string $path * @return bool */ public function exists($path) { return file_exists($path); } /** * Determine if a file or directory is missing. * * @param string $path * @return bool */ public function missing($path) { return ! $this->exists($path); } /** * Get the contents of a file. * * @param string $path * @param bool $lock * @return string * * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException */ public function get($path, $lock = false) { if ($this->isFile($path)) { return $lock ? $this->sharedGet($path) : file_get_contents($path); } throw new FileNotFoundException("File does not exist at path {$path}."); } /** * Get contents of a file with shared access. * * @param string $path * @return string */ public function sharedGet($path) { $contents = ''; $handle = fopen($path, 'rb'); if ($handle) { try { if (flock($handle, LOCK_SH)) { clearstatcache(true, $path); $contents = fread($handle, $this->size($path) ?: 1); flock($handle, LOCK_UN); } } finally { fclose($handle); } } return $contents; } /** * Get the returned value of a file. * * @param string $path * @param array $data * @return mixed * * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException */ public function getRequire($path, array $data = []) { if ($this->isFile($path)) { $__path = $path; $__data = $data; return (static function () use ($__path, $__data) { extract($__data, EXTR_SKIP); return require $__path; })(); } throw new FileNotFoundException("File does not exist at path {$path}."); } /** * Require the given file once. * * @param string $path * @param array $data * @return mixed * * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException */ public function requireOnce($path, array $data = []) { if ($this->isFile($path)) { $__path = $path; $__data = $data; return (static function () use ($__path, $__data) { extract($__data, EXTR_SKIP); return require_once $__path; })(); } throw new FileNotFoundException("File does not exist at path {$path}."); } /** * Get the contents of a file one line at a time. * * @param string $path * @return \Illuminate\Support\LazyCollection * * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException */ public function lines($path) { if (! $this->isFile($path)) { throw new FileNotFoundException( "File does not exist at path {$path}." ); } return LazyCollection::make(function () use ($path) { $file = new SplFileObject($path); $file->setFlags(SplFileObject::DROP_NEW_LINE); while (! $file->eof()) { yield $file->fgets(); } }); } /** * Get the hash of the file at the given path. * * @param string $path * @param string $algorithm * @return string */ public function hash($path, $algorithm = 'md5') { return hash_file($algorithm, $path); } /** * Write the contents of a file. * * @param string $path * @param string $contents * @param bool $lock * @return int|bool */ public function put($path, $contents, $lock = false) { return file_put_contents($path, $contents, $lock ? LOCK_EX : 0); } /** * Write the contents of a file, replacing it atomically if it already exists. * * @param string $path * @param string $content * @param int|null $mode * @return void */ public function replace($path, $content, $mode = null) { // If the path already exists and is a symlink, get the real path... clearstatcache(true, $path); $path = realpath($path) ?: $path; $tempPath = tempnam(dirname($path), basename($path)); // Fix permissions of tempPath because `tempnam()` creates it with permissions set to 0600... if (! is_null($mode)) { chmod($tempPath, $mode); } else { chmod($tempPath, 0777 - umask()); } file_put_contents($tempPath, $content); rename($tempPath, $path); } /** * Replace a given string within a given file. * * @param array|string $search * @param array|string $replace * @param string $path * @return void */ public function replaceInFile($search, $replace, $path) { file_put_contents($path, str_replace($search, $replace, file_get_contents($path))); } /** * Prepend to a file. * * @param string $path * @param string $data * @return int */ public function prepend($path, $data) { if ($this->exists($path)) { return $this->put($path, $data.$this->get($path)); } return $this->put($path, $data); } /** * Append to a file. * * @param string $path * @param string $data * @return int */ public function append($path, $data) { return file_put_contents($path, $data, FILE_APPEND); } /** * Get or set UNIX mode of a file or directory. * * @param string $path * @param int|null $mode * @return mixed */ public function chmod($path, $mode = null) { if ($mode) { return chmod($path, $mode); } return substr(sprintf('%o', fileperms($path)), -4); } /** * Delete the file at a given path. * * @param string|array $paths * @return bool */ public function delete($paths) { $paths = is_array($paths) ? $paths : func_get_args(); $success = true; foreach ($paths as $path) { try { if (@unlink($path)) { clearstatcache(false, $path); } else { $success = false; } } catch (ErrorException $e) { $success = false; } } return $success; } /** * Move a file to a new location. * * @param string $path * @param string $target * @return bool */ public function move($path, $target) { return rename($path, $target); } /** * Copy a file to a new location. * * @param string $path * @param string $target * @return bool */ public function copy($path, $target) { return copy($path, $target); } /** * Create a symlink to the target file or directory. On Windows, a hard link is created if the target is a file. * * @param string $target * @param string $link * @return void */ public function link($target, $link) { if (! windows_os()) { return symlink($target, $link); } $mode = $this->isDirectory($target) ? 'J' : 'H'; exec("mklink /{$mode} ".escapeshellarg($link).' '.escapeshellarg($target)); } /** * Create a relative symlink to the target file or directory. * * @param string $target * @param string $link * @return void * * @throws \RuntimeException */ public function relativeLink($target, $link) { if (! class_exists(SymfonyFilesystem::class)) { throw new RuntimeException( 'To enable support for relative links, please install the symfony/filesystem package.' ); } $relativeTarget = (new SymfonyFilesystem)->makePathRelative($target, dirname($link)); $this->link($this->isFile($target) ? rtrim($relativeTarget, '/') : $relativeTarget, $link); } /** * Extract the file name from a file path. * * @param string $path * @return string */ public function name($path) { return pathinfo($path, PATHINFO_FILENAME); } /** * Extract the trailing name component from a file path. * * @param string $path * @return string */ public function basename($path) { return pathinfo($path, PATHINFO_BASENAME); } /** * Extract the parent directory from a file path. * * @param string $path * @return string */ public function dirname($path) { return pathinfo($path, PATHINFO_DIRNAME); } /** * Extract the file extension from a file path. * * @param string $path * @return string */ public function extension($path) { return pathinfo($path, PATHINFO_EXTENSION); } /** * Guess the file extension from the mime-type of a given file. * * @param string $path * @return string|null * * @throws \RuntimeException */ public function guessExtension($path) { if (! class_exists(MimeTypes::class)) { throw new RuntimeException( 'To enable support for guessing extensions, please install the symfony/mime package.' ); } return (new MimeTypes)->getExtensions($this->mimeType($path))[0] ?? null; } /** * Get the file type of a given file. * * @param string $path * @return string */ public function type($path) { return filetype($path); } /** * Get the mime-type of a given file. * * @param string $path * @return string|false */ public function mimeType($path) { return finfo_file(finfo_open(FILEINFO_MIME_TYPE), $path); } /** * Get the file size of a given file. * * @param string $path * @return int */ public function size($path) { return filesize($path); } /** * Get the file's last modification time. * * @param string $path * @return int */ public function lastModified($path) { return filemtime($path); } /** * Determine if the given path is a directory. * * @param string $directory * @return bool */ public function isDirectory($directory) { return is_dir($directory); } /** * Determine if the given path is a directory that does not contain any other files or directories. * * @param string $directory * @param bool $ignoreDotFiles * @return bool */ public function isEmptyDirectory($directory, $ignoreDotFiles = false) { return ! Finder::create()->ignoreDotFiles($ignoreDotFiles)->in($directory)->depth(0)->hasResults(); } /** * Determine if the given path is readable. * * @param string $path * @return bool */ public function isReadable($path) { return is_readable($path); } /** * Determine if the given path is writable. * * @param string $path * @return bool */ public function isWritable($path) { return is_writable($path); } /** * Determine if two files are the same by comparing their hashes. * * @param string $firstFile * @param string $secondFile * @return bool */ public function hasSameHash($firstFile, $secondFile) { $hash = @md5_file($firstFile); return $hash && $hash === @md5_file($secondFile); } /** * Determine if the given path is a file. * * @param string $file * @return bool */ public function isFile($file) { return is_file($file); } /** * Find path names matching a given pattern. * * @param string $pattern * @param int $flags * @return array */ public function glob($pattern, $flags = 0) { return glob($pattern, $flags); } /** * Get an array of all files in a directory. * * @param string $directory * @param bool $hidden * @return \Symfony\Component\Finder\SplFileInfo[] */ public function files($directory, $hidden = false) { return iterator_to_array( Finder::create()->files()->ignoreDotFiles(! $hidden)->in($directory)->depth(0)->sortByName(), false ); } /** * Get all of the files from the given directory (recursive). * * @param string $directory * @param bool $hidden * @return \Symfony\Component\Finder\SplFileInfo[] */ public function allFiles($directory, $hidden = false) { return iterator_to_array( Finder::create()->files()->ignoreDotFiles(! $hidden)->in($directory)->sortByName(), false ); } /** * Get all of the directories within a given directory. * * @param string $directory * @return array */ public function directories($directory) { $directories = []; foreach (Finder::create()->in($directory)->directories()->depth(0)->sortByName() as $dir) { $directories[] = $dir->getPathname(); } return $directories; } /** * Ensure a directory exists. * * @param string $path * @param int $mode * @param bool $recursive * @return void */ public function ensureDirectoryExists($path, $mode = 0755, $recursive = true) { if (! $this->isDirectory($path)) { $this->makeDirectory($path, $mode, $recursive); } } /** * Create a directory. * * @param string $path * @param int $mode * @param bool $recursive * @param bool $force * @return bool */ public function makeDirectory($path, $mode = 0755, $recursive = false, $force = false) { if ($force) { return @mkdir($path, $mode, $recursive); } return mkdir($path, $mode, $recursive); } /** * Move a directory. * * @param string $from * @param string $to * @param bool $overwrite * @return bool */ public function moveDirectory($from, $to, $overwrite = false) { if ($overwrite && $this->isDirectory($to) && ! $this->deleteDirectory($to)) { return false; } return @rename($from, $to) === true; } /** * Copy a directory from one location to another. * * @param string $directory * @param string $destination * @param int|null $options * @return bool */ public function copyDirectory($directory, $destination, $options = null) { if (! $this->isDirectory($directory)) { return false; } $options = $options ?: FilesystemIterator::SKIP_DOTS; // If the destination directory does not actually exist, we will go ahead and // create it recursively, which just gets the destination prepared to copy // the files over. Once we make the directory we'll proceed the copying. $this->ensureDirectoryExists($destination, 0777); $items = new FilesystemIterator($directory, $options); foreach ($items as $item) { // As we spin through items, we will check to see if the current file is actually // a directory or a file. When it is actually a directory we will need to call // back into this function recursively to keep copying these nested folders. $target = $destination.'/'.$item->getBasename(); if ($item->isDir()) { $path = $item->getPathname(); if (! $this->copyDirectory($path, $target, $options)) { return false; } } // If the current items is just a regular file, we will just copy this to the new // location and keep looping. If for some reason the copy fails we'll bail out // and return false, so the developer is aware that the copy process failed. elseif (! $this->copy($item->getPathname(), $target)) { return false; } } return true; } /** * Recursively delete a directory. * * The directory itself may be optionally preserved. * * @param string $directory * @param bool $preserve * @return bool */ public function deleteDirectory($directory, $preserve = false) { if (! $this->isDirectory($directory)) { return false; } $items = new FilesystemIterator($directory); foreach ($items as $item) { // If the item is a directory, we can just recurse into the function and // delete that sub-directory otherwise we'll just delete the file and // keep iterating through each file until the directory is cleaned. if ($item->isDir() && ! $item->isLink()) { $this->deleteDirectory($item->getPathname()); } // If the item is just a file, we can go ahead and delete it since we're // just looping through and waxing all of the files in this directory // and calling directories recursively, so we delete the real path. else { $this->delete($item->getPathname()); } } if (! $preserve) { @rmdir($directory); } return true; } /** * Remove all of the directories within a given directory. * * @param string $directory * @return bool */ public function deleteDirectories($directory) { $allDirectories = $this->directories($directory); if (! empty($allDirectories)) { foreach ($allDirectories as $directoryName) { $this->deleteDirectory($directoryName); } return true; } return false; } /** * Empty the specified directory of all files and folders. * * @param string $directory * @return bool */ public function cleanDirectory($directory) { return $this->deleteDirectory($directory, true); } } PK������y ZŮ8b��b��+��Illuminate/Filesystem/FilesystemAdapter.phpnu�W+A��������<?php namespace Illuminate\Filesystem; use Closure; use Illuminate\Contracts\Filesystem\Cloud as CloudFilesystemContract; use Illuminate\Contracts\Filesystem\Filesystem as FilesystemContract; use Illuminate\Http\File; use Illuminate\Http\UploadedFile; use Illuminate\Support\Arr; use Illuminate\Support\Str; use Illuminate\Support\Traits\Conditionable; use Illuminate\Support\Traits\Macroable; use InvalidArgumentException; use League\Flysystem\FilesystemAdapter as FlysystemAdapter; use League\Flysystem\FilesystemOperator; use League\Flysystem\Ftp\FtpAdapter; use League\Flysystem\Local\LocalFilesystemAdapter as LocalAdapter; use League\Flysystem\PathPrefixer; use League\Flysystem\PhpseclibV3\SftpAdapter; use League\Flysystem\StorageAttributes; use League\Flysystem\UnableToCopyFile; use League\Flysystem\UnableToCreateDirectory; use League\Flysystem\UnableToDeleteDirectory; use League\Flysystem\UnableToDeleteFile; use League\Flysystem\UnableToMoveFile; use League\Flysystem\UnableToProvideChecksum; use League\Flysystem\UnableToReadFile; use League\Flysystem\UnableToRetrieveMetadata; use League\Flysystem\UnableToSetVisibility; use League\Flysystem\UnableToWriteFile; use League\Flysystem\Visibility; use PHPUnit\Framework\Assert as PHPUnit; use Psr\Http\Message\StreamInterface; use RuntimeException; use Symfony\Component\HttpFoundation\StreamedResponse; /** * @mixin \League\Flysystem\FilesystemOperator */ class FilesystemAdapter implements CloudFilesystemContract { use Conditionable; use Macroable { __call as macroCall; } /** * The Flysystem filesystem implementation. * * @var \League\Flysystem\FilesystemOperator */ protected $driver; /** * The Flysystem adapter implementation. * * @var \League\Flysystem\FilesystemAdapter */ protected $adapter; /** * The filesystem configuration. * * @var array */ protected $config; /** * The Flysystem PathPrefixer instance. * * @var \League\Flysystem\PathPrefixer */ protected $prefixer; /** * The temporary URL builder callback. * * @var \Closure|null */ protected $temporaryUrlCallback; /** * Create a new filesystem adapter instance. * * @param \League\Flysystem\FilesystemOperator $driver * @param \League\Flysystem\FilesystemAdapter $adapter * @param array $config * @return void */ public function __construct(FilesystemOperator $driver, FlysystemAdapter $adapter, array $config = []) { $this->driver = $driver; $this->adapter = $adapter; $this->config = $config; $separator = $config['directory_separator'] ?? DIRECTORY_SEPARATOR; $this->prefixer = new PathPrefixer($config['root'] ?? '', $separator); if (isset($config['prefix'])) { $this->prefixer = new PathPrefixer($this->prefixer->prefixPath($config['prefix']), $separator); } } /** * Assert that the given file or directory exists. * * @param string|array $path * @param string|null $content * @return $this */ public function assertExists($path, $content = null) { clearstatcache(); $paths = Arr::wrap($path); foreach ($paths as $path) { PHPUnit::assertTrue( $this->exists($path), "Unable to find a file or directory at path [{$path}]." ); if (! is_null($content)) { $actual = $this->get($path); PHPUnit::assertSame( $content, $actual, "File or directory [{$path}] was found, but content [{$actual}] does not match [{$content}]." ); } } return $this; } /** * Assert that the given file or directory does not exist. * * @param string|array $path * @return $this */ public function assertMissing($path) { clearstatcache(); $paths = Arr::wrap($path); foreach ($paths as $path) { PHPUnit::assertFalse( $this->exists($path), "Found unexpected file or directory at path [{$path}]." ); } return $this; } /** * Assert that the given directory is empty. * * @param string $path * @return $this */ public function assertDirectoryEmpty($path) { PHPUnit::assertEmpty( $this->allFiles($path), "Directory [{$path}] is not empty." ); return $this; } /** * Determine if a file or directory exists. * * @param string $path * @return bool */ public function exists($path) { return $this->driver->has($path); } /** * Determine if a file or directory is missing. * * @param string $path * @return bool */ public function missing($path) { return ! $this->exists($path); } /** * Determine if a file exists. * * @param string $path * @return bool */ public function fileExists($path) { return $this->driver->fileExists($path); } /** * Determine if a file is missing. * * @param string $path * @return bool */ public function fileMissing($path) { return ! $this->fileExists($path); } /** * Determine if a directory exists. * * @param string $path * @return bool */ public function directoryExists($path) { return $this->driver->directoryExists($path); } /** * Determine if a directory is missing. * * @param string $path * @return bool */ public function directoryMissing($path) { return ! $this->directoryExists($path); } /** * Get the full path for the file at the given "short" path. * * @param string $path * @return string */ public function path($path) { return $this->prefixer->prefixPath($path); } /** * Get the contents of a file. * * @param string $path * @return string|null */ public function get($path) { try { return $this->driver->read($path); } catch (UnableToReadFile $e) { throw_if($this->throwsExceptions(), $e); } } /** * Create a streamed response for a given file. * * @param string $path * @param string|null $name * @param array $headers * @param string|null $disposition * @return \Symfony\Component\HttpFoundation\StreamedResponse */ public function response($path, $name = null, array $headers = [], $disposition = 'inline') { $response = new StreamedResponse; if (! array_key_exists('Content-Type', $headers)) { $headers['Content-Type'] = $this->mimeType($path); } if (! array_key_exists('Content-Length', $headers)) { $headers['Content-Length'] = $this->size($path); } if (! array_key_exists('Content-Disposition', $headers)) { $filename = $name ?? basename($path); $disposition = $response->headers->makeDisposition( $disposition, $filename, $this->fallbackName($filename) ); $headers['Content-Disposition'] = $disposition; } $response->headers->replace($headers); $response->setCallback(function () use ($path) { $stream = $this->readStream($path); fpassthru($stream); fclose($stream); }); return $response; } /** * Create a streamed download response for a given file. * * @param string $path * @param string|null $name * @return \Symfony\Component\HttpFoundation\StreamedResponse */ public function download($path, $name = null, array $headers = []) { return $this->response($path, $name, $headers, 'attachment'); } /** * Convert the string to ASCII characters that are equivalent to the given name. * * @param string $name * @return string */ protected function fallbackName($name) { return str_replace('%', '', Str::ascii($name)); } /** * Write the contents of a file. * * @param string $path * @param \Psr\Http\Message\StreamInterface|\Illuminate\Http\File|\Illuminate\Http\UploadedFile|string|resource $contents * @param mixed $options * @return string|bool */ public function put($path, $contents, $options = []) { $options = is_string($options) ? ['visibility' => $options] : (array) $options; // If the given contents is actually a file or uploaded file instance than we will // automatically store the file using a stream. This provides a convenient path // for the developer to store streams without managing them manually in code. if ($contents instanceof File || $contents instanceof UploadedFile) { return $this->putFile($path, $contents, $options); } try { if ($contents instanceof StreamInterface) { $this->driver->writeStream($path, $contents->detach(), $options); return true; } is_resource($contents) ? $this->driver->writeStream($path, $contents, $options) : $this->driver->write($path, $contents, $options); } catch (UnableToWriteFile|UnableToSetVisibility $e) { throw_if($this->throwsExceptions(), $e); return false; } return true; } /** * Store the uploaded file on the disk. * * @param string $path * @param \Illuminate\Http\File|\Illuminate\Http\UploadedFile|string $file * @param mixed $options * @return string|false */ public function putFile($path, $file, $options = []) { $file = is_string($file) ? new File($file) : $file; return $this->putFileAs($path, $file, $file->hashName(), $options); } /** * Store the uploaded file on the disk with a given name. * * @param string $path * @param \Illuminate\Http\File|\Illuminate\Http\UploadedFile|string $file * @param string $name * @param mixed $options * @return string|false */ public function putFileAs($path, $file, $name, $options = []) { $stream = fopen(is_string($file) ? $file : $file->getRealPath(), 'r'); // Next, we will format the path of the file and store the file using a stream since // they provide better performance than alternatives. Once we write the file this // stream will get closed automatically by us so the developer doesn't have to. $result = $this->put( $path = trim($path.'/'.$name, '/'), $stream, $options ); if (is_resource($stream)) { fclose($stream); } return $result ? $path : false; } /** * Get the visibility for the given path. * * @param string $path * @return string */ public function getVisibility($path) { if ($this->driver->visibility($path) == Visibility::PUBLIC) { return FilesystemContract::VISIBILITY_PUBLIC; } return FilesystemContract::VISIBILITY_PRIVATE; } /** * Set the visibility for the given path. * * @param string $path * @param string $visibility * @return bool */ public function setVisibility($path, $visibility) { try { $this->driver->setVisibility($path, $this->parseVisibility($visibility)); } catch (UnableToSetVisibility $e) { throw_if($this->throwsExceptions(), $e); return false; } return true; } /** * Prepend to a file. * * @param string $path * @param string $data * @param string $separator * @return bool */ public function prepend($path, $data, $separator = PHP_EOL) { if ($this->fileExists($path)) { return $this->put($path, $data.$separator.$this->get($path)); } return $this->put($path, $data); } /** * Append to a file. * * @param string $path * @param string $data * @param string $separator * @return bool */ public function append($path, $data, $separator = PHP_EOL) { if ($this->fileExists($path)) { return $this->put($path, $this->get($path).$separator.$data); } return $this->put($path, $data); } /** * Delete the file at a given path. * * @param string|array $paths * @return bool */ public function delete($paths) { $paths = is_array($paths) ? $paths : func_get_args(); $success = true; foreach ($paths as $path) { try { $this->driver->delete($path); } catch (UnableToDeleteFile $e) { throw_if($this->throwsExceptions(), $e); $success = false; } } return $success; } /** * Copy a file to a new location. * * @param string $from * @param string $to * @return bool */ public function copy($from, $to) { try { $this->driver->copy($from, $to); } catch (UnableToCopyFile $e) { throw_if($this->throwsExceptions(), $e); return false; } return true; } /** * Move a file to a new location. * * @param string $from * @param string $to * @return bool */ public function move($from, $to) { try { $this->driver->move($from, $to); } catch (UnableToMoveFile $e) { throw_if($this->throwsExceptions(), $e); return false; } return true; } /** * Get the file size of a given file. * * @param string $path * @return int */ public function size($path) { return $this->driver->fileSize($path); } /** * Get the checksum for a file. * * @return string|false * * @throws UnableToProvideChecksum */ public function checksum(string $path, array $options = []) { try { return $this->driver->checksum($path, $options); } catch (UnableToProvideChecksum $e) { throw_if($this->throwsExceptions(), $e); return false; } } /** * Get the mime-type of a given file. * * @param string $path * @return string|false */ public function mimeType($path) { try { return $this->driver->mimeType($path); } catch (UnableToRetrieveMetadata $e) { throw_if($this->throwsExceptions(), $e); } return false; } /** * Get the file's last modification time. * * @param string $path * @return int */ public function lastModified($path) { return $this->driver->lastModified($path); } /** * {@inheritdoc} */ public function readStream($path) { try { return $this->driver->readStream($path); } catch (UnableToReadFile $e) { throw_if($this->throwsExceptions(), $e); } } /** * {@inheritdoc} */ public function writeStream($path, $resource, array $options = []) { try { $this->driver->writeStream($path, $resource, $options); } catch (UnableToWriteFile|UnableToSetVisibility $e) { throw_if($this->throwsExceptions(), $e); return false; } return true; } /** * Get the URL for the file at the given path. * * @param string $path * @return string * * @throws \RuntimeException */ public function url($path) { if (isset($this->config['prefix'])) { $path = $this->concatPathToUrl($this->config['prefix'], $path); } $adapter = $this->adapter; if (method_exists($adapter, 'getUrl')) { return $adapter->getUrl($path); } elseif (method_exists($this->driver, 'getUrl')) { return $this->driver->getUrl($path); } elseif ($adapter instanceof FtpAdapter || $adapter instanceof SftpAdapter) { return $this->getFtpUrl($path); } elseif ($adapter instanceof LocalAdapter) { return $this->getLocalUrl($path); } else { throw new RuntimeException('This driver does not support retrieving URLs.'); } } /** * Get the URL for the file at the given path. * * @param string $path * @return string */ protected function getFtpUrl($path) { return isset($this->config['url']) ? $this->concatPathToUrl($this->config['url'], $path) : $path; } /** * Get the URL for the file at the given path. * * @param string $path * @return string */ protected function getLocalUrl($path) { // If an explicit base URL has been set on the disk configuration then we will use // it as the base URL instead of the default path. This allows the developer to // have full control over the base path for this filesystem's generated URLs. if (isset($this->config['url'])) { return $this->concatPathToUrl($this->config['url'], $path); } $path = '/storage/'.$path; // If the path contains "storage/public", it probably means the developer is using // the default disk to generate the path instead of the "public" disk like they // are really supposed to use. We will remove the public from this path here. if (str_contains($path, '/storage/public/')) { return Str::replaceFirst('/public/', '/', $path); } return $path; } /** * Determine if temporary URLs can be generated. * * @return bool */ public function providesTemporaryUrls() { return method_exists($this->adapter, 'getTemporaryUrl') || isset($this->temporaryUrlCallback); } /** * Get a temporary URL for the file at the given path. * * @param string $path * @param \DateTimeInterface $expiration * @param array $options * @return string * * @throws \RuntimeException */ public function temporaryUrl($path, $expiration, array $options = []) { if (method_exists($this->adapter, 'getTemporaryUrl')) { return $this->adapter->getTemporaryUrl($path, $expiration, $options); } if ($this->temporaryUrlCallback) { return $this->temporaryUrlCallback->bindTo($this, static::class)( $path, $expiration, $options ); } throw new RuntimeException('This driver does not support creating temporary URLs.'); } /** * Get a temporary upload URL for the file at the given path. * * @param string $path * @param \DateTimeInterface $expiration * @param array $options * @return array * * @throws \RuntimeException */ public function temporaryUploadUrl($path, $expiration, array $options = []) { if (method_exists($this->adapter, 'temporaryUploadUrl')) { return $this->adapter->temporaryUploadUrl($path, $expiration, $options); } throw new RuntimeException('This driver does not support creating temporary upload URLs.'); } /** * Concatenate a path to a URL. * * @param string $url * @param string $path * @return string */ protected function concatPathToUrl($url, $path) { return rtrim($url, '/').'/'.ltrim($path, '/'); } /** * Replace the scheme, host and port of the given UriInterface with values from the given URL. * * @param \Psr\Http\Message\UriInterface $uri * @param string $url * @return \Psr\Http\Message\UriInterface */ protected function replaceBaseUrl($uri, $url) { $parsed = parse_url($url); return $uri ->withScheme($parsed['scheme']) ->withHost($parsed['host']) ->withPort($parsed['port'] ?? null); } /** * Get an array of all files in a directory. * * @param string|null $directory * @param bool $recursive * @return array */ public function files($directory = null, $recursive = false) { return $this->driver->listContents($directory ?? '', $recursive) ->filter(function (StorageAttributes $attributes) { return $attributes->isFile(); }) ->sortByPath() ->map(function (StorageAttributes $attributes) { return $attributes->path(); }) ->toArray(); } /** * Get all of the files from the given directory (recursive). * * @param string|null $directory * @return array */ public function allFiles($directory = null) { return $this->files($directory, true); } /** * Get all of the directories within a given directory. * * @param string|null $directory * @param bool $recursive * @return array */ public function directories($directory = null, $recursive = false) { return $this->driver->listContents($directory ?? '', $recursive) ->filter(function (StorageAttributes $attributes) { return $attributes->isDir(); }) ->map(function (StorageAttributes $attributes) { return $attributes->path(); }) ->toArray(); } /** * Get all the directories within a given directory (recursive). * * @param string|null $directory * @return array */ public function allDirectories($directory = null) { return $this->directories($directory, true); } /** * Create a directory. * * @param string $path * @return bool */ public function makeDirectory($path) { try { $this->driver->createDirectory($path); } catch (UnableToCreateDirectory|UnableToSetVisibility $e) { throw_if($this->throwsExceptions(), $e); return false; } return true; } /** * Recursively delete a directory. * * @param string $directory * @return bool */ public function deleteDirectory($directory) { try { $this->driver->deleteDirectory($directory); } catch (UnableToDeleteDirectory $e) { throw_if($this->throwsExceptions(), $e); return false; } return true; } /** * Get the Flysystem driver. * * @return \League\Flysystem\FilesystemOperator */ public function getDriver() { return $this->driver; } /** * Get the Flysystem adapter. * * @return \League\Flysystem\FilesystemAdapter */ public function getAdapter() { return $this->adapter; } /** * Get the configuration values. * * @return array */ public function getConfig() { return $this->config; } /** * Parse the given visibility value. * * @param string|null $visibility * @return string|null * * @throws \InvalidArgumentException */ protected function parseVisibility($visibility) { if (is_null($visibility)) { return; } return match ($visibility) { FilesystemContract::VISIBILITY_PUBLIC => Visibility::PUBLIC, FilesystemContract::VISIBILITY_PRIVATE => Visibility::PRIVATE, default => throw new InvalidArgumentException("Unknown visibility: {$visibility}."), }; } /** * Define a custom temporary URL builder callback. * * @param \Closure $callback * @return void */ public function buildTemporaryUrlsUsing(Closure $callback) { $this->temporaryUrlCallback = $callback; } /** * Determine if Flysystem exceptions should be thrown. * * @return bool */ protected function throwsExceptions(): bool { return (bool) ($this->config['throw'] ?? false); } /** * Pass dynamic methods call onto Flysystem. * * @param string $method * @param array $parameters * @return mixed * * @throws \BadMethodCallException */ public function __call($method, array $parameters) { if (static::hasMacro($method)) { return $this->macroCall($method, $parameters); } return $this->driver->{$method}(...$parameters); } } PK������y Z����3��Illuminate/Filesystem/FilesystemServiceProvider.phpnu�W+A��������<?php namespace Illuminate\Filesystem; use Illuminate\Support\ServiceProvider; class FilesystemServiceProvider extends ServiceProvider { /** * Register the service provider. * * @return void */ public function register() { $this->registerNativeFilesystem(); $this->registerFlysystem(); } /** * Register the native filesystem implementation. * * @return void */ protected function registerNativeFilesystem() { $this->app->singleton('files', function () { return new Filesystem; }); } /** * Register the driver based filesystem. * * @return void */ protected function registerFlysystem() { $this->registerManager(); $this->app->singleton('filesystem.disk', function ($app) { return $app['filesystem']->disk($this->getDefaultDriver()); }); $this->app->singleton('filesystem.cloud', function ($app) { return $app['filesystem']->disk($this->getCloudDriver()); }); } /** * Register the filesystem manager. * * @return void */ protected function registerManager() { $this->app->singleton('filesystem', function ($app) { return new FilesystemManager($app); }); } /** * Get the default file driver. * * @return string */ protected function getDefaultDriver() { return $this->app['config']['filesystems.default']; } /** * Get the default cloud based file driver. * * @return string */ protected function getCloudDriver() { return $this->app['config']['filesystems.cloud']; } } PK������y ZRs����&��Illuminate/Filesystem/LockableFile.phpnu�W+A��������<?php namespace Illuminate\Filesystem; use Exception; use Illuminate\Contracts\Filesystem\LockTimeoutException; class LockableFile { /** * The file resource. * * @var resource */ protected $handle; /** * The file path. * * @var string */ protected $path; /** * Indicates if the file is locked. * * @var bool */ protected $isLocked = false; /** * Create a new File instance. * * @param string $path * @param string $mode * @return void */ public function __construct($path, $mode) { $this->path = $path; $this->ensureDirectoryExists($path); $this->createResource($path, $mode); } /** * Create the file's directory if necessary. * * @param string $path * @return void */ protected function ensureDirectoryExists($path) { if (! file_exists(dirname($path))) { @mkdir(dirname($path), 0777, true); } } /** * Create the file resource. * * @param string $path * @param string $mode * @return void * * @throws \Exception */ protected function createResource($path, $mode) { $this->handle = @fopen($path, $mode); if (! $this->handle) { throw new Exception('Unable to create lockable file: '.$path.'. Please ensure you have permission to create files in this location.'); } } /** * Read the file contents. * * @param int|null $length * @return string */ public function read($length = null) { clearstatcache(true, $this->path); return fread($this->handle, $length ?? ($this->size() ?: 1)); } /** * Get the file size. * * @return int */ public function size() { return filesize($this->path); } /** * Write to the file. * * @param string $contents * @return $this */ public function write($contents) { fwrite($this->handle, $contents); fflush($this->handle); return $this; } /** * Truncate the file. * * @return $this */ public function truncate() { rewind($this->handle); ftruncate($this->handle, 0); return $this; } /** * Get a shared lock on the file. * * @param bool $block * @return $this * * @throws \Illuminate\Contracts\Filesystem\LockTimeoutException */ public function getSharedLock($block = false) { if (! flock($this->handle, LOCK_SH | ($block ? 0 : LOCK_NB))) { throw new LockTimeoutException("Unable to acquire file lock at path [{$this->path}]."); } $this->isLocked = true; return $this; } /** * Get an exclusive lock on the file. * * @param bool $block * @return bool * * @throws \Illuminate\Contracts\Filesystem\LockTimeoutException */ public function getExclusiveLock($block = false) { if (! flock($this->handle, LOCK_EX | ($block ? 0 : LOCK_NB))) { throw new LockTimeoutException("Unable to acquire file lock at path [{$this->path}]."); } $this->isLocked = true; return $this; } /** * Release the lock on the file. * * @return $this */ public function releaseLock() { flock($this->handle, LOCK_UN); $this->isLocked = false; return $this; } /** * Close the file. * * @return bool */ public function close() { if ($this->isLocked) { $this->releaseLock(); } return fclose($this->handle); } } PK������y Z륄fD��D��#��Illuminate/Filesystem/composer.jsonnu�W+A��������{ "name": "illuminate/filesystem", "description": "The Illuminate Filesystem package.", "license": "MIT", "homepage": "https://laravel.com", "support": { "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, "authors": [ { "name": "Taylor Otwell", "email": "taylor@laravel.com" } ], "require": { "php": "^8.0.2", "illuminate/collections": "^9.0", "illuminate/contracts": "^9.0", "illuminate/macroable": "^9.0", "illuminate/support": "^9.0", "symfony/finder": "^6.0" }, "autoload": { "psr-4": { "Illuminate\\Filesystem\\": "" } }, "extra": { "branch-alias": { "dev-master": "9.x-dev" } }, "suggest": { "ext-fileinfo": "Required to use the Filesystem class.", "ext-ftp": "Required to use the Flysystem FTP driver.", "ext-hash": "Required to use the Filesystem class.", "illuminate/http": "Required for handling uploaded files (^7.0).", "league/flysystem": "Required to use the Flysystem local driver (^3.0.16).", "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.0).", "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.0).", "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.0).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", "symfony/filesystem": "Required to enable support for relative symbolic links (^6.0).", "symfony/mime": "Required to enable support for guessing extensions (^6.0)." }, "config": { "sort-packages": true }, "minimum-stability": "dev" } PK������y Zα3��3��!��Illuminate/Translation/LICENSE.mdnu�W+A��������The MIT License (MIT) Copyright (c) Taylor Otwell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PK������y Z8vO��O��&��Illuminate/Translation/ArrayLoader.phpnu�W+A��������<?php namespace Illuminate\Translation; use Illuminate\Contracts\Translation\Loader; class ArrayLoader implements Loader { /** * All of the translation messages. * * @var array */ protected $messages = []; /** * Load the messages for the given locale. * * @param string $locale * @param string $group * @param string|null $namespace * @return array */ public function load($locale, $group, $namespace = null) { $namespace = $namespace ?: '*'; return $this->messages[$namespace][$locale][$group] ?? []; } /** * Add a new namespace to the loader. * * @param string $namespace * @param string $hint * @return void */ public function addNamespace($namespace, $hint) { // } /** * Add a new JSON path to the loader. * * @param string $path * @return void */ public function addJsonPath($path) { // } /** * Add messages to the loader. * * @param string $locale * @param string $group * @param array $messages * @param string|null $namespace * @return $this */ public function addMessages($locale, $group, array $messages, $namespace = null) { $namespace = $namespace ?: '*'; $this->messages[$namespace][$locale][$group] = $messages; return $this; } /** * Get an array of all the registered namespaces. * * @return array */ public function namespaces() { return []; } } PK������y Z����6��Illuminate/Translation/PotentiallyTranslatedString.phpnu�W+A��������<?php namespace Illuminate\Translation; use Stringable; class PotentiallyTranslatedString implements Stringable { /** * The string that may be translated. * * @var string */ protected $string; /** * The translated string. * * @var string|null */ protected $translation; /** * The validator that may perform the translation. * * @var \Illuminate\Contracts\Translation\Translator */ protected $translator; /** * Create a new potentially translated string. * * @param string $string * @param \Illuminate\Contracts\Translation\Translator $translator */ public function __construct($string, $translator) { $this->string = $string; $this->translator = $translator; } /** * Translate the string. * * @param array $replace * @param string|null $locale * @return $this */ public function translate($replace = [], $locale = null) { $this->translation = $this->translator->get($this->string, $replace, $locale); return $this; } /** * Translates the string based on a count. * * @param \Countable|int|array $number * @param array $replace * @param string|null $locale * @return $this */ public function translateChoice($number, array $replace = [], $locale = null) { $this->translation = $this->translator->choice($this->string, $number, $replace, $locale); return $this; } /** * Get the original string. * * @return string */ public function original() { return $this->string; } /** * Get the potentially translated string. * * @return string */ public function __toString() { return $this->translation ?? $this->string; } /** * Get the potentially translated string. * * @return string */ public function toString() { return (string) $this; } } PK������y Z6ao��o��%��Illuminate/Translation/FileLoader.phpnu�W+A��������<?php namespace Illuminate\Translation; use Illuminate\Contracts\Translation\Loader; use Illuminate\Filesystem\Filesystem; use RuntimeException; class FileLoader implements Loader { /** * The filesystem instance. * * @var \Illuminate\Filesystem\Filesystem */ protected $files; /** * The default path for the loader. * * @var string */ protected $path; /** * All of the registered paths to JSON translation files. * * @var array */ protected $jsonPaths = []; /** * All of the namespace hints. * * @var array */ protected $hints = []; /** * Create a new file loader instance. * * @param \Illuminate\Filesystem\Filesystem $files * @param string $path * @return void */ public function __construct(Filesystem $files, $path) { $this->path = $path; $this->files = $files; } /** * Load the messages for the given locale. * * @param string $locale * @param string $group * @param string|null $namespace * @return array */ public function load($locale, $group, $namespace = null) { if ($group === '*' && $namespace === '*') { return $this->loadJsonPaths($locale); } if (is_null($namespace) || $namespace === '*') { return $this->loadPath($this->path, $locale, $group); } return $this->loadNamespaced($locale, $group, $namespace); } /** * Load a namespaced translation group. * * @param string $locale * @param string $group * @param string $namespace * @return array */ protected function loadNamespaced($locale, $group, $namespace) { if (isset($this->hints[$namespace])) { $lines = $this->loadPath($this->hints[$namespace], $locale, $group); return $this->loadNamespaceOverrides($lines, $locale, $group, $namespace); } return []; } /** * Load a local namespaced translation group for overrides. * * @param array $lines * @param string $locale * @param string $group * @param string $namespace * @return array */ protected function loadNamespaceOverrides(array $lines, $locale, $group, $namespace) { $file = "{$this->path}/vendor/{$namespace}/{$locale}/{$group}.php"; if ($this->files->exists($file)) { return array_replace_recursive($lines, $this->files->getRequire($file)); } return $lines; } /** * Load a locale from a given path. * * @param string $path * @param string $locale * @param string $group * @return array */ protected function loadPath($path, $locale, $group) { if ($this->files->exists($full = "{$path}/{$locale}/{$group}.php")) { return $this->files->getRequire($full); } return []; } /** * Load a locale from the given JSON file path. * * @param string $locale * @return array * * @throws \RuntimeException */ protected function loadJsonPaths($locale) { return collect(array_merge($this->jsonPaths, [$this->path])) ->reduce(function ($output, $path) use ($locale) { if ($this->files->exists($full = "{$path}/{$locale}.json")) { $decoded = json_decode($this->files->get($full), true); if (is_null($decoded) || json_last_error() !== JSON_ERROR_NONE) { throw new RuntimeException("Translation file [{$full}] contains an invalid JSON structure."); } $output = array_merge($output, $decoded); } return $output; }, []); } /** * Add a new namespace to the loader. * * @param string $namespace * @param string $hint * @return void */ public function addNamespace($namespace, $hint) { $this->hints[$namespace] = $hint; } /** * Get an array of all the registered namespaces. * * @return array */ public function namespaces() { return $this->hints; } /** * Add a new JSON path to the loader. * * @param string $path * @return void */ public function addJsonPath($path) { $this->jsonPaths[] = $path; } /** * Get an array of all the registered paths to JSON translation files. * * @return array */ public function jsonPaths() { return $this->jsonPaths; } } PK������y ZTN2��N2��%��Illuminate/Translation/Translator.phpnu�W+A��������<?php namespace Illuminate\Translation; use Closure; use Illuminate\Contracts\Translation\Loader; use Illuminate\Contracts\Translation\Translator as TranslatorContract; use Illuminate\Support\Arr; use Illuminate\Support\NamespacedItemResolver; use Illuminate\Support\Str; use Illuminate\Support\Traits\Macroable; use Illuminate\Support\Traits\ReflectsClosures; use InvalidArgumentException; class Translator extends NamespacedItemResolver implements TranslatorContract { use Macroable, ReflectsClosures; /** * The loader implementation. * * @var \Illuminate\Contracts\Translation\Loader */ protected $loader; /** * The default locale being used by the translator. * * @var string */ protected $locale; /** * The fallback locale used by the translator. * * @var string */ protected $fallback; /** * The array of loaded translation groups. * * @var array */ protected $loaded = []; /** * The message selector. * * @var \Illuminate\Translation\MessageSelector */ protected $selector; /** * The callable that should be invoked to determine applicable locales. * * @var callable */ protected $determineLocalesUsing; /** * The custom rendering callbacks for stringable objects. * * @var array */ protected $stringableHandlers = []; /** * Create a new translator instance. * * @param \Illuminate\Contracts\Translation\Loader $loader * @param string $locale * @return void */ public function __construct(Loader $loader, $locale) { $this->loader = $loader; $this->setLocale($locale); } /** * Determine if a translation exists for a given locale. * * @param string $key * @param string|null $locale * @return bool */ public function hasForLocale($key, $locale = null) { return $this->has($key, $locale, false); } /** * Determine if a translation exists. * * @param string $key * @param string|null $locale * @param bool $fallback * @return bool */ public function has($key, $locale = null, $fallback = true) { return $this->get($key, [], $locale, $fallback) !== $key; } /** * Get the translation for the given key. * * @param string $key * @param array $replace * @param string|null $locale * @param bool $fallback * @return string|array */ public function get($key, array $replace = [], $locale = null, $fallback = true) { $locale = $locale ?: $this->locale; // For JSON translations, there is only one file per locale, so we will simply load // that file and then we will be ready to check the array for the key. These are // only one level deep so we do not need to do any fancy searching through it. $this->load('*', '*', $locale); $line = $this->loaded['*']['*'][$locale][$key] ?? null; // If we can't find a translation for the JSON key, we will attempt to translate it // using the typical translation file. This way developers can always just use a // helper such as __ instead of having to pick between trans or __ with views. if (! isset($line)) { [$namespace, $group, $item] = $this->parseKey($key); // Here we will get the locale that should be used for the language line. If one // was not passed, we will use the default locales which was given to us when // the translator was instantiated. Then, we can load the lines and return. $locales = $fallback ? $this->localeArray($locale) : [$locale]; foreach ($locales as $locale) { if (! is_null($line = $this->getLine( $namespace, $group, $locale, $item, $replace ))) { return $line; } } } // If the line doesn't exist, we will return back the key which was requested as // that will be quick to spot in the UI if language keys are wrong or missing // from the application's language files. Otherwise we can return the line. return $this->makeReplacements($line ?: $key, $replace); } /** * Get a translation according to an integer value. * * @param string $key * @param \Countable|int|array $number * @param array $replace * @param string|null $locale * @return string */ public function choice($key, $number, array $replace = [], $locale = null) { $line = $this->get( $key, $replace, $locale = $this->localeForChoice($locale) ); // If the given "number" is actually an array or countable we will simply count the // number of elements in an instance. This allows developers to pass an array of // items without having to count it on their end first which gives bad syntax. if (is_countable($number)) { $number = count($number); } $replace['count'] = $number; return $this->makeReplacements( $this->getSelector()->choose($line, $number, $locale), $replace ); } /** * Get the proper locale for a choice operation. * * @param string|null $locale * @return string */ protected function localeForChoice($locale) { return $locale ?: $this->locale ?: $this->fallback; } /** * Retrieve a language line out the loaded array. * * @param string $namespace * @param string $group * @param string $locale * @param string $item * @param array $replace * @return string|array|null */ protected function getLine($namespace, $group, $locale, $item, array $replace) { $this->load($namespace, $group, $locale); $line = Arr::get($this->loaded[$namespace][$group][$locale], $item); if (is_string($line)) { return $this->makeReplacements($line, $replace); } elseif (is_array($line) && count($line) > 0) { array_walk_recursive($line, function (&$value, $key) use ($replace) { $value = $this->makeReplacements($value, $replace); }); return $line; } } /** * Make the place-holder replacements on a line. * * @param string $line * @param array $replace * @return string */ protected function makeReplacements($line, array $replace) { if (empty($replace)) { return $line; } $shouldReplace = []; foreach ($replace as $key => $value) { if (is_object($value) && isset($this->stringableHandlers[get_class($value)])) { $value = call_user_func($this->stringableHandlers[get_class($value)], $value); } $shouldReplace[':'.Str::ucfirst($key ?? '')] = Str::ucfirst($value ?? ''); $shouldReplace[':'.Str::upper($key ?? '')] = Str::upper($value ?? ''); $shouldReplace[':'.$key] = $value; } return strtr($line, $shouldReplace); } /** * Add translation lines to the given locale. * * @param array $lines * @param string $locale * @param string $namespace * @return void */ public function addLines(array $lines, $locale, $namespace = '*') { foreach ($lines as $key => $value) { [$group, $item] = explode('.', $key, 2); Arr::set($this->loaded, "$namespace.$group.$locale.$item", $value); } } /** * Load the specified language group. * * @param string $namespace * @param string $group * @param string $locale * @return void */ public function load($namespace, $group, $locale) { if ($this->isLoaded($namespace, $group, $locale)) { return; } // The loader is responsible for returning the array of language lines for the // given namespace, group, and locale. We'll set the lines in this array of // lines that have already been loaded so that we can easily access them. $lines = $this->loader->load($locale, $group, $namespace); $this->loaded[$namespace][$group][$locale] = $lines; } /** * Determine if the given group has been loaded. * * @param string $namespace * @param string $group * @param string $locale * @return bool */ protected function isLoaded($namespace, $group, $locale) { return isset($this->loaded[$namespace][$group][$locale]); } /** * Add a new namespace to the loader. * * @param string $namespace * @param string $hint * @return void */ public function addNamespace($namespace, $hint) { $this->loader->addNamespace($namespace, $hint); } /** * Add a new JSON path to the loader. * * @param string $path * @return void */ public function addJsonPath($path) { $this->loader->addJsonPath($path); } /** * Parse a key into namespace, group, and item. * * @param string $key * @return array */ public function parseKey($key) { $segments = parent::parseKey($key); if (is_null($segments[0])) { $segments[0] = '*'; } return $segments; } /** * Get the array of locales to be checked. * * @param string|null $locale * @return array */ protected function localeArray($locale) { $locales = array_filter([$locale ?: $this->locale, $this->fallback]); return call_user_func($this->determineLocalesUsing ?: fn () => $locales, $locales); } /** * Specify a callback that should be invoked to determined the applicable locale array. * * @param callable $callback * @return void */ public function determineLocalesUsing($callback) { $this->determineLocalesUsing = $callback; } /** * Get the message selector instance. * * @return \Illuminate\Translation\MessageSelector */ public function getSelector() { if (! isset($this->selector)) { $this->selector = new MessageSelector; } return $this->selector; } /** * Set the message selector instance. * * @param \Illuminate\Translation\MessageSelector $selector * @return void */ public function setSelector(MessageSelector $selector) { $this->selector = $selector; } /** * Get the language line loader implementation. * * @return \Illuminate\Contracts\Translation\Loader */ public function getLoader() { return $this->loader; } /** * Get the default locale being used. * * @return string */ public function locale() { return $this->getLocale(); } /** * Get the default locale being used. * * @return string */ public function getLocale() { return $this->locale; } /** * Set the default locale. * * @param string $locale * @return void * * @throws \InvalidArgumentException */ public function setLocale($locale) { if (Str::contains($locale, ['/', '\\'])) { throw new InvalidArgumentException('Invalid characters present in locale.'); } $this->locale = $locale; } /** * Get the fallback locale being used. * * @return string */ public function getFallback() { return $this->fallback; } /** * Set the fallback locale being used. * * @param string $fallback * @return void */ public function setFallback($fallback) { $this->fallback = $fallback; } /** * Set the loaded translation groups. * * @param array $loaded * @return void */ public function setLoaded(array $loaded) { $this->loaded = $loaded; } /** * Add a handler to be executed in order to format a given class to a string during translation replacements. * * @param callable|string $class * @param callable|null $handler * @return void */ public function stringable($class, $handler = null) { if ($class instanceof Closure) { [$class, $handler] = [ $this->firstClosureParameterType($class), $class, ]; } $this->stringableHandlers[$class] = $handler; } } PK������y Z����5��Illuminate/Translation/TranslationServiceProvider.phpnu�W+A��������<?php namespace Illuminate\Translation; use Illuminate\Contracts\Support\DeferrableProvider; use Illuminate\Support\ServiceProvider; class TranslationServiceProvider extends ServiceProvider implements DeferrableProvider { /** * Register the service provider. * * @return void */ public function register() { $this->registerLoader(); $this->app->singleton('translator', function ($app) { $loader = $app['translation.loader']; // When registering the translator component, we'll need to set the default // locale as well as the fallback locale. So, we'll grab the application // configuration so we can easily get both of these values from there. $locale = $app->getLocale(); $trans = new Translator($loader, $locale); $trans->setFallback($app->getFallbackLocale()); return $trans; }); } /** * Register the translation line loader. * * @return void */ protected function registerLoader() { $this->app->singleton('translation.loader', function ($app) { return new FileLoader($app['files'], $app['path.lang']); }); } /** * Get the services provided by the provider. * * @return array */ public function provides() { return ['translator', 'translation.loader']; } } PK������y Zė-��-��*��Illuminate/Translation/MessageSelector.phpnu�W+A��������<?php namespace Illuminate\Translation; class MessageSelector { /** * Select a proper translation string based on the given number. * * @param string $line * @param int $number * @param string $locale * @return mixed */ public function choose($line, $number, $locale) { $segments = explode('|', $line); if (($value = $this->extract($segments, $number)) !== null) { return trim($value); } $segments = $this->stripConditions($segments); $pluralIndex = $this->getPluralIndex($locale, $number); if (count($segments) === 1 || ! isset($segments[$pluralIndex])) { return $segments[0]; } return $segments[$pluralIndex]; } /** * Extract a translation string using inline conditions. * * @param array $segments * @param int $number * @return mixed */ private function extract($segments, $number) { foreach ($segments as $part) { if (! is_null($line = $this->extractFromString($part, $number))) { return $line; } } } /** * Get the translation string if the condition matches. * * @param string $part * @param int $number * @return mixed */ private function extractFromString($part, $number) { preg_match('/^[\{\[]([^\[\]\{\}]*)[\}\]](.*)/s', $part, $matches); if (count($matches) !== 3) { return null; } $condition = $matches[1]; $value = $matches[2]; if (str_contains($condition, ',')) { [$from, $to] = explode(',', $condition, 2); if ($to === '*' && $number >= $from) { return $value; } elseif ($from === '*' && $number <= $to) { return $value; } elseif ($number >= $from && $number <= $to) { return $value; } } return $condition == $number ? $value : null; } /** * Strip the inline conditions from each segment, just leaving the text. * * @param array $segments * @return array */ private function stripConditions($segments) { return collect($segments) ->map(fn ($part) => preg_replace('/^[\{\[]([^\[\]\{\}]*)[\}\]]/', '', $part)) ->all(); } /** * Get the index to use for pluralization. * * The plural rules are derived from code of the Zend Framework (2010-09-25), which * is subject to the new BSD license (https://framework.zend.com/license) * Copyright (c) 2005-2010 - Zend Technologies USA Inc. (http://www.zend.com) * * @param string $locale * @param int $number * @return int */ public function getPluralIndex($locale, $number) { switch ($locale) { case 'az': case 'az_AZ': case 'bo': case 'bo_CN': case 'bo_IN': case 'dz': case 'dz_BT': case 'id': case 'id_ID': case 'ja': case 'ja_JP': case 'jv': case 'ka': case 'ka_GE': case 'km': case 'km_KH': case 'kn': case 'kn_IN': case 'ko': case 'ko_KR': case 'ms': case 'ms_MY': case 'th': case 'th_TH': case 'tr': case 'tr_CY': case 'tr_TR': case 'vi': case 'vi_VN': case 'zh': case 'zh_CN': case 'zh_HK': case 'zh_SG': case 'zh_TW': return 0; case 'af': case 'af_ZA': case 'bn': case 'bn_BD': case 'bn_IN': case 'bg': case 'bg_BG': case 'ca': case 'ca_AD': case 'ca_ES': case 'ca_FR': case 'ca_IT': case 'da': case 'da_DK': case 'de': case 'de_AT': case 'de_BE': case 'de_CH': case 'de_DE': case 'de_LI': case 'de_LU': case 'el': case 'el_CY': case 'el_GR': case 'en': case 'en_AG': case 'en_AU': case 'en_BW': case 'en_CA': case 'en_DK': case 'en_GB': case 'en_HK': case 'en_IE': case 'en_IN': case 'en_NG': case 'en_NZ': case 'en_PH': case 'en_SG': case 'en_US': case 'en_ZA': case 'en_ZM': case 'en_ZW': case 'eo': case 'eo_US': case 'es': case 'es_AR': case 'es_BO': case 'es_CL': case 'es_CO': case 'es_CR': case 'es_CU': case 'es_DO': case 'es_EC': case 'es_ES': case 'es_GT': case 'es_HN': case 'es_MX': case 'es_NI': case 'es_PA': case 'es_PE': case 'es_PR': case 'es_PY': case 'es_SV': case 'es_US': case 'es_UY': case 'es_VE': case 'et': case 'et_EE': case 'eu': case 'eu_ES': case 'eu_FR': case 'fa': case 'fa_IR': case 'fi': case 'fi_FI': case 'fo': case 'fo_FO': case 'fur': case 'fur_IT': case 'fy': case 'fy_DE': case 'fy_NL': case 'gl': case 'gl_ES': case 'gu': case 'gu_IN': case 'ha': case 'ha_NG': case 'he': case 'he_IL': case 'hu': case 'hu_HU': case 'is': case 'is_IS': case 'it': case 'it_CH': case 'it_IT': case 'ku': case 'ku_TR': case 'lb': case 'lb_LU': case 'ml': case 'ml_IN': case 'mn': case 'mn_MN': case 'mr': case 'mr_IN': case 'nah': case 'nb': case 'nb_NO': case 'ne': case 'ne_NP': case 'nl': case 'nl_AW': case 'nl_BE': case 'nl_NL': case 'nn': case 'nn_NO': case 'no': case 'om': case 'om_ET': case 'om_KE': case 'or': case 'or_IN': case 'pa': case 'pa_IN': case 'pa_PK': case 'pap': case 'pap_AN': case 'pap_AW': case 'pap_CW': case 'ps': case 'ps_AF': case 'pt': case 'pt_BR': case 'pt_PT': case 'so': case 'so_DJ': case 'so_ET': case 'so_KE': case 'so_SO': case 'sq': case 'sq_AL': case 'sq_MK': case 'sv': case 'sv_FI': case 'sv_SE': case 'sw': case 'sw_KE': case 'sw_TZ': case 'ta': case 'ta_IN': case 'ta_LK': case 'te': case 'te_IN': case 'tk': case 'tk_TM': case 'ur': case 'ur_IN': case 'ur_PK': case 'zu': case 'zu_ZA': return ($number == 1) ? 0 : 1; case 'am': case 'am_ET': case 'bh': case 'fil': case 'fil_PH': case 'fr': case 'fr_BE': case 'fr_CA': case 'fr_CH': case 'fr_FR': case 'fr_LU': case 'gun': case 'hi': case 'hi_IN': case 'hy': case 'hy_AM': case 'ln': case 'ln_CD': case 'mg': case 'mg_MG': case 'nso': case 'nso_ZA': case 'ti': case 'ti_ER': case 'ti_ET': case 'wa': case 'wa_BE': case 'xbr': return (($number == 0) || ($number == 1)) ? 0 : 1; case 'be': case 'be_BY': case 'bs': case 'bs_BA': case 'hr': case 'hr_HR': case 'ru': case 'ru_RU': case 'ru_UA': case 'sr': case 'sr_ME': case 'sr_RS': case 'uk': case 'uk_UA': return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); case 'cs': case 'cs_CZ': case 'sk': case 'sk_SK': return ($number == 1) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2); case 'ga': case 'ga_IE': return ($number == 1) ? 0 : (($number == 2) ? 1 : 2); case 'lt': case 'lt_LT': return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); case 'sl': case 'sl_SI': return ($number % 100 == 1) ? 0 : (($number % 100 == 2) ? 1 : ((($number % 100 == 3) || ($number % 100 == 4)) ? 2 : 3)); case 'mk': case 'mk_MK': return ($number % 10 == 1) ? 0 : 1; case 'mt': case 'mt_MT': return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3)); case 'lv': case 'lv_LV': return ($number == 0) ? 0 : ((($number % 10 == 1) && ($number % 100 != 11)) ? 1 : 2); case 'pl': case 'pl_PL': return ($number == 1) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2); case 'cy': case 'cy_GB': return ($number == 1) ? 0 : (($number == 2) ? 1 : ((($number == 8) || ($number == 11)) ? 2 : 3)); case 'ro': case 'ro_RO': return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2); case 'ar': case 'ar_AE': case 'ar_BH': case 'ar_DZ': case 'ar_EG': case 'ar_IN': case 'ar_IQ': case 'ar_JO': case 'ar_KW': case 'ar_LB': case 'ar_LY': case 'ar_MA': case 'ar_OM': case 'ar_QA': case 'ar_SA': case 'ar_SD': case 'ar_SS': case 'ar_SY': case 'ar_TN': case 'ar_YE': return ($number == 0) ? 0 : (($number == 1) ? 1 : (($number == 2) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : 5)))); default: return 0; } } } PK������y Z珡����$��Illuminate/Translation/composer.jsonnu�W+A��������{ "name": "illuminate/translation", "description": "The Illuminate Translation package.", "license": "MIT", "homepage": "https://laravel.com", "support": { "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, "authors": [ { "name": "Taylor Otwell", "email": "taylor@laravel.com" } ], "require": { "php": "^8.0.2", "illuminate/collections": "^9.0", "illuminate/contracts": "^9.0", "illuminate/macroable": "^9.0", "illuminate/filesystem": "^9.0", "illuminate/support": "^9.0" }, "autoload": { "psr-4": { "Illuminate\\Translation\\": "" } }, "extra": { "branch-alias": { "dev-master": "9.x-dev" } }, "config": { "sort-packages": true }, "minimum-stability": "dev" } PK������y ZIs ��s ����Illuminate/Auth/TokenGuard.phpnu�W+A��������<?php namespace Illuminate\Auth; use Illuminate\Contracts\Auth\Guard; use Illuminate\Contracts\Auth\UserProvider; use Illuminate\Http\Request; class TokenGuard implements Guard { use GuardHelpers; /** * The request instance. * * @var \Illuminate\Http\Request */ protected $request; /** * The name of the query string item from the request containing the API token. * * @var string */ protected $inputKey; /** * The name of the token "column" in persistent storage. * * @var string */ protected $storageKey; /** * Indicates if the API token is hashed in storage. * * @var bool */ protected $hash = false; /** * Create a new authentication guard. * * @param \Illuminate\Contracts\Auth\UserProvider $provider * @param \Illuminate\Http\Request $request * @param string $inputKey * @param string $storageKey * @param bool $hash * @return void */ public function __construct( UserProvider $provider, Request $request, $inputKey = 'api_token', $storageKey = 'api_token', $hash = false) { $this->hash = $hash; $this->request = $request; $this->provider = $provider; $this->inputKey = $inputKey; $this->storageKey = $storageKey; } /** * Get the currently authenticated user. * * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function user() { // If we've already retrieved the user for the current request we can just // return it back immediately. We do not want to fetch the user data on // every call to this method because that would be tremendously slow. if (! is_null($this->user)) { return $this->user; } $user = null; $token = $this->getTokenForRequest(); if (! empty($token)) { $user = $this->provider->retrieveByCredentials([ $this->storageKey => $this->hash ? hash('sha256', $token) : $token, ]); } return $this->user = $user; } /** * Get the token for the current request. * * @return string */ public function getTokenForRequest() { $token = $this->request->query($this->inputKey); if (empty($token)) { $token = $this->request->input($this->inputKey); } if (empty($token)) { $token = $this->request->bearerToken(); } if (empty($token)) { $token = $this->request->getPassword(); } return $token; } /** * Validate a user's credentials. * * @param array $credentials * @return bool */ public function validate(array $credentials = []) { if (empty($credentials[$this->inputKey])) { return false; } $credentials = [$this->storageKey => $credentials[$this->inputKey]]; if ($this->provider->retrieveByCredentials($credentials)) { return true; } return false; } /** * Set the current request instance. * * @param \Illuminate\Http\Request $request * @return $this */ public function setRequest(Request $request) { $this->request = $request; return $this; } } PK������y ZJJ��J��+��Illuminate/Auth/AuthenticationException.phpnu�W+A��������<?php namespace Illuminate\Auth; use Exception; class AuthenticationException extends Exception { /** * All of the guards that were checked. * * @var array */ protected $guards; /** * The path the user should be redirected to. * * @var string|null */ protected $redirectTo; /** * Create a new authentication exception. * * @param string $message * @param array $guards * @param string|null $redirectTo * @return void */ public function __construct($message = 'Unauthenticated.', array $guards = [], $redirectTo = null) { parent::__construct($message); $this->guards = $guards; $this->redirectTo = $redirectTo; } /** * Get the guards that were checked. * * @return array */ public function guards() { return $this->guards; } /** * Get the path the user should be redirected to. * * @return string|null */ public function redirectTo() { return $this->redirectTo; } } PK������y Zα3��3����Illuminate/Auth/LICENSE.mdnu�W+A��������The MIT License (MIT) Copyright (c) Taylor Otwell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PK������y Zs6i��i�� ��Illuminate/Auth/SessionGuard.phpnu�W+A��������<?php namespace Illuminate\Auth; use Illuminate\Auth\Events\Attempting; use Illuminate\Auth\Events\Authenticated; use Illuminate\Auth\Events\CurrentDeviceLogout; use Illuminate\Auth\Events\Failed; use Illuminate\Auth\Events\Login; use Illuminate\Auth\Events\Logout; use Illuminate\Auth\Events\OtherDeviceLogout; use Illuminate\Auth\Events\Validated; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\StatefulGuard; use Illuminate\Contracts\Auth\SupportsBasicAuth; use Illuminate\Contracts\Auth\UserProvider; use Illuminate\Contracts\Cookie\QueueingFactory as CookieJar; use Illuminate\Contracts\Events\Dispatcher; use Illuminate\Contracts\Session\Session; use Illuminate\Support\Arr; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Str; use Illuminate\Support\Timebox; use Illuminate\Support\Traits\Macroable; use InvalidArgumentException; use RuntimeException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; class SessionGuard implements StatefulGuard, SupportsBasicAuth { use GuardHelpers, Macroable; /** * The name of the guard. Typically "web". * * Corresponds to guard name in authentication configuration. * * @var string */ protected $name; /** * The user we last attempted to retrieve. * * @var \Illuminate\Contracts\Auth\Authenticatable */ protected $lastAttempted; /** * Indicates if the user was authenticated via a recaller cookie. * * @var bool */ protected $viaRemember = false; /** * The number of minutes that the "remember me" cookie should be valid for. * * @var int */ protected $rememberDuration = 576000; /** * The session used by the guard. * * @var \Illuminate\Contracts\Session\Session */ protected $session; /** * The Illuminate cookie creator service. * * @var \Illuminate\Contracts\Cookie\QueueingFactory */ protected $cookie; /** * The request instance. * * @var \Symfony\Component\HttpFoundation\Request */ protected $request; /** * The event dispatcher instance. * * @var \Illuminate\Contracts\Events\Dispatcher */ protected $events; /** * The timebox instance. * * @var \Illuminate\Support\Timebox */ protected $timebox; /** * Indicates if the logout method has been called. * * @var bool */ protected $loggedOut = false; /** * Indicates if a token user retrieval has been attempted. * * @var bool */ protected $recallAttempted = false; /** * Create a new authentication guard. * * @param string $name * @param \Illuminate\Contracts\Auth\UserProvider $provider * @param \Illuminate\Contracts\Session\Session $session * @param \Symfony\Component\HttpFoundation\Request|null $request * @param \Illuminate\Support\Timebox|null $timebox * @return void */ public function __construct($name, UserProvider $provider, Session $session, Request $request = null, Timebox $timebox = null) { $this->name = $name; $this->session = $session; $this->request = $request; $this->provider = $provider; $this->timebox = $timebox ?: new Timebox; } /** * Get the currently authenticated user. * * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function user() { if ($this->loggedOut) { return; } // If we've already retrieved the user for the current request we can just // return it back immediately. We do not want to fetch the user data on // every call to this method because that would be tremendously slow. if (! is_null($this->user)) { return $this->user; } $id = $this->session->get($this->getName()); // First we will try to load the user using the identifier in the session if // one exists. Otherwise we will check for a "remember me" cookie in this // request, and if one exists, attempt to retrieve the user using that. if (! is_null($id) && $this->user = $this->provider->retrieveById($id)) { $this->fireAuthenticatedEvent($this->user); } // If the user is null, but we decrypt a "recaller" cookie we can attempt to // pull the user data on that cookie which serves as a remember cookie on // the application. Once we have a user we can return it to the caller. if (is_null($this->user) && ! is_null($recaller = $this->recaller())) { $this->user = $this->userFromRecaller($recaller); if ($this->user) { $this->updateSession($this->user->getAuthIdentifier()); $this->fireLoginEvent($this->user, true); } } return $this->user; } /** * Pull a user from the repository by its "remember me" cookie token. * * @param \Illuminate\Auth\Recaller $recaller * @return mixed */ protected function userFromRecaller($recaller) { if (! $recaller->valid() || $this->recallAttempted) { return; } // If the user is null, but we decrypt a "recaller" cookie we can attempt to // pull the user data on that cookie which serves as a remember cookie on // the application. Once we have a user we can return it to the caller. $this->recallAttempted = true; $this->viaRemember = ! is_null($user = $this->provider->retrieveByToken( $recaller->id(), $recaller->token() )); return $user; } /** * Get the decrypted recaller cookie for the request. * * @return \Illuminate\Auth\Recaller|null */ protected function recaller() { if (is_null($this->request)) { return; } if ($recaller = $this->request->cookies->get($this->getRecallerName())) { return new Recaller($recaller); } } /** * Get the ID for the currently authenticated user. * * @return int|string|null */ public function id() { if ($this->loggedOut) { return; } return $this->user() ? $this->user()->getAuthIdentifier() : $this->session->get($this->getName()); } /** * Log a user into the application without sessions or cookies. * * @param array $credentials * @return bool */ public function once(array $credentials = []) { $this->fireAttemptEvent($credentials); if ($this->validate($credentials)) { $this->setUser($this->lastAttempted); return true; } return false; } /** * Log the given user ID into the application without sessions or cookies. * * @param mixed $id * @return \Illuminate\Contracts\Auth\Authenticatable|false */ public function onceUsingId($id) { if (! is_null($user = $this->provider->retrieveById($id))) { $this->setUser($user); return $user; } return false; } /** * Validate a user's credentials. * * @param array $credentials * @return bool */ public function validate(array $credentials = []) { $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials); return $this->hasValidCredentials($user, $credentials); } /** * Attempt to authenticate using HTTP Basic Auth. * * @param string $field * @param array $extraConditions * @return \Symfony\Component\HttpFoundation\Response|null * * @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException */ public function basic($field = 'email', $extraConditions = []) { if ($this->check()) { return; } // If a username is set on the HTTP basic request, we will return out without // interrupting the request lifecycle. Otherwise, we'll need to generate a // request indicating that the given credentials were invalid for login. if ($this->attemptBasic($this->getRequest(), $field, $extraConditions)) { return; } return $this->failedBasicResponse(); } /** * Perform a stateless HTTP Basic login attempt. * * @param string $field * @param array $extraConditions * @return \Symfony\Component\HttpFoundation\Response|null * * @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException */ public function onceBasic($field = 'email', $extraConditions = []) { $credentials = $this->basicCredentials($this->getRequest(), $field); if (! $this->once(array_merge($credentials, $extraConditions))) { return $this->failedBasicResponse(); } } /** * Attempt to authenticate using basic authentication. * * @param \Symfony\Component\HttpFoundation\Request $request * @param string $field * @param array $extraConditions * @return bool */ protected function attemptBasic(Request $request, $field, $extraConditions = []) { if (! $request->getUser()) { return false; } return $this->attempt(array_merge( $this->basicCredentials($request, $field), $extraConditions )); } /** * Get the credential array for an HTTP Basic request. * * @param \Symfony\Component\HttpFoundation\Request $request * @param string $field * @return array */ protected function basicCredentials(Request $request, $field) { return [$field => $request->getUser(), 'password' => $request->getPassword()]; } /** * Get the response for basic authentication. * * @return void * * @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException */ protected function failedBasicResponse() { throw new UnauthorizedHttpException('Basic', 'Invalid credentials.'); } /** * Attempt to authenticate a user using the given credentials. * * @param array $credentials * @param bool $remember * @return bool */ public function attempt(array $credentials = [], $remember = false) { $this->fireAttemptEvent($credentials, $remember); $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials); // If an implementation of UserInterface was returned, we'll ask the provider // to validate the user against the given credentials, and if they are in // fact valid we'll log the users into the application and return true. if ($this->hasValidCredentials($user, $credentials)) { $this->login($user, $remember); return true; } // If the authentication attempt fails we will fire an event so that the user // may be notified of any suspicious attempts to access their account from // an unrecognized user. A developer may listen to this event as needed. $this->fireFailedEvent($user, $credentials); return false; } /** * Attempt to authenticate a user with credentials and additional callbacks. * * @param array $credentials * @param array|callable|null $callbacks * @param bool $remember * @return bool */ public function attemptWhen(array $credentials = [], $callbacks = null, $remember = false) { $this->fireAttemptEvent($credentials, $remember); $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials); // This method does the exact same thing as attempt, but also executes callbacks after // the user is retrieved and validated. If one of the callbacks returns falsy we do // not login the user. Instead, we will fail the specific authentication attempt. if ($this->hasValidCredentials($user, $credentials) && $this->shouldLogin($callbacks, $user)) { $this->login($user, $remember); return true; } $this->fireFailedEvent($user, $credentials); return false; } /** * Determine if the user matches the credentials. * * @param mixed $user * @param array $credentials * @return bool */ protected function hasValidCredentials($user, $credentials) { return $this->timebox->call(function ($timebox) use ($user, $credentials) { $validated = ! is_null($user) && $this->provider->validateCredentials($user, $credentials); if ($validated) { $timebox->returnEarly(); $this->fireValidatedEvent($user); } return $validated; }, 200 * 1000); } /** * Determine if the user should login by executing the given callbacks. * * @param array|callable|null $callbacks * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return bool */ protected function shouldLogin($callbacks, AuthenticatableContract $user) { foreach (Arr::wrap($callbacks) as $callback) { if (! $callback($user, $this)) { return false; } } return true; } /** * Log the given user ID into the application. * * @param mixed $id * @param bool $remember * @return \Illuminate\Contracts\Auth\Authenticatable|false */ public function loginUsingId($id, $remember = false) { if (! is_null($user = $this->provider->retrieveById($id))) { $this->login($user, $remember); return $user; } return false; } /** * Log a user into the application. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param bool $remember * @return void */ public function login(AuthenticatableContract $user, $remember = false) { $this->updateSession($user->getAuthIdentifier()); // If the user should be permanently "remembered" by the application we will // queue a permanent cookie that contains the encrypted copy of the user // identifier. We will then decrypt this later to retrieve the users. if ($remember) { $this->ensureRememberTokenIsSet($user); $this->queueRecallerCookie($user); } // If we have an event dispatcher instance set we will fire an event so that // any listeners will hook into the authentication events and run actions // based on the login and logout events fired from the guard instances. $this->fireLoginEvent($user, $remember); $this->setUser($user); } /** * Update the session with the given ID. * * @param string $id * @return void */ protected function updateSession($id) { $this->session->put($this->getName(), $id); $this->session->migrate(true); } /** * Create a new "remember me" token for the user if one doesn't already exist. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return void */ protected function ensureRememberTokenIsSet(AuthenticatableContract $user) { if (empty($user->getRememberToken())) { $this->cycleRememberToken($user); } } /** * Queue the recaller cookie into the cookie jar. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return void */ protected function queueRecallerCookie(AuthenticatableContract $user) { $this->getCookieJar()->queue($this->createRecaller( $user->getAuthIdentifier().'|'.$user->getRememberToken().'|'.$user->getAuthPassword() )); } /** * Create a "remember me" cookie for a given ID. * * @param string $value * @return \Symfony\Component\HttpFoundation\Cookie */ protected function createRecaller($value) { return $this->getCookieJar()->make($this->getRecallerName(), $value, $this->getRememberDuration()); } /** * Log the user out of the application. * * @return void */ public function logout() { $user = $this->user(); $this->clearUserDataFromStorage(); if (! is_null($this->user) && ! empty($user->getRememberToken())) { $this->cycleRememberToken($user); } // If we have an event dispatcher instance, we can fire off the logout event // so any further processing can be done. This allows the developer to be // listening for anytime a user signs out of this application manually. if (isset($this->events)) { $this->events->dispatch(new Logout($this->name, $user)); } // Once we have fired the logout event we will clear the users out of memory // so they are no longer available as the user is no longer considered as // being signed into this application and should not be available here. $this->user = null; $this->loggedOut = true; } /** * Log the user out of the application on their current device only. * * This method does not cycle the "remember" token. * * @return void */ public function logoutCurrentDevice() { $user = $this->user(); $this->clearUserDataFromStorage(); // If we have an event dispatcher instance, we can fire off the logout event // so any further processing can be done. This allows the developer to be // listening for anytime a user signs out of this application manually. if (isset($this->events)) { $this->events->dispatch(new CurrentDeviceLogout($this->name, $user)); } // Once we have fired the logout event we will clear the users out of memory // so they are no longer available as the user is no longer considered as // being signed into this application and should not be available here. $this->user = null; $this->loggedOut = true; } /** * Remove the user data from the session and cookies. * * @return void */ protected function clearUserDataFromStorage() { $this->session->remove($this->getName()); $this->getCookieJar()->unqueue($this->getRecallerName()); if (! is_null($this->recaller())) { $this->getCookieJar()->queue( $this->getCookieJar()->forget($this->getRecallerName()) ); } } /** * Refresh the "remember me" token for the user. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return void */ protected function cycleRememberToken(AuthenticatableContract $user) { $user->setRememberToken($token = Str::random(60)); $this->provider->updateRememberToken($user, $token); } /** * Invalidate other sessions for the current user. * * The application must be using the AuthenticateSession middleware. * * @param string $password * @param string $attribute * @return \Illuminate\Contracts\Auth\Authenticatable|null * * @throws \Illuminate\Auth\AuthenticationException */ public function logoutOtherDevices($password, $attribute = 'password') { if (! $this->user()) { return; } $result = $this->rehashUserPassword($password, $attribute); if ($this->recaller() || $this->getCookieJar()->hasQueued($this->getRecallerName())) { $this->queueRecallerCookie($this->user()); } $this->fireOtherDeviceLogoutEvent($this->user()); return $result; } /** * Rehash the current user's password. * * @param string $password * @param string $attribute * @return \Illuminate\Contracts\Auth\Authenticatable|null * * @throws \InvalidArgumentException */ protected function rehashUserPassword($password, $attribute) { if (! Hash::check($password, $this->user()->{$attribute})) { throw new InvalidArgumentException('The given password does not match the current password.'); } return tap($this->user()->forceFill([ $attribute => Hash::make($password), ]))->save(); } /** * Register an authentication attempt event listener. * * @param mixed $callback * @return void */ public function attempting($callback) { $this->events?->listen(Events\Attempting::class, $callback); } /** * Fire the attempt event with the arguments. * * @param array $credentials * @param bool $remember * @return void */ protected function fireAttemptEvent(array $credentials, $remember = false) { $this->events?->dispatch(new Attempting($this->name, $credentials, $remember)); } /** * Fires the validated event if the dispatcher is set. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return void */ protected function fireValidatedEvent($user) { $this->events?->dispatch(new Validated($this->name, $user)); } /** * Fire the login event if the dispatcher is set. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param bool $remember * @return void */ protected function fireLoginEvent($user, $remember = false) { $this->events?->dispatch(new Login($this->name, $user, $remember)); } /** * Fire the authenticated event if the dispatcher is set. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return void */ protected function fireAuthenticatedEvent($user) { $this->events?->dispatch(new Authenticated($this->name, $user)); } /** * Fire the other device logout event if the dispatcher is set. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return void */ protected function fireOtherDeviceLogoutEvent($user) { $this->events?->dispatch(new OtherDeviceLogout($this->name, $user)); } /** * Fire the failed authentication attempt event with the given arguments. * * @param \Illuminate\Contracts\Auth\Authenticatable|null $user * @param array $credentials * @return void */ protected function fireFailedEvent($user, array $credentials) { $this->events?->dispatch(new Failed($this->name, $user, $credentials)); } /** * Get the last user we attempted to authenticate. * * @return \Illuminate\Contracts\Auth\Authenticatable */ public function getLastAttempted() { return $this->lastAttempted; } /** * Get a unique identifier for the auth session value. * * @return string */ public function getName() { return 'login_'.$this->name.'_'.sha1(static::class); } /** * Get the name of the cookie used to store the "recaller". * * @return string */ public function getRecallerName() { return 'remember_'.$this->name.'_'.sha1(static::class); } /** * Determine if the user was authenticated via "remember me" cookie. * * @return bool */ public function viaRemember() { return $this->viaRemember; } /** * Get the number of minutes the remember me cookie should be valid for. * * @return int */ protected function getRememberDuration() { return $this->rememberDuration; } /** * Set the number of minutes the remember me cookie should be valid for. * * @param int $minutes * @return $this */ public function setRememberDuration($minutes) { $this->rememberDuration = $minutes; return $this; } /** * Get the cookie creator instance used by the guard. * * @return \Illuminate\Contracts\Cookie\QueueingFactory * * @throws \RuntimeException */ public function getCookieJar() { if (! isset($this->cookie)) { throw new RuntimeException('Cookie jar has not been set.'); } return $this->cookie; } /** * Set the cookie creator instance used by the guard. * * @param \Illuminate\Contracts\Cookie\QueueingFactory $cookie * @return void */ public function setCookieJar(CookieJar $cookie) { $this->cookie = $cookie; } /** * Get the event dispatcher instance. * * @return \Illuminate\Contracts\Events\Dispatcher */ public function getDispatcher() { return $this->events; } /** * Set the event dispatcher instance. * * @param \Illuminate\Contracts\Events\Dispatcher $events * @return void */ public function setDispatcher(Dispatcher $events) { $this->events = $events; } /** * Get the session store used by the guard. * * @return \Illuminate\Contracts\Session\Session */ public function getSession() { return $this->session; } /** * Return the currently cached user. * * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function getUser() { return $this->user; } /** * Set the current user. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return $this */ public function setUser(AuthenticatableContract $user) { $this->user = $user; $this->loggedOut = false; $this->fireAuthenticatedEvent($user); return $this; } /** * Get the current request instance. * * @return \Symfony\Component\HttpFoundation\Request */ public function getRequest() { return $this->request ?: Request::createFromGlobals(); } /** * Set the current request instance. * * @param \Symfony\Component\HttpFoundation\Request $request * @return $this */ public function setRequest(Request $request) { $this->request = $request; return $this; } /** * Get the timebox instance used by the guard. * * @return \Illuminate\Support\Timebox */ public function getTimebox() { return $this->timebox; } } PK������y ZyU) ��) �� ��Illuminate/Auth/GuardHelpers.phpnu�W+A��������<?php namespace Illuminate\Auth; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\UserProvider; /** * These methods are typically the same across all guards. */ trait GuardHelpers { /** * The currently authenticated user. * * @var \Illuminate\Contracts\Auth\Authenticatable|null */ protected $user; /** * The user provider implementation. * * @var \Illuminate\Contracts\Auth\UserProvider */ protected $provider; /** * Determine if the current user is authenticated. If not, throw an exception. * * @return \Illuminate\Contracts\Auth\Authenticatable * * @throws \Illuminate\Auth\AuthenticationException */ public function authenticate() { if (! is_null($user = $this->user())) { return $user; } throw new AuthenticationException; } /** * Determine if the guard has a user instance. * * @return bool */ public function hasUser() { return ! is_null($this->user); } /** * Determine if the current user is authenticated. * * @return bool */ public function check() { return ! is_null($this->user()); } /** * Determine if the current user is a guest. * * @return bool */ public function guest() { return ! $this->check(); } /** * Get the ID for the currently authenticated user. * * @return int|string|null */ public function id() { if ($this->user()) { return $this->user()->getAuthIdentifier(); } } /** * Set the current user. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return $this */ public function setUser(AuthenticatableContract $user) { $this->user = $user; return $this; } /** * Forget the current user. * * @return $this */ public function forgetUser() { $this->user = null; return $this; } /** * Get the user provider used by the guard. * * @return \Illuminate\Contracts\Auth\UserProvider */ public function getProvider() { return $this->provider; } /** * Set the user provider used by the guard. * * @param \Illuminate\Contracts\Auth\UserProvider $provider * @return void */ public function setProvider(UserProvider $provider) { $this->provider = $provider; } } PK������y Za@e��e��(��Illuminate/Auth/DatabaseUserProvider.phpnu�W+A��������<?php namespace Illuminate\Auth; use Closure; use Illuminate\Contracts\Auth\Authenticatable as UserContract; use Illuminate\Contracts\Auth\UserProvider; use Illuminate\Contracts\Hashing\Hasher as HasherContract; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Database\ConnectionInterface; class DatabaseUserProvider implements UserProvider { /** * The active database connection. * * @var \Illuminate\Database\ConnectionInterface */ protected $connection; /** * The hasher implementation. * * @var \Illuminate\Contracts\Hashing\Hasher */ protected $hasher; /** * The table containing the users. * * @var string */ protected $table; /** * Create a new database user provider. * * @param \Illuminate\Database\ConnectionInterface $connection * @param \Illuminate\Contracts\Hashing\Hasher $hasher * @param string $table * @return void */ public function __construct(ConnectionInterface $connection, HasherContract $hasher, $table) { $this->connection = $connection; $this->table = $table; $this->hasher = $hasher; } /** * Retrieve a user by their unique identifier. * * @param mixed $identifier * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function retrieveById($identifier) { $user = $this->connection->table($this->table)->find($identifier); return $this->getGenericUser($user); } /** * Retrieve a user by their unique identifier and "remember me" token. * * @param mixed $identifier * @param string $token * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function retrieveByToken($identifier, $token) { $user = $this->getGenericUser( $this->connection->table($this->table)->find($identifier) ); return $user && $user->getRememberToken() && hash_equals($user->getRememberToken(), $token) ? $user : null; } /** * Update the "remember me" token for the given user in storage. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param string $token * @return void */ public function updateRememberToken(UserContract $user, $token) { $this->connection->table($this->table) ->where($user->getAuthIdentifierName(), $user->getAuthIdentifier()) ->update([$user->getRememberTokenName() => $token]); } /** * Retrieve a user by the given credentials. * * @param array $credentials * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function retrieveByCredentials(array $credentials) { $credentials = array_filter( $credentials, fn ($key) => ! str_contains($key, 'password'), ARRAY_FILTER_USE_KEY ); if (empty($credentials)) { return; } // First we will add each credential element to the query as a where clause. // Then we can execute the query and, if we found a user, return it in a // generic "user" object that will be utilized by the Guard instances. $query = $this->connection->table($this->table); foreach ($credentials as $key => $value) { if (is_array($value) || $value instanceof Arrayable) { $query->whereIn($key, $value); } elseif ($value instanceof Closure) { $value($query); } else { $query->where($key, $value); } } // Now we are ready to execute the query to see if we have a user matching // the given credentials. If not, we will just return null and indicate // that there are no matching users from the given credential arrays. $user = $query->first(); return $this->getGenericUser($user); } /** * Get the generic user. * * @param mixed $user * @return \Illuminate\Auth\GenericUser|null */ protected function getGenericUser($user) { if (! is_null($user)) { return new GenericUser((array) $user); } } /** * Validate a user against the given credentials. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param array $credentials * @return bool */ public function validateCredentials(UserContract $user, array $credentials) { return $this->hasher->check( $credentials['password'], $user->getAuthPassword() ); } } PK������y Zrl7����#��Illuminate/Auth/MustVerifyEmail.phpnu�W+A��������<?php namespace Illuminate\Auth; use Illuminate\Auth\Notifications\VerifyEmail; trait MustVerifyEmail { /** * Determine if the user has verified their email address. * * @return bool */ public function hasVerifiedEmail() { return ! is_null($this->email_verified_at); } /** * Mark the given user's email as verified. * * @return bool */ public function markEmailAsVerified() { return $this->forceFill([ 'email_verified_at' => $this->freshTimestamp(), ])->save(); } /** * Send the email verification notification. * * @return void */ public function sendEmailVerificationNotification() { $this->notify(new VerifyEmail); } /** * Get the email address that should be used for verification. * * @return string */ public function getEmailForVerification() { return $this->email; } } PK������y ZXJ:����#��Illuminate/Auth/Authenticatable.phpnu�W+A��������<?php namespace Illuminate\Auth; trait Authenticatable { /** * The column name of the "remember me" token. * * @var string */ protected $rememberTokenName = 'remember_token'; /** * Get the name of the unique identifier for the user. * * @return string */ public function getAuthIdentifierName() { return $this->getKeyName(); } /** * Get the unique identifier for the user. * * @return mixed */ public function getAuthIdentifier() { return $this->{$this->getAuthIdentifierName()}; } /** * Get the unique broadcast identifier for the user. * * @return mixed */ public function getAuthIdentifierForBroadcasting() { return $this->getAuthIdentifier(); } /** * Get the password for the user. * * @return string */ public function getAuthPassword() { return $this->password; } /** * Get the token value for the "remember me" session. * * @return string|null */ public function getRememberToken() { if (! empty($this->getRememberTokenName())) { return (string) $this->{$this->getRememberTokenName()}; } } /** * Set the token value for the "remember me" session. * * @param string $value * @return void */ public function setRememberToken($value) { if (! empty($this->getRememberTokenName())) { $this->{$this->getRememberTokenName()} = $value; } } /** * Get the column name for the "remember me" token. * * @return string */ public function getRememberTokenName() { return $this->rememberTokenName; } } PK������y Z 9V��V����Illuminate/Auth/Recaller.phpnu�W+A��������<?php namespace Illuminate\Auth; class Recaller { /** * The "recaller" / "remember me" cookie string. * * @var string */ protected $recaller; /** * Create a new recaller instance. * * @param string $recaller * @return void */ public function __construct($recaller) { $this->recaller = @unserialize($recaller, ['allowed_classes' => false]) ?: $recaller; } /** * Get the user ID from the recaller. * * @return string */ public function id() { return explode('|', $this->recaller, 3)[0]; } /** * Get the "remember token" token from the recaller. * * @return string */ public function token() { return explode('|', $this->recaller, 3)[1]; } /** * Get the password from the recaller. * * @return string */ public function hash() { return explode('|', $this->recaller, 4)[2]; } /** * Determine if the recaller is valid. * * @return bool */ public function valid() { return $this->properString() && $this->hasAllSegments(); } /** * Determine if the recaller is an invalid string. * * @return bool */ protected function properString() { return is_string($this->recaller) && str_contains($this->recaller, '|'); } /** * Determine if the recaller has all segments. * * @return bool */ protected function hasAllSegments() { $segments = explode('|', $this->recaller); return count($segments) >= 3 && trim($segments[0]) !== '' && trim($segments[1]) !== ''; } /** * Get the recaller's segments. * * @return array */ public function segments() { return explode('|', $this->recaller); } } PK������y Zc �� ����Illuminate/Auth/GenericUser.phpnu�W+A��������<?php namespace Illuminate\Auth; use Illuminate\Contracts\Auth\Authenticatable as UserContract; class GenericUser implements UserContract { /** * All of the user's attributes. * * @var array */ protected $attributes; /** * Create a new generic User object. * * @param array $attributes * @return void */ public function __construct(array $attributes) { $this->attributes = $attributes; } /** * Get the name of the unique identifier for the user. * * @return string */ public function getAuthIdentifierName() { return 'id'; } /** * Get the unique identifier for the user. * * @return mixed */ public function getAuthIdentifier() { return $this->attributes[$this->getAuthIdentifierName()]; } /** * Get the password for the user. * * @return string */ public function getAuthPassword() { return $this->attributes['password']; } /** * Get the "remember me" token value. * * @return string */ public function getRememberToken() { return $this->attributes[$this->getRememberTokenName()]; } /** * Set the "remember me" token value. * * @param string $value * @return void */ public function setRememberToken($value) { $this->attributes[$this->getRememberTokenName()] = $value; } /** * Get the column name for the "remember me" token. * * @return string */ public function getRememberTokenName() { return 'remember_token'; } /** * Dynamically access the user's attributes. * * @param string $key * @return mixed */ public function __get($key) { return $this->attributes[$key]; } /** * Dynamically set an attribute on the user. * * @param string $key * @param mixed $value * @return void */ public function __set($key, $value) { $this->attributes[$key] = $value; } /** * Dynamically check if a value is set on the user. * * @param string $key * @return bool */ public function __isset($key) { return isset($this->attributes[$key]); } /** * Dynamically unset a value on the user. * * @param string $key * @return void */ public function __unset($key) { unset($this->attributes[$key]); } } PK������y ZlTJ��J�� ��Illuminate/Auth/RequestGuard.phpnu�W+A��������<?php namespace Illuminate\Auth; use Illuminate\Contracts\Auth\Guard; use Illuminate\Contracts\Auth\UserProvider; use Illuminate\Http\Request; use Illuminate\Support\Traits\Macroable; class RequestGuard implements Guard { use GuardHelpers, Macroable; /** * The guard callback. * * @var callable */ protected $callback; /** * The request instance. * * @var \Illuminate\Http\Request */ protected $request; /** * Create a new authentication guard. * * @param callable $callback * @param \Illuminate\Http\Request $request * @param \Illuminate\Contracts\Auth\UserProvider|null $provider * @return void */ public function __construct(callable $callback, Request $request, UserProvider $provider = null) { $this->request = $request; $this->callback = $callback; $this->provider = $provider; } /** * Get the currently authenticated user. * * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function user() { // If we've already retrieved the user for the current request we can just // return it back immediately. We do not want to fetch the user data on // every call to this method because that would be tremendously slow. if (! is_null($this->user)) { return $this->user; } return $this->user = call_user_func( $this->callback, $this->request, $this->getProvider() ); } /** * Validate a user's credentials. * * @param array $credentials * @return bool */ public function validate(array $credentials = []) { return ! is_null((new static( $this->callback, $credentials['request'], $this->getProvider() ))->user()); } /** * Set the current request instance. * * @param \Illuminate\Http\Request $request * @return $this */ public function setRequest(Request $request) { $this->request = $request; return $this; } } PK������y Z,4Z����?��Illuminate/Auth/Listeners/SendEmailVerificationNotification.phpnu�W+A��������<?php namespace Illuminate\Auth\Listeners; use Illuminate\Auth\Events\Registered; use Illuminate\Contracts\Auth\MustVerifyEmail; class SendEmailVerificationNotification { /** * Handle the event. * * @param \Illuminate\Auth\Events\Registered $event * @return void */ public function handle(Registered $event) { if ($event->user instanceof MustVerifyEmail && ! $event->user->hasVerifiedEmail()) { $event->user->sendEmailVerificationNotification(); } } } PK������y Z7 �� ��.��Illuminate/Auth/Middleware/RequirePassword.phpnu�W+A��������<?php namespace Illuminate\Auth\Middleware; use Closure; use Illuminate\Contracts\Routing\ResponseFactory; use Illuminate\Contracts\Routing\UrlGenerator; class RequirePassword { /** * The response factory instance. * * @var \Illuminate\Contracts\Routing\ResponseFactory */ protected $responseFactory; /** * The URL generator instance. * * @var \Illuminate\Contracts\Routing\UrlGenerator */ protected $urlGenerator; /** * The password timeout. * * @var int */ protected $passwordTimeout; /** * Create a new middleware instance. * * @param \Illuminate\Contracts\Routing\ResponseFactory $responseFactory * @param \Illuminate\Contracts\Routing\UrlGenerator $urlGenerator * @param int|null $passwordTimeout * @return void */ public function __construct(ResponseFactory $responseFactory, UrlGenerator $urlGenerator, $passwordTimeout = null) { $this->responseFactory = $responseFactory; $this->urlGenerator = $urlGenerator; $this->passwordTimeout = $passwordTimeout ?: 10800; } /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param string|null $redirectToRoute * @param int|null $passwordTimeoutSeconds * @return mixed */ public function handle($request, Closure $next, $redirectToRoute = null, $passwordTimeoutSeconds = null) { if ($this->shouldConfirmPassword($request, $passwordTimeoutSeconds)) { if ($request->expectsJson()) { return $this->responseFactory->json([ 'message' => 'Password confirmation required.', ], 423); } return $this->responseFactory->redirectGuest( $this->urlGenerator->route($redirectToRoute ?? 'password.confirm') ); } return $next($request); } /** * Determine if the confirmation timeout has expired. * * @param \Illuminate\Http\Request $request * @param int|null $passwordTimeoutSeconds * @return bool */ protected function shouldConfirmPassword($request, $passwordTimeoutSeconds = null) { $confirmedAt = time() - $request->session()->get('auth.password_confirmed_at', 0); return $confirmedAt > ($passwordTimeoutSeconds ?? $this->passwordTimeout); } } PK������y Z3M3 ��3 ��+��Illuminate/Auth/Middleware/Authenticate.phpnu�W+A��������<?php namespace Illuminate\Auth\Middleware; use Closure; use Illuminate\Auth\AuthenticationException; use Illuminate\Contracts\Auth\Factory as Auth; use Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests; class Authenticate implements AuthenticatesRequests { /** * The authentication factory instance. * * @var \Illuminate\Contracts\Auth\Factory */ protected $auth; /** * Create a new middleware instance. * * @param \Illuminate\Contracts\Auth\Factory $auth * @return void */ public function __construct(Auth $auth) { $this->auth = $auth; } /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param string[] ...$guards * @return mixed * * @throws \Illuminate\Auth\AuthenticationException */ public function handle($request, Closure $next, ...$guards) { $this->authenticate($request, $guards); return $next($request); } /** * Determine if the user is logged in to any of the given guards. * * @param \Illuminate\Http\Request $request * @param array $guards * @return void * * @throws \Illuminate\Auth\AuthenticationException */ protected function authenticate($request, array $guards) { if (empty($guards)) { $guards = [null]; } foreach ($guards as $guard) { if ($this->auth->guard($guard)->check()) { return $this->auth->shouldUse($guard); } } $this->unauthenticated($request, $guards); } /** * Handle an unauthenticated user. * * @param \Illuminate\Http\Request $request * @param array $guards * @return void * * @throws \Illuminate\Auth\AuthenticationException */ protected function unauthenticated($request, array $guards) { throw new AuthenticationException( 'Unauthenticated.', $guards, $this->redirectTo($request) ); } /** * Get the path the user should be redirected to when they are not authenticated. * * @param \Illuminate\Http\Request $request * @return string|null */ protected function redirectTo($request) { // } } PK������y ZQ!F ��F ��(��Illuminate/Auth/Middleware/Authorize.phpnu�W+A��������<?php namespace Illuminate\Auth\Middleware; use Closure; use Illuminate\Contracts\Auth\Access\Gate; use Illuminate\Database\Eloquent\Model; class Authorize { /** * The gate instance. * * @var \Illuminate\Contracts\Auth\Access\Gate */ protected $gate; /** * Create a new middleware instance. * * @param \Illuminate\Contracts\Auth\Access\Gate $gate * @return void */ public function __construct(Gate $gate) { $this->gate = $gate; } /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param string $ability * @param array|null ...$models * @return mixed * * @throws \Illuminate\Auth\AuthenticationException * @throws \Illuminate\Auth\Access\AuthorizationException */ public function handle($request, Closure $next, $ability, ...$models) { $this->gate->authorize($ability, $this->getGateArguments($request, $models)); return $next($request); } /** * Get the arguments parameter for the gate. * * @param \Illuminate\Http\Request $request * @param array|null $models * @return \Illuminate\Database\Eloquent\Model|array|string */ protected function getGateArguments($request, $models) { if (is_null($models)) { return []; } return collect($models)->map(function ($model) use ($request) { return $model instanceof Model ? $model : $this->getModel($request, $model); })->all(); } /** * Get the model to authorize. * * @param \Illuminate\Http\Request $request * @param string $model * @return \Illuminate\Database\Eloquent\Model|string */ protected function getModel($request, $model) { if ($this->isClassName($model)) { return trim($model); } else { return $request->route($model, null) ?? ((preg_match("/^['\"](.*)['\"]$/", trim($model), $matches)) ? $matches[1] : null); } } /** * Checks if the given string looks like a fully qualified class name. * * @param string $value * @return bool */ protected function isClassName($value) { return str_contains($value, '\\'); } } PK������y Zlu����8��Illuminate/Auth/Middleware/AuthenticateWithBasicAuth.phpnu�W+A��������<?php namespace Illuminate\Auth\Middleware; use Closure; use Illuminate\Contracts\Auth\Factory as AuthFactory; class AuthenticateWithBasicAuth { /** * The guard factory instance. * * @var \Illuminate\Contracts\Auth\Factory */ protected $auth; /** * Create a new middleware instance. * * @param \Illuminate\Contracts\Auth\Factory $auth * @return void */ public function __construct(AuthFactory $auth) { $this->auth = $auth; } /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param string|null $guard * @param string|null $field * @return mixed * * @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException */ public function handle($request, Closure $next, $guard = null, $field = null) { $this->auth->guard($guard)->basic($field ?: 'email'); return $next($request); } } PK������y Z$K����4��Illuminate/Auth/Middleware/EnsureEmailIsVerified.phpnu�W+A��������<?php namespace Illuminate\Auth\Middleware; use Closure; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Support\Facades\Redirect; use Illuminate\Support\Facades\URL; class EnsureEmailIsVerified { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param string|null $redirectToRoute * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse|null */ public function handle($request, Closure $next, $redirectToRoute = null) { if (! $request->user() || ($request->user() instanceof MustVerifyEmail && ! $request->user()->hasVerifiedEmail())) { return $request->expectsJson() ? abort(403, 'Your email address is not verified.') : Redirect::guest(URL::route($redirectToRoute ?: 'verification.notice')); } return $next($request); } } PK������y Zn����"��Illuminate/Auth/Events/Lockout.phpnu�W+A��������<?php namespace Illuminate\Auth\Events; use Illuminate\Http\Request; class Lockout { /** * The throttled request. * * @var \Illuminate\Http\Request */ public $request; /** * Create a new event instance. * * @param \Illuminate\Http\Request $request * @return void */ public function __construct(Request $request) { $this->request = $request; } } PK������y Z~�����%��Illuminate/Auth/Events/Registered.phpnu�W+A��������<?php namespace Illuminate\Auth\Events; use Illuminate\Queue\SerializesModels; class Registered { use SerializesModels; /** * The authenticated user. * * @var \Illuminate\Contracts\Auth\Authenticatable */ public $user; /** * Create a new event instance. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return void */ public function __construct($user) { $this->user = $user; } } PK������y Z^X����#��Illuminate/Auth/Events/Verified.phpnu�W+A��������<?php namespace Illuminate\Auth\Events; use Illuminate\Queue\SerializesModels; class Verified { use SerializesModels; /** * The verified user. * * @var \Illuminate\Contracts\Auth\MustVerifyEmail */ public $user; /** * Create a new event instance. * * @param \Illuminate\Contracts\Auth\MustVerifyEmail $user * @return void */ public function __construct($user) { $this->user = $user; } } PK������y Z"(����.��Illuminate/Auth/Events/CurrentDeviceLogout.phpnu�W+A��������<?php namespace Illuminate\Auth\Events; use Illuminate\Queue\SerializesModels; class CurrentDeviceLogout { use SerializesModels; /** * The authentication guard name. * * @var string */ public $guard; /** * The authenticated user. * * @var \Illuminate\Contracts\Auth\Authenticatable */ public $user; /** * Create a new event instance. * * @param string $guard * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return void */ public function __construct($guard, $user) { $this->user = $user; $this->guard = $guard; } } PK������y Zw:����%��Illuminate/Auth/Events/Attempting.phpnu�W+A��������<?php namespace Illuminate\Auth\Events; class Attempting { /** * The authentication guard name. * * @var string */ public $guard; /** * The credentials for the user. * * @var array */ public $credentials; /** * Indicates if the user should be "remembered". * * @var bool */ public $remember; /** * Create a new event instance. * * @param string $guard * @param array $credentials * @param bool $remember * @return void */ public function __construct($guard, $credentials, $remember) { $this->guard = $guard; $this->remember = $remember; $this->credentials = $credentials; } } PK������y ZL@����(��Illuminate/Auth/Events/PasswordReset.phpnu�W+A��������<?php namespace Illuminate\Auth\Events; use Illuminate\Queue\SerializesModels; class PasswordReset { use SerializesModels; /** * The user. * * @var \Illuminate\Contracts\Auth\Authenticatable */ public $user; /** * Create a new event instance. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return void */ public function __construct($user) { $this->user = $user; } } PK������y ZVd����$��Illuminate/Auth/Events/Validated.phpnu�W+A��������<?php namespace Illuminate\Auth\Events; use Illuminate\Queue\SerializesModels; class Validated { use SerializesModels; /** * The authentication guard name. * * @var string */ public $guard; /** * The user retrieved and validated from the User Provider. * * @var \Illuminate\Contracts\Auth\Authenticatable */ public $user; /** * Create a new event instance. * * @param string $guard * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return void */ public function __construct($guard, $user) { $this->user = $user; $this->guard = $guard; } } PK������y Zӻ0̎����(��Illuminate/Auth/Events/Authenticated.phpnu�W+A��������<?php namespace Illuminate\Auth\Events; use Illuminate\Queue\SerializesModels; class Authenticated { use SerializesModels; /** * The authentication guard name. * * @var string */ public $guard; /** * The authenticated user. * * @var \Illuminate\Contracts\Auth\Authenticatable */ public $user; /** * Create a new event instance. * * @param string $guard * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return void */ public function __construct($guard, $user) { $this->user = $user; $this->guard = $guard; } } PK������y Zy����!��Illuminate/Auth/Events/Logout.phpnu�W+A��������<?php namespace Illuminate\Auth\Events; use Illuminate\Queue\SerializesModels; class Logout { use SerializesModels; /** * The authentication guard name. * * @var string */ public $guard; /** * The authenticated user. * * @var \Illuminate\Contracts\Auth\Authenticatable */ public $user; /** * Create a new event instance. * * @param string $guard * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return void */ public function __construct($guard, $user) { $this->user = $user; $this->guard = $guard; } } PK������y Zri=��=��!��Illuminate/Auth/Events/Failed.phpnu�W+A��������<?php namespace Illuminate\Auth\Events; class Failed { /** * The authentication guard name. * * @var string */ public $guard; /** * The user the attempter was trying to authenticate as. * * @var \Illuminate\Contracts\Auth\Authenticatable|null */ public $user; /** * The credentials provided by the attempter. * * @var array */ public $credentials; /** * Create a new event instance. * * @param string $guard * @param \Illuminate\Contracts\Auth\Authenticatable|null $user * @param array $credentials * @return void */ public function __construct($guard, $user, $credentials) { $this->user = $user; $this->guard = $guard; $this->credentials = $credentials; } } PK������y Z+I��I�� ��Illuminate/Auth/Events/Login.phpnu�W+A��������<?php namespace Illuminate\Auth\Events; use Illuminate\Queue\SerializesModels; class Login { use SerializesModels; /** * The authentication guard name. * * @var string */ public $guard; /** * The authenticated user. * * @var \Illuminate\Contracts\Auth\Authenticatable */ public $user; /** * Indicates if the user should be "remembered". * * @var bool */ public $remember; /** * Create a new event instance. * * @param string $guard * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param bool $remember * @return void */ public function __construct($guard, $user, $remember) { $this->user = $user; $this->guard = $guard; $this->remember = $remember; } } PK������y Z=����,��Illuminate/Auth/Events/OtherDeviceLogout.phpnu�W+A��������<?php namespace Illuminate\Auth\Events; use Illuminate\Queue\SerializesModels; class OtherDeviceLogout { use SerializesModels; /** * The authentication guard name. * * @var string */ public $guard; /** * The authenticated user. * * @var \Illuminate\Contracts\Auth\Authenticatable */ public $user; /** * Create a new event instance. * * @param string $guard * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return void */ public function __construct($guard, $user) { $this->user = $user; $this->guard = $guard; } } PK������y Z*Do& ��& ��'��Illuminate/Auth/AuthServiceProvider.phpnu�W+A��������<?php namespace Illuminate\Auth; use Illuminate\Auth\Access\Gate; use Illuminate\Auth\Middleware\RequirePassword; use Illuminate\Contracts\Auth\Access\Gate as GateContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Routing\ResponseFactory; use Illuminate\Contracts\Routing\UrlGenerator; use Illuminate\Support\ServiceProvider; class AuthServiceProvider extends ServiceProvider { /** * Register the service provider. * * @return void */ public function register() { $this->registerAuthenticator(); $this->registerUserResolver(); $this->registerAccessGate(); $this->registerRequirePassword(); $this->registerRequestRebindHandler(); $this->registerEventRebindHandler(); } /** * Register the authenticator services. * * @return void */ protected function registerAuthenticator() { $this->app->singleton('auth', fn ($app) => new AuthManager($app)); $this->app->singleton('auth.driver', fn ($app) => $app['auth']->guard()); } /** * Register a resolver for the authenticated user. * * @return void */ protected function registerUserResolver() { $this->app->bind(AuthenticatableContract::class, fn ($app) => call_user_func($app['auth']->userResolver())); } /** * Register the access gate service. * * @return void */ protected function registerAccessGate() { $this->app->singleton(GateContract::class, function ($app) { return new Gate($app, fn () => call_user_func($app['auth']->userResolver())); }); } /** * Register a resolver for the authenticated user. * * @return void */ protected function registerRequirePassword() { $this->app->bind(RequirePassword::class, function ($app) { return new RequirePassword( $app[ResponseFactory::class], $app[UrlGenerator::class], $app['config']->get('auth.password_timeout') ); }); } /** * Handle the re-binding of the request binding. * * @return void */ protected function registerRequestRebindHandler() { $this->app->rebinding('request', function ($app, $request) { $request->setUserResolver(function ($guard = null) use ($app) { return call_user_func($app['auth']->userResolver(), $guard); }); }); } /** * Handle the re-binding of the event dispatcher binding. * * @return void */ protected function registerEventRebindHandler() { $this->app->rebinding('events', function ($app, $dispatcher) { if (! $app->resolved('auth') || $app['auth']->hasResolvedGuards() === false) { return; } if (method_exists($guard = $app['auth']->guard(), 'setDispatcher')) { $guard->setDispatcher($dispatcher); } }); } } PK������y ZGe. �� ��(��Illuminate/Auth/CreatesUserProviders.phpnu�W+A��������<?php namespace Illuminate\Auth; use InvalidArgumentException; trait CreatesUserProviders { /** * The registered custom provider creators. * * @var array */ protected $customProviderCreators = []; /** * Create the user provider implementation for the driver. * * @param string|null $provider * @return \Illuminate\Contracts\Auth\UserProvider|null * * @throws \InvalidArgumentException */ public function createUserProvider($provider = null) { if (is_null($config = $this->getProviderConfiguration($provider))) { return; } if (isset($this->customProviderCreators[$driver = ($config['driver'] ?? null)])) { return call_user_func( $this->customProviderCreators[$driver], $this->app, $config ); } return match ($driver) { 'database' => $this->createDatabaseProvider($config), 'eloquent' => $this->createEloquentProvider($config), default => throw new InvalidArgumentException( "Authentication user provider [{$driver}] is not defined." ), }; } /** * Get the user provider configuration. * * @param string|null $provider * @return array|null */ protected function getProviderConfiguration($provider) { if ($provider = $provider ?: $this->getDefaultUserProvider()) { return $this->app['config']['auth.providers.'.$provider]; } } /** * Create an instance of the database user provider. * * @param array $config * @return \Illuminate\Auth\DatabaseUserProvider */ protected function createDatabaseProvider($config) { $connection = $this->app['db']->connection($config['connection'] ?? null); return new DatabaseUserProvider($connection, $this->app['hash'], $config['table']); } /** * Create an instance of the Eloquent user provider. * * @param array $config * @return \Illuminate\Auth\EloquentUserProvider */ protected function createEloquentProvider($config) { return new EloquentUserProvider($this->app['hash'], $config['model']); } /** * Get the default user provider name. * * @return string */ public function getDefaultUserProvider() { return $this->app['config']['auth.defaults.provider']; } } PK������y Z123 ��3 ��-��Illuminate/Auth/Notifications/VerifyEmail.phpnu�W+A��������<?php namespace Illuminate\Auth\Notifications; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notification; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Lang; use Illuminate\Support\Facades\URL; class VerifyEmail extends Notification { /** * The callback that should be used to create the verify email URL. * * @var \Closure|null */ public static $createUrlCallback; /** * The callback that should be used to build the mail message. * * @var \Closure|null */ public static $toMailCallback; /** * Get the notification's channels. * * @param mixed $notifiable * @return array|string */ public function via($notifiable) { return ['mail']; } /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } return $this->buildMailMessage($verificationUrl); } /** * Get the verify email notification mail message for the given URL. * * @param string $url * @return \Illuminate\Notifications\Messages\MailMessage */ protected function buildMailMessage($url) { return (new MailMessage) ->subject(Lang::get('Verify Email Address')) ->line(Lang::get('Please click the button below to verify your email address.')) ->action(Lang::get('Verify Email Address'), $url) ->line(Lang::get('If you did not create an account, no further action is required.')); } /** * Get the verification URL for the given notifiable. * * @param mixed $notifiable * @return string */ protected function verificationUrl($notifiable) { if (static::$createUrlCallback) { return call_user_func(static::$createUrlCallback, $notifiable); } return URL::temporarySignedRoute( 'verification.verify', Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)), [ 'id' => $notifiable->getKey(), 'hash' => sha1($notifiable->getEmailForVerification()), ] ); } /** * Set a callback that should be used when creating the email verification URL. * * @param \Closure $callback * @return void */ public static function createUrlUsing($callback) { static::$createUrlCallback = $callback; } /** * Set a callback that should be used when building the notification mail message. * * @param \Closure $callback * @return void */ public static function toMailUsing($callback) { static::$toMailCallback = $callback; } } PK������y Z �� ��/��Illuminate/Auth/Notifications/ResetPassword.phpnu�W+A��������<?php namespace Illuminate\Auth\Notifications; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notification; use Illuminate\Support\Facades\Lang; class ResetPassword extends Notification { /** * The password reset token. * * @var string */ public $token; /** * The callback that should be used to create the reset password URL. * * @var (\Closure(mixed, string): string)|null */ public static $createUrlCallback; /** * The callback that should be used to build the mail message. * * @var (\Closure(mixed, string): \Illuminate\Notifications\Messages\MailMessage)|null */ public static $toMailCallback; /** * Create a notification instance. * * @param string $token * @return void */ public function __construct($token) { $this->token = $token; } /** * Get the notification's channels. * * @param mixed $notifiable * @return array|string */ public function via($notifiable) { return ['mail']; } /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $this->token); } return $this->buildMailMessage($this->resetUrl($notifiable)); } /** * Get the reset password notification mail message for the given URL. * * @param string $url * @return \Illuminate\Notifications\Messages\MailMessage */ protected function buildMailMessage($url) { return (new MailMessage) ->subject(Lang::get('Reset Password Notification')) ->line(Lang::get('You are receiving this email because we received a password reset request for your account.')) ->action(Lang::get('Reset Password'), $url) ->line(Lang::get('This password reset link will expire in :count minutes.', ['count' => config('auth.passwords.'.config('auth.defaults.passwords').'.expire')])) ->line(Lang::get('If you did not request a password reset, no further action is required.')); } /** * Get the reset URL for the given notifiable. * * @param mixed $notifiable * @return string */ protected function resetUrl($notifiable) { if (static::$createUrlCallback) { return call_user_func(static::$createUrlCallback, $notifiable, $this->token); } return url(route('password.reset', [ 'token' => $this->token, 'email' => $notifiable->getEmailForPasswordReset(), ], false)); } /** * Set a callback that should be used when creating the reset password button URL. * * @param \Closure(mixed, string): string $callback * @return void */ public static function createUrlUsing($callback) { static::$createUrlCallback = $callback; } /** * Set a callback that should be used when building the notification mail message. * * @param \Closure(mixed, string): \Illuminate\Notifications\Messages\MailMessage $callback * @return void */ public static function toMailUsing($callback) { static::$toMailCallback = $callback; } } PK������y Z1`# ��# ��9��Illuminate/Auth/Console/stubs/make/views/layouts/app.stubnu�W+A��������<!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- CSRF Token --> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>{{ config('app.name', 'Laravel') }}
@yield('content')
PKy Zv RR.Illuminate/Auth/Console/ClearResetsCommand.phpnuW+Alaravel['auth.password']->broker($this->argument('name'))->getRepository()->deleteExpired(); $this->components->info('Expired reset tokens cleared successfully.'); } } PKy ZHO:Illuminate/Auth/Passwords/PasswordResetServiceProvider.phpnuW+AregisterPasswordBroker(); } /** * Register the password broker instance. * * @return void */ protected function registerPasswordBroker() { $this->app->singleton('auth.password', function ($app) { return new PasswordBrokerManager($app); }); $this->app->bind('auth.password.broker', function ($app) { return $app->make('auth.password')->broker(); }); } /** * Get the services provided by the provider. * * @return array */ public function provides() { return ['auth.password', 'auth.password.broker']; } } PKy ZO\ZZ.Illuminate/Auth/Passwords/CanResetPassword.phpnuW+Aemail; } /** * Send the password reset notification. * * @param string $token * @return void */ public function sendPasswordResetNotification($token) { $this->notify(new ResetPasswordNotification($token)); } } PKy ZSEZZ3Illuminate/Auth/Passwords/PasswordBrokerManager.phpnuW+Aapp = $app; } /** * Attempt to get the broker from the local cache. * * @param string|null $name * @return \Illuminate\Contracts\Auth\PasswordBroker */ public function broker($name = null) { $name = $name ?: $this->getDefaultDriver(); return $this->brokers[$name] ?? ($this->brokers[$name] = $this->resolve($name)); } /** * Resolve the given broker. * * @param string $name * @return \Illuminate\Contracts\Auth\PasswordBroker * * @throws \InvalidArgumentException */ protected function resolve($name) { $config = $this->getConfig($name); if (is_null($config)) { throw new InvalidArgumentException("Password resetter [{$name}] is not defined."); } // The password broker uses a token repository to validate tokens and send user // password e-mails, as well as validating that password reset process as an // aggregate service of sorts providing a convenient interface for resets. return new PasswordBroker( $this->createTokenRepository($config), $this->app['auth']->createUserProvider($config['provider'] ?? null) ); } /** * Create a token repository instance based on the given configuration. * * @param array $config * @return \Illuminate\Auth\Passwords\TokenRepositoryInterface */ protected function createTokenRepository(array $config) { $key = $this->app['config']['app.key']; if (str_starts_with($key, 'base64:')) { $key = base64_decode(substr($key, 7)); } $connection = $config['connection'] ?? null; return new DatabaseTokenRepository( $this->app['db']->connection($connection), $this->app['hash'], $config['table'], $key, $config['expire'], $config['throttle'] ?? 0 ); } /** * Get the password broker configuration. * * @param string $name * @return array */ protected function getConfig($name) { return $this->app['config']["auth.passwords.{$name}"]; } /** * Get the default password broker name. * * @return string */ public function getDefaultDriver() { return $this->app['config']['auth.defaults.passwords']; } /** * Set the default password broker name. * * @param string $name * @return void */ public function setDefaultDriver($name) { $this->app['config']['auth.defaults.passwords'] = $name; } /** * Dynamically call the default driver instance. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { return $this->broker()->{$method}(...$parameters); } } PKy ZUx26Illuminate/Auth/Passwords/TokenRepositoryInterface.phpnuW+Ausers = $users; $this->tokens = $tokens; } /** * Send a password reset link to a user. * * @param array $credentials * @param \Closure|null $callback * @return string */ public function sendResetLink(array $credentials, Closure $callback = null) { // First we will check to see if we found a user at the given credentials and // if we did not we will redirect back to this current URI with a piece of // "flash" data in the session to indicate to the developers the errors. $user = $this->getUser($credentials); if (is_null($user)) { return static::INVALID_USER; } if ($this->tokens->recentlyCreatedToken($user)) { return static::RESET_THROTTLED; } $token = $this->tokens->create($user); if ($callback) { $callback($user, $token); } else { // Once we have the reset token, we are ready to send the message out to this // user with a link to reset their password. We will then redirect back to // the current URI having nothing set in the session to indicate errors. $user->sendPasswordResetNotification($token); } return static::RESET_LINK_SENT; } /** * Reset the password for the given token. * * @param array $credentials * @param \Closure $callback * @return mixed */ public function reset(array $credentials, Closure $callback) { $user = $this->validateReset($credentials); // If the responses from the validate method is not a user instance, we will // assume that it is a redirect and simply return it from this method and // the user is properly redirected having an error message on the post. if (! $user instanceof CanResetPasswordContract) { return $user; } $password = $credentials['password']; // Once the reset has been validated, we'll call the given callback with the // new password. This gives the user an opportunity to store the password // in their persistent storage. Then we'll delete the token and return. $callback($user, $password); $this->tokens->delete($user); return static::PASSWORD_RESET; } /** * Validate a password reset for the given credentials. * * @param array $credentials * @return \Illuminate\Contracts\Auth\CanResetPassword|string */ protected function validateReset(array $credentials) { if (is_null($user = $this->getUser($credentials))) { return static::INVALID_USER; } if (! $this->tokens->exists($user, $credentials['token'])) { return static::INVALID_TOKEN; } return $user; } /** * Get the user for the given credentials. * * @param array $credentials * @return \Illuminate\Contracts\Auth\CanResetPassword|null * * @throws \UnexpectedValueException */ public function getUser(array $credentials) { $credentials = Arr::except($credentials, ['token']); $user = $this->users->retrieveByCredentials($credentials); if ($user && ! $user instanceof CanResetPasswordContract) { throw new UnexpectedValueException('User must implement CanResetPassword interface.'); } return $user; } /** * Create a new password reset token for the given user. * * @param \Illuminate\Contracts\Auth\CanResetPassword $user * @return string */ public function createToken(CanResetPasswordContract $user) { return $this->tokens->create($user); } /** * Delete password reset tokens of the given user. * * @param \Illuminate\Contracts\Auth\CanResetPassword $user * @return void */ public function deleteToken(CanResetPasswordContract $user) { $this->tokens->delete($user); } /** * Validate the given password reset token. * * @param \Illuminate\Contracts\Auth\CanResetPassword $user * @param string $token * @return bool */ public function tokenExists(CanResetPasswordContract $user, $token) { return $this->tokens->exists($user, $token); } /** * Get the password reset token repository implementation. * * @return \Illuminate\Auth\Passwords\TokenRepositoryInterface */ public function getRepository() { return $this->tokens; } } PKy Z.==5Illuminate/Auth/Passwords/DatabaseTokenRepository.phpnuW+Atable = $table; $this->hasher = $hasher; $this->hashKey = $hashKey; $this->expires = $expires * 60; $this->connection = $connection; $this->throttle = $throttle; } /** * Create a new token record. * * @param \Illuminate\Contracts\Auth\CanResetPassword $user * @return string */ public function create(CanResetPasswordContract $user) { $email = $user->getEmailForPasswordReset(); $this->deleteExisting($user); // We will create a new, random token for the user so that we can e-mail them // a safe link to the password reset form. Then we will insert a record in // the database so that we can verify the token within the actual reset. $token = $this->createNewToken(); $this->getTable()->insert($this->getPayload($email, $token)); return $token; } /** * Delete all existing reset tokens from the database. * * @param \Illuminate\Contracts\Auth\CanResetPassword $user * @return int */ protected function deleteExisting(CanResetPasswordContract $user) { return $this->getTable()->where('email', $user->getEmailForPasswordReset())->delete(); } /** * Build the record payload for the table. * * @param string $email * @param string $token * @return array */ protected function getPayload($email, $token) { return ['email' => $email, 'token' => $this->hasher->make($token), 'created_at' => new Carbon]; } /** * Determine if a token record exists and is valid. * * @param \Illuminate\Contracts\Auth\CanResetPassword $user * @param string $token * @return bool */ public function exists(CanResetPasswordContract $user, $token) { $record = (array) $this->getTable()->where( 'email', $user->getEmailForPasswordReset() )->first(); return $record && ! $this->tokenExpired($record['created_at']) && $this->hasher->check($token, $record['token']); } /** * Determine if the token has expired. * * @param string $createdAt * @return bool */ protected function tokenExpired($createdAt) { return Carbon::parse($createdAt)->addSeconds($this->expires)->isPast(); } /** * Determine if the given user recently created a password reset token. * * @param \Illuminate\Contracts\Auth\CanResetPassword $user * @return bool */ public function recentlyCreatedToken(CanResetPasswordContract $user) { $record = (array) $this->getTable()->where( 'email', $user->getEmailForPasswordReset() )->first(); return $record && $this->tokenRecentlyCreated($record['created_at']); } /** * Determine if the token was recently created. * * @param string $createdAt * @return bool */ protected function tokenRecentlyCreated($createdAt) { if ($this->throttle <= 0) { return false; } return Carbon::parse($createdAt)->addSeconds( $this->throttle )->isFuture(); } /** * Delete a token record by user. * * @param \Illuminate\Contracts\Auth\CanResetPassword $user * @return void */ public function delete(CanResetPasswordContract $user) { $this->deleteExisting($user); } /** * Delete expired tokens. * * @return void */ public function deleteExpired() { $expiredAt = Carbon::now()->subSeconds($this->expires); $this->getTable()->where('created_at', '<', $expiredAt)->delete(); } /** * Create a new token for the user. * * @return string */ public function createNewToken() { return hash_hmac('sha256', Str::random(40), $this->hashKey); } /** * Get the database connection instance. * * @return \Illuminate\Database\ConnectionInterface */ public function getConnection() { return $this->connection; } /** * Begin a new database query against the table. * * @return \Illuminate\Database\Query\Builder */ protected function getTable() { return $this->connection->table($this->table); } /** * Get the hasher instance. * * @return \Illuminate\Contracts\Hashing\Hasher */ public function getHasher() { return $this->hasher; } } PKy Zӑ= #Illuminate/Auth/Access/Response.phpnuW+Acode = $code; $this->allowed = $allowed; $this->message = $message; } /** * Create a new "allow" Response. * * @param string|null $message * @param mixed $code * @return \Illuminate\Auth\Access\Response */ public static function allow($message = null, $code = null) { return new static(true, $message, $code); } /** * Create a new "deny" Response. * * @param string|null $message * @param mixed $code * @return \Illuminate\Auth\Access\Response */ public static function deny($message = null, $code = null) { return new static(false, $message, $code); } /** * Create a new "deny" Response with a HTTP status code. * * @param int $status * @param string|null $message * @param mixed $code * @return \Illuminate\Auth\Access\Response */ public static function denyWithStatus($status, $message = null, $code = null) { return static::deny($message, $code)->withStatus($status); } /** * Create a new "deny" Response with a 404 HTTP status code. * * @param string|null $message * @param mixed $code * @return \Illuminate\Auth\Access\Response */ public static function denyAsNotFound($message = null, $code = null) { return static::denyWithStatus(404, $message, $code); } /** * Determine if the response was allowed. * * @return bool */ public function allowed() { return $this->allowed; } /** * Determine if the response was denied. * * @return bool */ public function denied() { return ! $this->allowed(); } /** * Get the response message. * * @return string|null */ public function message() { return $this->message; } /** * Get the response code / reason. * * @return mixed */ public function code() { return $this->code; } /** * Throw authorization exception if response was denied. * * @return \Illuminate\Auth\Access\Response * * @throws \Illuminate\Auth\Access\AuthorizationException */ public function authorize() { if ($this->denied()) { throw (new AuthorizationException($this->message(), $this->code())) ->setResponse($this) ->withStatus($this->status); } return $this; } /** * Set the HTTP response status code. * * @param null|int $status * @return $this */ public function withStatus($status) { $this->status = $status; return $this; } /** * Set the HTTP response status code to 404. * * @return $this */ public function asNotFound() { return $this->withStatus(404); } /** * Get the HTTP status code. * * @return int|null */ public function status() { return $this->status; } /** * Convert the response to an array. * * @return array */ public function toArray() { return [ 'allowed' => $this->allowed(), 'message' => $this->message(), 'code' => $this->code(), ]; } /** * Get the string representation of the message. * * @return string */ public function __toString() { return (string) $this->message(); } } PKy Z6Q 1Illuminate/Auth/Access/AuthorizationException.phpnuW+Acode = $code ?: 0; } /** * Get the response from the gate. * * @return \Illuminate\Auth\Access\Response */ public function response() { return $this->response; } /** * Set the response from the gate. * * @param \Illuminate\Auth\Access\Response $response * @return $this */ public function setResponse($response) { $this->response = $response; return $this; } /** * Set the HTTP response status code. * * @param int|null $status * @return $this */ public function withStatus($status) { $this->status = $status; return $this; } /** * Set the HTTP response status code to 404. * * @return $this */ public function asNotFound() { return $this->withStatus(404); } /** * Determine if the HTTP status code has been set. * * @return bool */ public function hasStatus() { return $this->status !== null; } /** * Get the HTTP status code. * * @return int|null */ public function status() { return $this->status; } /** * Create a deny response object from this exception. * * @return \Illuminate\Auth\Access\Response */ public function toResponse() { return Response::deny($this->message, $this->code)->withStatus($this->status); } } PKy ZYZ3FF/Illuminate/Auth/Access/HandlesAuthorization.phpnuW+Auser = $user; $this->ability = $ability; $this->result = $result; $this->arguments = $arguments; } } PKy ZCbCbIlluminate/Auth/Access/Gate.phpnuW+Apolicies = $policies; $this->container = $container; $this->abilities = $abilities; $this->userResolver = $userResolver; $this->afterCallbacks = $afterCallbacks; $this->beforeCallbacks = $beforeCallbacks; $this->guessPolicyNamesUsingCallback = $guessPolicyNamesUsingCallback; } /** * Determine if a given ability has been defined. * * @param string|array $ability * @return bool */ public function has($ability) { $abilities = is_array($ability) ? $ability : func_get_args(); foreach ($abilities as $ability) { if (! isset($this->abilities[$ability])) { return false; } } return true; } /** * Perform an on-demand authorization check. Throw an authorization exception if the condition or callback is false. * * @param \Illuminate\Auth\Access\Response|\Closure|bool $condition * @param string|null $message * @param string|null $code * @return \Illuminate\Auth\Access\Response * * @throws \Illuminate\Auth\Access\AuthorizationException */ public function allowIf($condition, $message = null, $code = null) { return $this->authorizeOnDemand($condition, $message, $code, true); } /** * Perform an on-demand authorization check. Throw an authorization exception if the condition or callback is true. * * @param \Illuminate\Auth\Access\Response|\Closure|bool $condition * @param string|null $message * @param string|null $code * @return \Illuminate\Auth\Access\Response * * @throws \Illuminate\Auth\Access\AuthorizationException */ public function denyIf($condition, $message = null, $code = null) { return $this->authorizeOnDemand($condition, $message, $code, false); } /** * Authorize a given condition or callback. * * @param \Illuminate\Auth\Access\Response|\Closure|bool $condition * @param string|null $message * @param string|null $code * @param bool $allowWhenResponseIs * @return \Illuminate\Auth\Access\Response * * @throws \Illuminate\Auth\Access\AuthorizationException */ protected function authorizeOnDemand($condition, $message, $code, $allowWhenResponseIs) { $user = $this->resolveUser(); if ($condition instanceof Closure) { $response = $this->canBeCalledWithUser($user, $condition) ? $condition($user) : new Response(false, $message, $code); } else { $response = $condition; } return with($response instanceof Response ? $response : new Response( (bool) $response === $allowWhenResponseIs, $message, $code ))->authorize(); } /** * Define a new ability. * * @param string $ability * @param callable|array|string $callback * @return $this * * @throws \InvalidArgumentException */ public function define($ability, $callback) { if (is_array($callback) && isset($callback[0]) && is_string($callback[0])) { $callback = $callback[0].'@'.$callback[1]; } if (is_callable($callback)) { $this->abilities[$ability] = $callback; } elseif (is_string($callback)) { $this->stringCallbacks[$ability] = $callback; $this->abilities[$ability] = $this->buildAbilityCallback($ability, $callback); } else { throw new InvalidArgumentException("Callback must be a callable, callback array, or a 'Class@method' string."); } return $this; } /** * Define abilities for a resource. * * @param string $name * @param string $class * @param array|null $abilities * @return $this */ public function resource($name, $class, array $abilities = null) { $abilities = $abilities ?: [ 'viewAny' => 'viewAny', 'view' => 'view', 'create' => 'create', 'update' => 'update', 'delete' => 'delete', ]; foreach ($abilities as $ability => $method) { $this->define($name.'.'.$ability, $class.'@'.$method); } return $this; } /** * Create the ability callback for a callback string. * * @param string $ability * @param string $callback * @return \Closure */ protected function buildAbilityCallback($ability, $callback) { return function () use ($ability, $callback) { if (str_contains($callback, '@')) { [$class, $method] = Str::parseCallback($callback); } else { $class = $callback; } $policy = $this->resolvePolicy($class); $arguments = func_get_args(); $user = array_shift($arguments); $result = $this->callPolicyBefore( $policy, $user, $ability, $arguments ); if (! is_null($result)) { return $result; } return isset($method) ? $policy->{$method}(...func_get_args()) : $policy(...func_get_args()); }; } /** * Define a policy class for a given class type. * * @param string $class * @param string $policy * @return $this */ public function policy($class, $policy) { $this->policies[$class] = $policy; return $this; } /** * Register a callback to run before all Gate checks. * * @param callable $callback * @return $this */ public function before(callable $callback) { $this->beforeCallbacks[] = $callback; return $this; } /** * Register a callback to run after all Gate checks. * * @param callable $callback * @return $this */ public function after(callable $callback) { $this->afterCallbacks[] = $callback; return $this; } /** * Determine if the given ability should be granted for the current user. * * @param string $ability * @param array|mixed $arguments * @return bool */ public function allows($ability, $arguments = []) { return $this->check($ability, $arguments); } /** * Determine if the given ability should be denied for the current user. * * @param string $ability * @param array|mixed $arguments * @return bool */ public function denies($ability, $arguments = []) { return ! $this->allows($ability, $arguments); } /** * Determine if all of the given abilities should be granted for the current user. * * @param iterable|string $abilities * @param array|mixed $arguments * @return bool */ public function check($abilities, $arguments = []) { return collect($abilities)->every( fn ($ability) => $this->inspect($ability, $arguments)->allowed() ); } /** * Determine if any one of the given abilities should be granted for the current user. * * @param iterable|string $abilities * @param array|mixed $arguments * @return bool */ public function any($abilities, $arguments = []) { return collect($abilities)->contains(fn ($ability) => $this->check($ability, $arguments)); } /** * Determine if all of the given abilities should be denied for the current user. * * @param iterable|string $abilities * @param array|mixed $arguments * @return bool */ public function none($abilities, $arguments = []) { return ! $this->any($abilities, $arguments); } /** * Determine if the given ability should be granted for the current user. * * @param string $ability * @param array|mixed $arguments * @return \Illuminate\Auth\Access\Response * * @throws \Illuminate\Auth\Access\AuthorizationException */ public function authorize($ability, $arguments = []) { return $this->inspect($ability, $arguments)->authorize(); } /** * Inspect the user for the given ability. * * @param string $ability * @param array|mixed $arguments * @return \Illuminate\Auth\Access\Response */ public function inspect($ability, $arguments = []) { try { $result = $this->raw($ability, $arguments); if ($result instanceof Response) { return $result; } return $result ? Response::allow() : Response::deny(); } catch (AuthorizationException $e) { return $e->toResponse(); } } /** * Get the raw result from the authorization callback. * * @param string $ability * @param array|mixed $arguments * @return mixed * * @throws \Illuminate\Auth\Access\AuthorizationException */ public function raw($ability, $arguments = []) { $arguments = Arr::wrap($arguments); $user = $this->resolveUser(); // First we will call the "before" callbacks for the Gate. If any of these give // back a non-null response, we will immediately return that result in order // to let the developers override all checks for some authorization cases. $result = $this->callBeforeCallbacks( $user, $ability, $arguments ); if (is_null($result)) { $result = $this->callAuthCallback($user, $ability, $arguments); } // After calling the authorization callback, we will call the "after" callbacks // that are registered with the Gate, which allows a developer to do logging // if that is required for this application. Then we'll return the result. return tap($this->callAfterCallbacks( $user, $ability, $arguments, $result ), function ($result) use ($user, $ability, $arguments) { $this->dispatchGateEvaluatedEvent($user, $ability, $arguments, $result); }); } /** * Determine whether the callback/method can be called with the given user. * * @param \Illuminate\Contracts\Auth\Authenticatable|null $user * @param \Closure|string|array $class * @param string|null $method * @return bool */ protected function canBeCalledWithUser($user, $class, $method = null) { if (! is_null($user)) { return true; } if (! is_null($method)) { return $this->methodAllowsGuests($class, $method); } if (is_array($class)) { $className = is_string($class[0]) ? $class[0] : get_class($class[0]); return $this->methodAllowsGuests($className, $class[1]); } return $this->callbackAllowsGuests($class); } /** * Determine if the given class method allows guests. * * @param string $class * @param string $method * @return bool */ protected function methodAllowsGuests($class, $method) { try { $reflection = new ReflectionClass($class); $method = $reflection->getMethod($method); } catch (Exception $e) { return false; } if ($method) { $parameters = $method->getParameters(); return isset($parameters[0]) && $this->parameterAllowsGuests($parameters[0]); } return false; } /** * Determine if the callback allows guests. * * @param callable $callback * @return bool * * @throws \ReflectionException */ protected function callbackAllowsGuests($callback) { $parameters = (new ReflectionFunction($callback))->getParameters(); return isset($parameters[0]) && $this->parameterAllowsGuests($parameters[0]); } /** * Determine if the given parameter allows guests. * * @param \ReflectionParameter $parameter * @return bool */ protected function parameterAllowsGuests($parameter) { return ($parameter->hasType() && $parameter->allowsNull()) || ($parameter->isDefaultValueAvailable() && is_null($parameter->getDefaultValue())); } /** * Resolve and call the appropriate authorization callback. * * @param \Illuminate\Contracts\Auth\Authenticatable|null $user * @param string $ability * @param array $arguments * @return bool */ protected function callAuthCallback($user, $ability, array $arguments) { $callback = $this->resolveAuthCallback($user, $ability, $arguments); return $callback($user, ...$arguments); } /** * Call all of the before callbacks and return if a result is given. * * @param \Illuminate\Contracts\Auth\Authenticatable|null $user * @param string $ability * @param array $arguments * @return bool|null */ protected function callBeforeCallbacks($user, $ability, array $arguments) { foreach ($this->beforeCallbacks as $before) { if (! $this->canBeCalledWithUser($user, $before)) { continue; } if (! is_null($result = $before($user, $ability, $arguments))) { return $result; } } } /** * Call all of the after callbacks with check result. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param string $ability * @param array $arguments * @param bool $result * @return bool|null */ protected function callAfterCallbacks($user, $ability, array $arguments, $result) { foreach ($this->afterCallbacks as $after) { if (! $this->canBeCalledWithUser($user, $after)) { continue; } $afterResult = $after($user, $ability, $result, $arguments); $result ??= $afterResult; } return $result; } /** * Dispatch a gate evaluation event. * * @param \Illuminate\Contracts\Auth\Authenticatable|null $user * @param string $ability * @param array $arguments * @param bool|null $result * @return void */ protected function dispatchGateEvaluatedEvent($user, $ability, array $arguments, $result) { if ($this->container->bound(Dispatcher::class)) { $this->container->make(Dispatcher::class)->dispatch( new GateEvaluated($user, $ability, $result, $arguments) ); } } /** * Resolve the callable for the given ability and arguments. * * @param \Illuminate\Contracts\Auth\Authenticatable|null $user * @param string $ability * @param array $arguments * @return callable */ protected function resolveAuthCallback($user, $ability, array $arguments) { if (isset($arguments[0]) && ! is_null($policy = $this->getPolicyFor($arguments[0])) && $callback = $this->resolvePolicyCallback($user, $ability, $arguments, $policy)) { return $callback; } if (isset($this->stringCallbacks[$ability])) { [$class, $method] = Str::parseCallback($this->stringCallbacks[$ability]); if ($this->canBeCalledWithUser($user, $class, $method ?: '__invoke')) { return $this->abilities[$ability]; } } if (isset($this->abilities[$ability]) && $this->canBeCalledWithUser($user, $this->abilities[$ability])) { return $this->abilities[$ability]; } return function () { // }; } /** * Get a policy instance for a given class. * * @param object|string $class * @return mixed */ public function getPolicyFor($class) { if (is_object($class)) { $class = get_class($class); } if (! is_string($class)) { return; } if (isset($this->policies[$class])) { return $this->resolvePolicy($this->policies[$class]); } foreach ($this->guessPolicyName($class) as $guessedPolicy) { if (class_exists($guessedPolicy)) { return $this->resolvePolicy($guessedPolicy); } } foreach ($this->policies as $expected => $policy) { if (is_subclass_of($class, $expected)) { return $this->resolvePolicy($policy); } } } /** * Guess the policy name for the given class. * * @param string $class * @return array */ protected function guessPolicyName($class) { if ($this->guessPolicyNamesUsingCallback) { return Arr::wrap(call_user_func($this->guessPolicyNamesUsingCallback, $class)); } $classDirname = str_replace('/', '\\', dirname(str_replace('\\', '/', $class))); $classDirnameSegments = explode('\\', $classDirname); return Arr::wrap(Collection::times(count($classDirnameSegments), function ($index) use ($class, $classDirnameSegments) { $classDirname = implode('\\', array_slice($classDirnameSegments, 0, $index)); return $classDirname.'\\Policies\\'.class_basename($class).'Policy'; })->reverse()->values()->first(function ($class) { return class_exists($class); }) ?: [$classDirname.'\\Policies\\'.class_basename($class).'Policy']); } /** * Specify a callback to be used to guess policy names. * * @param callable $callback * @return $this */ public function guessPolicyNamesUsing(callable $callback) { $this->guessPolicyNamesUsingCallback = $callback; return $this; } /** * Build a policy class instance of the given type. * * @param object|string $class * @return mixed * * @throws \Illuminate\Contracts\Container\BindingResolutionException */ public function resolvePolicy($class) { return $this->container->make($class); } /** * Resolve the callback for a policy check. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param string $ability * @param array $arguments * @param mixed $policy * @return bool|callable */ protected function resolvePolicyCallback($user, $ability, array $arguments, $policy) { if (! is_callable([$policy, $this->formatAbilityToMethod($ability)])) { return false; } return function () use ($user, $ability, $arguments, $policy) { // This callback will be responsible for calling the policy's before method and // running this policy method if necessary. This is used to when objects are // mapped to policy objects in the user's configurations or on this class. $result = $this->callPolicyBefore( $policy, $user, $ability, $arguments ); // When we receive a non-null result from this before method, we will return it // as the "final" results. This will allow developers to override the checks // in this policy to return the result for all rules defined in the class. if (! is_null($result)) { return $result; } $method = $this->formatAbilityToMethod($ability); return $this->callPolicyMethod($policy, $method, $user, $arguments); }; } /** * Call the "before" method on the given policy, if applicable. * * @param mixed $policy * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param string $ability * @param array $arguments * @return mixed */ protected function callPolicyBefore($policy, $user, $ability, $arguments) { if (! method_exists($policy, 'before')) { return; } if ($this->canBeCalledWithUser($user, $policy, 'before')) { return $policy->before($user, $ability, ...$arguments); } } /** * Call the appropriate method on the given policy. * * @param mixed $policy * @param string $method * @param \Illuminate\Contracts\Auth\Authenticatable|null $user * @param array $arguments * @return mixed */ protected function callPolicyMethod($policy, $method, $user, array $arguments) { // If this first argument is a string, that means they are passing a class name // to the policy. We will remove the first argument from this argument array // because this policy already knows what type of models it can authorize. if (isset($arguments[0]) && is_string($arguments[0])) { array_shift($arguments); } if (! is_callable([$policy, $method])) { return; } if ($this->canBeCalledWithUser($user, $policy, $method)) { return $policy->{$method}($user, ...$arguments); } } /** * Format the policy ability into a method name. * * @param string $ability * @return string */ protected function formatAbilityToMethod($ability) { return str_contains($ability, '-') ? Str::camel($ability) : $ability; } /** * Get a gate instance for the given user. * * @param \Illuminate\Contracts\Auth\Authenticatable|mixed $user * @return static */ public function forUser($user) { $callback = fn () => $user; return new static( $this->container, $callback, $this->abilities, $this->policies, $this->beforeCallbacks, $this->afterCallbacks, $this->guessPolicyNamesUsingCallback ); } /** * Resolve the user from the user resolver. * * @return mixed */ protected function resolveUser() { return call_user_func($this->userResolver); } /** * Get all of the defined abilities. * * @return array */ public function abilities() { return $this->abilities; } /** * Get all of the defined policies. * * @return array */ public function policies() { return $this->policies; } /** * Set the container instance used by the gate. * * @param \Illuminate\Contracts\Container\Container $container * @return $this */ public function setContainer(Container $container) { $this->container = $container; return $this; } } PKy Z !!Illuminate/Auth/AuthManager.phpnuW+Aapp = $app; $this->userResolver = fn ($guard = null) => $this->guard($guard)->user(); } /** * Attempt to get the guard from the local cache. * * @param string|null $name * @return \Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard */ public function guard($name = null) { $name = $name ?: $this->getDefaultDriver(); return $this->guards[$name] ?? $this->guards[$name] = $this->resolve($name); } /** * Resolve the given guard. * * @param string $name * @return \Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard * * @throws \InvalidArgumentException */ protected function resolve($name) { $config = $this->getConfig($name); if (is_null($config)) { throw new InvalidArgumentException("Auth guard [{$name}] is not defined."); } if (isset($this->customCreators[$config['driver']])) { return $this->callCustomCreator($name, $config); } $driverMethod = 'create'.ucfirst($config['driver']).'Driver'; if (method_exists($this, $driverMethod)) { return $this->{$driverMethod}($name, $config); } throw new InvalidArgumentException( "Auth driver [{$config['driver']}] for guard [{$name}] is not defined." ); } /** * Call a custom driver creator. * * @param string $name * @param array $config * @return mixed */ protected function callCustomCreator($name, array $config) { return $this->customCreators[$config['driver']]($this->app, $name, $config); } /** * Create a session based authentication guard. * * @param string $name * @param array $config * @return \Illuminate\Auth\SessionGuard */ public function createSessionDriver($name, $config) { $provider = $this->createUserProvider($config['provider'] ?? null); $guard = new SessionGuard( $name, $provider, $this->app['session.store'], ); // When using the remember me functionality of the authentication services we // will need to be set the encryption instance of the guard, which allows // secure, encrypted cookie values to get generated for those cookies. if (method_exists($guard, 'setCookieJar')) { $guard->setCookieJar($this->app['cookie']); } if (method_exists($guard, 'setDispatcher')) { $guard->setDispatcher($this->app['events']); } if (method_exists($guard, 'setRequest')) { $guard->setRequest($this->app->refresh('request', $guard, 'setRequest')); } if (isset($config['remember'])) { $guard->setRememberDuration($config['remember']); } return $guard; } /** * Create a token based authentication guard. * * @param string $name * @param array $config * @return \Illuminate\Auth\TokenGuard */ public function createTokenDriver($name, $config) { // The token guard implements a basic API token based guard implementation // that takes an API token field from the request and matches it to the // user in the database or another persistence layer where users are. $guard = new TokenGuard( $this->createUserProvider($config['provider'] ?? null), $this->app['request'], $config['input_key'] ?? 'api_token', $config['storage_key'] ?? 'api_token', $config['hash'] ?? false ); $this->app->refresh('request', $guard, 'setRequest'); return $guard; } /** * Get the guard configuration. * * @param string $name * @return array */ protected function getConfig($name) { return $this->app['config']["auth.guards.{$name}"]; } /** * Get the default authentication driver name. * * @return string */ public function getDefaultDriver() { return $this->app['config']['auth.defaults.guard']; } /** * Set the default guard driver the factory should serve. * * @param string $name * @return void */ public function shouldUse($name) { $name = $name ?: $this->getDefaultDriver(); $this->setDefaultDriver($name); $this->userResolver = fn ($name = null) => $this->guard($name)->user(); } /** * Set the default authentication driver name. * * @param string $name * @return void */ public function setDefaultDriver($name) { $this->app['config']['auth.defaults.guard'] = $name; } /** * Register a new callback based request guard. * * @param string $driver * @param callable $callback * @return $this */ public function viaRequest($driver, callable $callback) { return $this->extend($driver, function () use ($callback) { $guard = new RequestGuard($callback, $this->app['request'], $this->createUserProvider()); $this->app->refresh('request', $guard, 'setRequest'); return $guard; }); } /** * Get the user resolver callback. * * @return \Closure */ public function userResolver() { return $this->userResolver; } /** * Set the callback to be used to resolve users. * * @param \Closure $userResolver * @return $this */ public function resolveUsersUsing(Closure $userResolver) { $this->userResolver = $userResolver; return $this; } /** * Register a custom driver creator Closure. * * @param string $driver * @param \Closure $callback * @return $this */ public function extend($driver, Closure $callback) { $this->customCreators[$driver] = $callback; return $this; } /** * Register a custom provider creator Closure. * * @param string $name * @param \Closure $callback * @return $this */ public function provider($name, Closure $callback) { $this->customProviderCreators[$name] = $callback; return $this; } /** * Determines if any guards have already been resolved. * * @return bool */ public function hasResolvedGuards() { return count($this->guards) > 0; } /** * Forget all of the resolved guard instances. * * @return $this */ public function forgetGuards() { $this->guards = []; return $this; } /** * Set the application instance used by the manager. * * @param \Illuminate\Contracts\Foundation\Application $app * @return $this */ public function setApplication($app) { $this->app = $app; return $this; } /** * Dynamically call the default driver instance. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { return $this->guard()->{$method}(...$parameters); } } PKy Z6Illuminate/Auth/composer.jsonnuW+A{ "name": "illuminate/auth", "description": "The Illuminate Auth package.", "license": "MIT", "homepage": "https://laravel.com", "support": { "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, "authors": [ { "name": "Taylor Otwell", "email": "taylor@laravel.com" } ], "require": { "php": "^8.0.2", "ext-hash": "*", "illuminate/collections": "^9.0", "illuminate/contracts": "^9.0", "illuminate/http": "^9.0", "illuminate/macroable": "^9.0", "illuminate/queue": "^9.0", "illuminate/support": "^9.0" }, "autoload": { "psr-4": { "Illuminate\\Auth\\": "" } }, "extra": { "branch-alias": { "dev-master": "9.x-dev" } }, "suggest": { "illuminate/console": "Required to use the auth:clear-resets command (^9.0).", "illuminate/queue": "Required to fire login / logout events (^9.0).", "illuminate/session": "Required to use the session based guard (^9.0)." }, "config": { "sort-packages": true }, "minimum-stability": "dev" } PKy ZNO(Illuminate/Auth/EloquentUserProvider.phpnuW+Amodel = $model; $this->hasher = $hasher; } /** * Retrieve a user by their unique identifier. * * @param mixed $identifier * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function retrieveById($identifier) { $model = $this->createModel(); return $this->newModelQuery($model) ->where($model->getAuthIdentifierName(), $identifier) ->first(); } /** * Retrieve a user by their unique identifier and "remember me" token. * * @param mixed $identifier * @param string $token * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function retrieveByToken($identifier, $token) { $model = $this->createModel(); $retrievedModel = $this->newModelQuery($model)->where( $model->getAuthIdentifierName(), $identifier )->first(); if (! $retrievedModel) { return; } $rememberToken = $retrievedModel->getRememberToken(); return $rememberToken && hash_equals($rememberToken, $token) ? $retrievedModel : null; } /** * Update the "remember me" token for the given user in storage. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param string $token * @return void */ public function updateRememberToken(UserContract $user, $token) { $user->setRememberToken($token); $timestamps = $user->timestamps; $user->timestamps = false; $user->save(); $user->timestamps = $timestamps; } /** * Retrieve a user by the given credentials. * * @param array $credentials * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function retrieveByCredentials(array $credentials) { $credentials = array_filter( $credentials, fn ($key) => ! str_contains($key, 'password'), ARRAY_FILTER_USE_KEY ); if (empty($credentials)) { return; } // First we will add each credential element to the query as a where clause. // Then we can execute the query and, if we found a user, return it in a // Eloquent User "model" that will be utilized by the Guard instances. $query = $this->newModelQuery(); foreach ($credentials as $key => $value) { if (is_array($value) || $value instanceof Arrayable) { $query->whereIn($key, $value); } elseif ($value instanceof Closure) { $value($query); } else { $query->where($key, $value); } } return $query->first(); } /** * Validate a user against the given credentials. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param array $credentials * @return bool */ public function validateCredentials(UserContract $user, array $credentials) { if (is_null($plain = $credentials['password'])) { return false; } return $this->hasher->check($plain, $user->getAuthPassword()); } /** * Get a new query builder for the model instance. * * @param \Illuminate\Database\Eloquent\Model|null $model * @return \Illuminate\Database\Eloquent\Builder */ protected function newModelQuery($model = null) { $query = is_null($model) ? $this->createModel()->newQuery() : $model->newQuery(); with($query, $this->queryCallback); return $query; } /** * Create a new instance of the model. * * @return \Illuminate\Database\Eloquent\Model */ public function createModel() { $class = '\\'.ltrim($this->model, '\\'); return new $class; } /** * Gets the hasher implementation. * * @return \Illuminate\Contracts\Hashing\Hasher */ public function getHasher() { return $this->hasher; } /** * Sets the hasher implementation. * * @param \Illuminate\Contracts\Hashing\Hasher $hasher * @return $this */ public function setHasher(HasherContract $hasher) { $this->hasher = $hasher; return $this; } /** * Gets the name of the Eloquent user model. * * @return string */ public function getModel() { return $this->model; } /** * Sets the name of the Eloquent user model. * * @param string $model * @return $this */ public function setModel($model) { $this->model = $model; return $this; } /** * Get the callback that modifies the query before retrieving users. * * @return \Closure|null */ public function getQueryCallback() { return $this->queryCallback; } /** * Sets the callback to modify the query before retrieving users. * * @param (\Closure(\Illuminate\Database\Eloquent\Builder):mixed)|null $queryCallback * @return $this */ public function withQuery($queryCallback = null) { $this->queryCallback = $queryCallback; return $this; } } PKy Z-W&W&!Illuminate/Support/MessageBag.phpnuW+A $value) { $value = $value instanceof Arrayable ? $value->toArray() : (array) $value; $this->messages[$key] = array_unique($value); } } /** * Get the keys present in the message bag. * * @return array */ public function keys() { return array_keys($this->messages); } /** * Add a message to the message bag. * * @param string $key * @param string $message * @return $this */ public function add($key, $message) { if ($this->isUnique($key, $message)) { $this->messages[$key][] = $message; } return $this; } /** * Add a message to the message bag if the given conditional is "true". * * @param bool $boolean * @param string $key * @param string $message * @return $this */ public function addIf($boolean, $key, $message) { return $boolean ? $this->add($key, $message) : $this; } /** * Determine if a key and message combination already exists. * * @param string $key * @param string $message * @return bool */ protected function isUnique($key, $message) { $messages = (array) $this->messages; return ! isset($messages[$key]) || ! in_array($message, $messages[$key]); } /** * Merge a new array of messages into the message bag. * * @param \Illuminate\Contracts\Support\MessageProvider|array $messages * @return $this */ public function merge($messages) { if ($messages instanceof MessageProvider) { $messages = $messages->getMessageBag()->getMessages(); } $this->messages = array_merge_recursive($this->messages, $messages); return $this; } /** * Determine if messages exist for all of the given keys. * * @param array|string|null $key * @return bool */ public function has($key) { if ($this->isEmpty()) { return false; } if (is_null($key)) { return $this->any(); } $keys = is_array($key) ? $key : func_get_args(); foreach ($keys as $key) { if ($this->first($key) === '') { return false; } } return true; } /** * Determine if messages exist for any of the given keys. * * @param array|string|null $keys * @return bool */ public function hasAny($keys = []) { if ($this->isEmpty()) { return false; } $keys = is_array($keys) ? $keys : func_get_args(); foreach ($keys as $key) { if ($this->has($key)) { return true; } } return false; } /** * Get the first message from the message bag for a given key. * * @param string|null $key * @param string|null $format * @return string */ public function first($key = null, $format = null) { $messages = is_null($key) ? $this->all($format) : $this->get($key, $format); $firstMessage = Arr::first($messages, null, ''); return is_array($firstMessage) ? Arr::first($firstMessage) : $firstMessage; } /** * Get all of the messages from the message bag for a given key. * * @param string $key * @param string|null $format * @return array */ public function get($key, $format = null) { // If the message exists in the message bag, we will transform it and return // the message. Otherwise, we will check if the key is implicit & collect // all the messages that match the given key and output it as an array. if (array_key_exists($key, $this->messages)) { return $this->transform( $this->messages[$key], $this->checkFormat($format), $key ); } if (str_contains($key, '*')) { return $this->getMessagesForWildcardKey($key, $format); } return []; } /** * Get the messages for a wildcard key. * * @param string $key * @param string|null $format * @return array */ protected function getMessagesForWildcardKey($key, $format) { return collect($this->messages) ->filter(function ($messages, $messageKey) use ($key) { return Str::is($key, $messageKey); }) ->map(function ($messages, $messageKey) use ($format) { return $this->transform( $messages, $this->checkFormat($format), $messageKey ); })->all(); } /** * Get all of the messages for every key in the message bag. * * @param string|null $format * @return array */ public function all($format = null) { $format = $this->checkFormat($format); $all = []; foreach ($this->messages as $key => $messages) { $all = array_merge($all, $this->transform($messages, $format, $key)); } return $all; } /** * Get all of the unique messages for every key in the message bag. * * @param string|null $format * @return array */ public function unique($format = null) { return array_unique($this->all($format)); } /** * Format an array of messages. * * @param array $messages * @param string $format * @param string $messageKey * @return array */ protected function transform($messages, $format, $messageKey) { if ($format == ':message') { return (array) $messages; } return collect((array) $messages) ->map(function ($message) use ($format, $messageKey) { // We will simply spin through the given messages and transform each one // replacing the :message place holder with the real message allowing // the messages to be easily formatted to each developer's desires. return str_replace([':message', ':key'], [$message, $messageKey], $format); })->all(); } /** * Get the appropriate format based on the given format. * * @param string $format * @return string */ protected function checkFormat($format) { return $format ?: $this->format; } /** * Get the raw messages in the message bag. * * @return array */ public function messages() { return $this->messages; } /** * Get the raw messages in the message bag. * * @return array */ public function getMessages() { return $this->messages(); } /** * Get the messages for the instance. * * @return \Illuminate\Support\MessageBag */ public function getMessageBag() { return $this; } /** * Get the default message format. * * @return string */ public function getFormat() { return $this->format; } /** * Set the default message format. * * @param string $format * @return \Illuminate\Support\MessageBag */ public function setFormat($format = ':message') { $this->format = $format; return $this; } /** * Determine if the message bag has any messages. * * @return bool */ public function isEmpty() { return ! $this->any(); } /** * Determine if the message bag has any messages. * * @return bool */ public function isNotEmpty() { return $this->any(); } /** * Determine if the message bag has any messages. * * @return bool */ public function any() { return $this->count() > 0; } /** * Get the number of messages in the message bag. * * @return int */ public function count(): int { return count($this->messages, COUNT_RECURSIVE) - count($this->messages); } /** * Get the instance as an array. * * @return array */ public function toArray() { return $this->getMessages(); } /** * Convert the object into something JSON serializable. * * @return array */ public function jsonSerialize(): array { return $this->toArray(); } /** * Convert the object to its JSON representation. * * @param int $options * @return string */ public function toJson($options = 0) { return json_encode($this->jsonSerialize(), $options); } /** * Convert the message bag to its string representation. * * @return string */ public function __toString() { return $this->toJson(); } } PKy Zd Z Z,Illuminate/Support/Testing/Fakes/BusFake.phpnuW+Adispatcher = $dispatcher; $this->jobsToFake = Arr::wrap($jobsToFake); $this->batchRepository = $batchRepository ?: new BatchRepositoryFake; } /** * Specify the jobs that should be dispatched instead of faked. * * @param array|string $jobsToDispatch * @return void */ public function except($jobsToDispatch) { $this->jobsToDispatch = array_merge($this->jobsToDispatch, Arr::wrap($jobsToDispatch)); return $this; } /** * Assert if a job was dispatched based on a truth-test callback. * * @param string|\Closure $command * @param callable|int|null $callback * @return void */ public function assertDispatched($command, $callback = null) { if ($command instanceof Closure) { [$command, $callback] = [$this->firstClosureParameterType($command), $command]; } if (is_numeric($callback)) { return $this->assertDispatchedTimes($command, $callback); } PHPUnit::assertTrue( $this->dispatched($command, $callback)->count() > 0 || $this->dispatchedAfterResponse($command, $callback)->count() > 0 || $this->dispatchedSync($command, $callback)->count() > 0, "The expected [{$command}] job was not dispatched." ); } /** * Assert if a job was pushed a number of times. * * @param string|\Closure $command * @param int $times * @return void */ public function assertDispatchedTimes($command, $times = 1) { $callback = null; if ($command instanceof Closure) { [$command, $callback] = [$this->firstClosureParameterType($command), $command]; } $count = $this->dispatched($command, $callback)->count() + $this->dispatchedAfterResponse($command, $callback)->count() + $this->dispatchedSync($command, $callback)->count(); PHPUnit::assertSame( $times, $count, "The expected [{$command}] job was pushed {$count} times instead of {$times} times." ); } /** * Determine if a job was dispatched based on a truth-test callback. * * @param string|\Closure $command * @param callable|null $callback * @return void */ public function assertNotDispatched($command, $callback = null) { if ($command instanceof Closure) { [$command, $callback] = [$this->firstClosureParameterType($command), $command]; } PHPUnit::assertTrue( $this->dispatched($command, $callback)->count() === 0 && $this->dispatchedAfterResponse($command, $callback)->count() === 0 && $this->dispatchedSync($command, $callback)->count() === 0, "The unexpected [{$command}] job was dispatched." ); } /** * Assert that no jobs were dispatched. * * @return void */ public function assertNothingDispatched() { PHPUnit::assertEmpty($this->commands, 'Jobs were dispatched unexpectedly.'); } /** * Assert if a job was explicitly dispatched synchronously based on a truth-test callback. * * @param string|\Closure $command * @param callable|int|null $callback * @return void */ public function assertDispatchedSync($command, $callback = null) { if ($command instanceof Closure) { [$command, $callback] = [$this->firstClosureParameterType($command), $command]; } if (is_numeric($callback)) { return $this->assertDispatchedSyncTimes($command, $callback); } PHPUnit::assertTrue( $this->dispatchedSync($command, $callback)->count() > 0, "The expected [{$command}] job was not dispatched synchronously." ); } /** * Assert if a job was pushed synchronously a number of times. * * @param string|\Closure $command * @param int $times * @return void */ public function assertDispatchedSyncTimes($command, $times = 1) { $callback = null; if ($command instanceof Closure) { [$command, $callback] = [$this->firstClosureParameterType($command), $command]; } $count = $this->dispatchedSync($command, $callback)->count(); PHPUnit::assertSame( $times, $count, "The expected [{$command}] job was synchronously pushed {$count} times instead of {$times} times." ); } /** * Determine if a job was dispatched based on a truth-test callback. * * @param string|\Closure $command * @param callable|null $callback * @return void */ public function assertNotDispatchedSync($command, $callback = null) { if ($command instanceof Closure) { [$command, $callback] = [$this->firstClosureParameterType($command), $command]; } PHPUnit::assertCount( 0, $this->dispatchedSync($command, $callback), "The unexpected [{$command}] job was dispatched synchronously." ); } /** * Assert if a job was dispatched after the response was sent based on a truth-test callback. * * @param string|\Closure $command * @param callable|int|null $callback * @return void */ public function assertDispatchedAfterResponse($command, $callback = null) { if ($command instanceof Closure) { [$command, $callback] = [$this->firstClosureParameterType($command), $command]; } if (is_numeric($callback)) { return $this->assertDispatchedAfterResponseTimes($command, $callback); } PHPUnit::assertTrue( $this->dispatchedAfterResponse($command, $callback)->count() > 0, "The expected [{$command}] job was not dispatched after sending the response." ); } /** * Assert if a job was pushed after the response was sent a number of times. * * @param string|\Closure $command * @param int $times * @return void */ public function assertDispatchedAfterResponseTimes($command, $times = 1) { $callback = null; if ($command instanceof Closure) { [$command, $callback] = [$this->firstClosureParameterType($command), $command]; } $count = $this->dispatchedAfterResponse($command, $callback)->count(); PHPUnit::assertSame( $times, $count, "The expected [{$command}] job was pushed {$count} times instead of {$times} times." ); } /** * Determine if a job was dispatched based on a truth-test callback. * * @param string|\Closure $command * @param callable|null $callback * @return void */ public function assertNotDispatchedAfterResponse($command, $callback = null) { if ($command instanceof Closure) { [$command, $callback] = [$this->firstClosureParameterType($command), $command]; } PHPUnit::assertCount( 0, $this->dispatchedAfterResponse($command, $callback), "The unexpected [{$command}] job was dispatched after sending the response." ); } /** * Assert if a chain of jobs was dispatched. * * @param array $expectedChain * @return void */ public function assertChained(array $expectedChain) { $command = $expectedChain[0]; $expectedChain = array_slice($expectedChain, 1); $callback = null; if ($command instanceof Closure) { [$command, $callback] = [$this->firstClosureParameterType($command), $command]; } elseif (! is_string($command)) { $instance = $command; $command = get_class($instance); $callback = function ($job) use ($instance) { return serialize($this->resetChainPropertiesToDefaults($job)) === serialize($instance); }; } PHPUnit::assertTrue( $this->dispatched($command, $callback)->isNotEmpty(), "The expected [{$command}] job was not dispatched." ); PHPUnit::assertTrue( collect($expectedChain)->isNotEmpty(), 'The expected chain can not be empty.' ); $this->isChainOfObjects($expectedChain) ? $this->assertDispatchedWithChainOfObjects($command, $expectedChain, $callback) : $this->assertDispatchedWithChainOfClasses($command, $expectedChain, $callback); } /** * Reset the chain properties to their default values on the job. * * @param mixed $job * @return mixed */ protected function resetChainPropertiesToDefaults($job) { return tap(clone $job, function ($job) { $job->chainConnection = null; $job->chainQueue = null; $job->chainCatchCallbacks = null; $job->chained = []; }); } /** * Assert if a job was dispatched with an empty chain based on a truth-test callback. * * @param string|\Closure $command * @param callable|null $callback * @return void */ public function assertDispatchedWithoutChain($command, $callback = null) { if ($command instanceof Closure) { [$command, $callback] = [$this->firstClosureParameterType($command), $command]; } PHPUnit::assertTrue( $this->dispatched($command, $callback)->isNotEmpty(), "The expected [{$command}] job was not dispatched." ); $this->assertDispatchedWithChainOfClasses($command, [], $callback); } /** * Assert if a job was dispatched with chained jobs based on a truth-test callback. * * @param string $command * @param array $expectedChain * @param callable|null $callback * @return void */ protected function assertDispatchedWithChainOfObjects($command, $expectedChain, $callback) { $chain = collect($expectedChain)->map(fn ($job) => serialize($job))->all(); PHPUnit::assertTrue( $this->dispatched($command, $callback)->filter( fn ($job) => $job->chained == $chain )->isNotEmpty(), 'The expected chain was not dispatched.' ); } /** * Assert if a job was dispatched with chained jobs based on a truth-test callback. * * @param string $command * @param array $expectedChain * @param callable|null $callback * @return void */ protected function assertDispatchedWithChainOfClasses($command, $expectedChain, $callback) { $matching = $this->dispatched($command, $callback)->map->chained->map(function ($chain) { return collect($chain)->map( fn ($job) => get_class(unserialize($job)) ); })->filter( fn ($chain) => $chain->all() === $expectedChain ); PHPUnit::assertTrue( $matching->isNotEmpty(), 'The expected chain was not dispatched.' ); } /** * Determine if the given chain is entirely composed of objects. * * @param array $chain * @return bool */ protected function isChainOfObjects($chain) { return ! collect($chain)->contains(fn ($job) => ! is_object($job)); } /** * Assert if a batch was dispatched based on a truth-test callback. * * @param callable $callback * @return void */ public function assertBatched(callable $callback) { PHPUnit::assertTrue( $this->batched($callback)->count() > 0, 'The expected batch was not dispatched.' ); } /** * Assert the number of batches that have been dispatched. * * @param int $count * @return void */ public function assertBatchCount($count) { PHPUnit::assertCount( $count, $this->batches, ); } /** * Assert that no batched jobs were dispatched. * * @return void */ public function assertNothingBatched() { PHPUnit::assertEmpty($this->batches, 'Batched jobs were dispatched unexpectedly.'); } /** * Get all of the jobs matching a truth-test callback. * * @param string $command * @param callable|null $callback * @return \Illuminate\Support\Collection */ public function dispatched($command, $callback = null) { if (! $this->hasDispatched($command)) { return collect(); } $callback = $callback ?: fn () => true; return collect($this->commands[$command])->filter(fn ($command) => $callback($command)); } /** * Get all of the jobs dispatched synchronously matching a truth-test callback. * * @param string $command * @param callable|null $callback * @return \Illuminate\Support\Collection */ public function dispatchedSync(string $command, $callback = null) { if (! $this->hasDispatchedSync($command)) { return collect(); } $callback = $callback ?: fn () => true; return collect($this->commandsSync[$command])->filter(fn ($command) => $callback($command)); } /** * Get all of the jobs dispatched after the response was sent matching a truth-test callback. * * @param string $command * @param callable|null $callback * @return \Illuminate\Support\Collection */ public function dispatchedAfterResponse(string $command, $callback = null) { if (! $this->hasDispatchedAfterResponse($command)) { return collect(); } $callback = $callback ?: fn () => true; return collect($this->commandsAfterResponse[$command])->filter(fn ($command) => $callback($command)); } /** * Get all of the pending batches matching a truth-test callback. * * @param callable $callback * @return \Illuminate\Support\Collection */ public function batched(callable $callback) { if (empty($this->batches)) { return collect(); } return collect($this->batches)->filter(fn ($batch) => $callback($batch)); } /** * Determine if there are any stored commands for a given class. * * @param string $command * @return bool */ public function hasDispatched($command) { return isset($this->commands[$command]) && ! empty($this->commands[$command]); } /** * Determine if there are any stored commands for a given class. * * @param string $command * @return bool */ public function hasDispatchedSync($command) { return isset($this->commandsSync[$command]) && ! empty($this->commandsSync[$command]); } /** * Determine if there are any stored commands for a given class. * * @param string $command * @return bool */ public function hasDispatchedAfterResponse($command) { return isset($this->commandsAfterResponse[$command]) && ! empty($this->commandsAfterResponse[$command]); } /** * Dispatch a command to its appropriate handler. * * @param mixed $command * @return mixed */ public function dispatch($command) { if ($this->shouldFakeJob($command)) { $this->commands[get_class($command)][] = $command; } else { return $this->dispatcher->dispatch($command); } } /** * Dispatch a command to its appropriate handler in the current process. * * Queueable jobs will be dispatched to the "sync" queue. * * @param mixed $command * @param mixed $handler * @return mixed */ public function dispatchSync($command, $handler = null) { if ($this->shouldFakeJob($command)) { $this->commandsSync[get_class($command)][] = $command; } else { return $this->dispatcher->dispatchSync($command, $handler); } } /** * Dispatch a command to its appropriate handler in the current process. * * @param mixed $command * @param mixed $handler * @return mixed */ public function dispatchNow($command, $handler = null) { if ($this->shouldFakeJob($command)) { $this->commands[get_class($command)][] = $command; } else { return $this->dispatcher->dispatchNow($command, $handler); } } /** * Dispatch a command to its appropriate handler behind a queue. * * @param mixed $command * @return mixed */ public function dispatchToQueue($command) { if ($this->shouldFakeJob($command)) { $this->commands[get_class($command)][] = $command; } else { return $this->dispatcher->dispatchToQueue($command); } } /** * Dispatch a command to its appropriate handler. * * @param mixed $command * @return mixed */ public function dispatchAfterResponse($command) { if ($this->shouldFakeJob($command)) { $this->commandsAfterResponse[get_class($command)][] = $command; } else { return $this->dispatcher->dispatch($command); } } /** * Create a new chain of queueable jobs. * * @param \Illuminate\Support\Collection|array $jobs * @return \Illuminate\Foundation\Bus\PendingChain */ public function chain($jobs) { $jobs = Collection::wrap($jobs); return new PendingChainFake($this, $jobs->shift(), $jobs->toArray()); } /** * Attempt to find the batch with the given ID. * * @param string $batchId * @return \Illuminate\Bus\Batch|null */ public function findBatch(string $batchId) { return $this->batchRepository->find($batchId); } /** * Create a new batch of queueable jobs. * * @param \Illuminate\Support\Collection|array $jobs * @return \Illuminate\Bus\PendingBatch */ public function batch($jobs) { return new PendingBatchFake($this, Collection::wrap($jobs)); } /** * Dispatch an empty job batch for testing. * * @param string $name * @return \Illuminate\Bus\Batch */ public function dispatchFakeBatch($name = '') { return $this->batch([])->name($name)->dispatch(); } /** * Record the fake pending batch dispatch. * * @param \Illuminate\Bus\PendingBatch $pendingBatch * @return \Illuminate\Bus\Batch */ public function recordPendingBatch(PendingBatch $pendingBatch) { $this->batches[] = $pendingBatch; return $this->batchRepository->store($pendingBatch); } /** * Determine if a command should be faked or actually dispatched. * * @param mixed $command * @return bool */ protected function shouldFakeJob($command) { if ($this->shouldDispatchCommand($command)) { return false; } if (empty($this->jobsToFake)) { return true; } return collect($this->jobsToFake) ->filter(function ($job) use ($command) { return $job instanceof Closure ? $job($command) : $job === get_class($command); })->isNotEmpty(); } /** * Determine if a command should be dispatched or not. * * @param mixed $command * @return bool */ protected function shouldDispatchCommand($command) { return collect($this->jobsToDispatch) ->filter(function ($job) use ($command) { return $job instanceof Closure ? $job($command) : $job === get_class($command); })->isNotEmpty(); } /** * Set the pipes commands should be piped through before dispatching. * * @param array $pipes * @return $this */ public function pipeThrough(array $pipes) { $this->dispatcher->pipeThrough($pipes); return $this; } /** * Determine if the given command has a handler. * * @param mixed $command * @return bool */ public function hasCommandHandler($command) { return $this->dispatcher->hasCommandHandler($command); } /** * Retrieve the handler for a command. * * @param mixed $command * @return mixed */ public function getCommandHandler($command) { return $this->dispatcher->getCommandHandler($command); } /** * Map a command to a handler. * * @param array $map * @return $this */ public function map(array $map) { $this->dispatcher->map($map); return $this; } } PKy ZN.Illuminate/Support/Testing/Fakes/BatchFake.phpnuW+Aid = $id; $this->name = $name; $this->totalJobs = $totalJobs; $this->pendingJobs = $pendingJobs; $this->failedJobs = $failedJobs; $this->failedJobIds = $failedJobIds; $this->options = $options; $this->createdAt = $createdAt; $this->cancelledAt = $cancelledAt; $this->finishedAt = $finishedAt; } /** * Get a fresh instance of the batch represented by this ID. * * @return self */ public function fresh() { return $this; } /** * Add additional jobs to the batch. * * @param \Illuminate\Support\Enumerable|object|array $jobs * @return self */ public function add($jobs) { foreach ($jobs as $job) { $this->added[] = $job; } return $this; } /** * Record that a job within the batch finished successfully, executing any callbacks if necessary. * * @param string $jobId * @return void */ public function recordSuccessfulJob(string $jobId) { // } /** * Decrement the pending jobs for the batch. * * @param string $jobId * @return \Illuminate\Bus\UpdatedBatchJobCounts */ public function decrementPendingJobs(string $jobId) { // } /** * Record that a job within the batch failed to finish successfully, executing any callbacks if necessary. * * @param string $jobId * @param \Throwable $e * @return void */ public function recordFailedJob(string $jobId, $e) { // } /** * Increment the failed jobs for the batch. * * @param string $jobId * @return \Illuminate\Bus\UpdatedBatchJobCounts */ public function incrementFailedJobs(string $jobId) { return new UpdatedBatchJobCounts; } /** * Cancel the batch. * * @return void */ public function cancel() { $this->cancelledAt = Carbon::now(); } /** * Delete the batch from storage. * * @return void */ public function delete() { $this->deleted = true; } /** * Determine if the batch has been deleted. * * @return bool */ public function deleted() { return $this->deleted; } } PKy Z i4Illuminate/Support/Testing/Fakes/PendingMailFake.phpnuW+Amailer = $mailer; } /** * Send a new mailable message instance. * * @param \Illuminate\Contracts\Mail\Mailable $mailable * @return void */ public function send(Mailable $mailable) { $this->mailer->send($this->fill($mailable)); } /** * Push the given mailable onto the queue. * * @param \Illuminate\Contracts\Mail\Mailable $mailable * @return mixed */ public function queue(Mailable $mailable) { return $this->mailer->queue($this->fill($mailable)); } } PKy Z 35Illuminate/Support/Testing/Fakes/PendingChainFake.phpnuW+Abus = $bus; $this->job = $job; $this->chain = $chain; } /** * Dispatch the job with the given arguments. * * @return \Illuminate\Foundation\Bus\PendingDispatch */ public function dispatch() { if (is_string($this->job)) { $firstJob = new $this->job(...func_get_args()); } elseif ($this->job instanceof Closure) { $firstJob = CallQueuedClosure::create($this->job); } else { $firstJob = $this->job; } $firstJob->allOnConnection($this->connection); $firstJob->allOnQueue($this->queue); $firstJob->chain($this->chain); $firstJob->delay($this->delay); $firstJob->chainCatchCallbacks = $this->catchCallbacks(); return $this->bus->dispatch($firstJob); } } PKy ZmΚ^ ' '.Illuminate/Support/Testing/Fakes/EventFake.phpnuW+Adispatcher = $dispatcher; $this->eventsToFake = Arr::wrap($eventsToFake); } /** * Specify the events that should be dispatched instead of faked. * * @param array|string $eventsToDispatch * @return $this */ public function except($eventsToDispatch) { $this->eventsToDispatch = array_merge( $this->eventsToDispatch, Arr::wrap($eventsToDispatch) ); return $this; } /** * Assert if an event has a listener attached to it. * * @param string $expectedEvent * @param string|array $expectedListener * @return void */ public function assertListening($expectedEvent, $expectedListener) { foreach ($this->dispatcher->getListeners($expectedEvent) as $listenerClosure) { $actualListener = (new ReflectionFunction($listenerClosure)) ->getStaticVariables()['listener']; $normalizedListener = $expectedListener; if (is_string($actualListener) && Str::contains($actualListener, '@')) { $actualListener = Str::parseCallback($actualListener); if (is_string($expectedListener)) { if (Str::contains($expectedListener, '@')) { $normalizedListener = Str::parseCallback($expectedListener); } else { $normalizedListener = [ $expectedListener, method_exists($expectedListener, 'handle') ? 'handle' : '__invoke', ]; } } } if ($actualListener === $normalizedListener || ($actualListener instanceof Closure && $normalizedListener === Closure::class)) { PHPUnit::assertTrue(true); return; } } PHPUnit::assertTrue( false, sprintf( 'Event [%s] does not have the [%s] listener attached to it', $expectedEvent, print_r($expectedListener, true) ) ); } /** * Assert if an event was dispatched based on a truth-test callback. * * @param string|\Closure $event * @param callable|int|null $callback * @return void */ public function assertDispatched($event, $callback = null) { if ($event instanceof Closure) { [$event, $callback] = [$this->firstClosureParameterType($event), $event]; } if (is_int($callback)) { return $this->assertDispatchedTimes($event, $callback); } PHPUnit::assertTrue( $this->dispatched($event, $callback)->count() > 0, "The expected [{$event}] event was not dispatched." ); } /** * Assert if an event was dispatched a number of times. * * @param string $event * @param int $times * @return void */ public function assertDispatchedTimes($event, $times = 1) { $count = $this->dispatched($event)->count(); PHPUnit::assertSame( $times, $count, "The expected [{$event}] event was dispatched {$count} times instead of {$times} times." ); } /** * Determine if an event was dispatched based on a truth-test callback. * * @param string|\Closure $event * @param callable|null $callback * @return void */ public function assertNotDispatched($event, $callback = null) { if ($event instanceof Closure) { [$event, $callback] = [$this->firstClosureParameterType($event), $event]; } PHPUnit::assertCount( 0, $this->dispatched($event, $callback), "The unexpected [{$event}] event was dispatched." ); } /** * Assert that no events were dispatched. * * @return void */ public function assertNothingDispatched() { $count = count(Arr::flatten($this->events)); PHPUnit::assertSame( 0, $count, "{$count} unexpected events were dispatched." ); } /** * Get all of the events matching a truth-test callback. * * @param string $event * @param callable|null $callback * @return \Illuminate\Support\Collection */ public function dispatched($event, $callback = null) { if (! $this->hasDispatched($event)) { return collect(); } $callback = $callback ?: fn () => true; return collect($this->events[$event])->filter( fn ($arguments) => $callback(...$arguments) ); } /** * Determine if the given event has been dispatched. * * @param string $event * @return bool */ public function hasDispatched($event) { return isset($this->events[$event]) && ! empty($this->events[$event]); } /** * Register an event listener with the dispatcher. * * @param \Closure|string|array $events * @param mixed $listener * @return void */ public function listen($events, $listener = null) { $this->dispatcher->listen($events, $listener); } /** * Determine if a given event has listeners. * * @param string $eventName * @return bool */ public function hasListeners($eventName) { return $this->dispatcher->hasListeners($eventName); } /** * Register an event and payload to be dispatched later. * * @param string $event * @param array $payload * @return void */ public function push($event, $payload = []) { // } /** * Register an event subscriber with the dispatcher. * * @param object|string $subscriber * @return void */ public function subscribe($subscriber) { $this->dispatcher->subscribe($subscriber); } /** * Flush a set of pushed events. * * @param string $event * @return void */ public function flush($event) { // } /** * Fire an event and call the listeners. * * @param string|object $event * @param mixed $payload * @param bool $halt * @return array|null */ public function dispatch($event, $payload = [], $halt = false) { $name = is_object($event) ? get_class($event) : (string) $event; if ($this->shouldFakeEvent($name, $payload)) { $this->events[$name][] = func_get_args(); } else { return $this->dispatcher->dispatch($event, $payload, $halt); } } /** * Determine if an event should be faked or actually dispatched. * * @param string $eventName * @param mixed $payload * @return bool */ protected function shouldFakeEvent($eventName, $payload) { if ($this->shouldDispatchEvent($eventName, $payload)) { return false; } if (empty($this->eventsToFake)) { return true; } return collect($this->eventsToFake) ->filter(function ($event) use ($eventName, $payload) { return $event instanceof Closure ? $event($eventName, $payload) : $event === $eventName; }) ->isNotEmpty(); } /** * Determine whether an event should be dispatched or not. * * @param string $eventName * @param mixed $payload * @return bool */ protected function shouldDispatchEvent($eventName, $payload) { if (empty($this->eventsToDispatch)) { return false; } return collect($this->eventsToDispatch) ->filter(function ($event) use ($eventName, $payload) { return $event instanceof Closure ? $event($eventName, $payload) : $event === $eventName; }) ->isNotEmpty(); } /** * Remove a set of listeners from the dispatcher. * * @param string $event * @return void */ public function forget($event) { // } /** * Forget all of the queued listeners. * * @return void */ public function forgetPushed() { // } /** * Dispatch an event and call the listeners. * * @param string|object $event * @param mixed $payload * @return array|null */ public function until($event, $payload = []) { return $this->dispatch($event, $payload, true); } } PKy Z˵ **5Illuminate/Support/Testing/Fakes/NotificationFake.phpnuW+AassertSentTo(new AnonymousNotifiable, $notification, $callback); } /** * Assert if a notification was sent based on a truth-test callback. * * @param mixed $notifiable * @param string|\Closure $notification * @param callable|null $callback * @return void * * @throws \Exception */ public function assertSentTo($notifiable, $notification, $callback = null) { if (is_array($notifiable) || $notifiable instanceof Collection) { if (count($notifiable) === 0) { throw new Exception('No notifiable given.'); } foreach ($notifiable as $singleNotifiable) { $this->assertSentTo($singleNotifiable, $notification, $callback); } return; } if ($notification instanceof Closure) { [$notification, $callback] = [$this->firstClosureParameterType($notification), $notification]; } if (is_numeric($callback)) { return $this->assertSentToTimes($notifiable, $notification, $callback); } PHPUnit::assertTrue( $this->sent($notifiable, $notification, $callback)->count() > 0, "The expected [{$notification}] notification was not sent." ); } /** * Assert if a notification was sent on-demand a number of times. * * @param string $notification * @param int $times * @return void */ public function assertSentOnDemandTimes($notification, $times = 1) { return $this->assertSentToTimes(new AnonymousNotifiable, $notification, $times); } /** * Assert if a notification was sent a number of times. * * @param mixed $notifiable * @param string $notification * @param int $times * @return void */ public function assertSentToTimes($notifiable, $notification, $times = 1) { $count = $this->sent($notifiable, $notification)->count(); PHPUnit::assertSame( $times, $count, "Expected [{$notification}] to be sent {$times} times, but was sent {$count} times." ); } /** * Determine if a notification was sent based on a truth-test callback. * * @param mixed $notifiable * @param string|\Closure $notification * @param callable|null $callback * @return void * * @throws \Exception */ public function assertNotSentTo($notifiable, $notification, $callback = null) { if (is_array($notifiable) || $notifiable instanceof Collection) { if (count($notifiable) === 0) { throw new Exception('No notifiable given.'); } foreach ($notifiable as $singleNotifiable) { $this->assertNotSentTo($singleNotifiable, $notification, $callback); } return; } if ($notification instanceof Closure) { [$notification, $callback] = [$this->firstClosureParameterType($notification), $notification]; } PHPUnit::assertCount( 0, $this->sent($notifiable, $notification, $callback), "The unexpected [{$notification}] notification was sent." ); } /** * Assert that no notifications were sent. * * @return void */ public function assertNothingSent() { PHPUnit::assertEmpty($this->notifications, 'Notifications were sent unexpectedly.'); } /** * Assert that no notifications were sent to the given notifiable. * * @param mixed $notifiable * @return void * * @throws \Exception */ public function assertNothingSentTo($notifiable) { if (is_array($notifiable) || $notifiable instanceof Collection) { if (count($notifiable) === 0) { throw new Exception('No notifiable given.'); } foreach ($notifiable as $singleNotifiable) { $this->assertNothingSentTo($singleNotifiable); } return; } PHPUnit::assertEmpty( $this->notifications[get_class($notifiable)][$notifiable->getKey()] ?? [], 'Notifications were sent unexpectedly.', ); } /** * Assert the total amount of times a notification was sent. * * @param string $notification * @param int $expectedCount * @return void */ public function assertSentTimes($notification, $expectedCount) { $actualCount = collect($this->notifications) ->flatten(1) ->reduce(fn ($count, $sent) => $count + count($sent[$notification] ?? []), 0); PHPUnit::assertSame( $expectedCount, $actualCount, "Expected [{$notification}] to be sent {$expectedCount} times, but was sent {$actualCount} times." ); } /** * Assert the total count of notification that were sent. * * @param int $expectedCount * @return void */ public function assertCount($expectedCount) { $actualCount = collect($this->notifications)->flatten(3)->count(); PHPUnit::assertSame( $expectedCount, $actualCount, "Expected {$expectedCount} notifications to be sent, but {$actualCount} were sent." ); } /** * Assert the total amount of times a notification was sent. * * @param int $expectedCount * @param string $notification * @return void * * @deprecated Use the assertSentTimes method instead */ public function assertTimesSent($expectedCount, $notification) { $this->assertSentTimes($notification, $expectedCount); } /** * Get all of the notifications matching a truth-test callback. * * @param mixed $notifiable * @param string $notification * @param callable|null $callback * @return \Illuminate\Support\Collection */ public function sent($notifiable, $notification, $callback = null) { if (! $this->hasSent($notifiable, $notification)) { return collect(); } $callback = $callback ?: fn () => true; $notifications = collect($this->notificationsFor($notifiable, $notification)); return $notifications->filter( fn ($arguments) => $callback(...array_values($arguments)) )->pluck('notification'); } /** * Determine if there are more notifications left to inspect. * * @param mixed $notifiable * @param string $notification * @return bool */ public function hasSent($notifiable, $notification) { return ! empty($this->notificationsFor($notifiable, $notification)); } /** * Get all of the notifications for a notifiable entity by type. * * @param mixed $notifiable * @param string $notification * @return array */ protected function notificationsFor($notifiable, $notification) { return $this->notifications[get_class($notifiable)][$notifiable->getKey()][$notification] ?? []; } /** * Send the given notification to the given notifiable entities. * * @param \Illuminate\Support\Collection|array|mixed $notifiables * @param mixed $notification * @return void */ public function send($notifiables, $notification) { $this->sendNow($notifiables, $notification); } /** * Send the given notification immediately. * * @param \Illuminate\Support\Collection|array|mixed $notifiables * @param mixed $notification * @param array|null $channels * @return void */ public function sendNow($notifiables, $notification, array $channels = null) { if (! $notifiables instanceof Collection && ! is_array($notifiables)) { $notifiables = [$notifiables]; } foreach ($notifiables as $notifiable) { if (! $notification->id) { $notification->id = Str::uuid()->toString(); } $notifiableChannels = $channels ?: $notification->via($notifiable); if (method_exists($notification, 'shouldSend')) { $notifiableChannels = array_filter( $notifiableChannels, fn ($channel) => $notification->shouldSend($notifiable, $channel) !== false ); if (empty($notifiableChannels)) { continue; } } $this->notifications[get_class($notifiable)][$notifiable->getKey()][get_class($notification)][] = [ 'notification' => $notification, 'channels' => $notifiableChannels, 'notifiable' => $notifiable, 'locale' => $notification->locale ?? $this->locale ?? value(function () use ($notifiable) { if ($notifiable instanceof HasLocalePreference) { return $notifiable->preferredLocale(); } }), ]; } } /** * Get a channel instance by name. * * @param string|null $name * @return mixed */ public function channel($name = null) { // } /** * Set the locale of notifications. * * @param string $locale * @return $this */ public function locale($locale) { $this->locale = $locale; return $this; } /** * Get the notifications that have been sent. * * @return array */ public function sentNotifications() { return $this->notifications; } } PKy Z|g 8Illuminate/Support/Testing/Fakes/BatchRepositoryFake.phpnuW+Abatches; } /** * Retrieve information about an existing batch. * * @param string $batchId * @return \Illuminate\Bus\Batch|null */ public function find(string $batchId) { return $this->batches[$batchId] ?? null; } /** * Store a new pending batch. * * @param \Illuminate\Bus\PendingBatch $batch * @return \Illuminate\Bus\Batch */ public function store(PendingBatch $batch) { $id = (string) Str::orderedUuid(); $this->batches[$id] = new BatchFake( $id, $batch->name, count($batch->jobs), count($batch->jobs), 0, [], $batch->options, CarbonImmutable::now(), null, null ); return $this->batches[$id]; } /** * Increment the total number of jobs within the batch. * * @param string $batchId * @param int $amount * @return void */ public function incrementTotalJobs(string $batchId, int $amount) { // } /** * Decrement the total number of pending jobs for the batch. * * @param string $batchId * @param string $jobId * @return \Illuminate\Bus\UpdatedBatchJobCounts */ public function decrementPendingJobs(string $batchId, string $jobId) { return new UpdatedBatchJobCounts; } /** * Increment the total number of failed jobs for the batch. * * @param string $batchId * @param string $jobId * @return \Illuminate\Bus\UpdatedBatchJobCounts */ public function incrementFailedJobs(string $batchId, string $jobId) { return new UpdatedBatchJobCounts; } /** * Mark the batch that has the given ID as finished. * * @param string $batchId * @return void */ public function markAsFinished(string $batchId) { if (isset($this->batches[$batchId])) { $this->batches[$batchId]->finishedAt = now(); } } /** * Cancel the batch that has the given ID. * * @param string $batchId * @return void */ public function cancel(string $batchId) { if (isset($this->batches[$batchId])) { $this->batches[$batchId]->cancel(); } } /** * Delete the batch that has the given ID. * * @param string $batchId * @return void */ public function delete(string $batchId) { unset($this->batches[$batchId]); } /** * Execute the given Closure within a storage specific transaction. * * @param \Closure $callback * @return mixed */ public function transaction(Closure $callback) { return $callback(); } } PKy Z7373.Illuminate/Support/Testing/Fakes/QueueFake.phpnuW+AjobsToFake = Collection::wrap($jobsToFake); $this->jobsToBeQueued = Collection::make(); $this->queue = $queue; } /** * Specify the jobs that should be queued instead of faked. * * @param array|string $jobsToBeQueued * @return $this */ public function except($jobsToBeQueued) { $this->jobsToBeQueued = Collection::wrap($jobsToBeQueued)->merge($this->jobsToBeQueued); return $this; } /** * Assert if a job was pushed based on a truth-test callback. * * @param string|\Closure $job * @param callable|int|null $callback * @return void */ public function assertPushed($job, $callback = null) { if ($job instanceof Closure) { [$job, $callback] = [$this->firstClosureParameterType($job), $job]; } if (is_numeric($callback)) { return $this->assertPushedTimes($job, $callback); } PHPUnit::assertTrue( $this->pushed($job, $callback)->count() > 0, "The expected [{$job}] job was not pushed." ); } /** * Assert if a job was pushed a number of times. * * @param string $job * @param int $times * @return void */ protected function assertPushedTimes($job, $times = 1) { $count = $this->pushed($job)->count(); PHPUnit::assertSame( $times, $count, "The expected [{$job}] job was pushed {$count} times instead of {$times} times." ); } /** * Assert if a job was pushed based on a truth-test callback. * * @param string $queue * @param string|\Closure $job * @param callable|null $callback * @return void */ public function assertPushedOn($queue, $job, $callback = null) { if ($job instanceof Closure) { [$job, $callback] = [$this->firstClosureParameterType($job), $job]; } $this->assertPushed($job, function ($job, $pushedQueue) use ($callback, $queue) { if ($pushedQueue !== $queue) { return false; } return $callback ? $callback(...func_get_args()) : true; }); } /** * Assert if a job was pushed with chained jobs based on a truth-test callback. * * @param string $job * @param array $expectedChain * @param callable|null $callback * @return void */ public function assertPushedWithChain($job, $expectedChain = [], $callback = null) { PHPUnit::assertTrue( $this->pushed($job, $callback)->isNotEmpty(), "The expected [{$job}] job was not pushed." ); PHPUnit::assertTrue( collect($expectedChain)->isNotEmpty(), 'The expected chain can not be empty.' ); $this->isChainOfObjects($expectedChain) ? $this->assertPushedWithChainOfObjects($job, $expectedChain, $callback) : $this->assertPushedWithChainOfClasses($job, $expectedChain, $callback); } /** * Assert if a job was pushed with an empty chain based on a truth-test callback. * * @param string $job * @param callable|null $callback * @return void */ public function assertPushedWithoutChain($job, $callback = null) { PHPUnit::assertTrue( $this->pushed($job, $callback)->isNotEmpty(), "The expected [{$job}] job was not pushed." ); $this->assertPushedWithChainOfClasses($job, [], $callback); } /** * Assert if a job was pushed with chained jobs based on a truth-test callback. * * @param string $job * @param array $expectedChain * @param callable|null $callback * @return void */ protected function assertPushedWithChainOfObjects($job, $expectedChain, $callback) { $chain = collect($expectedChain)->map(fn ($job) => serialize($job))->all(); PHPUnit::assertTrue( $this->pushed($job, $callback)->filter(fn ($job) => $job->chained == $chain)->isNotEmpty(), 'The expected chain was not pushed.' ); } /** * Assert if a job was pushed with chained jobs based on a truth-test callback. * * @param string $job * @param array $expectedChain * @param callable|null $callback * @return void */ protected function assertPushedWithChainOfClasses($job, $expectedChain, $callback) { $matching = $this->pushed($job, $callback)->map->chained->map(function ($chain) { return collect($chain)->map(function ($job) { return get_class(unserialize($job)); }); })->filter(function ($chain) use ($expectedChain) { return $chain->all() === $expectedChain; }); PHPUnit::assertTrue( $matching->isNotEmpty(), 'The expected chain was not pushed.' ); } /** * Determine if the given chain is entirely composed of objects. * * @param array $chain * @return bool */ protected function isChainOfObjects($chain) { return ! collect($chain)->contains(fn ($job) => ! is_object($job)); } /** * Determine if a job was pushed based on a truth-test callback. * * @param string|\Closure $job * @param callable|null $callback * @return void */ public function assertNotPushed($job, $callback = null) { if ($job instanceof Closure) { [$job, $callback] = [$this->firstClosureParameterType($job), $job]; } PHPUnit::assertCount( 0, $this->pushed($job, $callback), "The unexpected [{$job}] job was pushed." ); } /** * Assert that no jobs were pushed. * * @return void */ public function assertNothingPushed() { PHPUnit::assertEmpty($this->jobs, 'Jobs were pushed unexpectedly.'); } /** * Get all of the jobs matching a truth-test callback. * * @param string $job * @param callable|null $callback * @return \Illuminate\Support\Collection */ public function pushed($job, $callback = null) { if (! $this->hasPushed($job)) { return collect(); } $callback = $callback ?: fn () => true; return collect($this->jobs[$job])->filter( fn ($data) => $callback($data['job'], $data['queue'], $data['data']) )->pluck('job'); } /** * Determine if there are any stored jobs for a given class. * * @param string $job * @return bool */ public function hasPushed($job) { return isset($this->jobs[$job]) && ! empty($this->jobs[$job]); } /** * Resolve a queue connection instance. * * @param mixed $value * @return \Illuminate\Contracts\Queue\Queue */ public function connection($value = null) { return $this; } /** * Get the size of the queue. * * @param string|null $queue * @return int */ public function size($queue = null) { return collect($this->jobs)->flatten(1)->filter( fn ($job) => $job['queue'] === $queue )->count(); } /** * Push a new job onto the queue. * * @param string|object $job * @param mixed $data * @param string|null $queue * @return mixed */ public function push($job, $data = '', $queue = null) { if ($this->shouldFakeJob($job)) { $this->jobs[is_object($job) ? get_class($job) : $job][] = [ 'job' => $job, 'queue' => $queue, 'data' => $data, ]; } else { is_object($job) && isset($job->connection) ? $this->queue->connection($job->connection)->push($job, $data, $queue) : $this->queue->push($job, $data, $queue); } } /** * Determine if a job should be faked or actually dispatched. * * @param object $job * @return bool */ public function shouldFakeJob($job) { if ($this->shouldDispatchJob($job)) { return false; } if ($this->jobsToFake->isEmpty()) { return true; } return $this->jobsToFake->contains( fn ($jobToFake) => $job instanceof ((string) $jobToFake) ); } /** * Determine if a job should be pushed to the queue instead of faked. * * @param object $job * @return bool */ protected function shouldDispatchJob($job) { if ($this->jobsToBeQueued->isEmpty()) { return false; } return $this->jobsToBeQueued->contains( fn ($jobToQueue) => $job instanceof ((string) $jobToQueue) ); } /** * Push a raw payload onto the queue. * * @param string $payload * @param string|null $queue * @param array $options * @return mixed */ public function pushRaw($payload, $queue = null, array $options = []) { // } /** * Push a new job onto the queue after (n) seconds. * * @param \DateTimeInterface|\DateInterval|int $delay * @param string|object $job * @param mixed $data * @param string|null $queue * @return mixed */ public function later($delay, $job, $data = '', $queue = null) { return $this->push($job, $data, $queue); } /** * Push a new job onto the queue. * * @param string $queue * @param string|object $job * @param mixed $data * @return mixed */ public function pushOn($queue, $job, $data = '') { return $this->push($job, $data, $queue); } /** * Push a new job onto a specific queue after (n) seconds. * * @param string $queue * @param \DateTimeInterface|\DateInterval|int $delay * @param string|object $job * @param mixed $data * @return mixed */ public function laterOn($queue, $delay, $job, $data = '') { return $this->push($job, $data, $queue); } /** * Pop the next job off of the queue. * * @param string|null $queue * @return \Illuminate\Contracts\Queue\Job|null */ public function pop($queue = null) { // } /** * Push an array of jobs onto the queue. * * @param array $jobs * @param mixed $data * @param string|null $queue * @return mixed */ public function bulk($jobs, $data = '', $queue = null) { foreach ($jobs as $job) { $this->push($job, $data, $queue); } } /** * Get the jobs that have been pushed. * * @return array */ public function pushedJobs() { return $this->jobs; } /** * Get the connection name for the queue. * * @return string */ public function getConnectionName() { // } /** * Set the connection name for the queue. * * @param string $name * @return $this */ public function setConnectionName($name) { return $this; } /** * Override the QueueManager to prevent circular dependency. * * @param string $method * @param array $parameters * @return mixed * * @throws \BadMethodCallException */ public function __call($method, $parameters) { throw new BadMethodCallException(sprintf( 'Call to undefined method %s::%s()', static::class, $method )); } } PKy Z!!5Illuminate/Support/Testing/Fakes/PendingBatchFake.phpnuW+Abus = $bus; $this->jobs = $jobs; } /** * Dispatch the batch. * * @return \Illuminate\Bus\Batch */ public function dispatch() { return $this->bus->recordPendingBatch($this); } /** * Dispatch the batch after the response is sent to the browser. * * @return \Illuminate\Bus\Batch */ public function dispatchAfterResponse() { return $this->bus->recordPendingBatch($this); } } PKy Z/?%-%--Illuminate/Support/Testing/Fakes/MailFake.phpnuW+AprepareMailableAndCallback($mailable, $callback); if (is_numeric($callback)) { return $this->assertSentTimes($mailable, $callback); } $message = "The expected [{$mailable}] mailable was not sent."; if (count($this->queuedMailables) > 0) { $message .= ' Did you mean to use assertQueued() instead?'; } PHPUnit::assertTrue( $this->sent($mailable, $callback)->count() > 0, $message ); } /** * Assert if a mailable was sent a number of times. * * @param string $mailable * @param int $times * @return void */ protected function assertSentTimes($mailable, $times = 1) { $count = $this->sent($mailable)->count(); PHPUnit::assertSame( $times, $count, "The expected [{$mailable}] mailable was sent {$count} times instead of {$times} times." ); } /** * Determine if a mailable was not sent or queued to be sent based on a truth-test callback. * * @param string|\Closure $mailable * @param callable|null $callback * @return void */ public function assertNotOutgoing($mailable, $callback = null) { $this->assertNotSent($mailable, $callback); $this->assertNotQueued($mailable, $callback); } /** * Determine if a mailable was not sent based on a truth-test callback. * * @param string|\Closure $mailable * @param callable|null $callback * @return void */ public function assertNotSent($mailable, $callback = null) { [$mailable, $callback] = $this->prepareMailableAndCallback($mailable, $callback); PHPUnit::assertCount( 0, $this->sent($mailable, $callback), "The unexpected [{$mailable}] mailable was sent." ); } /** * Assert that no mailables were sent or queued to be sent. * * @return void */ public function assertNothingOutgoing() { $this->assertNothingSent(); $this->assertNothingQueued(); } /** * Assert that no mailables were sent. * * @return void */ public function assertNothingSent() { $mailableNames = collect($this->mailables)->map( fn ($mailable) => get_class($mailable) )->join(', '); PHPUnit::assertEmpty($this->mailables, 'The following mailables were sent unexpectedly: '.$mailableNames); } /** * Assert if a mailable was queued based on a truth-test callback. * * @param string|\Closure $mailable * @param callable|int|null $callback * @return void */ public function assertQueued($mailable, $callback = null) { [$mailable, $callback] = $this->prepareMailableAndCallback($mailable, $callback); if (is_numeric($callback)) { return $this->assertQueuedTimes($mailable, $callback); } PHPUnit::assertTrue( $this->queued($mailable, $callback)->count() > 0, "The expected [{$mailable}] mailable was not queued." ); } /** * Assert if a mailable was queued a number of times. * * @param string $mailable * @param int $times * @return void */ protected function assertQueuedTimes($mailable, $times = 1) { $count = $this->queued($mailable)->count(); PHPUnit::assertSame( $times, $count, "The expected [{$mailable}] mailable was queued {$count} times instead of {$times} times." ); } /** * Determine if a mailable was not queued based on a truth-test callback. * * @param string|\Closure $mailable * @param callable|null $callback * @return void */ public function assertNotQueued($mailable, $callback = null) { [$mailable, $callback] = $this->prepareMailableAndCallback($mailable, $callback); PHPUnit::assertCount( 0, $this->queued($mailable, $callback), "The unexpected [{$mailable}] mailable was queued." ); } /** * Assert that no mailables were queued. * * @return void */ public function assertNothingQueued() { $mailableNames = collect($this->queuedMailables)->map( fn ($mailable) => get_class($mailable) )->join(', '); PHPUnit::assertEmpty($this->queuedMailables, 'The following mailables were queued unexpectedly: '.$mailableNames); } /** * Get all of the mailables matching a truth-test callback. * * @param string|\Closure $mailable * @param callable|null $callback * @return \Illuminate\Support\Collection */ public function sent($mailable, $callback = null) { [$mailable, $callback] = $this->prepareMailableAndCallback($mailable, $callback); if (! $this->hasSent($mailable)) { return collect(); } $callback = $callback ?: fn () => true; return $this->mailablesOf($mailable)->filter(fn ($mailable) => $callback($mailable)); } /** * Determine if the given mailable has been sent. * * @param string $mailable * @return bool */ public function hasSent($mailable) { return $this->mailablesOf($mailable)->count() > 0; } /** * Get all of the queued mailables matching a truth-test callback. * * @param string|\Closure $mailable * @param callable|null $callback * @return \Illuminate\Support\Collection */ public function queued($mailable, $callback = null) { [$mailable, $callback] = $this->prepareMailableAndCallback($mailable, $callback); if (! $this->hasQueued($mailable)) { return collect(); } $callback = $callback ?: fn () => true; return $this->queuedMailablesOf($mailable)->filter(fn ($mailable) => $callback($mailable)); } /** * Determine if the given mailable has been queued. * * @param string $mailable * @return bool */ public function hasQueued($mailable) { return $this->queuedMailablesOf($mailable)->count() > 0; } /** * Get all of the mailed mailables for a given type. * * @param string $type * @return \Illuminate\Support\Collection */ protected function mailablesOf($type) { return collect($this->mailables)->filter(fn ($mailable) => $mailable instanceof $type); } /** * Get all of the mailed mailables for a given type. * * @param string $type * @return \Illuminate\Support\Collection */ protected function queuedMailablesOf($type) { return collect($this->queuedMailables)->filter(fn ($mailable) => $mailable instanceof $type); } /** * Get a mailer instance by name. * * @param string|null $name * @return \Illuminate\Contracts\Mail\Mailer */ public function mailer($name = null) { $this->currentMailer = $name; return $this; } /** * Begin the process of mailing a mailable class instance. * * @param mixed $users * @return \Illuminate\Mail\PendingMail */ public function to($users) { return (new PendingMailFake($this))->to($users); } /** * Begin the process of mailing a mailable class instance. * * @param mixed $users * @return \Illuminate\Mail\PendingMail */ public function cc($users) { return (new PendingMailFake($this))->cc($users); } /** * Begin the process of mailing a mailable class instance. * * @param mixed $users * @return \Illuminate\Mail\PendingMail */ public function bcc($users) { return (new PendingMailFake($this))->bcc($users); } /** * Send a new message with only a raw text part. * * @param string $text * @param \Closure|string $callback * @return void */ public function raw($text, $callback) { // } /** * Send a new message using a view. * * @param \Illuminate\Contracts\Mail\Mailable|string|array $view * @param array $data * @param \Closure|string|null $callback * @return void */ public function send($view, array $data = [], $callback = null) { if (! $view instanceof Mailable) { return; } $view->mailer($this->currentMailer); if ($view instanceof ShouldQueue) { return $this->queue($view, $data); } $this->currentMailer = null; $this->mailables[] = $view; } /** * Queue a new e-mail message for sending. * * @param \Illuminate\Contracts\Mail\Mailable|string|array $view * @param string|null $queue * @return mixed */ public function queue($view, $queue = null) { if (! $view instanceof Mailable) { return; } $view->mailer($this->currentMailer); $this->currentMailer = null; $this->queuedMailables[] = $view; } /** * Queue a new e-mail message for sending after (n) seconds. * * @param \DateTimeInterface|\DateInterval|int $delay * @param \Illuminate\Contracts\Mail\Mailable|string|array $view * @param string|null $queue * @return mixed */ public function later($delay, $view, $queue = null) { $this->queue($view, $queue); } /** * Get the array of failed recipients. * * @return array */ public function failures() { return []; } /** * Infer mailable class using reflection if a typehinted closure is passed to assertion. * * @param string|\Closure $mailable * @param callable|null $callback * @return array */ protected function prepareMailableAndCallback($mailable, $callback) { if ($mailable instanceof Closure) { return [$this->firstClosureParameterType($mailable), $mailable]; } return [$mailable, $callback]; } /** * Forget all of the resolved mailer instances. * * @return $this */ public function forgetMailers() { $this->currentMailer = null; return $this; } } PKy Zeo0d d -Illuminate/Support/NamespacedItemResolver.phpnuW+Aparsed[$key])) { return $this->parsed[$key]; } // If the key does not contain a double colon, it means the key is not in a // namespace, and is just a regular configuration item. Namespaces are a // tool for organizing configuration items for things such as modules. if (! str_contains($key, '::')) { $segments = explode('.', $key); $parsed = $this->parseBasicSegments($segments); } else { $parsed = $this->parseNamespacedSegments($key); } // Once we have the parsed array of this key's elements, such as its groups // and namespace, we will cache each array inside a simple list that has // the key and the parsed array for quick look-ups for later requests. return $this->parsed[$key] = $parsed; } /** * Parse an array of basic segments. * * @param array $segments * @return array */ protected function parseBasicSegments(array $segments) { // The first segment in a basic array will always be the group, so we can go // ahead and grab that segment. If there is only one total segment we are // just pulling an entire group out of the array and not a single item. $group = $segments[0]; // If there is more than one segment in this group, it means we are pulling // a specific item out of a group and will need to return this item name // as well as the group so we know which item to pull from the arrays. $item = count($segments) === 1 ? null : implode('.', array_slice($segments, 1)); return [null, $group, $item]; } /** * Parse an array of namespaced segments. * * @param string $key * @return array */ protected function parseNamespacedSegments($key) { [$namespace, $item] = explode('::', $key); // First we'll just explode the first segment to get the namespace and group // since the item should be in the remaining segments. Once we have these // two pieces of data we can proceed with parsing out the item's value. $itemSegments = explode('.', $item); $groupAndItem = array_slice( $this->parseBasicSegments($itemSegments), 1 ); return array_merge([$namespace], $groupAndItem); } /** * Set the parsed value of a key. * * @param string $key * @param array $parsed * @return void */ public function setParsedKey($key, $parsed) { $this->parsed[$key] = $parsed; } /** * Flush the cache of parsed keys. * * @return void */ public function flushParsedKeys() { $this->parsed = []; } } PKy Z><ԥIlluminate/Support/Timebox.phpnuW+AearlyReturn && $remainder > 0) { $this->usleep($remainder); } return $result; } /** * Indicate that the timebox can return early. * * @return $this */ public function returnEarly() { $this->earlyReturn = true; return $this; } /** * Indicate that the timebox cannot return early. * * @return $this */ public function dontReturnEarly() { $this->earlyReturn = false; return $this; } /** * Sleep for the specified number of microseconds. * * @param int $microseconds * @return void */ protected function usleep(int $microseconds) { usleep($microseconds); } } PKy Z\|C C Illuminate/Support/Composer.phpnuW+Afiles = $files; $this->workingPath = $workingPath; } /** * Regenerate the Composer autoloader files. * * @param string|array $extra * @return int */ public function dumpAutoloads($extra = '') { $extra = $extra ? (array) $extra : []; $command = array_merge($this->findComposer(), ['dump-autoload'], $extra); return $this->getProcess($command)->run(); } /** * Regenerate the optimized Composer autoloader files. * * @return int */ public function dumpOptimized() { return $this->dumpAutoloads('--optimize'); } /** * Get the composer command for the environment. * * @return array */ public function findComposer() { if ($this->files->exists($this->workingPath.'/composer.phar')) { return [$this->phpBinary(), 'composer.phar']; } return ['composer']; } /** * Get the PHP binary. * * @return string */ protected function phpBinary() { return ProcessUtils::escapeArgument((new PhpExecutableFinder)->find(false)); } /** * Get a new Symfony process instance. * * @param array $command * @return \Symfony\Component\Process\Process */ protected function getProcess(array $command) { return (new Process($command, $this->workingPath))->setTimeout(null); } /** * Set the working path used by the class. * * @param string $path * @return $this */ public function setWorkingPath($path) { $this->workingPath = realpath($path); return $this; } /** * Get the version of Composer. * * @return string|null */ public function getVersion() { $command = array_merge($this->findComposer(), ['-V', '--no-ansi']); $process = $this->getProcess($command); $process->run(); $output = $process->getOutput(); if (preg_match('/(\d+(\.\d+){2})/', $output, $version)) { return $version[1]; } return explode(' ', $output)[2] ?? null; } } PKy Zα33Illuminate/Support/LICENSE.mdnuW+AThe MIT License (MIT) Copyright (c) Taylor Otwell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PKy Z>%C C #Illuminate/Support/ViewErrorBag.phpnuW+Abags[$key]); } /** * Get a MessageBag instance from the bags. * * @param string $key * @return \Illuminate\Contracts\Support\MessageBag */ public function getBag($key) { return Arr::get($this->bags, $key) ?: new MessageBag; } /** * Get all the bags. * * @return array */ public function getBags() { return $this->bags; } /** * Add a new MessageBag instance to the bags. * * @param string $key * @param \Illuminate\Contracts\Support\MessageBag $bag * @return $this */ public function put($key, MessageBagContract $bag) { $this->bags[$key] = $bag; return $this; } /** * Determine if the default message bag has any messages. * * @return bool */ public function any() { return $this->count() > 0; } /** * Get the number of messages in the default bag. * * @return int */ public function count(): int { return $this->getBag('default')->count(); } /** * Dynamically call methods on the default bag. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { return $this->getBag('default')->$method(...$parameters); } /** * Dynamically access a view error bag. * * @param string $key * @return \Illuminate\Contracts\Support\MessageBag */ public function __get($key) { return $this->getBag($key); } /** * Dynamically set a view error bag. * * @param string $key * @param \Illuminate\Contracts\Support\MessageBag $value * @return void */ public function __set($key, $value) { $this->put($key, $value); } /** * Convert the default bag to its string representation. * * @return string */ public function __toString() { return (string) $this->getBag('default'); } } PKy Z;+!!!Illuminate/Support/HtmlString.phpnuW+Ahtml = $html; } /** * Get the HTML string. * * @return string */ public function toHtml() { return $this->html; } /** * Determine if the given HTML string is empty. * * @return bool */ public function isEmpty() { return $this->html === ''; } /** * Determine if the given HTML string is not empty. * * @return bool */ public function isNotEmpty() { return ! $this->isEmpty(); } /** * Get the HTML string. * * @return string */ public function __toString() { return $this->toHtml(); } } PKy Z۳att%Illuminate/Support/ValidatedInput.phpnuW+Ainput = $input; } /** * Determine if the validated input has one or more keys. * * @param mixed $keys * @return bool */ public function has($keys) { $keys = is_array($keys) ? $keys : func_get_args(); foreach ($keys as $key) { if (! Arr::has($this->input, $key)) { return false; } } return true; } /** * Determine if the validated input is missing one or more keys. * * @param mixed $keys * @return bool */ public function missing($keys) { return ! $this->has($keys); } /** * Get a subset containing the provided keys with values from the input data. * * @param mixed $keys * @return array */ public function only($keys) { $results = []; $input = $this->input; $placeholder = new stdClass; foreach (is_array($keys) ? $keys : func_get_args() as $key) { $value = data_get($input, $key, $placeholder); if ($value !== $placeholder) { Arr::set($results, $key, $value); } } return $results; } /** * Get all of the input except for a specified array of items. * * @param mixed $keys * @return array */ public function except($keys) { $keys = is_array($keys) ? $keys : func_get_args(); $results = $this->input; Arr::forget($results, $keys); return $results; } /** * Merge the validated input with the given array of additional data. * * @param array $items * @return static */ public function merge(array $items) { return new static(array_merge($this->input, $items)); } /** * Get the input as a collection. * * @return \Illuminate\Support\Collection */ public function collect() { return new Collection($this->input); } /** * Get the raw, underlying input array. * * @return array */ public function all() { return $this->input; } /** * Get the instance as an array. * * @return array */ public function toArray() { return $this->all(); } /** * Dynamically access input data. * * @param string $name * @return mixed */ public function __get($name) { return $this->input[$name]; } /** * Dynamically set input data. * * @param string $name * @param mixed $value * @return mixed */ public function __set($name, $value) { $this->input[$name] = $value; } /** * Determine if an input key is set. * * @return bool */ public function __isset($name) { return isset($this->input[$name]); } /** * Remove an input key. * * @param string $name * @return void */ public function __unset($name) { unset($this->input[$name]); } /** * Determine if an item exists at an offset. * * @param mixed $key * @return bool */ public function offsetExists($key): bool { return isset($this->input[$key]); } /** * Get an item at a given offset. * * @param mixed $key * @return mixed */ public function offsetGet($key): mixed { return $this->input[$key]; } /** * Set the item at a given offset. * * @param mixed $key * @param mixed $value * @return void */ public function offsetSet($key, $value): void { if (is_null($key)) { $this->input[] = $value; } else { $this->input[$key] = $value; } } /** * Unset the item at a given offset. * * @param string $key * @return void */ public function offsetUnset($key): void { unset($this->input[$key]); } /** * Get an iterator for the input. * * @return \ArrayIterator */ public function getIterator(): Traversable { return new ArrayIterator($this->input); } } PKy Zg{Illuminate/Support/Carbon.phpnuW+Ainstances = []; foreach ($this->providers as $provider) { $this->instances[] = $this->app->register($provider); } } /** * Get the services provided by the provider. * * @return array */ public function provides() { $provides = []; foreach ($this->providers as $provider) { $instance = $this->app->resolveProvider($provider); $provides = array_merge($provides, $instance->provides()); } return $provides; } } PKy Z\ L Illuminate/Support/Optional.phpnuW+Avalue = $value; } /** * Dynamically access a property on the underlying object. * * @param string $key * @return mixed */ public function __get($key) { if (is_object($this->value)) { return $this->value->{$key} ?? null; } } /** * Dynamically check a property exists on the underlying object. * * @param mixed $name * @return bool */ public function __isset($name) { if (is_object($this->value)) { return isset($this->value->{$name}); } if (is_array($this->value) || $this->value instanceof ArrayObject) { return isset($this->value[$name]); } return false; } /** * Determine if an item exists at an offset. * * @param mixed $key * @return bool */ public function offsetExists($key): bool { return Arr::accessible($this->value) && Arr::exists($this->value, $key); } /** * Get an item at a given offset. * * @param mixed $key * @return mixed */ public function offsetGet($key): mixed { return Arr::get($this->value, $key); } /** * Set the item at a given offset. * * @param mixed $key * @param mixed $value * @return void */ public function offsetSet($key, $value): void { if (Arr::accessible($this->value)) { $this->value[$key] = $value; } } /** * Unset the item at a given offset. * * @param string $key * @return void */ public function offsetUnset($key): void { if (Arr::accessible($this->value)) { unset($this->value[$key]); } } /** * Dynamically pass a method to the underlying object. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { if (static::hasMacro($method)) { return $this->macroCall($method, $parameters); } if (is_object($this->value)) { return $this->value->{$method}(...$parameters); } } } PKy Zi3 + +&Illuminate/Support/ServiceProvider.phpnuW+Aapp = $app; } /** * Register any application services. * * @return void */ public function register() { // } /** * Register a booting callback to be run before the "boot" method is called. * * @param \Closure $callback * @return void */ public function booting(Closure $callback) { $this->bootingCallbacks[] = $callback; } /** * Register a booted callback to be run after the "boot" method is called. * * @param \Closure $callback * @return void */ public function booted(Closure $callback) { $this->bootedCallbacks[] = $callback; } /** * Call the registered booting callbacks. * * @return void */ public function callBootingCallbacks() { $index = 0; while ($index < count($this->bootingCallbacks)) { $this->app->call($this->bootingCallbacks[$index]); $index++; } } /** * Call the registered booted callbacks. * * @return void */ public function callBootedCallbacks() { $index = 0; while ($index < count($this->bootedCallbacks)) { $this->app->call($this->bootedCallbacks[$index]); $index++; } } /** * Merge the given configuration with the existing configuration. * * @param string $path * @param string $key * @return void */ protected function mergeConfigFrom($path, $key) { if (! ($this->app instanceof CachesConfiguration && $this->app->configurationIsCached())) { $config = $this->app->make('config'); $config->set($key, array_merge( require $path, $config->get($key, []) )); } } /** * Load the given routes file if routes are not already cached. * * @param string $path * @return void */ protected function loadRoutesFrom($path) { if (! ($this->app instanceof CachesRoutes && $this->app->routesAreCached())) { require $path; } } /** * Register a view file namespace. * * @param string|array $path * @param string $namespace * @return void */ protected function loadViewsFrom($path, $namespace) { $this->callAfterResolving('view', function ($view) use ($path, $namespace) { if (isset($this->app->config['view']['paths']) && is_array($this->app->config['view']['paths'])) { foreach ($this->app->config['view']['paths'] as $viewPath) { if (is_dir($appPath = $viewPath.'/vendor/'.$namespace)) { $view->addNamespace($namespace, $appPath); } } } $view->addNamespace($namespace, $path); }); } /** * Register the given view components with a custom prefix. * * @param string $prefix * @param array $components * @return void */ protected function loadViewComponentsAs($prefix, array $components) { $this->callAfterResolving(BladeCompiler::class, function ($blade) use ($prefix, $components) { foreach ($components as $alias => $component) { $blade->component($component, is_string($alias) ? $alias : null, $prefix); } }); } /** * Register a translation file namespace. * * @param string $path * @param string $namespace * @return void */ protected function loadTranslationsFrom($path, $namespace) { $this->callAfterResolving('translator', function ($translator) use ($path, $namespace) { $translator->addNamespace($namespace, $path); }); } /** * Register a JSON translation file path. * * @param string $path * @return void */ protected function loadJsonTranslationsFrom($path) { $this->callAfterResolving('translator', function ($translator) use ($path) { $translator->addJsonPath($path); }); } /** * Register database migration paths. * * @param array|string $paths * @return void */ protected function loadMigrationsFrom($paths) { $this->callAfterResolving('migrator', function ($migrator) use ($paths) { foreach ((array) $paths as $path) { $migrator->path($path); } }); } /** * Register Eloquent model factory paths. * * @deprecated Will be removed in a future Laravel version. * * @param array|string $paths * @return void */ protected function loadFactoriesFrom($paths) { $this->callAfterResolving(ModelFactory::class, function ($factory) use ($paths) { foreach ((array) $paths as $path) { $factory->load($path); } }); } /** * Setup an after resolving listener, or fire immediately if already resolved. * * @param string $name * @param callable $callback * @return void */ protected function callAfterResolving($name, $callback) { $this->app->afterResolving($name, $callback); if ($this->app->resolved($name)) { $callback($this->app->make($name), $this->app); } } /** * Register paths to be published by the publish command. * * @param array $paths * @param mixed $groups * @return void */ protected function publishes(array $paths, $groups = null) { $this->ensurePublishArrayInitialized($class = static::class); static::$publishes[$class] = array_merge(static::$publishes[$class], $paths); foreach ((array) $groups as $group) { $this->addPublishGroup($group, $paths); } } /** * Ensure the publish array for the service provider is initialized. * * @param string $class * @return void */ protected function ensurePublishArrayInitialized($class) { if (! array_key_exists($class, static::$publishes)) { static::$publishes[$class] = []; } } /** * Add a publish group / tag to the service provider. * * @param string $group * @param array $paths * @return void */ protected function addPublishGroup($group, $paths) { if (! array_key_exists($group, static::$publishGroups)) { static::$publishGroups[$group] = []; } static::$publishGroups[$group] = array_merge( static::$publishGroups[$group], $paths ); } /** * Get the paths to publish. * * @param string|null $provider * @param string|null $group * @return array */ public static function pathsToPublish($provider = null, $group = null) { if (! is_null($paths = static::pathsForProviderOrGroup($provider, $group))) { return $paths; } return collect(static::$publishes)->reduce(function ($paths, $p) { return array_merge($paths, $p); }, []); } /** * Get the paths for the provider or group (or both). * * @param string|null $provider * @param string|null $group * @return array */ protected static function pathsForProviderOrGroup($provider, $group) { if ($provider && $group) { return static::pathsForProviderAndGroup($provider, $group); } elseif ($group && array_key_exists($group, static::$publishGroups)) { return static::$publishGroups[$group]; } elseif ($provider && array_key_exists($provider, static::$publishes)) { return static::$publishes[$provider]; } elseif ($group || $provider) { return []; } } /** * Get the paths for the provider and group. * * @param string $provider * @param string $group * @return array */ protected static function pathsForProviderAndGroup($provider, $group) { if (! empty(static::$publishes[$provider]) && ! empty(static::$publishGroups[$group])) { return array_intersect_key(static::$publishes[$provider], static::$publishGroups[$group]); } return []; } /** * Get the service providers available for publishing. * * @return array */ public static function publishableProviders() { return array_keys(static::$publishes); } /** * Get the groups available for publishing. * * @return array */ public static function publishableGroups() { return array_keys(static::$publishGroups); } /** * Register the package's custom Artisan commands. * * @param array|mixed $commands * @return void */ public function commands($commands) { $commands = is_array($commands) ? $commands : func_get_args(); Artisan::starting(function ($artisan) use ($commands) { $artisan->resolveCommands($commands); }); } /** * Get the services provided by the provider. * * @return array */ public function provides() { return []; } /** * Get the events that trigger this service provider to register. * * @return array */ public function when() { return []; } /** * Determine if the provider is deferred. * * @return bool */ public function isDeferred() { return $this instanceof DeferrableProvider; } } PKy ZPqq!Illuminate/Support/Stringable.phpnuW+Avalue = (string) $value; } /** * Return the remainder of a string after the first occurrence of a given value. * * @param string $search * @return static */ public function after($search) { return new static(Str::after($this->value, $search)); } /** * Return the remainder of a string after the last occurrence of a given value. * * @param string $search * @return static */ public function afterLast($search) { return new static(Str::afterLast($this->value, $search)); } /** * Append the given values to the string. * * @param string ...$values * @return static */ public function append(...$values) { return new static($this->value.implode('', $values)); } /** * Append a new line to the string. * * @param int $count * @return $this */ public function newLine($count = 1) { return $this->append(str_repeat(PHP_EOL, $count)); } /** * Transliterate a UTF-8 value to ASCII. * * @param string $language * @return static */ public function ascii($language = 'en') { return new static(Str::ascii($this->value, $language)); } /** * Get the trailing name component of the path. * * @param string $suffix * @return static */ public function basename($suffix = '') { return new static(basename($this->value, $suffix)); } /** * Get the basename of the class path. * * @return static */ public function classBasename() { return new static(class_basename($this->value)); } /** * Get the portion of a string before the first occurrence of a given value. * * @param string $search * @return static */ public function before($search) { return new static(Str::before($this->value, $search)); } /** * Get the portion of a string before the last occurrence of a given value. * * @param string $search * @return static */ public function beforeLast($search) { return new static(Str::beforeLast($this->value, $search)); } /** * Get the portion of a string between two given values. * * @param string $from * @param string $to * @return static */ public function between($from, $to) { return new static(Str::between($this->value, $from, $to)); } /** * Get the smallest possible portion of a string between two given values. * * @param string $from * @param string $to * @return static */ public function betweenFirst($from, $to) { return new static(Str::betweenFirst($this->value, $from, $to)); } /** * Convert a value to camel case. * * @return static */ public function camel() { return new static(Str::camel($this->value)); } /** * Determine if a given string contains a given substring. * * @param string|iterable $needles * @param bool $ignoreCase * @return bool */ public function contains($needles, $ignoreCase = false) { return Str::contains($this->value, $needles, $ignoreCase); } /** * Determine if a given string contains all array values. * * @param iterable $needles * @param bool $ignoreCase * @return bool */ public function containsAll($needles, $ignoreCase = false) { return Str::containsAll($this->value, $needles, $ignoreCase); } /** * Get the parent directory's path. * * @param int $levels * @return static */ public function dirname($levels = 1) { return new static(dirname($this->value, $levels)); } /** * Determine if a given string ends with a given substring. * * @param string|iterable $needles * @return bool */ public function endsWith($needles) { return Str::endsWith($this->value, $needles); } /** * Determine if the string is an exact match with the given value. * * @param \Illuminate\Support\Stringable|string $value * @return bool */ public function exactly($value) { if ($value instanceof Stringable) { $value = $value->toString(); } return $this->value === $value; } /** * Extracts an excerpt from text that matches the first instance of a phrase. * * @param string $phrase * @param array $options * @return string|null */ public function excerpt($phrase = '', $options = []) { return Str::excerpt($this->value, $phrase, $options); } /** * Explode the string into an array. * * @param string $delimiter * @param int $limit * @return \Illuminate\Support\Collection */ public function explode($delimiter, $limit = PHP_INT_MAX) { return collect(explode($delimiter, $this->value, $limit)); } /** * Split a string using a regular expression or by length. * * @param string|int $pattern * @param int $limit * @param int $flags * @return \Illuminate\Support\Collection */ public function split($pattern, $limit = -1, $flags = 0) { if (filter_var($pattern, FILTER_VALIDATE_INT) !== false) { return collect(mb_str_split($this->value, $pattern)); } $segments = preg_split($pattern, $this->value, $limit, $flags); return ! empty($segments) ? collect($segments) : collect(); } /** * Cap a string with a single instance of a given value. * * @param string $cap * @return static */ public function finish($cap) { return new static(Str::finish($this->value, $cap)); } /** * Determine if a given string matches a given pattern. * * @param string|iterable $pattern * @return bool */ public function is($pattern) { return Str::is($pattern, $this->value); } /** * Determine if a given string is 7 bit ASCII. * * @return bool */ public function isAscii() { return Str::isAscii($this->value); } /** * Determine if a given string is valid JSON. * * @return bool */ public function isJson() { return Str::isJson($this->value); } /** * Determine if a given string is a valid UUID. * * @return bool */ public function isUuid() { return Str::isUuid($this->value); } /** * Determine if a given string is a valid ULID. * * @return bool */ public function isUlid() { return Str::isUlid($this->value); } /** * Determine if the given string is empty. * * @return bool */ public function isEmpty() { return $this->value === ''; } /** * Determine if the given string is not empty. * * @return bool */ public function isNotEmpty() { return ! $this->isEmpty(); } /** * Convert a string to kebab case. * * @return static */ public function kebab() { return new static(Str::kebab($this->value)); } /** * Return the length of the given string. * * @param string|null $encoding * @return int */ public function length($encoding = null) { return Str::length($this->value, $encoding); } /** * Limit the number of characters in a string. * * @param int $limit * @param string $end * @return static */ public function limit($limit = 100, $end = '...') { return new static(Str::limit($this->value, $limit, $end)); } /** * Convert the given string to lower-case. * * @return static */ public function lower() { return new static(Str::lower($this->value)); } /** * Convert GitHub flavored Markdown into HTML. * * @param array $options * @return static */ public function markdown(array $options = []) { return new static(Str::markdown($this->value, $options)); } /** * Convert inline Markdown into HTML. * * @param array $options * @return static */ public function inlineMarkdown(array $options = []) { return new static(Str::inlineMarkdown($this->value, $options)); } /** * Masks a portion of a string with a repeated character. * * @param string $character * @param int $index * @param int|null $length * @param string $encoding * @return static */ public function mask($character, $index, $length = null, $encoding = 'UTF-8') { return new static(Str::mask($this->value, $character, $index, $length, $encoding)); } /** * Get the string matching the given pattern. * * @param string $pattern * @return static */ public function match($pattern) { return new static(Str::match($pattern, $this->value)); } /** * Get the string matching the given pattern. * * @param string $pattern * @return \Illuminate\Support\Collection */ public function matchAll($pattern) { return Str::matchAll($pattern, $this->value); } /** * Determine if the string matches the given pattern. * * @param string $pattern * @return bool */ public function test($pattern) { return $this->match($pattern)->isNotEmpty(); } /** * Pad both sides of the string with another. * * @param int $length * @param string $pad * @return static */ public function padBoth($length, $pad = ' ') { return new static(Str::padBoth($this->value, $length, $pad)); } /** * Pad the left side of the string with another. * * @param int $length * @param string $pad * @return static */ public function padLeft($length, $pad = ' ') { return new static(Str::padLeft($this->value, $length, $pad)); } /** * Pad the right side of the string with another. * * @param int $length * @param string $pad * @return static */ public function padRight($length, $pad = ' ') { return new static(Str::padRight($this->value, $length, $pad)); } /** * Parse a Class@method style callback into class and method. * * @param string|null $default * @return array */ public function parseCallback($default = null) { return Str::parseCallback($this->value, $default); } /** * Call the given callback and return a new string. * * @param callable $callback * @return static */ public function pipe(callable $callback) { return new static($callback($this)); } /** * Get the plural form of an English word. * * @param int|array|\Countable $count * @return static */ public function plural($count = 2) { return new static(Str::plural($this->value, $count)); } /** * Pluralize the last word of an English, studly caps case string. * * @param int|array|\Countable $count * @return static */ public function pluralStudly($count = 2) { return new static(Str::pluralStudly($this->value, $count)); } /** * Prepend the given values to the string. * * @param string ...$values * @return static */ public function prepend(...$values) { return new static(implode('', $values).$this->value); } /** * Remove any occurrence of the given string in the subject. * * @param string|iterable $search * @param bool $caseSensitive * @return static */ public function remove($search, $caseSensitive = true) { return new static(Str::remove($search, $this->value, $caseSensitive)); } /** * Reverse the string. * * @return static */ public function reverse() { return new static(Str::reverse($this->value)); } /** * Repeat the string. * * @param int $times * @return static */ public function repeat(int $times) { return new static(str_repeat($this->value, $times)); } /** * Replace the given value in the given string. * * @param string|iterable $search * @param string|iterable $replace * @return static */ public function replace($search, $replace) { return new static(Str::replace($search, $replace, $this->value)); } /** * Replace a given value in the string sequentially with an array. * * @param string $search * @param iterable $replace * @return static */ public function replaceArray($search, $replace) { return new static(Str::replaceArray($search, $replace, $this->value)); } /** * Replace the first occurrence of a given value in the string. * * @param string $search * @param string $replace * @return static */ public function replaceFirst($search, $replace) { return new static(Str::replaceFirst($search, $replace, $this->value)); } /** * Replace the last occurrence of a given value in the string. * * @param string $search * @param string $replace * @return static */ public function replaceLast($search, $replace) { return new static(Str::replaceLast($search, $replace, $this->value)); } /** * Replace the patterns matching the given regular expression. * * @param string $pattern * @param \Closure|string $replace * @param int $limit * @return static */ public function replaceMatches($pattern, $replace, $limit = -1) { if ($replace instanceof Closure) { return new static(preg_replace_callback($pattern, $replace, $this->value, $limit)); } return new static(preg_replace($pattern, $replace, $this->value, $limit)); } /** * Parse input from a string to a collection, according to a format. * * @param string $format * @return \Illuminate\Support\Collection */ public function scan($format) { return collect(sscanf($this->value, $format)); } /** * Remove all "extra" blank space from the given string. * * @return static */ public function squish() { return new static(Str::squish($this->value)); } /** * Begin a string with a single instance of a given value. * * @param string $prefix * @return static */ public function start($prefix) { return new static(Str::start($this->value, $prefix)); } /** * Strip HTML and PHP tags from the given string. * * @param string $allowedTags * @return static */ public function stripTags($allowedTags = null) { return new static(strip_tags($this->value, $allowedTags)); } /** * Convert the given string to upper-case. * * @return static */ public function upper() { return new static(Str::upper($this->value)); } /** * Convert the given string to title case. * * @return static */ public function title() { return new static(Str::title($this->value)); } /** * Convert the given string to title case for each word. * * @return static */ public function headline() { return new static(Str::headline($this->value)); } /** * Get the singular form of an English word. * * @return static */ public function singular() { return new static(Str::singular($this->value)); } /** * Generate a URL friendly "slug" from a given string. * * @param string $separator * @param string|null $language * @param array $dictionary * @return static */ public function slug($separator = '-', $language = 'en', $dictionary = ['@' => 'at']) { return new static(Str::slug($this->value, $separator, $language, $dictionary)); } /** * Convert a string to snake case. * * @param string $delimiter * @return static */ public function snake($delimiter = '_') { return new static(Str::snake($this->value, $delimiter)); } /** * Determine if a given string starts with a given substring. * * @param string|iterable $needles * @return bool */ public function startsWith($needles) { return Str::startsWith($this->value, $needles); } /** * Convert a value to studly caps case. * * @return static */ public function studly() { return new static(Str::studly($this->value)); } /** * Returns the portion of the string specified by the start and length parameters. * * @param int $start * @param int|null $length * @param string $encoding * @return static */ public function substr($start, $length = null, $encoding = 'UTF-8') { return new static(Str::substr($this->value, $start, $length, $encoding)); } /** * Returns the number of substring occurrences. * * @param string $needle * @param int $offset * @param int|null $length * @return int */ public function substrCount($needle, $offset = 0, $length = null) { return Str::substrCount($this->value, $needle, $offset, $length); } /** * Replace text within a portion of a string. * * @param string|string[] $replace * @param int|int[] $offset * @param int|int[]|null $length * @return static */ public function substrReplace($replace, $offset = 0, $length = null) { return new static(Str::substrReplace($this->value, $replace, $offset, $length)); } /** * Swap multiple keywords in a string with other keywords. * * @param array $map * @return static */ public function swap(array $map) { return new static(strtr($this->value, $map)); } /** * Trim the string of the given characters. * * @param string $characters * @return static */ public function trim($characters = null) { return new static(trim(...array_merge([$this->value], func_get_args()))); } /** * Left trim the string of the given characters. * * @param string $characters * @return static */ public function ltrim($characters = null) { return new static(ltrim(...array_merge([$this->value], func_get_args()))); } /** * Right trim the string of the given characters. * * @param string $characters * @return static */ public function rtrim($characters = null) { return new static(rtrim(...array_merge([$this->value], func_get_args()))); } /** * Make a string's first character lowercase. * * @return static */ public function lcfirst() { return new static(Str::lcfirst($this->value)); } /** * Make a string's first character uppercase. * * @return static */ public function ucfirst() { return new static(Str::ucfirst($this->value)); } /** * Split a string by uppercase characters. * * @return \Illuminate\Support\Collection */ public function ucsplit() { return collect(Str::ucsplit($this->value)); } /** * Execute the given callback if the string contains a given substring. * * @param string|iterable $needles * @param callable $callback * @param callable|null $default * @return static */ public function whenContains($needles, $callback, $default = null) { return $this->when($this->contains($needles), $callback, $default); } /** * Execute the given callback if the string contains all array values. * * @param iterable $needles * @param callable $callback * @param callable|null $default * @return static */ public function whenContainsAll(array $needles, $callback, $default = null) { return $this->when($this->containsAll($needles), $callback, $default); } /** * Execute the given callback if the string is empty. * * @param callable $callback * @param callable|null $default * @return static */ public function whenEmpty($callback, $default = null) { return $this->when($this->isEmpty(), $callback, $default); } /** * Execute the given callback if the string is not empty. * * @param callable $callback * @param callable|null $default * @return static */ public function whenNotEmpty($callback, $default = null) { return $this->when($this->isNotEmpty(), $callback, $default); } /** * Execute the given callback if the string ends with a given substring. * * @param string|iterable $needles * @param callable $callback * @param callable|null $default * @return static */ public function whenEndsWith($needles, $callback, $default = null) { return $this->when($this->endsWith($needles), $callback, $default); } /** * Execute the given callback if the string is an exact match with the given value. * * @param string $value * @param callable $callback * @param callable|null $default * @return static */ public function whenExactly($value, $callback, $default = null) { return $this->when($this->exactly($value), $callback, $default); } /** * Execute the given callback if the string is not an exact match with the given value. * * @param string $value * @param callable $callback * @param callable|null $default * @return static */ public function whenNotExactly($value, $callback, $default = null) { return $this->when(! $this->exactly($value), $callback, $default); } /** * Execute the given callback if the string matches a given pattern. * * @param string|iterable $pattern * @param callable $callback * @param callable|null $default * @return static */ public function whenIs($pattern, $callback, $default = null) { return $this->when($this->is($pattern), $callback, $default); } /** * Execute the given callback if the string is 7 bit ASCII. * * @param callable $callback * @param callable|null $default * @return static */ public function whenIsAscii($callback, $default = null) { return $this->when($this->isAscii(), $callback, $default); } /** * Execute the given callback if the string is a valid UUID. * * @param callable $callback * @param callable|null $default * @return static */ public function whenIsUuid($callback, $default = null) { return $this->when($this->isUuid(), $callback, $default); } /** * Execute the given callback if the string is a valid ULID. * * @param callable $callback * @param callable|null $default * @return static */ public function whenIsUlid($callback, $default = null) { return $this->when($this->isUlid(), $callback, $default); } /** * Execute the given callback if the string starts with a given substring. * * @param string|iterable $needles * @param callable $callback * @param callable|null $default * @return static */ public function whenStartsWith($needles, $callback, $default = null) { return $this->when($this->startsWith($needles), $callback, $default); } /** * Execute the given callback if the string matches the given pattern. * * @param string $pattern * @param callable $callback * @param callable|null $default * @return static */ public function whenTest($pattern, $callback, $default = null) { return $this->when($this->test($pattern), $callback, $default); } /** * Limit the number of words in a string. * * @param int $words * @param string $end * @return static */ public function words($words = 100, $end = '...') { return new static(Str::words($this->value, $words, $end)); } /** * Get the number of words a string contains. * * @param string|null $characters * @return int */ public function wordCount($characters = null) { return Str::wordCount($this->value, $characters); } /** * Wrap the string with the given strings. * * @param string $before * @param string|null $after * @return static */ public function wrap($before, $after = null) { return new static(Str::wrap($this->value, $before, $after)); } /** * Convert the string into a `HtmlString` instance. * * @return \Illuminate\Support\HtmlString */ public function toHtmlString() { return new HtmlString($this->value); } /** * Dump the string. * * @return $this */ public function dump() { VarDumper::dump($this->value); return $this; } /** * Dump the string and end the script. * * @return never */ public function dd() { $this->dump(); exit(1); } /** * Get the underlying string value. * * @return string */ public function value() { return $this->toString(); } /** * Get the underlying string value. * * @return string */ public function toString() { return $this->value; } /** * Get the underlying string value as an integer. * * @return int */ public function toInteger() { return intval($this->value); } /** * Get the underlying string value as a float. * * @return float */ public function toFloat() { return floatval($this->value); } /** * Get the underlying string value as a boolean. * * Returns true when value is "1", "true", "on", and "yes". Otherwise, returns false. * * @return bool */ public function toBoolean() { return filter_var($this->value, FILTER_VALIDATE_BOOLEAN); } /** * Get the underlying string value as a Carbon instance. * * @param string|null $format * @param string|null $tz * @return \Illuminate\Support\Carbon * * @throws \Carbon\Exceptions\InvalidFormatException */ public function toDate($format = null, $tz = null) { if (is_null($format)) { return Date::parse($this->value, $tz); } return Date::createFromFormat($format, $this->value, $tz); } /** * Convert the object to a string when JSON encoded. * * @return string */ public function jsonSerialize(): string { return $this->__toString(); } /** * Proxy dynamic properties onto methods. * * @param string $key * @return mixed */ public function __get($key) { return $this->{$key}(); } /** * Get the raw string value. * * @return string */ public function __toString() { return (string) $this->value; } } PKy Z Ȱu u Illuminate/Support/Env.phpnuW+AaddAdapter(PutenvAdapter::class); } static::$repository = $builder->immutable()->make(); } return static::$repository; } /** * Gets the value of an environment variable. * * @param string $key * @param mixed $default * @return mixed */ public static function get($key, $default = null) { return Option::fromValue(static::getRepository()->get($key)) ->map(function ($value) { switch (strtolower($value)) { case 'true': case '(true)': return true; case 'false': case '(false)': return false; case 'empty': case '(empty)': return ''; case 'null': case '(null)': return; } if (preg_match('/\A([\'"])(.*)\1\z/', $value, $matches)) { return $matches[2]; } return $value; }) ->getOrCall(fn () => value($default)); } } PKy Z\K/Illuminate/Support/Exceptions/MathException.phpnuW+Amap(function ($callback) use ($iterations) { return collect(range(1, $iterations))->map(function () use ($callback) { gc_collect_cycles(); $start = hrtime(true); $callback(); return (hrtime(true) - $start) / 1000000; })->average(); })->when( $benchmarkables instanceof Closure, fn ($c) => $c->first(), fn ($c) => $c->all(), ); } /** * Measure a callable or array of callables over the given number of iterations, then dump and die. * * @param \Closure|array $benchmarkables * @param int $iterations * @return never */ public static function dd(Closure|array $benchmarkables, int $iterations = 1): void { $result = collect(static::measure(Arr::wrap($benchmarkables), $iterations)) ->map(fn ($average) => number_format($average, 3).'ms') ->when($benchmarkables instanceof Closure, fn ($c) => $c->first(), fn ($c) => $c->all()); dd($result); } } PKy Z,mm!Illuminate/Support/Facades/DB.phpnuW+Aconnection($name)->getSchemaBuilder(); } /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return 'db.schema'; } } PKy Z``#Illuminate/Support/Facades/Auth.phpnuW+AproviderIsLoaded(UiServiceProvider::class)) { throw new RuntimeException('In order to use the Auth::routes() method, please install the laravel/ui package.'); } static::$app->make('router')->auth($options); } } PKy ZYm %Illuminate/Support/Facades/Cookie.phpnuW+Acookie($key, null)); } /** * Retrieve a cookie from the request. * * @param string|null $key * @param mixed $default * @return string|array|null */ public static function get($key = null, $default = null) { return static::$app['request']->cookie($key, $default); } /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return 'cookie'; } } PKy Zh#Illuminate/Support/Facades/Mail.phpnuW+Aresolved($accessor) === true) { $callback(static::getFacadeRoot()); } static::$app->afterResolving($accessor, function ($service) use ($callback) { $callback($service); }); } /** * Convert the facade into a Mockery spy. * * @return \Mockery\MockInterface */ public static function spy() { if (! static::isMock()) { $class = static::getMockableClass(); return tap($class ? Mockery::spy($class) : Mockery::spy(), function ($spy) { static::swap($spy); }); } } /** * Initiate a partial mock on the facade. * * @return \Mockery\MockInterface */ public static function partialMock() { $name = static::getFacadeAccessor(); $mock = static::isMock() ? static::$resolvedInstance[$name] : static::createFreshMockInstance(); return $mock->makePartial(); } /** * Initiate a mock expectation on the facade. * * @return \Mockery\Expectation */ public static function shouldReceive() { $name = static::getFacadeAccessor(); $mock = static::isMock() ? static::$resolvedInstance[$name] : static::createFreshMockInstance(); return $mock->shouldReceive(...func_get_args()); } /** * Initiate a mock expectation on the facade. * * @return \Mockery\Expectation */ public static function expects() { $name = static::getFacadeAccessor(); $mock = static::isMock() ? static::$resolvedInstance[$name] : static::createFreshMockInstance(); return $mock->expects(...func_get_args()); } /** * Create a fresh mock instance for the given class. * * @return \Mockery\MockInterface */ protected static function createFreshMockInstance() { return tap(static::createMock(), function ($mock) { static::swap($mock); $mock->shouldAllowMockingProtectedMethods(); }); } /** * Create a fresh mock instance for the given class. * * @return \Mockery\MockInterface */ protected static function createMock() { $class = static::getMockableClass(); return $class ? Mockery::mock($class) : Mockery::mock(); } /** * Determines whether a mock is set as the instance of the facade. * * @return bool */ protected static function isMock() { $name = static::getFacadeAccessor(); return isset(static::$resolvedInstance[$name]) && static::$resolvedInstance[$name] instanceof LegacyMockInterface; } /** * Get the mockable class for the bound instance. * * @return string|null */ protected static function getMockableClass() { if ($root = static::getFacadeRoot()) { return get_class($root); } } /** * Hotswap the underlying instance behind the facade. * * @param mixed $instance * @return void */ public static function swap($instance) { static::$resolvedInstance[static::getFacadeAccessor()] = $instance; if (isset(static::$app)) { static::$app->instance(static::getFacadeAccessor(), $instance); } } /** * Get the root object behind the facade. * * @return mixed */ public static function getFacadeRoot() { return static::resolveFacadeInstance(static::getFacadeAccessor()); } /** * Get the registered name of the component. * * @return string * * @throws \RuntimeException */ protected static function getFacadeAccessor() { throw new RuntimeException('Facade does not implement getFacadeAccessor method.'); } /** * Resolve the facade root instance from the container. * * @param string $name * @return mixed */ protected static function resolveFacadeInstance($name) { if (isset(static::$resolvedInstance[$name])) { return static::$resolvedInstance[$name]; } if (static::$app) { if (static::$cached) { return static::$resolvedInstance[$name] = static::$app[$name]; } return static::$app[$name]; } } /** * Clear a resolved facade instance. * * @param string $name * @return void */ public static function clearResolvedInstance($name) { unset(static::$resolvedInstance[$name]); } /** * Clear all of the resolved instances. * * @return void */ public static function clearResolvedInstances() { static::$resolvedInstance = []; } /** * Get the application default aliases. * * @return \Illuminate\Support\Collection */ public static function defaultAliases() { return collect([ 'App' => App::class, 'Arr' => Arr::class, 'Artisan' => Artisan::class, 'Auth' => Auth::class, 'Blade' => Blade::class, 'Broadcast' => Broadcast::class, 'Bus' => Bus::class, 'Cache' => Cache::class, 'Config' => Config::class, 'Cookie' => Cookie::class, 'Crypt' => Crypt::class, 'Date' => Date::class, 'DB' => DB::class, 'Eloquent' => Model::class, 'Event' => Event::class, 'File' => File::class, 'Gate' => Gate::class, 'Hash' => Hash::class, 'Http' => Http::class, 'Js' => Js::class, 'Lang' => Lang::class, 'Log' => Log::class, 'Mail' => Mail::class, 'Notification' => Notification::class, 'Password' => Password::class, 'Queue' => Queue::class, 'RateLimiter' => RateLimiter::class, 'Redirect' => Redirect::class, 'Request' => Request::class, 'Response' => Response::class, 'Route' => Route::class, 'Schema' => Schema::class, 'Session' => Session::class, 'Storage' => Storage::class, 'Str' => Str::class, 'URL' => URL::class, 'Validator' => Validator::class, 'View' => View::class, 'Vite' => Vite::class, ]); } /** * Get the application instance behind the facade. * * @return \Illuminate\Contracts\Foundation\Application */ public static function getFacadeApplication() { return static::$app; } /** * Set the application instance. * * @param \Illuminate\Contracts\Foundation\Application $app * @return void */ public static function setFacadeApplication($app) { static::$app = $app; } /** * Handle dynamic, static calls to the object. * * @param string $method * @param array $args * @return mixed * * @throws \RuntimeException */ public static function __callStatic($method, $args) { $instance = static::getFacadeRoot(); if (! $instance) { throw new RuntimeException('A facade root has not been set.'); } return $instance->$method(...$args); } } PKy Z>*&Illuminate/Support/Facades/Artisan.phpnuW+Aroute($channel, $route); } /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return ChannelManager::class; } } PKy ZnI"Illuminate/Support/Facades/App.phpnuW+Aget('filesystems.default'); $root = storage_path('framework/testing/disks/'.$disk); if ($token = ParallelTesting::token()) { $root = "{$root}_test_{$token}"; } (new Filesystem)->cleanDirectory($root); static::set($disk, $fake = static::createLocalDriver(array_merge($config, [ 'root' => $root, ]))); return tap($fake)->buildTemporaryUrlsUsing(function ($path, $expiration) { return URL::to($path.'?expiration='.$expiration->getTimestamp()); }); } /** * Replace the given disk with a persistent local testing disk. * * @param string|null $disk * @param array $config * @return \Illuminate\Contracts\Filesystem\Filesystem */ public static function persistentFake($disk = null, array $config = []) { $disk = $disk ?: static::$app['config']->get('filesystems.default'); static::set($disk, $fake = static::createLocalDriver(array_merge($config, [ 'root' => storage_path('framework/testing/disks/'.$disk), ]))); return $fake; } /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return 'filesystem'; } } PKy Z#EV &Illuminate/Support/Facades/Session.phpnuW+Afake($callback)); }); } /** * Register a response sequence for the given URL pattern. * * @param string $urlPattern * @return \Illuminate\Http\Client\ResponseSequence */ public static function fakeSequence(string $urlPattern = '*') { $fake = tap(static::getFacadeRoot(), function ($fake) { static::swap($fake); }); return $fake->fakeSequence($urlPattern); } /** * Indicate that an exception should be thrown if any request is not faked. * * @return \Illuminate\Http\Client\Factory */ public static function preventStrayRequests() { return tap(static::getFacadeRoot(), function ($fake) { static::swap($fake->preventStrayRequests()); }); } /** * Stub the given URL using the given callback. * * @param string $url * @param \Illuminate\Http\Client\Response|\GuzzleHttp\Promise\PromiseInterface|callable $callback * @return \Illuminate\Http\Client\Factory */ public static function stubUrl($url, $callback) { return tap(static::getFacadeRoot(), function ($fake) use ($url, $callback) { static::swap($fake->stubUrl($url, $callback)); }); } } PKy ZgJ|xb*b*&Illuminate/Support/Facades/Request.phpnuW+Adispatch(); } /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return BusDispatcherContract::class; } } PKy Z  "Illuminate/Support/Facades/Log.phpnuW+Ajs = $this->convertDataToJavaScriptExpression($data, $flags, $depth); } /** * Create a new JavaScript string from the given data. * * @param mixed $data * @param int $flags * @param int $depth * @return static * * @throws \JsonException */ public static function from($data, $flags = 0, $depth = 512) { return new static($data, $flags, $depth); } /** * Convert the given data to a JavaScript expression. * * @param mixed $data * @param int $flags * @param int $depth * @return string * * @throws \JsonException */ protected function convertDataToJavaScriptExpression($data, $flags = 0, $depth = 512) { if ($data instanceof self) { return $data->toHtml(); } if ($data instanceof BackedEnum) { $data = $data->value; } $json = $this->jsonEncode($data, $flags, $depth); if (is_string($data)) { return "'".substr($json, 1, -1)."'"; } return $this->convertJsonToJavaScriptExpression($json, $flags); } /** * Encode the given data as JSON. * * @param mixed $data * @param int $flags * @param int $depth * @return string * * @throws \JsonException */ protected function jsonEncode($data, $flags = 0, $depth = 512) { if ($data instanceof Jsonable) { return $data->toJson($flags | static::REQUIRED_FLAGS); } if ($data instanceof Arrayable && ! ($data instanceof JsonSerializable)) { $data = $data->toArray(); } return json_encode($data, $flags | static::REQUIRED_FLAGS, $depth); } /** * Convert the given JSON to a JavaScript expression. * * @param string $json * @param int $flags * @return string * * @throws \JsonException */ protected function convertJsonToJavaScriptExpression($json, $flags = 0) { if ($json === '[]' || $json === '{}') { return $json; } if (Str::startsWith($json, ['"', '{', '['])) { return "JSON.parse('".substr(json_encode($json, $flags | static::REQUIRED_FLAGS), 1, -1)."')"; } return $json; } /** * Get the string representation of the data for use in HTML. * * @return string */ public function toHtml() { return $this->js; } /** * Get the string representation of the data for use in HTML. * * @return string */ public function __toString() { return $this->toHtml(); } } PKy ZH44(Illuminate/Support/InteractsWithTime.phpnuW+AparseDateInterval($delay); return $delay instanceof DateTimeInterface ? max(0, $delay->getTimestamp() - $this->currentTime()) : (int) $delay; } /** * Get the "available at" UNIX timestamp. * * @param \DateTimeInterface|\DateInterval|int $delay * @return int */ protected function availableAt($delay = 0) { $delay = $this->parseDateInterval($delay); return $delay instanceof DateTimeInterface ? $delay->getTimestamp() : Carbon::now()->addRealSeconds($delay)->getTimestamp(); } /** * If the given value is an interval, convert it to a DateTime instance. * * @param \DateTimeInterface|\DateInterval|int $delay * @return \DateTimeInterface|int */ protected function parseDateInterval($delay) { if ($delay instanceof DateInterval) { $delay = Carbon::now()->add($delay); } return $delay; } /** * Get the current system time as a UNIX timestamp. * * @return int */ protected function currentTime() { return Carbon::now()->getTimestamp(); } } PKy ZDIlluminate/Support/Manager.phpnuW+Acontainer = $container; $this->config = $container->make('config'); } /** * Get the default driver name. * * @return string */ abstract public function getDefaultDriver(); /** * Get a driver instance. * * @param string|null $driver * @return mixed * * @throws \InvalidArgumentException */ public function driver($driver = null) { $driver = $driver ?: $this->getDefaultDriver(); if (is_null($driver)) { throw new InvalidArgumentException(sprintf( 'Unable to resolve NULL driver for [%s].', static::class )); } // If the given driver has not been created before, we will create the instances // here and cache it so we can return it next time very quickly. If there is // already a driver created by this name, we'll just return that instance. if (! isset($this->drivers[$driver])) { $this->drivers[$driver] = $this->createDriver($driver); } return $this->drivers[$driver]; } /** * Create a new driver instance. * * @param string $driver * @return mixed * * @throws \InvalidArgumentException */ protected function createDriver($driver) { // First, we will determine if a custom driver creator exists for the given driver and // if it does not we will check for a creator method for the driver. Custom creator // callbacks allow developers to build their own "drivers" easily using Closures. if (isset($this->customCreators[$driver])) { return $this->callCustomCreator($driver); } else { $method = 'create'.Str::studly($driver).'Driver'; if (method_exists($this, $method)) { return $this->$method(); } } throw new InvalidArgumentException("Driver [$driver] not supported."); } /** * Call a custom driver creator. * * @param string $driver * @return mixed */ protected function callCustomCreator($driver) { return $this->customCreators[$driver]($this->container); } /** * Register a custom driver creator Closure. * * @param string $driver * @param \Closure $callback * @return $this */ public function extend($driver, Closure $callback) { $this->customCreators[$driver] = $callback; return $this; } /** * Get all of the created "drivers". * * @return array */ public function getDrivers() { return $this->drivers; } /** * Get the container instance used by the manager. * * @return \Illuminate\Contracts\Container\Container */ public function getContainer() { return $this->container; } /** * Set the container instance used by the manager. * * @param \Illuminate\Contracts\Container\Container $container * @return $this */ public function setContainer(Container $container) { $this->container = $container; return $this; } /** * Forget all of the resolved driver instances. * * @return $this */ public function forgetDrivers() { $this->drivers = []; return $this; } /** * Dynamically call the default driver instance. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { return $this->driver()->$method(...$parameters); } } PKy ZpIlluminate/Support/Fluent.phpnuW+A * @implements \ArrayAccess */ class Fluent implements Arrayable, ArrayAccess, Jsonable, JsonSerializable { /** * All of the attributes set on the fluent instance. * * @var array */ protected $attributes = []; /** * Create a new fluent instance. * * @param iterable $attributes * @return void */ public function __construct($attributes = []) { foreach ($attributes as $key => $value) { $this->attributes[$key] = $value; } } /** * Get an attribute from the fluent instance. * * @template TGetDefault * * @param TKey $key * @param TGetDefault|(\Closure(): TGetDefault) $default * @return TValue|TGetDefault */ public function get($key, $default = null) { if (array_key_exists($key, $this->attributes)) { return $this->attributes[$key]; } return value($default); } /** * Get the attributes from the fluent instance. * * @return array */ public function getAttributes() { return $this->attributes; } /** * Convert the fluent instance to an array. * * @return array */ public function toArray() { return $this->attributes; } /** * Convert the object into something JSON serializable. * * @return array */ public function jsonSerialize(): array { return $this->toArray(); } /** * Convert the fluent instance to JSON. * * @param int $options * @return string */ public function toJson($options = 0) { return json_encode($this->jsonSerialize(), $options); } /** * Determine if the given offset exists. * * @param TKey $offset * @return bool */ public function offsetExists($offset): bool { return isset($this->attributes[$offset]); } /** * Get the value for a given offset. * * @param TKey $offset * @return TValue|null */ public function offsetGet($offset): mixed { return $this->get($offset); } /** * Set the value at the given offset. * * @param TKey $offset * @param TValue $value * @return void */ public function offsetSet($offset, $value): void { $this->attributes[$offset] = $value; } /** * Unset the value at the given offset. * * @param TKey $offset * @return void */ public function offsetUnset($offset): void { unset($this->attributes[$offset]); } /** * Handle dynamic calls to the fluent instance to set attributes. * * @param TKey $method * @param array{0: ?TValue} $parameters * @return $this */ public function __call($method, $parameters) { $this->attributes[$method] = count($parameters) > 0 ? reset($parameters) : true; return $this; } /** * Dynamically retrieve the value of an attribute. * * @param TKey $key * @return TValue|null */ public function __get($key) { return $this->get($key); } /** * Dynamically set the value of an attribute. * * @param TKey $key * @param TValue $value * @return void */ public function __set($key, $value) { $this->offsetSet($key, $value); } /** * Dynamically check if an attribute is set. * * @param TKey $key * @return bool */ public function __isset($key) { return $this->offsetExists($key); } /** * Dynamically unset an attribute. * * @param TKey $key * @return void */ public function __unset($key) { $this->offsetUnset($key); } } PKy Z߷ E.Illuminate/Support/MultipleInstanceManager.phpnuW+Aapp = $app; } /** * Get the default instance name. * * @return string */ abstract public function getDefaultInstance(); /** * Set the default instance name. * * @param string $name * @return void */ abstract public function setDefaultInstance($name); /** * Get the instance specific configuration. * * @param string $name * @return array */ abstract public function getInstanceConfig($name); /** * Get an instance instance by name. * * @param string|null $name * @return mixed */ public function instance($name = null) { $name = $name ?: $this->getDefaultInstance(); return $this->instances[$name] = $this->get($name); } /** * Attempt to get an instance from the local cache. * * @param string $name * @return mixed */ protected function get($name) { return $this->instances[$name] ?? $this->resolve($name); } /** * Resolve the given instance. * * @param string $name * @return mixed * * @throws \InvalidArgumentException */ protected function resolve($name) { $config = $this->getInstanceConfig($name); if (is_null($config)) { throw new InvalidArgumentException("Instance [{$name}] is not defined."); } if (! array_key_exists('driver', $config)) { throw new RuntimeException("Instance [{$name}] does not specify a driver."); } if (isset($this->customCreators[$config['driver']])) { return $this->callCustomCreator($config); } else { $driverMethod = 'create'.ucfirst($config['driver']).'Driver'; if (method_exists($this, $driverMethod)) { return $this->{$driverMethod}($config); } else { throw new InvalidArgumentException("Instance driver [{$config['driver']}] is not supported."); } } } /** * Call a custom instance creator. * * @param array $config * @return mixed */ protected function callCustomCreator(array $config) { return $this->customCreators[$config['driver']]($this->app, $config); } /** * Unset the given instances. * * @param array|string|null $name * @return $this */ public function forgetInstance($name = null) { $name ??= $this->getDefaultInstance(); foreach ((array) $name as $instanceName) { if (isset($this->instances[$instanceName])) { unset($this->instances[$instanceName]); } } return $this; } /** * Disconnect the given instance and remove from local cache. * * @param string|null $name * @return void */ public function purge($name = null) { $name ??= $this->getDefaultInstance(); unset($this->instances[$name]); } /** * Register a custom instance creator Closure. * * @param string $name * @param \Closure $callback * @return $this */ public function extend($name, Closure $callback) { $this->customCreators[$name] = $callback->bindTo($this, $this); return $this; } /** * Dynamically call the default instance. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { return $this->instance()->$method(...$parameters); } } PKy Z(ee Illuminate/Support/Reflector.phpnuW+AisPublic(); } if (is_object($var[0]) && method_exists($class, '__call')) { return (new ReflectionMethod($class, '__call'))->isPublic(); } if (! is_object($var[0]) && method_exists($class, '__callStatic')) { return (new ReflectionMethod($class, '__callStatic'))->isPublic(); } return false; } /** * Get the class name of the given parameter's type, if possible. * * @param \ReflectionParameter $parameter * @return string|null */ public static function getParameterClassName($parameter) { $type = $parameter->getType(); if (! $type instanceof ReflectionNamedType || $type->isBuiltin()) { return; } return static::getTypeName($parameter, $type); } /** * Get the class names of the given parameter's type, including union types. * * @param \ReflectionParameter $parameter * @return array */ public static function getParameterClassNames($parameter) { $type = $parameter->getType(); if (! $type instanceof ReflectionUnionType) { return array_filter([static::getParameterClassName($parameter)]); } $unionTypes = []; foreach ($type->getTypes() as $listedType) { if (! $listedType instanceof ReflectionNamedType || $listedType->isBuiltin()) { continue; } $unionTypes[] = static::getTypeName($parameter, $listedType); } return array_filter($unionTypes); } /** * Get the given type's class name. * * @param \ReflectionParameter $parameter * @param \ReflectionNamedType $type * @return string */ protected static function getTypeName($parameter, $type) { $name = $type->getName(); if (! is_null($class = $parameter->getDeclaringClass())) { if ($name === 'self') { return $class->getName(); } if ($name === 'parent' && $parent = $class->getParentClass()) { return $parent->getName(); } } return $name; } /** * Determine if the parameter's type is a subclass of the given type. * * @param \ReflectionParameter $parameter * @param string $className * @return bool */ public static function isParameterSubclassOf($parameter, $className) { $paramClassName = static::getParameterClassName($parameter); return $paramClassName && (class_exists($paramClassName) || interface_exists($paramClassName)) && (new ReflectionClass($paramClassName))->isSubclassOf($className); } /** * Determine if the parameter's type is a Backed Enum with a string backing type. * * @param \ReflectionParameter $parameter * @return bool */ public static function isParameterBackedEnumWithStringBackingType($parameter) { $backedEnumClass = (string) $parameter->getType(); if (function_exists('enum_exists') && enum_exists($backedEnumClass)) { $reflectionBackedEnum = new ReflectionEnum($backedEnumClass); return $reflectionBackedEnum->isBacked() && $reflectionBackedEnum->getBackingType()->getName() == 'string'; } return false; } } PKy ZX,*Illuminate/Support/HigherOrderTapProxy.phpnuW+Atarget = $target; } /** * Dynamically pass method calls to the target. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { $this->target->{$method}(...$parameters); return $this->target; } } PKy Zw4v'v'Illuminate/Support/helpers.phpnuW+A $value) { if (is_numeric($key)) { $start++; $array[$start] = Arr::pull($array, $key); } } return $array; } } if (! function_exists('blank')) { /** * Determine if the given value is "blank". * * @param mixed $value * @return bool */ function blank($value) { if (is_null($value)) { return true; } if (is_string($value)) { return trim($value) === ''; } if (is_numeric($value) || is_bool($value)) { return false; } if ($value instanceof Countable) { return count($value) === 0; } return empty($value); } } if (! function_exists('class_basename')) { /** * Get the class "basename" of the given object / class. * * @param string|object $class * @return string */ function class_basename($class) { $class = is_object($class) ? get_class($class) : $class; return basename(str_replace('\\', '/', $class)); } } if (! function_exists('class_uses_recursive')) { /** * Returns all traits used by a class, its parent classes and trait of their traits. * * @param object|string $class * @return array */ function class_uses_recursive($class) { if (is_object($class)) { $class = get_class($class); } $results = []; foreach (array_reverse(class_parents($class)) + [$class => $class] as $class) { $results += trait_uses_recursive($class); } return array_unique($results); } } if (! function_exists('e')) { /** * Encode HTML special characters in a string. * * @param \Illuminate\Contracts\Support\DeferringDisplayableValue|\Illuminate\Contracts\Support\Htmlable|\BackedEnum|string|null $value * @param bool $doubleEncode * @return string */ function e($value, $doubleEncode = true) { if ($value instanceof DeferringDisplayableValue) { $value = $value->resolveDisplayableValue(); } if ($value instanceof Htmlable) { return $value->toHtml(); } if ($value instanceof BackedEnum) { $value = $value->value; } return htmlspecialchars($value ?? '', ENT_QUOTES, 'UTF-8', $doubleEncode); } } if (! function_exists('env')) { /** * Gets the value of an environment variable. * * @param string $key * @param mixed $default * @return mixed */ function env($key, $default = null) { return Env::get($key, $default); } } if (! function_exists('filled')) { /** * Determine if a value is "filled". * * @param mixed $value * @return bool */ function filled($value) { return ! blank($value); } } if (! function_exists('object_get')) { /** * Get an item from an object using "dot" notation. * * @param object $object * @param string|null $key * @param mixed $default * @return mixed */ function object_get($object, $key, $default = null) { if (is_null($key) || trim($key) === '') { return $object; } foreach (explode('.', $key) as $segment) { if (! is_object($object) || ! isset($object->{$segment})) { return value($default); } $object = $object->{$segment}; } return $object; } } if (! function_exists('optional')) { /** * Provide access to optional objects. * * @param mixed $value * @param callable|null $callback * @return mixed */ function optional($value = null, callable $callback = null) { if (is_null($callback)) { return new Optional($value); } elseif (! is_null($value)) { return $callback($value); } } } if (! function_exists('preg_replace_array')) { /** * Replace a given pattern with each value in the array in sequentially. * * @param string $pattern * @param array $replacements * @param string $subject * @return string */ function preg_replace_array($pattern, array $replacements, $subject) { return preg_replace_callback($pattern, function () use (&$replacements) { foreach ($replacements as $value) { return array_shift($replacements); } }, $subject); } } if (! function_exists('retry')) { /** * Retry an operation a given number of times. * * @param int|array $times * @param callable $callback * @param int|\Closure $sleepMilliseconds * @param callable|null $when * @return mixed * * @throws \Exception */ function retry($times, callable $callback, $sleepMilliseconds = 0, $when = null) { $attempts = 0; $backoff = []; if (is_array($times)) { $backoff = $times; $times = count($times) + 1; } beginning: $attempts++; $times--; try { return $callback($attempts); } catch (Exception $e) { if ($times < 1 || ($when && ! $when($e))) { throw $e; } $sleepMilliseconds = $backoff[$attempts - 1] ?? $sleepMilliseconds; if ($sleepMilliseconds) { usleep(value($sleepMilliseconds, $attempts, $e) * 1000); } goto beginning; } } } if (! function_exists('str')) { /** * Get a new stringable object from the given string. * * @param string|null $string * @return \Illuminate\Support\Stringable|mixed */ function str($string = null) { if (func_num_args() === 0) { return new class { public function __call($method, $parameters) { return Str::$method(...$parameters); } public function __toString() { return ''; } }; } return Str::of($string); } } if (! function_exists('tap')) { /** * Call the given Closure with the given value then return the value. * * @param mixed $value * @param callable|null $callback * @return mixed */ function tap($value, $callback = null) { if (is_null($callback)) { return new HigherOrderTapProxy($value); } $callback($value); return $value; } } if (! function_exists('throw_if')) { /** * Throw the given exception if the given condition is true. * * @param mixed $condition * @param \Throwable|string $exception * @param mixed ...$parameters * @return mixed * * @throws \Throwable */ function throw_if($condition, $exception = 'RuntimeException', ...$parameters) { if ($condition) { if (is_string($exception) && class_exists($exception)) { $exception = new $exception(...$parameters); } throw is_string($exception) ? new RuntimeException($exception) : $exception; } return $condition; } } if (! function_exists('throw_unless')) { /** * Throw the given exception unless the given condition is true. * * @param mixed $condition * @param \Throwable|string $exception * @param mixed ...$parameters * @return mixed * * @throws \Throwable */ function throw_unless($condition, $exception = 'RuntimeException', ...$parameters) { throw_if(! $condition, $exception, ...$parameters); return $condition; } } if (! function_exists('trait_uses_recursive')) { /** * Returns all traits used by a trait and its traits. * * @param string $trait * @return array */ function trait_uses_recursive($trait) { $traits = class_uses($trait) ?: []; foreach ($traits as $trait) { $traits += trait_uses_recursive($trait); } return $traits; } } if (! function_exists('transform')) { /** * Transform the given value if it is present. * * @param mixed $value * @param callable $callback * @param mixed $default * @return mixed|null */ function transform($value, callable $callback, $default = null) { if (filled($value)) { return $callback($value); } if (is_callable($default)) { return $default($value); } return $default; } } if (! function_exists('windows_os')) { /** * Determine whether the current environment is Windows based. * * @return bool */ function windows_os() { return PHP_OS_FAMILY === 'Windows'; } } if (! function_exists('with')) { /** * Return the given value, optionally passed through the given callback. * * @template TValue * @template TReturn * * @param TValue $value * @param (callable(TValue): (TReturn))|null $callback * @return ($callback is null ? TValue : TReturn) */ function with($value, callable $callback = null) { return is_null($callback) ? $value : $callback($value); } } PKy ZG{{+Illuminate/Support/Traits/ForwardsCalls.phpnuW+A{$method}(...$parameters); } catch (Error|BadMethodCallException $e) { $pattern = '~^Call to undefined method (?P[^:]+)::(?P[^\(]+)\(\)$~'; if (! preg_match($pattern, $e->getMessage(), $matches)) { throw $e; } if ($matches['class'] != get_class($object) || $matches['method'] != $method) { throw $e; } static::throwBadMethodCallException($method); } } /** * Forward a method call to the given object, returning $this if the forwarded call returned itself. * * @param mixed $object * @param string $method * @param array $parameters * @return mixed * * @throws \BadMethodCallException */ protected function forwardDecoratedCallTo($object, $method, $parameters) { $result = $this->forwardCallTo($object, $method, $parameters); if ($result === $object) { return $this; } return $result; } /** * Throw a bad method call exception for the given method. * * @param string $method * @return void * * @throws \BadMethodCallException */ protected static function throwBadMethodCallException($method) { throw new BadMethodCallException(sprintf( 'Call to undefined method %s::%s()', static::class, $method )); } } PKy Z]Juu)Illuminate/Support/Traits/Localizable.phpnuW+AgetLocale(); try { $app->setLocale($locale); return $callback(); } finally { $app->setLocale($original); } } } PKy Z-8j .Illuminate/Support/Traits/ReflectsClosures.phpnuW+AclosureParameterTypes($closure)); if (! $types) { throw new RuntimeException('The given Closure has no parameters.'); } if ($types[0] === null) { throw new RuntimeException('The first parameter of the given Closure is missing a type hint.'); } return $types[0]; } /** * Get the class names of the first parameter of the given Closure, including union types. * * @param \Closure $closure * @return array * * @throws \ReflectionException * @throws \RuntimeException */ protected function firstClosureParameterTypes(Closure $closure) { $reflection = new ReflectionFunction($closure); $types = collect($reflection->getParameters())->mapWithKeys(function ($parameter) { if ($parameter->isVariadic()) { return [$parameter->getName() => null]; } return [$parameter->getName() => Reflector::getParameterClassNames($parameter)]; })->filter()->values()->all(); if (empty($types)) { throw new RuntimeException('The given Closure has no parameters.'); } if (isset($types[0]) && empty($types[0])) { throw new RuntimeException('The first parameter of the given Closure is missing a type hint.'); } return $types[0]; } /** * Get the class names / types of the parameters of the given Closure. * * @param \Closure $closure * @return array * * @throws \ReflectionException */ protected function closureParameterTypes(Closure $closure) { $reflection = new ReflectionFunction($closure); return collect($reflection->getParameters())->mapWithKeys(function ($parameter) { if ($parameter->isVariadic()) { return [$parameter->getName() => null]; } return [$parameter->getName() => Reflector::getParameterClassName($parameter)]; })->all(); } } PKy Z 1Illuminate/Support/Traits/CapsuleManagerTrait.phpnuW+Acontainer = $container; if (! $this->container->bound('config')) { $this->container->instance('config', new Fluent); } } /** * Make this capsule instance available globally. * * @return void */ public function setAsGlobal() { static::$instance = $this; } /** * Get the IoC container instance. * * @return \Illuminate\Contracts\Container\Container */ public function getContainer() { return $this->container; } /** * Set the IoC container instance. * * @param \Illuminate\Contracts\Container\Container $container * @return void */ public function setContainer(Container $container) { $this->container = $container; } } PKy Z &!cc&Illuminate/Support/Traits/Tappable.phpnuW+A $needles * @param bool $ignoreCase * @return bool */ public static function contains($haystack, $needles, $ignoreCase = false) { if ($ignoreCase) { $haystack = mb_strtolower($haystack); } if (! is_iterable($needles)) { $needles = (array) $needles; } foreach ($needles as $needle) { if ($ignoreCase) { $needle = mb_strtolower($needle); } if ($needle !== '' && str_contains($haystack, $needle)) { return true; } } return false; } /** * Determine if a given string contains all array values. * * @param string $haystack * @param iterable $needles * @param bool $ignoreCase * @return bool */ public static function containsAll($haystack, $needles, $ignoreCase = false) { foreach ($needles as $needle) { if (! static::contains($haystack, $needle, $ignoreCase)) { return false; } } return true; } /** * Determine if a given string ends with a given substring. * * @param string $haystack * @param string|iterable $needles * @return bool */ public static function endsWith($haystack, $needles) { if (! is_iterable($needles)) { $needles = (array) $needles; } foreach ($needles as $needle) { if ((string) $needle !== '' && str_ends_with($haystack, $needle)) { return true; } } return false; } /** * Extracts an excerpt from text that matches the first instance of a phrase. * * @param string $text * @param string $phrase * @param array $options * @return string|null */ public static function excerpt($text, $phrase = '', $options = []) { $radius = $options['radius'] ?? 100; $omission = $options['omission'] ?? '...'; preg_match('/^(.*?)('.preg_quote((string) $phrase).')(.*)$/iu', (string) $text, $matches); if (empty($matches)) { return null; } $start = ltrim($matches[1]); $start = str(mb_substr($start, max(mb_strlen($start, 'UTF-8') - $radius, 0), $radius, 'UTF-8'))->ltrim()->unless( fn ($startWithRadius) => $startWithRadius->exactly($start), fn ($startWithRadius) => $startWithRadius->prepend($omission), ); $end = rtrim($matches[3]); $end = str(mb_substr($end, 0, $radius, 'UTF-8'))->rtrim()->unless( fn ($endWithRadius) => $endWithRadius->exactly($end), fn ($endWithRadius) => $endWithRadius->append($omission), ); return $start->append($matches[2], $end)->toString(); } /** * Cap a string with a single instance of a given value. * * @param string $value * @param string $cap * @return string */ public static function finish($value, $cap) { $quoted = preg_quote($cap, '/'); return preg_replace('/(?:'.$quoted.')+$/u', '', $value).$cap; } /** * Wrap the string with the given strings. * * @param string $value * @param string $before * @param string|null $after * @return string */ public static function wrap($value, $before, $after = null) { return $before.$value.($after ??= $before); } /** * Determine if a given string matches a given pattern. * * @param string|iterable $pattern * @param string $value * @return bool */ public static function is($pattern, $value) { $value = (string) $value; if (! is_iterable($pattern)) { $pattern = [$pattern]; } foreach ($pattern as $pattern) { $pattern = (string) $pattern; // If the given value is an exact match we can of course return true right // from the beginning. Otherwise, we will translate asterisks and do an // actual pattern match against the two strings to see if they match. if ($pattern === $value) { return true; } $pattern = preg_quote($pattern, '#'); // Asterisks are translated into zero-or-more regular expression wildcards // to make it convenient to check if the strings starts with the given // pattern such as "library/*", making any string check convenient. $pattern = str_replace('\*', '.*', $pattern); if (preg_match('#^'.$pattern.'\z#u', $value) === 1) { return true; } } return false; } /** * Determine if a given string is 7 bit ASCII. * * @param string $value * @return bool */ public static function isAscii($value) { return ASCII::is_ascii((string) $value); } /** * Determine if a given string is valid JSON. * * @param string $value * @return bool */ public static function isJson($value) { if (! is_string($value)) { return false; } try { json_decode($value, true, 512, JSON_THROW_ON_ERROR); } catch (JsonException) { return false; } return true; } /** * Determine if a given string is a valid UUID. * * @param string $value * @return bool */ public static function isUuid($value) { if (! is_string($value)) { return false; } return preg_match('/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iD', $value) > 0; } /** * Determine if a given string is a valid ULID. * * @param string $value * @return bool */ public static function isUlid($value) { if (! is_string($value)) { return false; } return Ulid::isValid($value); } /** * Convert a string to kebab case. * * @param string $value * @return string */ public static function kebab($value) { return static::snake($value, '-'); } /** * Return the length of the given string. * * @param string $value * @param string|null $encoding * @return int */ public static function length($value, $encoding = null) { if ($encoding) { return mb_strlen($value, $encoding); } return mb_strlen($value); } /** * Limit the number of characters in a string. * * @param string $value * @param int $limit * @param string $end * @return string */ public static function limit($value, $limit = 100, $end = '...') { if (mb_strwidth($value, 'UTF-8') <= $limit) { return $value; } return rtrim(mb_strimwidth($value, 0, $limit, '', 'UTF-8')).$end; } /** * Convert the given string to lower-case. * * @param string $value * @return string */ public static function lower($value) { return mb_strtolower($value, 'UTF-8'); } /** * Limit the number of words in a string. * * @param string $value * @param int $words * @param string $end * @return string */ public static function words($value, $words = 100, $end = '...') { preg_match('/^\s*+(?:\S++\s*+){1,'.$words.'}/u', $value, $matches); if (! isset($matches[0]) || static::length($value) === static::length($matches[0])) { return $value; } return rtrim($matches[0]).$end; } /** * Converts GitHub flavored Markdown into HTML. * * @param string $string * @param array $options * @return string */ public static function markdown($string, array $options = []) { $converter = new GithubFlavoredMarkdownConverter($options); return (string) $converter->convert($string); } /** * Converts inline Markdown into HTML. * * @param string $string * @param array $options * @return string */ public static function inlineMarkdown($string, array $options = []) { $environment = new Environment($options); $environment->addExtension(new GithubFlavoredMarkdownExtension()); $environment->addExtension(new InlinesOnlyExtension()); $converter = new MarkdownConverter($environment); return (string) $converter->convert($string); } /** * Masks a portion of a string with a repeated character. * * @param string $string * @param string $character * @param int $index * @param int|null $length * @param string $encoding * @return string */ public static function mask($string, $character, $index, $length = null, $encoding = 'UTF-8') { if ($character === '') { return $string; } $segment = mb_substr($string, $index, $length, $encoding); if ($segment === '') { return $string; } $strlen = mb_strlen($string, $encoding); $startIndex = $index; if ($index < 0) { $startIndex = $index < -$strlen ? 0 : $strlen + $index; } $start = mb_substr($string, 0, $startIndex, $encoding); $segmentLen = mb_strlen($segment, $encoding); $end = mb_substr($string, $startIndex + $segmentLen); return $start.str_repeat(mb_substr($character, 0, 1, $encoding), $segmentLen).$end; } /** * Get the string matching the given pattern. * * @param string $pattern * @param string $subject * @return string */ public static function match($pattern, $subject) { preg_match($pattern, $subject, $matches); if (! $matches) { return ''; } return $matches[1] ?? $matches[0]; } /** * Get the string matching the given pattern. * * @param string $pattern * @param string $subject * @return \Illuminate\Support\Collection */ public static function matchAll($pattern, $subject) { preg_match_all($pattern, $subject, $matches); if (empty($matches[0])) { return collect(); } return collect($matches[1] ?? $matches[0]); } /** * Pad both sides of a string with another. * * @param string $value * @param int $length * @param string $pad * @return string */ public static function padBoth($value, $length, $pad = ' ') { $short = max(0, $length - mb_strlen($value)); $shortLeft = floor($short / 2); $shortRight = ceil($short / 2); return mb_substr(str_repeat($pad, $shortLeft), 0, $shortLeft). $value. mb_substr(str_repeat($pad, $shortRight), 0, $shortRight); } /** * Pad the left side of a string with another. * * @param string $value * @param int $length * @param string $pad * @return string */ public static function padLeft($value, $length, $pad = ' ') { $short = max(0, $length - mb_strlen($value)); return mb_substr(str_repeat($pad, $short), 0, $short).$value; } /** * Pad the right side of a string with another. * * @param string $value * @param int $length * @param string $pad * @return string */ public static function padRight($value, $length, $pad = ' ') { $short = max(0, $length - mb_strlen($value)); return $value.mb_substr(str_repeat($pad, $short), 0, $short); } /** * Parse a Class[@]method style callback into class and method. * * @param string $callback * @param string|null $default * @return array */ public static function parseCallback($callback, $default = null) { return static::contains($callback, '@') ? explode('@', $callback, 2) : [$callback, $default]; } /** * Get the plural form of an English word. * * @param string $value * @param int|array|\Countable $count * @return string */ public static function plural($value, $count = 2) { return Pluralizer::plural($value, $count); } /** * Pluralize the last word of an English, studly caps case string. * * @param string $value * @param int|array|\Countable $count * @return string */ public static function pluralStudly($value, $count = 2) { $parts = preg_split('/(.)(?=[A-Z])/u', $value, -1, PREG_SPLIT_DELIM_CAPTURE); $lastWord = array_pop($parts); return implode('', $parts).self::plural($lastWord, $count); } /** * Generate a more truly "random" alpha-numeric string. * * @param int $length * @return string */ public static function random($length = 16) { return (static::$randomStringFactory ?? function ($length) { $string = ''; while (($len = strlen($string)) < $length) { $size = $length - $len; $bytesSize = (int) ceil($size / 3) * 3; $bytes = random_bytes($bytesSize); $string .= substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $size); } return $string; })($length); } /** * Set the callable that will be used to generate random strings. * * @param callable|null $factory * @return void */ public static function createRandomStringsUsing(callable $factory = null) { static::$randomStringFactory = $factory; } /** * Set the sequence that will be used to generate random strings. * * @param array $sequence * @param callable|null $whenMissing * @return void */ public static function createRandomStringsUsingSequence(array $sequence, $whenMissing = null) { $next = 0; $whenMissing ??= function ($length) use (&$next) { $factoryCache = static::$randomStringFactory; static::$randomStringFactory = null; $randomString = static::random($length); static::$randomStringFactory = $factoryCache; $next++; return $randomString; }; static::createRandomStringsUsing(function ($length) use (&$next, $sequence, $whenMissing) { if (array_key_exists($next, $sequence)) { return $sequence[$next++]; } return $whenMissing($length); }); } /** * Indicate that random strings should be created normally and not using a custom factory. * * @return void */ public static function createRandomStringsNormally() { static::$randomStringFactory = null; } /** * Repeat the given string. * * @param string $string * @param int $times * @return string */ public static function repeat(string $string, int $times) { return str_repeat($string, $times); } /** * Replace a given value in the string sequentially with an array. * * @param string $search * @param iterable $replace * @param string $subject * @return string */ public static function replaceArray($search, $replace, $subject) { if ($replace instanceof Traversable) { $replace = collect($replace)->all(); } $segments = explode($search, $subject); $result = array_shift($segments); foreach ($segments as $segment) { $result .= (array_shift($replace) ?? $search).$segment; } return $result; } /** * Replace the given value in the given string. * * @param string|iterable $search * @param string|iterable $replace * @param string|iterable $subject * @return string */ public static function replace($search, $replace, $subject) { if ($search instanceof Traversable) { $search = collect($search)->all(); } if ($replace instanceof Traversable) { $replace = collect($replace)->all(); } if ($subject instanceof Traversable) { $subject = collect($subject)->all(); } return str_replace($search, $replace, $subject); } /** * Replace the first occurrence of a given value in the string. * * @param string $search * @param string $replace * @param string $subject * @return string */ public static function replaceFirst($search, $replace, $subject) { $search = (string) $search; if ($search === '') { return $subject; } $position = strpos($subject, $search); if ($position !== false) { return substr_replace($subject, $replace, $position, strlen($search)); } return $subject; } /** * Replace the last occurrence of a given value in the string. * * @param string $search * @param string $replace * @param string $subject * @return string */ public static function replaceLast($search, $replace, $subject) { if ($search === '') { return $subject; } $position = strrpos($subject, $search); if ($position !== false) { return substr_replace($subject, $replace, $position, strlen($search)); } return $subject; } /** * Remove any occurrence of the given string in the subject. * * @param string|iterable $search * @param string $subject * @param bool $caseSensitive * @return string */ public static function remove($search, $subject, $caseSensitive = true) { if ($search instanceof Traversable) { $search = collect($search)->all(); } $subject = $caseSensitive ? str_replace($search, '', $subject) : str_ireplace($search, '', $subject); return $subject; } /** * Reverse the given string. * * @param string $value * @return string */ public static function reverse(string $value) { return implode(array_reverse(mb_str_split($value))); } /** * Begin a string with a single instance of a given value. * * @param string $value * @param string $prefix * @return string */ public static function start($value, $prefix) { $quoted = preg_quote($prefix, '/'); return $prefix.preg_replace('/^(?:'.$quoted.')+/u', '', $value); } /** * Convert the given string to upper-case. * * @param string $value * @return string */ public static function upper($value) { return mb_strtoupper($value, 'UTF-8'); } /** * Convert the given string to title case. * * @param string $value * @return string */ public static function title($value) { return mb_convert_case($value, MB_CASE_TITLE, 'UTF-8'); } /** * Convert the given string to title case for each word. * * @param string $value * @return string */ public static function headline($value) { $parts = explode(' ', $value); $parts = count($parts) > 1 ? array_map([static::class, 'title'], $parts) : array_map([static::class, 'title'], static::ucsplit(implode('_', $parts))); $collapsed = static::replace(['-', '_', ' '], '_', implode('_', $parts)); return implode(' ', array_filter(explode('_', $collapsed))); } /** * Get the singular form of an English word. * * @param string $value * @return string */ public static function singular($value) { return Pluralizer::singular($value); } /** * Generate a URL friendly "slug" from a given string. * * @param string $title * @param string $separator * @param string|null $language * @param array $dictionary * @return string */ public static function slug($title, $separator = '-', $language = 'en', $dictionary = ['@' => 'at']) { $title = $language ? static::ascii($title, $language) : $title; // Convert all dashes/underscores into separator $flip = $separator === '-' ? '_' : '-'; $title = preg_replace('!['.preg_quote($flip).']+!u', $separator, $title); // Replace dictionary words foreach ($dictionary as $key => $value) { $dictionary[$key] = $separator.$value.$separator; } $title = str_replace(array_keys($dictionary), array_values($dictionary), $title); // Remove all characters that are not the separator, letters, numbers, or whitespace $title = preg_replace('![^'.preg_quote($separator).'\pL\pN\s]+!u', '', static::lower($title)); // Replace all separator characters and whitespace by a single separator $title = preg_replace('!['.preg_quote($separator).'\s]+!u', $separator, $title); return trim($title, $separator); } /** * Convert a string to snake case. * * @param string $value * @param string $delimiter * @return string */ public static function snake($value, $delimiter = '_') { $key = $value; if (isset(static::$snakeCache[$key][$delimiter])) { return static::$snakeCache[$key][$delimiter]; } if (! ctype_lower($value)) { $value = preg_replace('/\s+/u', '', ucwords($value)); $value = static::lower(preg_replace('/(.)(?=[A-Z])/u', '$1'.$delimiter, $value)); } return static::$snakeCache[$key][$delimiter] = $value; } /** * Remove all "extra" blank space from the given string. * * @param string $value * @return string */ public static function squish($value) { return preg_replace('~(\s|\x{3164})+~u', ' ', preg_replace('~^[\s\x{FEFF}]+|[\s\x{FEFF}]+$~u', '', $value)); } /** * Determine if a given string starts with a given substring. * * @param string $haystack * @param string|iterable $needles * @return bool */ public static function startsWith($haystack, $needles) { if (! is_iterable($needles)) { $needles = [$needles]; } foreach ($needles as $needle) { if ((string) $needle !== '' && str_starts_with($haystack, $needle)) { return true; } } return false; } /** * Convert a value to studly caps case. * * @param string $value * @return string */ public static function studly($value) { $key = $value; if (isset(static::$studlyCache[$key])) { return static::$studlyCache[$key]; } $words = explode(' ', static::replace(['-', '_'], ' ', $value)); $studlyWords = array_map(fn ($word) => static::ucfirst($word), $words); return static::$studlyCache[$key] = implode($studlyWords); } /** * Returns the portion of the string specified by the start and length parameters. * * @param string $string * @param int $start * @param int|null $length * @param string $encoding * @return string */ public static function substr($string, $start, $length = null, $encoding = 'UTF-8') { return mb_substr($string, $start, $length, $encoding); } /** * Returns the number of substring occurrences. * * @param string $haystack * @param string $needle * @param int $offset * @param int|null $length * @return int */ public static function substrCount($haystack, $needle, $offset = 0, $length = null) { if (! is_null($length)) { return substr_count($haystack, $needle, $offset, $length); } return substr_count($haystack, $needle, $offset); } /** * Replace text within a portion of a string. * * @param string|string[] $string * @param string|string[] $replace * @param int|int[] $offset * @param int|int[]|null $length * @return string|string[] */ public static function substrReplace($string, $replace, $offset = 0, $length = null) { if ($length === null) { $length = strlen($string); } return substr_replace($string, $replace, $offset, $length); } /** * Swap multiple keywords in a string with other keywords. * * @param array $map * @param string $subject * @return string */ public static function swap(array $map, $subject) { return strtr($subject, $map); } /** * Make a string's first character lowercase. * * @param string $string * @return string */ public static function lcfirst($string) { return static::lower(static::substr($string, 0, 1)).static::substr($string, 1); } /** * Make a string's first character uppercase. * * @param string $string * @return string */ public static function ucfirst($string) { return static::upper(static::substr($string, 0, 1)).static::substr($string, 1); } /** * Split a string into pieces by uppercase characters. * * @param string $string * @return string[] */ public static function ucsplit($string) { return preg_split('/(?=\p{Lu})/u', $string, -1, PREG_SPLIT_NO_EMPTY); } /** * Get the number of words a string contains. * * @param string $string * @param string|null $characters * @return int */ public static function wordCount($string, $characters = null) { return str_word_count($string, 0, $characters); } /** * Generate a UUID (version 4). * * @return \Ramsey\Uuid\UuidInterface */ public static function uuid() { return static::$uuidFactory ? call_user_func(static::$uuidFactory) : Uuid::uuid4(); } /** * Generate a time-ordered UUID (version 4). * * @return \Ramsey\Uuid\UuidInterface */ public static function orderedUuid() { if (static::$uuidFactory) { return call_user_func(static::$uuidFactory); } $factory = new UuidFactory; $factory->setRandomGenerator(new CombGenerator( $factory->getRandomGenerator(), $factory->getNumberConverter() )); $factory->setCodec(new TimestampFirstCombCodec( $factory->getUuidBuilder() )); return $factory->uuid4(); } /** * Set the callable that will be used to generate UUIDs. * * @param callable|null $factory * @return void */ public static function createUuidsUsing(callable $factory = null) { static::$uuidFactory = $factory; } /** * Set the sequence that will be used to generate UUIDs. * * @param array $sequence * @param callable|null $whenMissing * @return void */ public static function createUuidsUsingSequence(array $sequence, $whenMissing = null) { $next = 0; $whenMissing ??= function () use (&$next) { $factoryCache = static::$uuidFactory; static::$uuidFactory = null; $uuid = static::uuid(); static::$uuidFactory = $factoryCache; $next++; return $uuid; }; static::createUuidsUsing(function () use (&$next, $sequence, $whenMissing) { if (array_key_exists($next, $sequence)) { return $sequence[$next++]; } return $whenMissing(); }); } /** * Always return the same UUID when generating new UUIDs. * * @param \Closure|null $callback * @return \Ramsey\Uuid\UuidInterface */ public static function freezeUuids(Closure $callback = null) { $uuid = Str::uuid(); Str::createUuidsUsing(fn () => $uuid); if ($callback !== null) { try { $callback($uuid); } finally { Str::createUuidsNormally(); } } return $uuid; } /** * Indicate that UUIDs should be created normally and not using a custom factory. * * @return void */ public static function createUuidsNormally() { static::$uuidFactory = null; } /** * Generate a ULID. * * @return \Symfony\Component\Uid\Ulid */ public static function ulid() { return new Ulid(); } /** * Remove all strings from the casing caches. * * @return void */ public static function flushCache() { static::$snakeCache = []; static::$camelCache = []; static::$studlyCache = []; } } PKy Zy\ \ !Illuminate/Support/Pluralizer.phpnuW+Apluralize($value); return static::matchCase($plural, $value); } /** * Get the singular form of an English word. * * @param string $value * @return string */ public static function singular($value) { $singular = static::inflector()->singularize($value); return static::matchCase($singular, $value); } /** * Determine if the given value is uncountable. * * @param string $value * @return bool */ protected static function uncountable($value) { return in_array(strtolower($value), static::$uncountable); } /** * Attempt to match the case on two strings. * * @param string $value * @param string $comparison * @return string */ protected static function matchCase($value, $comparison) { $functions = ['mb_strtolower', 'mb_strtoupper', 'ucfirst', 'ucwords']; foreach ($functions as $function) { if ($function($comparison) === $comparison) { return $function($value); } } return $value; } /** * Get the inflector instance. * * @return \Doctrine\Inflector\Inflector */ public static function inflector() { if (is_null(static::$inflector)) { static::$inflector = InflectorFactory::createForLanguage(static::$language)->build(); } return static::$inflector; } /** * Specify the language that should be used by the inflector. * * @param string $language * @return void */ public static function useLanguage(string $language) { static::$language = $language; static::$inflector = null; } } PKy Z#Illuminate/Support/ProcessUtils.phpnuW+A 2 && $char === $arg[0] && $char === $arg[strlen($arg) - 1]; } } PKy Z@-Illuminate/Support/ConfigurationUrlParser.phpnuW+A 'sqlsrv', 'mysql2' => 'mysql', // RDS 'postgres' => 'pgsql', 'postgresql' => 'pgsql', 'sqlite3' => 'sqlite', 'redis' => 'tcp', 'rediss' => 'tls', ]; /** * Parse the database configuration, hydrating options using a database configuration URL if possible. * * @param array|string $config * @return array */ public function parseConfiguration($config) { if (is_string($config)) { $config = ['url' => $config]; } $url = Arr::pull($config, 'url'); if (! $url) { return $config; } $rawComponents = $this->parseUrl($url); $decodedComponents = $this->parseStringsToNativeTypes( array_map('rawurldecode', $rawComponents) ); return array_merge( $config, $this->getPrimaryOptions($decodedComponents), $this->getQueryOptions($rawComponents) ); } /** * Get the primary database connection options. * * @param array $url * @return array */ protected function getPrimaryOptions($url) { return array_filter([ 'driver' => $this->getDriver($url), 'database' => $this->getDatabase($url), 'host' => $url['host'] ?? null, 'port' => $url['port'] ?? null, 'username' => $url['user'] ?? null, 'password' => $url['pass'] ?? null, ], fn ($value) => ! is_null($value)); } /** * Get the database driver from the URL. * * @param array $url * @return string|null */ protected function getDriver($url) { $alias = $url['scheme'] ?? null; if (! $alias) { return; } return static::$driverAliases[$alias] ?? $alias; } /** * Get the database name from the URL. * * @param array $url * @return string|null */ protected function getDatabase($url) { $path = $url['path'] ?? null; return $path && $path !== '/' ? substr($path, 1) : null; } /** * Get all of the additional database options from the query string. * * @param array $url * @return array */ protected function getQueryOptions($url) { $queryString = $url['query'] ?? null; if (! $queryString) { return []; } $query = []; parse_str($queryString, $query); return $this->parseStringsToNativeTypes($query); } /** * Parse the string URL to an array of components. * * @param string $url * @return array * * @throws \InvalidArgumentException */ protected function parseUrl($url) { $url = preg_replace('#^(sqlite3?):///#', '$1://null/', $url); $parsedUrl = parse_url($url); if ($parsedUrl === false) { throw new InvalidArgumentException('The database configuration URL is malformed.'); } return $parsedUrl; } /** * Convert string casted values to their native types. * * @param mixed $value * @return mixed */ protected function parseStringsToNativeTypes($value) { if (is_array($value)) { return array_map([$this, 'parseStringsToNativeTypes'], $value); } if (! is_string($value)) { return $value; } $parsedValue = json_decode($value, true); if (json_last_error() === JSON_ERROR_NONE) { return $parsedValue; } return $value; } /** * Get all of the current drivers' aliases. * * @return array */ public static function getDriverAliases() { return static::$driverAliases; } /** * Add the given driver alias to the driver aliases array. * * @param string $alias * @param string $driver * @return void */ public static function addDriverAlias($alias, $driver) { static::$driverAliases[$alias] = $driver; } } PKy ZE= Illuminate/Support/composer.jsonnuW+A{ "name": "illuminate/support", "description": "The Illuminate Support package.", "license": "MIT", "homepage": "https://laravel.com", "support": { "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, "authors": [ { "name": "Taylor Otwell", "email": "taylor@laravel.com" } ], "require": { "php": "^8.0.2", "ext-ctype": "*", "ext-filter": "*", "ext-mbstring": "*", "doctrine/inflector": "^2.0", "illuminate/collections": "^9.0", "illuminate/conditionable": "^9.0", "illuminate/contracts": "^9.0", "illuminate/macroable": "^9.0", "nesbot/carbon": "^2.62.1", "voku/portable-ascii": "^2.0" }, "conflict": { "tightenco/collect": "<5.5.33" }, "autoload": { "psr-4": { "Illuminate\\Support\\": "" }, "files": [ "helpers.php" ] }, "extra": { "branch-alias": { "dev-master": "9.x-dev" } }, "suggest": { "illuminate/filesystem": "Required to use the composer class (^9.0).", "league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.0.2).", "ramsey/uuid": "Required to use Str::uuid() (^4.7).", "symfony/process": "Required to use the composer class (^6.0).", "symfony/uid": "Required to use Str::ulid() (^6.0).", "symfony/var-dumper": "Required to use the dd function (^6.0).", "vlucas/phpdotenv": "Required to use the Env class and env helper (^5.4.1)." }, "config": { "sort-packages": true }, "minimum-stability": "dev" } PKy ZsIlluminate/Support/Lottery.phpnuW+A 1) { throw new RuntimeException('Float must not be greater than 1.'); } $this->chances = $chances; $this->outOf = $outOf; } /** * Create a new Lottery instance. * * @param int|float $chances * @param int|null $outOf * @return static */ public static function odds($chances, $outOf = null) { return new static($chances, $outOf); } /** * Set the winner callback. * * @param callable $callback * @return $this */ public function winner($callback) { $this->winner = $callback; return $this; } /** * Set the loser callback. * * @param callable $callback * @return $this */ public function loser($callback) { $this->loser = $callback; return $this; } /** * Run the lottery. * * @param mixed ...$args * @return mixed */ public function __invoke(...$args) { return $this->runCallback(...$args); } /** * Run the lottery. * * @param null|int $times * @return mixed */ public function choose($times = null) { if ($times === null) { return $this->runCallback(); } $results = []; for ($i = 0; $i < $times; $i++) { $results[] = $this->runCallback(); } return $results; } /** * Run the winner or loser callback, randomly. * * @param mixed ...$args * @return callable */ protected function runCallback(...$args) { return $this->wins() ? ($this->winner ?? fn () => true)(...$args) : ($this->loser ?? fn () => false)(...$args); } /** * Determine if the lottery "wins" or "loses". * * @return bool */ protected function wins() { return static::resultFactory()($this->chances, $this->outOf); } /** * The factory that determines the lottery result. * * @return callable */ protected static function resultFactory() { return static::$resultFactory ?? fn ($chances, $outOf) => $outOf === null ? random_int(0, PHP_INT_MAX) / PHP_INT_MAX <= $chances : random_int(1, $outOf) <= $chances; } /** * Force the lottery to always result in a win. * * @param callable|null $callback * @return void */ public static function alwaysWin($callback = null) { self::setResultFactory(fn () => true); if ($callback === null) { return; } $callback(); static::determineResultNormally(); } /** * Force the lottery to always result in a lose. * * @param callable|null $callback * @return void */ public static function alwaysLose($callback = null) { self::setResultFactory(fn () => false); if ($callback === null) { return; } $callback(); static::determineResultNormally(); } /** * Set the sequence that will be used to determine lottery results. * * @param array $sequence * @param callable|null $whenMissing * @return void */ public static function fix($sequence, $whenMissing = null) { return static::forceResultWithSequence($sequence, $whenMissing); } /** * Set the sequence that will be used to determine lottery results. * * @param array $sequence * @param callable|null $whenMissing * @return void */ public static function forceResultWithSequence($sequence, $whenMissing = null) { $next = 0; $whenMissing ??= function ($chances, $outOf) use (&$next) { $factoryCache = static::$resultFactory; static::$resultFactory = null; $result = static::resultFactory()($chances, $outOf); static::$resultFactory = $factoryCache; $next++; return $result; }; static::setResultFactory(function ($chances, $outOf) use (&$next, $sequence, $whenMissing) { if (array_key_exists($next, $sequence)) { return $sequence[$next++]; } return $whenMissing($chances, $outOf); }); } /** * Indicate that the lottery results should be determined normally. * * @return void */ public static function determineResultNormally() { static::$resultFactory = null; } /** * Set the factory that should be used to determine the lottery results. * * @param callable $factory * @return void */ public static function setResultFactory($factory) { self::$resultFactory = $factory; } } PKy Z"Illuminate/Support/DateFactory.phpnuW+A$method(...$parameters); } $dateClass = static::$dateClass ?: $defaultClassName; // Check if the date can be created using the public class method... if (method_exists($dateClass, $method) || method_exists($dateClass, 'hasMacro') && $dateClass::hasMacro($method)) { return $dateClass::$method(...$parameters); } // If that fails, create the date with the default class... $date = $defaultClassName::$method(...$parameters); // If the configured class has an "instance" method, we'll try to pass our date into there... if (method_exists($dateClass, 'instance')) { return $dateClass::instance($date); } // Otherwise, assume the configured class has a DateTime compatible constructor... return new $dateClass($date->format('Y-m-d H:i:s.u'), $date->getTimezone()); } } PKy ZOP  /Illuminate/Routing/RouteCollectionInterface.phpnuW+Auri = $uri; $this->methods = (array) $methods; $this->action = Arr::except($this->parseAction($action), ['prefix']); if (in_array('GET', $this->methods) && ! in_array('HEAD', $this->methods)) { $this->methods[] = 'HEAD'; } $this->prefix(is_array($action) ? Arr::get($action, 'prefix') : ''); } /** * Parse the route action into a standard array. * * @param callable|array|null $action * @return array * * @throws \UnexpectedValueException */ protected function parseAction($action) { return RouteAction::parse($this->uri, $action); } /** * Run the route action and return the response. * * @return mixed */ public function run() { $this->container = $this->container ?: new Container; try { if ($this->isControllerAction()) { return $this->runController(); } return $this->runCallable(); } catch (HttpResponseException $e) { return $e->getResponse(); } } /** * Checks whether the route's action is a controller. * * @return bool */ protected function isControllerAction() { return is_string($this->action['uses']) && ! $this->isSerializedClosure(); } /** * Run the route action and return the response. * * @return mixed */ protected function runCallable() { $callable = $this->action['uses']; if ($this->isSerializedClosure()) { $callable = unserialize($this->action['uses'])->getClosure(); } return $this->container[CallableDispatcher::class]->dispatch($this, $callable); } /** * Determine if the route action is a serialized Closure. * * @return bool */ protected function isSerializedClosure() { return RouteAction::containsSerializedClosure($this->action); } /** * Run the route action and return the response. * * @return mixed * * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ protected function runController() { return $this->controllerDispatcher()->dispatch( $this, $this->getController(), $this->getControllerMethod() ); } /** * Get the controller instance for the route. * * @return mixed */ public function getController() { if (! $this->controller) { $class = $this->getControllerClass(); $this->controller = $this->container->make(ltrim($class, '\\')); } return $this->controller; } /** * Get the controller class used for the route. * * @return string */ public function getControllerClass() { return $this->parseControllerCallback()[0]; } /** * Get the controller method used for the route. * * @return string */ protected function getControllerMethod() { return $this->parseControllerCallback()[1]; } /** * Parse the controller. * * @return array */ protected function parseControllerCallback() { return Str::parseCallback($this->action['uses']); } /** * Flush the cached container instance on the route. * * @return void */ public function flushController() { $this->computedMiddleware = null; $this->controller = null; } /** * Determine if the route matches a given request. * * @param \Illuminate\Http\Request $request * @param bool $includingMethod * @return bool */ public function matches(Request $request, $includingMethod = true) { $this->compileRoute(); foreach (self::getValidators() as $validator) { if (! $includingMethod && $validator instanceof MethodValidator) { continue; } if (! $validator->matches($this, $request)) { return false; } } return true; } /** * Compile the route into a Symfony CompiledRoute instance. * * @return \Symfony\Component\Routing\CompiledRoute */ protected function compileRoute() { if (! $this->compiled) { $this->compiled = $this->toSymfonyRoute()->compile(); } return $this->compiled; } /** * Bind the route to a given request for execution. * * @param \Illuminate\Http\Request $request * @return $this */ public function bind(Request $request) { $this->compileRoute(); $this->parameters = (new RouteParameterBinder($this)) ->parameters($request); $this->originalParameters = $this->parameters; return $this; } /** * Determine if the route has parameters. * * @return bool */ public function hasParameters() { return isset($this->parameters); } /** * Determine a given parameter exists from the route. * * @param string $name * @return bool */ public function hasParameter($name) { if ($this->hasParameters()) { return array_key_exists($name, $this->parameters()); } return false; } /** * Get a given parameter from the route. * * @param string $name * @param string|object|null $default * @return string|object|null */ public function parameter($name, $default = null) { return Arr::get($this->parameters(), $name, $default); } /** * Get original value of a given parameter from the route. * * @param string $name * @param string|null $default * @return string|null */ public function originalParameter($name, $default = null) { return Arr::get($this->originalParameters(), $name, $default); } /** * Set a parameter to the given value. * * @param string $name * @param string|object|null $value * @return void */ public function setParameter($name, $value) { $this->parameters(); $this->parameters[$name] = $value; } /** * Unset a parameter on the route if it is set. * * @param string $name * @return void */ public function forgetParameter($name) { $this->parameters(); unset($this->parameters[$name]); } /** * Get the key / value list of parameters for the route. * * @return array * * @throws \LogicException */ public function parameters() { if (isset($this->parameters)) { return $this->parameters; } throw new LogicException('Route is not bound.'); } /** * Get the key / value list of original parameters for the route. * * @return array * * @throws \LogicException */ public function originalParameters() { if (isset($this->originalParameters)) { return $this->originalParameters; } throw new LogicException('Route is not bound.'); } /** * Get the key / value list of parameters without null values. * * @return array */ public function parametersWithoutNulls() { return array_filter($this->parameters(), fn ($p) => ! is_null($p)); } /** * Get all of the parameter names for the route. * * @return array */ public function parameterNames() { if (isset($this->parameterNames)) { return $this->parameterNames; } return $this->parameterNames = $this->compileParameterNames(); } /** * Get the parameter names for the route. * * @return array */ protected function compileParameterNames() { preg_match_all('/\{(.*?)\}/', $this->getDomain().$this->uri, $matches); return array_map(fn ($m) => trim($m, '?'), $matches[1]); } /** * Get the parameters that are listed in the route / controller signature. * * @param array $conditions * @return array */ public function signatureParameters($conditions = []) { if (is_string($conditions)) { $conditions = ['subClass' => $conditions]; } return RouteSignatureParameters::fromAction($this->action, $conditions); } /** * Get the binding field for the given parameter. * * @param string|int $parameter * @return string|null */ public function bindingFieldFor($parameter) { $fields = is_int($parameter) ? array_values($this->bindingFields) : $this->bindingFields; return $fields[$parameter] ?? null; } /** * Get the binding fields for the route. * * @return array */ public function bindingFields() { return $this->bindingFields ?? []; } /** * Set the binding fields for the route. * * @param array $bindingFields * @return $this */ public function setBindingFields(array $bindingFields) { $this->bindingFields = $bindingFields; return $this; } /** * Get the parent parameter of the given parameter. * * @param string $parameter * @return string */ public function parentOfParameter($parameter) { $key = array_search($parameter, array_keys($this->parameters)); if ($key === 0) { return; } return array_values($this->parameters)[$key - 1]; } /** * Allow "trashed" models to be retrieved when resolving implicit model bindings for this route. * * @param bool $withTrashed * @return $this */ public function withTrashed($withTrashed = true) { $this->withTrashedBindings = $withTrashed; return $this; } /** * Determines if the route allows "trashed" models to be retrieved when resolving implicit model bindings. * * @return bool */ public function allowsTrashedBindings() { return $this->withTrashedBindings; } /** * Set a default value for the route. * * @param string $key * @param mixed $value * @return $this */ public function defaults($key, $value) { $this->defaults[$key] = $value; return $this; } /** * Set the default values for the route. * * @param array $defaults * @return $this */ public function setDefaults(array $defaults) { $this->defaults = $defaults; return $this; } /** * Set a regular expression requirement on the route. * * @param array|string $name * @param string|null $expression * @return $this */ public function where($name, $expression = null) { foreach ($this->parseWhere($name, $expression) as $name => $expression) { $this->wheres[$name] = $expression; } return $this; } /** * Parse arguments to the where method into an array. * * @param array|string $name * @param string $expression * @return array */ protected function parseWhere($name, $expression) { return is_array($name) ? $name : [$name => $expression]; } /** * Set a list of regular expression requirements on the route. * * @param array $wheres * @return $this */ public function setWheres(array $wheres) { foreach ($wheres as $name => $expression) { $this->where($name, $expression); } return $this; } /** * Mark this route as a fallback route. * * @return $this */ public function fallback() { $this->isFallback = true; return $this; } /** * Set the fallback value. * * @param bool $isFallback * @return $this */ public function setFallback($isFallback) { $this->isFallback = $isFallback; return $this; } /** * Get the HTTP verbs the route responds to. * * @return array */ public function methods() { return $this->methods; } /** * Determine if the route only responds to HTTP requests. * * @return bool */ public function httpOnly() { return in_array('http', $this->action, true); } /** * Determine if the route only responds to HTTPS requests. * * @return bool */ public function httpsOnly() { return $this->secure(); } /** * Determine if the route only responds to HTTPS requests. * * @return bool */ public function secure() { return in_array('https', $this->action, true); } /** * Get or set the domain for the route. * * @param string|null $domain * @return $this|string|null */ public function domain($domain = null) { if (is_null($domain)) { return $this->getDomain(); } $parsed = RouteUri::parse($domain); $this->action['domain'] = $parsed->uri; $this->bindingFields = array_merge( $this->bindingFields, $parsed->bindingFields ); return $this; } /** * Get the domain defined for the route. * * @return string|null */ public function getDomain() { return isset($this->action['domain']) ? str_replace(['http://', 'https://'], '', $this->action['domain']) : null; } /** * Get the prefix of the route instance. * * @return string|null */ public function getPrefix() { return $this->action['prefix'] ?? null; } /** * Add a prefix to the route URI. * * @param string $prefix * @return $this */ public function prefix($prefix) { $prefix ??= ''; $this->updatePrefixOnAction($prefix); $uri = rtrim($prefix, '/').'/'.ltrim($this->uri, '/'); return $this->setUri($uri !== '/' ? trim($uri, '/') : $uri); } /** * Update the "prefix" attribute on the action array. * * @param string $prefix * @return void */ protected function updatePrefixOnAction($prefix) { if (! empty($newPrefix = trim(rtrim($prefix, '/').'/'.ltrim($this->action['prefix'] ?? '', '/'), '/'))) { $this->action['prefix'] = $newPrefix; } } /** * Get the URI associated with the route. * * @return string */ public function uri() { return $this->uri; } /** * Set the URI that the route responds to. * * @param string $uri * @return $this */ public function setUri($uri) { $this->uri = $this->parseUri($uri); return $this; } /** * Parse the route URI and normalize / store any implicit binding fields. * * @param string $uri * @return string */ protected function parseUri($uri) { $this->bindingFields = []; return tap(RouteUri::parse($uri), function ($uri) { $this->bindingFields = $uri->bindingFields; })->uri; } /** * Get the name of the route instance. * * @return string|null */ public function getName() { return $this->action['as'] ?? null; } /** * Add or change the route name. * * @param string $name * @return $this */ public function name($name) { $this->action['as'] = isset($this->action['as']) ? $this->action['as'].$name : $name; return $this; } /** * Determine whether the route's name matches the given patterns. * * @param mixed ...$patterns * @return bool */ public function named(...$patterns) { if (is_null($routeName = $this->getName())) { return false; } foreach ($patterns as $pattern) { if (Str::is($pattern, $routeName)) { return true; } } return false; } /** * Set the handler for the route. * * @param \Closure|array|string $action * @return $this */ public function uses($action) { if (is_array($action)) { $action = $action[0].'@'.$action[1]; } $action = is_string($action) ? $this->addGroupNamespaceToStringUses($action) : $action; return $this->setAction(array_merge($this->action, $this->parseAction([ 'uses' => $action, 'controller' => $action, ]))); } /** * Parse a string based action for the "uses" fluent method. * * @param string $action * @return string */ protected function addGroupNamespaceToStringUses($action) { $groupStack = last($this->router->getGroupStack()); if (isset($groupStack['namespace']) && ! str_starts_with($action, '\\')) { return $groupStack['namespace'].'\\'.$action; } return $action; } /** * Get the action name for the route. * * @return string */ public function getActionName() { return $this->action['controller'] ?? 'Closure'; } /** * Get the method name of the route action. * * @return string */ public function getActionMethod() { return Arr::last(explode('@', $this->getActionName())); } /** * Get the action array or one of its properties for the route. * * @param string|null $key * @return mixed */ public function getAction($key = null) { return Arr::get($this->action, $key); } /** * Set the action array for the route. * * @param array $action * @return $this */ public function setAction(array $action) { $this->action = $action; if (isset($this->action['domain'])) { $this->domain($this->action['domain']); } return $this; } /** * Get the value of the action that should be taken on a missing model exception. * * @return \Closure|null */ public function getMissing() { $missing = $this->action['missing'] ?? null; return is_string($missing) && Str::startsWith($missing, [ 'O:47:"Laravel\\SerializableClosure\\SerializableClosure', ]) ? unserialize($missing) : $missing; } /** * Define the callable that should be invoked on a missing model exception. * * @param \Closure $missing * @return $this */ public function missing($missing) { $this->action['missing'] = $missing; return $this; } /** * Get all middleware, including the ones from the controller. * * @return array */ public function gatherMiddleware() { if (! is_null($this->computedMiddleware)) { return $this->computedMiddleware; } $this->computedMiddleware = []; return $this->computedMiddleware = Router::uniqueMiddleware(array_merge( $this->middleware(), $this->controllerMiddleware() )); } /** * Get or set the middlewares attached to the route. * * @param array|string|null $middleware * @return $this|array */ public function middleware($middleware = null) { if (is_null($middleware)) { return (array) ($this->action['middleware'] ?? []); } if (! is_array($middleware)) { $middleware = func_get_args(); } foreach ($middleware as $index => $value) { $middleware[$index] = (string) $value; } $this->action['middleware'] = array_merge( (array) ($this->action['middleware'] ?? []), $middleware ); return $this; } /** * Specify that the "Authorize" / "can" middleware should be applied to the route with the given options. * * @param string $ability * @param array|string $models * @return $this */ public function can($ability, $models = []) { return empty($models) ? $this->middleware(['can:'.$ability]) : $this->middleware(['can:'.$ability.','.implode(',', Arr::wrap($models))]); } /** * Get the middleware for the route's controller. * * @return array */ public function controllerMiddleware() { if (! $this->isControllerAction()) { return []; } [$controllerClass, $controllerMethod] = [ $this->getControllerClass(), $this->getControllerMethod(), ]; if (is_a($controllerClass, HasMiddleware::class, true)) { return $this->staticallyProvidedControllerMiddleware( $controllerClass, $controllerMethod ); } if (method_exists($controllerClass, 'getMiddleware')) { return $this->controllerDispatcher()->getMiddleware( $this->getController(), $controllerMethod ); } return []; } /** * Get the statically provided controller middleware for the given class and method. * * @param string $class * @param string $method * @return array */ protected function staticallyProvidedControllerMiddleware(string $class, string $method) { return collect($class::middleware())->reject(function ($middleware) use ($method) { return $this->controllerDispatcher()::methodExcludedByOptions( $method, ['only' => $middleware->only, 'except' => $middleware->except] ); })->map->middleware->values()->all(); } /** * Specify middleware that should be removed from the given route. * * @param array|string $middleware * @return $this */ public function withoutMiddleware($middleware) { $this->action['excluded_middleware'] = array_merge( (array) ($this->action['excluded_middleware'] ?? []), Arr::wrap($middleware) ); return $this; } /** * Get the middleware should be removed from the route. * * @return array */ public function excludedMiddleware() { return (array) ($this->action['excluded_middleware'] ?? []); } /** * Indicate that the route should enforce scoping of multiple implicit Eloquent bindings. * * @return $this */ public function scopeBindings() { $this->action['scope_bindings'] = true; return $this; } /** * Indicate that the route should not enforce scoping of multiple implicit Eloquent bindings. * * @return $this */ public function withoutScopedBindings() { $this->action['scope_bindings'] = false; return $this; } /** * Determine if the route should enforce scoping of multiple implicit Eloquent bindings. * * @return bool */ public function enforcesScopedBindings() { return (bool) ($this->action['scope_bindings'] ?? false); } /** * Determine if the route should prevent scoping of multiple implicit Eloquent bindings. * * @return bool */ public function preventsScopedBindings() { return isset($this->action['scope_bindings']) && $this->action['scope_bindings'] === false; } /** * Specify that the route should not allow concurrent requests from the same session. * * @param int|null $lockSeconds * @param int|null $waitSeconds * @return $this */ public function block($lockSeconds = 10, $waitSeconds = 10) { $this->lockSeconds = $lockSeconds; $this->waitSeconds = $waitSeconds; return $this; } /** * Specify that the route should allow concurrent requests from the same session. * * @return $this */ public function withoutBlocking() { return $this->block(null, null); } /** * Get the maximum number of seconds the route's session lock should be held for. * * @return int|null */ public function locksFor() { return $this->lockSeconds; } /** * Get the maximum number of seconds to wait while attempting to acquire a session lock. * * @return int|null */ public function waitsFor() { return $this->waitSeconds; } /** * Get the dispatcher for the route's controller. * * @return \Illuminate\Routing\Contracts\ControllerDispatcher */ public function controllerDispatcher() { if ($this->container->bound(ControllerDispatcherContract::class)) { return $this->container->make(ControllerDispatcherContract::class); } return new ControllerDispatcher($this->container); } /** * Get the route validators for the instance. * * @return array */ public static function getValidators() { if (isset(static::$validators)) { return static::$validators; } // To match the route, we will use a chain of responsibility pattern with the // validator implementations. We will spin through each one making sure it // passes and then we will know if the route as a whole matches request. return static::$validators = [ new UriValidator, new MethodValidator, new SchemeValidator, new HostValidator, ]; } /** * Convert the route to a Symfony route. * * @return \Symfony\Component\Routing\Route */ public function toSymfonyRoute() { return new SymfonyRoute( preg_replace('/\{(\w+?)\?\}/', '{$1}', $this->uri()), $this->getOptionalParameterNames(), $this->wheres, ['utf8' => true], $this->getDomain() ?: '', [], $this->methods ); } /** * Get the optional parameter names for the route. * * @return array */ protected function getOptionalParameterNames() { preg_match_all('/\{(\w+?)\?\}/', $this->uri(), $matches); return isset($matches[1]) ? array_fill_keys($matches[1], null) : []; } /** * Get the compiled version of the route. * * @return \Symfony\Component\Routing\CompiledRoute */ public function getCompiled() { return $this->compiled; } /** * Set the router instance on the route. * * @param \Illuminate\Routing\Router $router * @return $this */ public function setRouter(Router $router) { $this->router = $router; return $this; } /** * Set the container instance on the route. * * @param \Illuminate\Container\Container $container * @return $this */ public function setContainer(Container $container) { $this->container = $container; return $this; } /** * Prepare the route instance for serialization. * * @return void * * @throws \LogicException */ public function prepareForSerialization() { if ($this->action['uses'] instanceof Closure) { $this->action['uses'] = serialize( new SerializableClosure($this->action['uses']) ); } if (isset($this->action['missing']) && $this->action['missing'] instanceof Closure) { $this->action['missing'] = serialize( new SerializableClosure($this->action['missing']) ); } $this->compileRoute(); unset($this->router, $this->container); } /** * Dynamically access route parameters. * * @param string $key * @return mixed */ public function __get($key) { return $this->parameter($key); } } PKy Z8U  +Illuminate/Routing/ImplicitRouteBinding.phpnuW+A * @throws \Illuminate\Routing\Exceptions\BackedEnumCaseNotFoundException */ public static function resolveForRoute($container, $route) { $parameters = $route->parameters(); $route = static::resolveBackedEnumsForRoute($route, $parameters); foreach ($route->signatureParameters(['subClass' => UrlRoutable::class]) as $parameter) { if (! $parameterName = static::getParameterName($parameter->getName(), $parameters)) { continue; } $parameterValue = $parameters[$parameterName]; if ($parameterValue instanceof UrlRoutable) { continue; } $instance = $container->make(Reflector::getParameterClassName($parameter)); $parent = $route->parentOfParameter($parameterName); $routeBindingMethod = $route->allowsTrashedBindings() && in_array(SoftDeletes::class, class_uses_recursive($instance)) ? 'resolveSoftDeletableRouteBinding' : 'resolveRouteBinding'; if ($parent instanceof UrlRoutable && ! $route->preventsScopedBindings() && ($route->enforcesScopedBindings() || array_key_exists($parameterName, $route->bindingFields()))) { $childRouteBindingMethod = $route->allowsTrashedBindings() && in_array(SoftDeletes::class, class_uses_recursive($instance)) ? 'resolveSoftDeletableChildRouteBinding' : 'resolveChildRouteBinding'; if (! $model = $parent->{$childRouteBindingMethod}( $parameterName, $parameterValue, $route->bindingFieldFor($parameterName) )) { throw (new ModelNotFoundException)->setModel(get_class($instance), [$parameterValue]); } } elseif (! $model = $instance->{$routeBindingMethod}($parameterValue, $route->bindingFieldFor($parameterName))) { throw (new ModelNotFoundException)->setModel(get_class($instance), [$parameterValue]); } $route->setParameter($parameterName, $model); } } /** * Resolve the Backed Enums route bindings for the route. * * @param \Illuminate\Routing\Route $route * @param array $parameters * @return \Illuminate\Routing\Route * * @throws \Illuminate\Routing\Exceptions\BackedEnumCaseNotFoundException */ protected static function resolveBackedEnumsForRoute($route, $parameters) { foreach ($route->signatureParameters(['backedEnum' => true]) as $parameter) { if (! $parameterName = static::getParameterName($parameter->getName(), $parameters)) { continue; } $parameterValue = $parameters[$parameterName]; $backedEnumClass = (string) $parameter->getType(); $backedEnum = $backedEnumClass::tryFrom((string) $parameterValue); if (is_null($backedEnum)) { throw new BackedEnumCaseNotFoundException($backedEnumClass, $parameterValue); } $route->setParameter($parameterName, $backedEnum); } return $route; } /** * Return the parameter name if it exists in the given parameters. * * @param string $name * @param array $parameters * @return string|null */ protected static function getParameterName($name, $parameters) { if (array_key_exists($name, $parameters)) { return $name; } if (array_key_exists($snakedName = Str::snake($name), $parameters)) { return $snakedName; } } } PKy Zm?PP'Illuminate/Routing/SortedMiddleware.phpnuW+Aall(); } $this->items = $this->sortMiddleware($priorityMap, $middlewares); } /** * Sort the middlewares by the given priority map. * * Each call to this method makes one discrete middleware movement if necessary. * * @param array $priorityMap * @param array $middlewares * @return array */ protected function sortMiddleware($priorityMap, $middlewares) { $lastIndex = 0; foreach ($middlewares as $index => $middleware) { if (! is_string($middleware)) { continue; } $priorityIndex = $this->priorityMapIndex($priorityMap, $middleware); if (! is_null($priorityIndex)) { // This middleware is in the priority map. If we have encountered another middleware // that was also in the priority map and was at a lower priority than the current // middleware, we will move this middleware to be above the previous encounter. if (isset($lastPriorityIndex) && $priorityIndex < $lastPriorityIndex) { return $this->sortMiddleware( $priorityMap, array_values($this->moveMiddleware($middlewares, $index, $lastIndex)) ); } // This middleware is in the priority map; but, this is the first middleware we have // encountered from the map thus far. We'll save its current index plus its index // from the priority map so we can compare against them on the next iterations. $lastIndex = $index; $lastPriorityIndex = $priorityIndex; } } return Router::uniqueMiddleware($middlewares); } /** * Calculate the priority map index of the middleware. * * @param array $priorityMap * @param string $middleware * @return int|null */ protected function priorityMapIndex($priorityMap, $middleware) { foreach ($this->middlewareNames($middleware) as $name) { $priorityIndex = array_search($name, $priorityMap); if ($priorityIndex !== false) { return $priorityIndex; } } } /** * Resolve the middleware names to look for in the priority array. * * @param string $middleware * @return \Generator */ protected function middlewareNames($middleware) { $stripped = head(explode(':', $middleware)); yield $stripped; $interfaces = @class_implements($stripped); if ($interfaces !== false) { foreach ($interfaces as $interface) { yield $interface; } } } /** * Splice a middleware into a new position and remove the old entry. * * @param array $middlewares * @param int $from * @param int $to * @return array */ protected function moveMiddleware($middlewares, $from, $to) { array_splice($middlewares, $to, 0, $middlewares[$from]); unset($middlewares[$from + 1]); return $middlewares; } } PKy ZLii-Illuminate/Routing/RoutingServiceProvider.phpnuW+AregisterRouter(); $this->registerUrlGenerator(); $this->registerRedirector(); $this->registerPsrRequest(); $this->registerPsrResponse(); $this->registerResponseFactory(); $this->registerCallableDispatcher(); $this->registerControllerDispatcher(); } /** * Register the router instance. * * @return void */ protected function registerRouter() { $this->app->singleton('router', function ($app) { return new Router($app['events'], $app); }); } /** * Register the URL generator service. * * @return void */ protected function registerUrlGenerator() { $this->app->singleton('url', function ($app) { $routes = $app['router']->getRoutes(); // The URL generator needs the route collection that exists on the router. // Keep in mind this is an object, so we're passing by references here // and all the registered routes will be available to the generator. $app->instance('routes', $routes); return new UrlGenerator( $routes, $app->rebinding( 'request', $this->requestRebinder() ), $app['config']['app.asset_url'] ); }); $this->app->extend('url', function (UrlGeneratorContract $url, $app) { // Next we will set a few service resolvers on the URL generator so it can // get the information it needs to function. This just provides some of // the convenience features to this URL generator like "signed" URLs. $url->setSessionResolver(function () { return $this->app['session'] ?? null; }); $url->setKeyResolver(function () { return $this->app->make('config')->get('app.key'); }); // If the route collection is "rebound", for example, when the routes stay // cached for the application, we will need to rebind the routes on the // URL generator instance so it has the latest version of the routes. $app->rebinding('routes', function ($app, $routes) { $app['url']->setRoutes($routes); }); return $url; }); } /** * Get the URL generator request rebinder. * * @return \Closure */ protected function requestRebinder() { return function ($app, $request) { $app['url']->setRequest($request); }; } /** * Register the Redirector service. * * @return void */ protected function registerRedirector() { $this->app->singleton('redirect', function ($app) { $redirector = new Redirector($app['url']); // If the session is set on the application instance, we'll inject it into // the redirector instance. This allows the redirect responses to allow // for the quite convenient "with" methods that flash to the session. if (isset($app['session.store'])) { $redirector->setSession($app['session.store']); } return $redirector; }); } /** * Register a binding for the PSR-7 request implementation. * * @return void * * @throws \Illuminate\Contracts\Container\BindingResolutionException */ protected function registerPsrRequest() { $this->app->bind(ServerRequestInterface::class, function ($app) { if (class_exists(Psr17Factory::class) && class_exists(PsrHttpFactory::class)) { $psr17Factory = new Psr17Factory; return (new PsrHttpFactory($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory)) ->createRequest($app->make('request')); } throw new BindingResolutionException('Unable to resolve PSR request. Please install the symfony/psr-http-message-bridge and nyholm/psr7 packages.'); }); } /** * Register a binding for the PSR-7 response implementation. * * @return void * * @throws \Illuminate\Contracts\Container\BindingResolutionException */ protected function registerPsrResponse() { $this->app->bind(ResponseInterface::class, function () { if (class_exists(PsrResponse::class)) { return new PsrResponse; } throw new BindingResolutionException('Unable to resolve PSR response. Please install the nyholm/psr7 package.'); }); } /** * Register the response factory implementation. * * @return void */ protected function registerResponseFactory() { $this->app->singleton(ResponseFactoryContract::class, function ($app) { return new ResponseFactory($app[ViewFactoryContract::class], $app['redirect']); }); } /** * Register the callable dispatcher. * * @return void */ protected function registerCallableDispatcher() { $this->app->singleton(CallableDispatcherContract::class, function ($app) { return new CallableDispatcher($app); }); } /** * Register the controller dispatcher. * * @return void */ protected function registerControllerDispatcher() { $this->app->singleton(ControllerDispatcherContract::class, function ($app) { return new ControllerDispatcher($app); }); } } PKy Z7 ||!Illuminate/Routing/Controller.phpnuW+Amiddleware[] = [ 'middleware' => $m, 'options' => &$options, ]; } return new ControllerMiddlewareOptions($options); } /** * Get the middleware assigned to the controller. * * @return array */ public function getMiddleware() { return $this->middleware; } /** * Execute an action on the controller. * * @param string $method * @param array $parameters * @return \Symfony\Component\HttpFoundation\Response */ public function callAction($method, $parameters) { return $this->{$method}(...array_values($parameters)); } /** * Handle calls to missing methods on the controller. * * @param string $method * @param array $parameters * @return mixed * * @throws \BadMethodCallException */ public function __call($method, $parameters) { throw new BadMethodCallException(sprintf( 'Method %s::%s does not exist.', static::class, $method )); } } PKy Z7]])Illuminate/Routing/CallableDispatcher.phpnuW+Acontainer = $container; } /** * Dispatch a request to a given callable. * * @param \Illuminate\Routing\Route $route * @param callable $callable * @return mixed */ public function dispatch(Route $route, $callable) { return $callable(...array_values($this->resolveParameters($route, $callable))); } /** * Resolve the parameters for the callable. * * @param \Illuminate\Routing\Route $route * @param callable $callable * @return array */ protected function resolveParameters(Route $route, $callable) { return $this->resolveMethodDependencies($route->parametersWithoutNulls(), new ReflectionFunction($callable)); } } PKz Zα33Illuminate/Routing/LICENSE.mdnuW+AThe MIT License (MIT) Copyright (c) Taylor Otwell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PKz Z)Illuminate/Routing/RedirectController.phpnuW+Aroute()->parameters()); $status = $parameters->get('status'); $destination = $parameters->get('destination'); $parameters->forget('status')->forget('destination'); $route = (new Route('GET', $destination, [ 'as' => 'laravel_route_redirect_destination', ]))->bind($request); $parameters = $parameters->only( $route->getCompiled()->getPathVariables() )->toArray(); $url = $url->toRoute($route, $parameters, false); if (! str_starts_with($destination, '/') && str_starts_with($url, '/')) { $url = Str::after($url, '/'); } return new RedirectResponse($url, $status); } } PKz Z4J&Illuminate/Routing/ResponseFactory.phpnuW+Aview = $view; $this->redirector = $redirector; } /** * Create a new response instance. * * @param mixed $content * @param int $status * @param array $headers * @return \Illuminate\Http\Response */ public function make($content = '', $status = 200, array $headers = []) { return new Response($content, $status, $headers); } /** * Create a new "no content" response. * * @param int $status * @param array $headers * @return \Illuminate\Http\Response */ public function noContent($status = 204, array $headers = []) { return $this->make('', $status, $headers); } /** * Create a new response for a given view. * * @param string|array $view * @param array $data * @param int $status * @param array $headers * @return \Illuminate\Http\Response */ public function view($view, $data = [], $status = 200, array $headers = []) { if (is_array($view)) { return $this->make($this->view->first($view, $data), $status, $headers); } return $this->make($this->view->make($view, $data), $status, $headers); } /** * Create a new JSON response instance. * * @param mixed $data * @param int $status * @param array $headers * @param int $options * @return \Illuminate\Http\JsonResponse */ public function json($data = [], $status = 200, array $headers = [], $options = 0) { return new JsonResponse($data, $status, $headers, $options); } /** * Create a new JSONP response instance. * * @param string $callback * @param mixed $data * @param int $status * @param array $headers * @param int $options * @return \Illuminate\Http\JsonResponse */ public function jsonp($callback, $data = [], $status = 200, array $headers = [], $options = 0) { return $this->json($data, $status, $headers, $options)->setCallback($callback); } /** * Create a new streamed response instance. * * @param callable $callback * @param int $status * @param array $headers * @return \Symfony\Component\HttpFoundation\StreamedResponse */ public function stream($callback, $status = 200, array $headers = []) { return new StreamedResponse($callback, $status, $headers); } /** * Create a new streamed response instance as a file download. * * @param callable $callback * @param string|null $name * @param array $headers * @param string|null $disposition * @return \Symfony\Component\HttpFoundation\StreamedResponse */ public function streamDownload($callback, $name = null, array $headers = [], $disposition = 'attachment') { $withWrappedException = function () use ($callback) { try { $callback(); } catch (Throwable $e) { throw new StreamedResponseException($e); } }; $response = new StreamedResponse($withWrappedException, 200, $headers); if (! is_null($name)) { $response->headers->set('Content-Disposition', $response->headers->makeDisposition( $disposition, $name, $this->fallbackName($name) )); } return $response; } /** * Create a new file download response. * * @param \SplFileInfo|string $file * @param string|null $name * @param array $headers * @param string|null $disposition * @return \Symfony\Component\HttpFoundation\BinaryFileResponse */ public function download($file, $name = null, array $headers = [], $disposition = 'attachment') { $response = new BinaryFileResponse($file, 200, $headers, true, $disposition); if (! is_null($name)) { return $response->setContentDisposition($disposition, $name, $this->fallbackName($name)); } return $response; } /** * Convert the string to ASCII characters that are equivalent to the given name. * * @param string $name * @return string */ protected function fallbackName($name) { return str_replace('%', '', Str::ascii($name)); } /** * Return the raw contents of a binary file. * * @param \SplFileInfo|string $file * @param array $headers * @return \Symfony\Component\HttpFoundation\BinaryFileResponse */ public function file($file, array $headers = []) { return new BinaryFileResponse($file, 200, $headers); } /** * Create a new redirect response to the given path. * * @param string $path * @param int $status * @param array $headers * @param bool|null $secure * @return \Illuminate\Http\RedirectResponse */ public function redirectTo($path, $status = 302, $headers = [], $secure = null) { return $this->redirector->to($path, $status, $headers, $secure); } /** * Create a new redirect response to a named route. * * @param string $route * @param mixed $parameters * @param int $status * @param array $headers * @return \Illuminate\Http\RedirectResponse */ public function redirectToRoute($route, $parameters = [], $status = 302, $headers = []) { return $this->redirector->route($route, $parameters, $status, $headers); } /** * Create a new redirect response to a controller action. * * @param string $action * @param mixed $parameters * @param int $status * @param array $headers * @return \Illuminate\Http\RedirectResponse */ public function redirectToAction($action, $parameters = [], $status = 302, $headers = []) { return $this->redirector->action($action, $parameters, $status, $headers); } /** * Create a new redirect response, while putting the current URL in the session. * * @param string $path * @param int $status * @param array $headers * @param bool|null $secure * @return \Illuminate\Http\RedirectResponse */ public function redirectGuest($path, $status = 302, $headers = [], $secure = null) { return $this->redirector->guest($path, $status, $headers, $secure); } /** * Create a new redirect response to the previously intended location. * * @param string $default * @param int $status * @param array $headers * @param bool|null $secure * @return \Illuminate\Http\RedirectResponse */ public function redirectToIntended($default = '/', $status = 302, $headers = [], $secure = null) { return $this->redirector->intended($default, $status, $headers, $secure); } } PKz Zy)Illuminate/Routing/RouteFileRegistrar.phpnuW+Arouter = $router; } /** * Require the given routes file. * * @param string $routes * @return void */ public function register($routes) { $router = $this->router; require $routes; } } PKz Zx%j j -Illuminate/Routing/MiddlewareNameResolver.phpnuW+AtoResponse($this->getContainer()->make(Request::class)) : $carry; } /** * Handle the given exception. * * @param mixed $passable * @param \Throwable $e * @return mixed * * @throws \Throwable */ protected function handleException($passable, Throwable $e) { if (! $this->container->bound(ExceptionHandler::class) || ! $passable instanceof Request) { throw $e; } $handler = $this->container->make(ExceptionHandler::class); $handler->report($e); $response = $handler->render($passable, $e); if (is_object($response) && method_exists($response, 'withException')) { $response->withException($e); } return $this->handleCarry($response); } } PKz ZKl"".Illuminate/Routing/AbstractRouteCollection.phpnuW+Abind($request); } // If no route was found we will now check if a matching route is specified by // another HTTP verb. If it is we will need to throw a MethodNotAllowed and // inform the user agent of which HTTP verb it should use for this route. $others = $this->checkForAlternateVerbs($request); if (count($others) > 0) { return $this->getRouteForMethods($request, $others); } throw new NotFoundHttpException(sprintf( 'The route %s could not be found.', $request->path() )); } /** * Determine if any routes match on another HTTP verb. * * @param \Illuminate\Http\Request $request * @return array */ protected function checkForAlternateVerbs($request) { $methods = array_diff(Router::$verbs, [$request->getMethod()]); // Here we will spin through all verbs except for the current request verb and // check to see if any routes respond to them. If they do, we will return a // proper error response with the correct headers on the response string. return array_values(array_filter( $methods, function ($method) use ($request) { return ! is_null($this->matchAgainstRoutes($this->get($method), $request, false)); } )); } /** * Determine if a route in the array matches the request. * * @param \Illuminate\Routing\Route[] $routes * @param \Illuminate\Http\Request $request * @param bool $includingMethod * @return \Illuminate\Routing\Route|null */ protected function matchAgainstRoutes(array $routes, $request, $includingMethod = true) { [$fallbacks, $routes] = collect($routes)->partition(function ($route) { return $route->isFallback; }); return $routes->merge($fallbacks)->first( fn (Route $route) => $route->matches($request, $includingMethod) ); } /** * Get a route (if necessary) that responds when other available methods are present. * * @param \Illuminate\Http\Request $request * @param string[] $methods * @return \Illuminate\Routing\Route * * @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException */ protected function getRouteForMethods($request, array $methods) { if ($request->isMethod('OPTIONS')) { return (new Route('OPTIONS', $request->path(), function () use ($methods) { return new Response('', 200, ['Allow' => implode(',', $methods)]); }))->bind($request); } $this->requestMethodNotAllowed($request, $methods, $request->method()); } /** * Throw a method not allowed HTTP exception. * * @param \Illuminate\Http\Request $request * @param array $others * @param string $method * @return void * * @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException */ protected function requestMethodNotAllowed($request, array $others, $method) { throw new MethodNotAllowedHttpException( $others, sprintf( 'The %s method is not supported for route %s. Supported methods: %s.', $method, $request->path(), implode(', ', $others) ) ); } /** * Throw a method not allowed HTTP exception. * * @param array $others * @param string $method * @return void * * @deprecated use requestMethodNotAllowed * * @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException */ protected function methodNotAllowed(array $others, $method) { throw new MethodNotAllowedHttpException( $others, sprintf( 'The %s method is not supported for this route. Supported methods: %s.', $method, implode(', ', $others) ) ); } /** * Compile the routes for caching. * * @return array */ public function compile() { $compiled = $this->dumper()->getCompiledRoutes(); $attributes = []; foreach ($this->getRoutes() as $route) { $attributes[$route->getName()] = [ 'methods' => $route->methods(), 'uri' => $route->uri(), 'action' => $route->getAction(), 'fallback' => $route->isFallback, 'defaults' => $route->defaults, 'wheres' => $route->wheres, 'bindingFields' => $route->bindingFields(), 'lockSeconds' => $route->locksFor(), 'waitSeconds' => $route->waitsFor(), 'withTrashed' => $route->allowsTrashedBindings(), ]; } return compact('compiled', 'attributes'); } /** * Return the CompiledUrlMatcherDumper instance for the route collection. * * @return \Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper */ public function dumper() { return new CompiledUrlMatcherDumper($this->toSymfonyRouteCollection()); } /** * Convert the collection to a Symfony RouteCollection instance. * * @return \Symfony\Component\Routing\RouteCollection */ public function toSymfonyRouteCollection() { $symfonyRoutes = new SymfonyRouteCollection; $routes = $this->getRoutes(); foreach ($routes as $route) { if (! $route->isFallback) { $symfonyRoutes = $this->addToSymfonyRoutesCollection($symfonyRoutes, $route); } } foreach ($routes as $route) { if ($route->isFallback) { $symfonyRoutes = $this->addToSymfonyRoutesCollection($symfonyRoutes, $route); } } return $symfonyRoutes; } /** * Add a route to the SymfonyRouteCollection instance. * * @param \Symfony\Component\Routing\RouteCollection $symfonyRoutes * @param \Illuminate\Routing\Route $route * @return \Symfony\Component\Routing\RouteCollection * * @throws \LogicException */ protected function addToSymfonyRoutesCollection(SymfonyRouteCollection $symfonyRoutes, Route $route) { $name = $route->getName(); if ( ! is_null($name) && str_ends_with($name, '.') && ! is_null($symfonyRoutes->get($name)) ) { $name = null; } if (! $name) { $route->name($this->generateRouteName()); $this->add($route); } elseif (! is_null($symfonyRoutes->get($name))) { throw new LogicException("Unable to prepare route [{$route->uri}] for serialization. Another route has already been assigned name [{$name}]."); } $symfonyRoutes->add($route->getName(), $route->toSymfonyRoute()); return $symfonyRoutes; } /** * Get a randomly generated route name. * * @return string */ protected function generateRouteName() { return 'generated::'.Str::random(); } /** * Get an iterator for the items. * * @return \ArrayIterator */ public function getIterator(): Traversable { return new ArrayIterator($this->getRoutes()); } /** * Count the number of items in the collection. * * @return int */ public function count(): int { return count($this->getRoutes()); } } PKz Z ;-#-#.Illuminate/Routing/CompiledRouteCollection.phpnuW+Acompiled = $compiled; $this->attributes = $attributes; $this->routes = new RouteCollection; } /** * Add a Route instance to the collection. * * @param \Illuminate\Routing\Route $route * @return \Illuminate\Routing\Route */ public function add(Route $route) { return $this->routes->add($route); } /** * Refresh the name look-up table. * * This is done in case any names are fluently defined or if routes are overwritten. * * @return void */ public function refreshNameLookups() { // } /** * Refresh the action look-up table. * * This is done in case any actions are overwritten with new controllers. * * @return void */ public function refreshActionLookups() { // } /** * Find the first route matching a given request. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Routing\Route * * @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ public function match(Request $request) { $matcher = new CompiledUrlMatcher( $this->compiled, (new RequestContext)->fromRequest( $trimmedRequest = $this->requestWithoutTrailingSlash($request) ) ); $route = null; try { if ($result = $matcher->matchRequest($trimmedRequest)) { $route = $this->getByName($result['_route']); } } catch (ResourceNotFoundException|MethodNotAllowedException $e) { try { return $this->routes->match($request); } catch (NotFoundHttpException $e) { // } } if ($route && $route->isFallback) { try { $dynamicRoute = $this->routes->match($request); if (! $dynamicRoute->isFallback) { $route = $dynamicRoute; } } catch (NotFoundHttpException|MethodNotAllowedHttpException $e) { // } } return $this->handleMatchedRoute($request, $route); } /** * Get a cloned instance of the given request without any trailing slash on the URI. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Request */ protected function requestWithoutTrailingSlash(Request $request) { $trimmedRequest = $request->duplicate(); $parts = explode('?', $request->server->get('REQUEST_URI'), 2); $trimmedRequest->server->set( 'REQUEST_URI', rtrim($parts[0], '/').(isset($parts[1]) ? '?'.$parts[1] : '') ); return $trimmedRequest; } /** * Get routes from the collection by method. * * @param string|null $method * @return \Illuminate\Routing\Route[] */ public function get($method = null) { return $this->getRoutesByMethod()[$method] ?? []; } /** * Determine if the route collection contains a given named route. * * @param string $name * @return bool */ public function hasNamedRoute($name) { return isset($this->attributes[$name]) || $this->routes->hasNamedRoute($name); } /** * Get a route instance by its name. * * @param string $name * @return \Illuminate\Routing\Route|null */ public function getByName($name) { if (isset($this->attributes[$name])) { return $this->newRoute($this->attributes[$name]); } return $this->routes->getByName($name); } /** * Get a route instance by its controller action. * * @param string $action * @return \Illuminate\Routing\Route|null */ public function getByAction($action) { $attributes = collect($this->attributes)->first(function (array $attributes) use ($action) { if (isset($attributes['action']['controller'])) { return trim($attributes['action']['controller'], '\\') === $action; } return $attributes['action']['uses'] === $action; }); if ($attributes) { return $this->newRoute($attributes); } return $this->routes->getByAction($action); } /** * Get all of the routes in the collection. * * @return \Illuminate\Routing\Route[] */ public function getRoutes() { return collect($this->attributes) ->map(function (array $attributes) { return $this->newRoute($attributes); }) ->merge($this->routes->getRoutes()) ->values() ->all(); } /** * Get all of the routes keyed by their HTTP verb / method. * * @return array */ public function getRoutesByMethod() { return collect($this->getRoutes()) ->groupBy(function (Route $route) { return $route->methods(); }) ->map(function (Collection $routes) { return $routes->mapWithKeys(function (Route $route) { return [$route->getDomain().$route->uri => $route]; })->all(); }) ->all(); } /** * Get all of the routes keyed by their name. * * @return \Illuminate\Routing\Route[] */ public function getRoutesByName() { return collect($this->getRoutes()) ->keyBy(function (Route $route) { return $route->getName(); }) ->all(); } /** * Resolve an array of attributes to a Route instance. * * @param array $attributes * @return \Illuminate\Routing\Route */ protected function newRoute(array $attributes) { if (empty($attributes['action']['prefix'] ?? '')) { $baseUri = $attributes['uri']; } else { $prefix = trim($attributes['action']['prefix'], '/'); $baseUri = trim(implode( '/', array_slice( explode('/', trim($attributes['uri'], '/')), count($prefix !== '' ? explode('/', $prefix) : []) ) ), '/'); } return $this->router->newRoute($attributes['methods'], $baseUri === '' ? '/' : $baseUri, $attributes['action']) ->setFallback($attributes['fallback']) ->setDefaults($attributes['defaults']) ->setWheres($attributes['wheres']) ->setBindingFields($attributes['bindingFields']) ->block($attributes['lockSeconds'] ?? null, $attributes['waitSeconds'] ?? null) ->withTrashed($attributes['withTrashed'] ?? false); } /** * Set the router instance on the route. * * @param \Illuminate\Routing\Router $router * @return $this */ public function setRouter(Router $router) { $this->router = $router; return $this; } /** * Set the container instance on the route. * * @param \Illuminate\Container\Container $container * @return $this */ public function setContainer(Container $container) { $this->container = $container; return $this; } } PKz ZƢ2Illuminate/Routing/ControllerMiddlewareOptions.phpnuW+Aoptions = &$options; } /** * Set the controller methods the middleware should apply to. * * @param array|string|dynamic $methods * @return $this */ public function only($methods) { $this->options['only'] = is_array($methods) ? $methods : func_get_args(); return $this; } /** * Set the controller methods the middleware should exclude. * * @param array|string|dynamic $methods * @return $this */ public function except($methods) { $this->options['except'] = is_array($methods) ? $methods : func_get_args(); return $this; } } PKz ZS9 9 "Illuminate/Routing/RouteAction.phpnuW+A $action] : [ 'uses' => $action[0].'@'.$action[1], 'controller' => $action[0].'@'.$action[1], ]; } // If no "uses" property has been set, we will dig through the array to find a // Closure instance within this list. We will set the first Closure we come // across into the "uses" property that will get fired off by this route. elseif (! isset($action['uses'])) { $action['uses'] = static::findCallable($action); } if (! static::containsSerializedClosure($action) && is_string($action['uses']) && ! str_contains($action['uses'], '@')) { $action['uses'] = static::makeInvokable($action['uses']); } return $action; } /** * Get an action for a route that has no action. * * @param string $uri * @return array * * @throws \LogicException */ protected static function missingAction($uri) { return ['uses' => function () use ($uri) { throw new LogicException("Route for [{$uri}] has no action."); }]; } /** * Find the callable in an action array. * * @param array $action * @return callable */ protected static function findCallable(array $action) { return Arr::first($action, function ($value, $key) { return Reflector::isCallable($value) && is_numeric($key); }); } /** * Make an action for an invokable controller. * * @param string $action * @return string * * @throws \UnexpectedValueException */ protected static function makeInvokable($action) { if (! method_exists($action, '__invoke')) { throw new UnexpectedValueException("Invalid route action: [{$action}]."); } return $action.'@__invoke'; } /** * Determine if the given array actions contain a serialized Closure. * * @param array $action * @return bool */ public static function containsSerializedClosure(array $action) { return is_string($action['uses']) && Str::startsWith($action['uses'], [ 'O:47:"Laravel\\SerializableClosure\\SerializableClosure', ]) !== false; } } PKz Zhѥ4$4$(Illuminate/Routing/RouteUrlGenerator.phpnuW+A '/', '%40' => '@', '%3A' => ':', '%3B' => ';', '%2C' => ',', '%3D' => '=', '%2B' => '+', '%21' => '!', '%2A' => '*', '%7C' => '|', '%3F' => '?', '%26' => '&', '%23' => '#', '%25' => '%', ]; /** * Create a new Route URL generator. * * @param \Illuminate\Routing\UrlGenerator $url * @param \Illuminate\Http\Request $request * @return void */ public function __construct($url, $request) { $this->url = $url; $this->request = $request; } /** * Generate a URL for the given route. * * @param \Illuminate\Routing\Route $route * @param array $parameters * @param bool $absolute * @return string * * @throws \Illuminate\Routing\Exceptions\UrlGenerationException */ public function to($route, $parameters = [], $absolute = false) { $domain = $this->getRouteDomain($route, $parameters); // First we will construct the entire URI including the root and query string. Once it // has been constructed, we'll make sure we don't have any missing parameters or we // will need to throw the exception to let the developers know one was not given. $uri = $this->addQueryString($this->url->format( $root = $this->replaceRootParameters($route, $domain, $parameters), $this->replaceRouteParameters($route->uri(), $parameters), $route ), $parameters); if (preg_match_all('/{(.*?)}/', $uri, $matchedMissingParameters)) { throw UrlGenerationException::forMissingParameters($route, $matchedMissingParameters[1]); } // Once we have ensured that there are no missing parameters in the URI we will encode // the URI and prepare it for returning to the developer. If the URI is supposed to // be absolute, we will return it as-is. Otherwise we will remove the URL's root. $uri = strtr(rawurlencode($uri), $this->dontEncode); if (! $absolute) { $uri = preg_replace('#^(//|[^/?])+#', '', $uri); if ($base = $this->request->getBaseUrl()) { $uri = preg_replace('#^'.$base.'#i', '', $uri); } return '/'.ltrim($uri, '/'); } return $uri; } /** * Get the formatted domain for a given route. * * @param \Illuminate\Routing\Route $route * @param array $parameters * @return string */ protected function getRouteDomain($route, &$parameters) { return $route->getDomain() ? $this->formatDomain($route, $parameters) : null; } /** * Format the domain and port for the route and request. * * @param \Illuminate\Routing\Route $route * @param array $parameters * @return string */ protected function formatDomain($route, &$parameters) { return $this->addPortToDomain( $this->getRouteScheme($route).$route->getDomain() ); } /** * Get the scheme for the given route. * * @param \Illuminate\Routing\Route $route * @return string */ protected function getRouteScheme($route) { if ($route->httpOnly()) { return 'http://'; } elseif ($route->httpsOnly()) { return 'https://'; } return $this->url->formatScheme(); } /** * Add the port to the domain if necessary. * * @param string $domain * @return string */ protected function addPortToDomain($domain) { $secure = $this->request->isSecure(); $port = (int) $this->request->getPort(); return ($secure && $port === 443) || (! $secure && $port === 80) ? $domain : $domain.':'.$port; } /** * Replace the parameters on the root path. * * @param \Illuminate\Routing\Route $route * @param string $domain * @param array $parameters * @return string */ protected function replaceRootParameters($route, $domain, &$parameters) { $scheme = $this->getRouteScheme($route); return $this->replaceRouteParameters( $this->url->formatRoot($scheme, $domain), $parameters ); } /** * Replace all of the wildcard parameters for a route path. * * @param string $path * @param array $parameters * @return string */ protected function replaceRouteParameters($path, array &$parameters) { $path = $this->replaceNamedParameters($path, $parameters); $path = preg_replace_callback('/\{.*?\}/', function ($match) use (&$parameters) { // Reset only the numeric keys... $parameters = array_merge($parameters); return (! isset($parameters[0]) && ! str_ends_with($match[0], '?}')) ? $match[0] : Arr::pull($parameters, 0); }, $path); return trim(preg_replace('/\{.*?\?\}/', '', $path), '/'); } /** * Replace all of the named parameters in the path. * * @param string $path * @param array $parameters * @return string */ protected function replaceNamedParameters($path, &$parameters) { return preg_replace_callback('/\{(.*?)(\?)?\}/', function ($m) use (&$parameters) { if (isset($parameters[$m[1]]) && $parameters[$m[1]] !== '') { return Arr::pull($parameters, $m[1]); } elseif (isset($this->defaultParameters[$m[1]])) { return $this->defaultParameters[$m[1]]; } elseif (isset($parameters[$m[1]])) { Arr::pull($parameters, $m[1]); } return $m[0]; }, $path); } /** * Add a query string to the URI. * * @param string $uri * @param array $parameters * @return mixed|string */ protected function addQueryString($uri, array $parameters) { // If the URI has a fragment we will move it to the end of this URI since it will // need to come after any query string that may be added to the URL else it is // not going to be available. We will remove it then append it back on here. if (! is_null($fragment = parse_url($uri, PHP_URL_FRAGMENT))) { $uri = preg_replace('/#.*/', '', $uri); } $uri .= $this->getRouteQueryString($parameters); return is_null($fragment) ? $uri : $uri."#{$fragment}"; } /** * Get the query string for a given route. * * @param array $parameters * @return string */ protected function getRouteQueryString(array $parameters) { // First we will get all of the string parameters that are remaining after we // have replaced the route wildcards. We'll then build a query string from // these string parameters then use it as a starting point for the rest. if (count($parameters) === 0) { return ''; } $query = Arr::query( $keyed = $this->getStringParameters($parameters) ); // Lastly, if there are still parameters remaining, we will fetch the numeric // parameters that are in the array and add them to the query string or we // will make the initial query string if it wasn't started with strings. if (count($keyed) < count($parameters)) { $query .= '&'.implode( '&', $this->getNumericParameters($parameters) ); } $query = trim($query, '&'); return $query === '' ? '' : "?{$query}"; } /** * Get the string parameters from a given list. * * @param array $parameters * @return array */ protected function getStringParameters(array $parameters) { return array_filter($parameters, 'is_string', ARRAY_FILTER_USE_KEY); } /** * Get the numeric parameters from a given list. * * @param array $parameters * @return array */ protected function getNumericParameters(array $parameters) { return array_filter($parameters, 'is_numeric', ARRAY_FILTER_USE_KEY); } /** * Set the default named parameters used by the URL generator. * * @param array $defaults * @return void */ public function defaults(array $defaults) { $this->defaultParameters = array_merge( $this->defaultParameters, $defaults ); } } PKz ZDzaE__;Illuminate/Routing/Exceptions/InvalidSignatureException.phpnuW+AoriginalException = $originalException; parent::__construct($originalException->getMessage()); } /** * Render the exception. * * @return \Illuminate\Http\Response */ public function render() { return new Response(''); } /** * Get the actual exception thrown during the stream. * * @return \Throwable */ public function getInnerException() { return $this->originalException; } } PKz ZŠ8Illuminate/Routing/Exceptions/UrlGenerationException.phpnuW+AgetName(), $route->uri() ); if (count($parameters) > 0) { $message .= sprintf(' [Missing %s: %s]', $parameterLabel, implode(', ', $parameters)); } $message .= '.'; return new static($message); } } PKz ZZAIlluminate/Routing/Exceptions/BackedEnumCaseNotFoundException.phpnuW+A 'create', 'edit' => 'edit', ]; /** * Create a new resource registrar instance. * * @param \Illuminate\Routing\Router $router * @return void */ public function __construct(Router $router) { $this->router = $router; } /** * Route a resource to a controller. * * @param string $name * @param string $controller * @param array $options * @return \Illuminate\Routing\RouteCollection */ public function register($name, $controller, array $options = []) { if (isset($options['parameters']) && ! isset($this->parameters)) { $this->parameters = $options['parameters']; } // If the resource name contains a slash, we will assume the developer wishes to // register these resource routes with a prefix so we will set that up out of // the box so they don't have to mess with it. Otherwise, we will continue. if (str_contains($name, '/')) { $this->prefixedResource($name, $controller, $options); return; } // We need to extract the base resource from the resource name. Nested resources // are supported in the framework, but we need to know what name to use for a // place-holder on the route parameters, which should be the base resources. $base = $this->getResourceWildcard(last(explode('.', $name))); $defaults = $this->resourceDefaults; $collection = new RouteCollection; $resourceMethods = $this->getResourceMethods($defaults, $options); foreach ($resourceMethods as $m) { $route = $this->{'addResource'.ucfirst($m)}( $name, $base, $controller, $options ); if (isset($options['bindingFields'])) { $this->setResourceBindingFields($route, $options['bindingFields']); } if (isset($options['trashed']) && in_array($m, ! empty($options['trashed']) ? $options['trashed'] : array_intersect($resourceMethods, ['show', 'edit', 'update']))) { $route->withTrashed(); } $collection->add($route); } return $collection; } /** * Route a singleton resource to a controller. * * @param string $name * @param string $controller * @param array $options * @return \Illuminate\Routing\RouteCollection */ public function singleton($name, $controller, array $options = []) { if (isset($options['parameters']) && ! isset($this->parameters)) { $this->parameters = $options['parameters']; } // If the resource name contains a slash, we will assume the developer wishes to // register these singleton routes with a prefix so we will set that up out of // the box so they don't have to mess with it. Otherwise, we will continue. if (str_contains($name, '/')) { $this->prefixedSingleton($name, $controller, $options); return; } $defaults = $this->singletonResourceDefaults; $collection = new RouteCollection; $resourceMethods = $this->getResourceMethods($defaults, $options); foreach ($resourceMethods as $m) { $route = $this->{'addSingleton'.ucfirst($m)}( $name, $controller, $options ); if (isset($options['bindingFields'])) { $this->setResourceBindingFields($route, $options['bindingFields']); } $collection->add($route); } return $collection; } /** * Build a set of prefixed resource routes. * * @param string $name * @param string $controller * @param array $options * @return void */ protected function prefixedResource($name, $controller, array $options) { [$name, $prefix] = $this->getResourcePrefix($name); // We need to extract the base resource from the resource name. Nested resources // are supported in the framework, but we need to know what name to use for a // place-holder on the route parameters, which should be the base resources. $callback = function ($me) use ($name, $controller, $options) { $me->resource($name, $controller, $options); }; return $this->router->group(compact('prefix'), $callback); } /** * Build a set of prefixed singleton routes. * * @param string $name * @param string $controller * @param array $options * @return void */ protected function prefixedSingleton($name, $controller, array $options) { [$name, $prefix] = $this->getResourcePrefix($name); // We need to extract the base resource from the resource name. Nested resources // are supported in the framework, but we need to know what name to use for a // place-holder on the route parameters, which should be the base resources. $callback = function ($me) use ($name, $controller, $options) { $me->singleton($name, $controller, $options); }; return $this->router->group(compact('prefix'), $callback); } /** * Extract the resource and prefix from a resource name. * * @param string $name * @return array */ protected function getResourcePrefix($name) { $segments = explode('/', $name); // To get the prefix, we will take all of the name segments and implode them on // a slash. This will generate a proper URI prefix for us. Then we take this // last segment, which will be considered the final resources name we use. $prefix = implode('/', array_slice($segments, 0, -1)); return [end($segments), $prefix]; } /** * Get the applicable resource methods. * * @param array $defaults * @param array $options * @return array */ protected function getResourceMethods($defaults, $options) { $methods = $defaults; if (isset($options['only'])) { $methods = array_intersect($methods, (array) $options['only']); } if (isset($options['except'])) { $methods = array_diff($methods, (array) $options['except']); } if (isset($options['creatable'])) { $methods = isset($options['apiSingleton']) ? array_merge(['store', 'destroy'], $methods) : array_merge(['create', 'store', 'destroy'], $methods); return $this->getResourceMethods( $methods, array_values(Arr::except($options, ['creatable'])) ); } if (isset($options['destroyable'])) { $methods = array_merge(['destroy'], $methods); return $this->getResourceMethods( $methods, array_values(Arr::except($options, ['destroyable'])) ); } return $methods; } /** * Add the index method for a resourceful route. * * @param string $name * @param string $base * @param string $controller * @param array $options * @return \Illuminate\Routing\Route */ protected function addResourceIndex($name, $base, $controller, $options) { $uri = $this->getResourceUri($name); unset($options['missing']); $action = $this->getResourceAction($name, $controller, 'index', $options); return $this->router->get($uri, $action); } /** * Add the create method for a resourceful route. * * @param string $name * @param string $base * @param string $controller * @param array $options * @return \Illuminate\Routing\Route */ protected function addResourceCreate($name, $base, $controller, $options) { $uri = $this->getResourceUri($name).'/'.static::$verbs['create']; unset($options['missing']); $action = $this->getResourceAction($name, $controller, 'create', $options); return $this->router->get($uri, $action); } /** * Add the store method for a resourceful route. * * @param string $name * @param string $base * @param string $controller * @param array $options * @return \Illuminate\Routing\Route */ protected function addResourceStore($name, $base, $controller, $options) { $uri = $this->getResourceUri($name); unset($options['missing']); $action = $this->getResourceAction($name, $controller, 'store', $options); return $this->router->post($uri, $action); } /** * Add the show method for a resourceful route. * * @param string $name * @param string $base * @param string $controller * @param array $options * @return \Illuminate\Routing\Route */ protected function addResourceShow($name, $base, $controller, $options) { $name = $this->getShallowName($name, $options); $uri = $this->getResourceUri($name).'/{'.$base.'}'; $action = $this->getResourceAction($name, $controller, 'show', $options); return $this->router->get($uri, $action); } /** * Add the edit method for a resourceful route. * * @param string $name * @param string $base * @param string $controller * @param array $options * @return \Illuminate\Routing\Route */ protected function addResourceEdit($name, $base, $controller, $options) { $name = $this->getShallowName($name, $options); $uri = $this->getResourceUri($name).'/{'.$base.'}/'.static::$verbs['edit']; $action = $this->getResourceAction($name, $controller, 'edit', $options); return $this->router->get($uri, $action); } /** * Add the update method for a resourceful route. * * @param string $name * @param string $base * @param string $controller * @param array $options * @return \Illuminate\Routing\Route */ protected function addResourceUpdate($name, $base, $controller, $options) { $name = $this->getShallowName($name, $options); $uri = $this->getResourceUri($name).'/{'.$base.'}'; $action = $this->getResourceAction($name, $controller, 'update', $options); return $this->router->match(['PUT', 'PATCH'], $uri, $action); } /** * Add the destroy method for a resourceful route. * * @param string $name * @param string $base * @param string $controller * @param array $options * @return \Illuminate\Routing\Route */ protected function addResourceDestroy($name, $base, $controller, $options) { $name = $this->getShallowName($name, $options); $uri = $this->getResourceUri($name).'/{'.$base.'}'; $action = $this->getResourceAction($name, $controller, 'destroy', $options); return $this->router->delete($uri, $action); } /** * Add the create method for a singleton route. * * @param string $name * @param string $controller * @param array $options * @return \Illuminate\Routing\Route */ protected function addSingletonCreate($name, $controller, $options) { $uri = $this->getResourceUri($name).'/'.static::$verbs['create']; unset($options['missing']); $action = $this->getResourceAction($name, $controller, 'create', $options); return $this->router->get($uri, $action); } /** * Add the store method for a singleton route. * * @param string $name * @param string $controller * @param array $options * @return \Illuminate\Routing\Route */ protected function addSingletonStore($name, $controller, $options) { $uri = $this->getResourceUri($name); unset($options['missing']); $action = $this->getResourceAction($name, $controller, 'store', $options); return $this->router->post($uri, $action); } /** * Add the show method for a singleton route. * * @param string $name * @param string $controller * @param array $options * @return \Illuminate\Routing\Route */ protected function addSingletonShow($name, $controller, $options) { $uri = $this->getResourceUri($name); unset($options['missing']); $action = $this->getResourceAction($name, $controller, 'show', $options); return $this->router->get($uri, $action); } /** * Add the edit method for a singleton route. * * @param string $name * @param string $controller * @param array $options * @return \Illuminate\Routing\Route */ protected function addSingletonEdit($name, $controller, $options) { $name = $this->getShallowName($name, $options); $uri = $this->getResourceUri($name).'/'.static::$verbs['edit']; $action = $this->getResourceAction($name, $controller, 'edit', $options); return $this->router->get($uri, $action); } /** * Add the update method for a singleton route. * * @param string $name * @param string $base * @param string $controller * @param array $options * @return \Illuminate\Routing\Route */ protected function addSingletonUpdate($name, $controller, $options) { $name = $this->getShallowName($name, $options); $uri = $this->getResourceUri($name); $action = $this->getResourceAction($name, $controller, 'update', $options); return $this->router->match(['PUT', 'PATCH'], $uri, $action); } /** * Add the destroy method for a singleton route. * * @param string $name * @param string $controller * @param array $options * @return \Illuminate\Routing\Route */ protected function addSingletonDestroy($name, $controller, $options) { $name = $this->getShallowName($name, $options); $uri = $this->getResourceUri($name); $action = $this->getResourceAction($name, $controller, 'destroy', $options); return $this->router->delete($uri, $action); } /** * Get the name for a given resource with shallowness applied when applicable. * * @param string $name * @param array $options * @return string */ protected function getShallowName($name, $options) { return isset($options['shallow']) && $options['shallow'] ? last(explode('.', $name)) : $name; } /** * Set the route's binding fields if the resource is scoped. * * @param \Illuminate\Routing\Route $route * @param array $bindingFields * @return void */ protected function setResourceBindingFields($route, $bindingFields) { preg_match_all('/(?<={).*?(?=})/', $route->uri, $matches); $fields = array_fill_keys($matches[0], null); $route->setBindingFields(array_replace( $fields, array_intersect_key($bindingFields, $fields) )); } /** * Get the base resource URI for a given resource. * * @param string $resource * @return string */ public function getResourceUri($resource) { if (! str_contains($resource, '.')) { return $resource; } // Once we have built the base URI, we'll remove the parameter holder for this // base resource name so that the individual route adders can suffix these // paths however they need to, as some do not have any parameters at all. $segments = explode('.', $resource); $uri = $this->getNestedResourceUri($segments); return str_replace('/{'.$this->getResourceWildcard(end($segments)).'}', '', $uri); } /** * Get the URI for a nested resource segment array. * * @param array $segments * @return string */ protected function getNestedResourceUri(array $segments) { // We will spin through the segments and create a place-holder for each of the // resource segments, as well as the resource itself. Then we should get an // entire string for the resource URI that contains all nested resources. return implode('/', array_map(function ($s) { return $s.'/{'.$this->getResourceWildcard($s).'}'; }, $segments)); } /** * Format a resource parameter for usage. * * @param string $value * @return string */ public function getResourceWildcard($value) { if (isset($this->parameters[$value])) { $value = $this->parameters[$value]; } elseif (isset(static::$parameterMap[$value])) { $value = static::$parameterMap[$value]; } elseif ($this->parameters === 'singular' || static::$singularParameters) { $value = Str::singular($value); } return str_replace('-', '_', $value); } /** * Get the action array for a resource route. * * @param string $resource * @param string $controller * @param string $method * @param array $options * @return array */ protected function getResourceAction($resource, $controller, $method, $options) { $name = $this->getResourceRouteName($resource, $method, $options); $action = ['as' => $name, 'uses' => $controller.'@'.$method]; if (isset($options['middleware'])) { $action['middleware'] = $options['middleware']; } if (isset($options['excluded_middleware'])) { $action['excluded_middleware'] = $options['excluded_middleware']; } if (isset($options['wheres'])) { $action['where'] = $options['wheres']; } if (isset($options['missing'])) { $action['missing'] = $options['missing']; } return $action; } /** * Get the name for a given resource. * * @param string $resource * @param string $method * @param array $options * @return string */ protected function getResourceRouteName($resource, $method, $options) { $name = $resource; // If the names array has been provided to us we will check for an entry in the // array first. We will also check for the specific method within this array // so the names may be specified on a more "granular" level using methods. if (isset($options['names'])) { if (is_string($options['names'])) { $name = $options['names']; } elseif (isset($options['names'][$method])) { return $options['names'][$method]; } } // If a global prefix has been assigned to all names for this resource, we will // grab that so we can prepend it onto the name when we create this name for // the resource action. Otherwise we'll just use an empty string for here. $prefix = isset($options['as']) ? $options['as'].'.' : ''; return trim(sprintf('%s%s.%s', $prefix, $name, $method), '.'); } /** * Set or unset the unmapped global parameters to singular. * * @param bool $singular * @return void */ public static function singularParameters($singular = true) { static::$singularParameters = (bool) $singular; } /** * Get the global parameter map. * * @return array */ public static function getParameters() { return static::$parameterMap; } /** * Set the global parameter mapping. * * @param array $parameters * @return void */ public static function setParameters(array $parameters = []) { static::$parameterMap = $parameters; } /** * Get or set the action verbs used in the resource URIs. * * @param array $verbs * @return array */ public static function verbs(array $verbs = []) { if (empty($verbs)) { return static::$verbs; } else { static::$verbs = array_merge(static::$verbs, $verbs); } } } PKz ZԿ߽3Illuminate/Routing/Middleware/ValidateSignature.phpnuW+A */ protected $ignore = [ // ]; /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param string|null $relative * @return \Illuminate\Http\Response * * @throws \Illuminate\Routing\Exceptions\InvalidSignatureException */ public function handle($request, Closure $next, $relative = null) { $ignore = property_exists($this, 'except') ? $this->except : $this->ignore; if ($request->hasValidSignatureWhileIgnoring($ignore, $relative !== 'relative')) { return $next($request); } throw new InvalidSignatureException; } } PKz Zt]!!2Illuminate/Routing/Middleware/ThrottleRequests.phpnuW+Alimiter = $limiter; } /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param int|string $maxAttempts * @param float|int $decayMinutes * @param string $prefix * @return \Symfony\Component\HttpFoundation\Response * * @throws \Illuminate\Http\Exceptions\ThrottleRequestsException */ public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1, $prefix = '') { if (is_string($maxAttempts) && func_num_args() === 3 && ! is_null($limiter = $this->limiter->limiter($maxAttempts))) { return $this->handleRequestUsingNamedLimiter($request, $next, $maxAttempts, $limiter); } return $this->handleRequest( $request, $next, [ (object) [ 'key' => $prefix.$this->resolveRequestSignature($request), 'maxAttempts' => $this->resolveMaxAttempts($request, $maxAttempts), 'decayMinutes' => $decayMinutes, 'responseCallback' => null, ], ] ); } /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param string $limiterName * @param \Closure $limiter * @return \Symfony\Component\HttpFoundation\Response * * @throws \Illuminate\Http\Exceptions\ThrottleRequestsException */ protected function handleRequestUsingNamedLimiter($request, Closure $next, $limiterName, Closure $limiter) { $limiterResponse = $limiter($request); if ($limiterResponse instanceof Response) { return $limiterResponse; } elseif ($limiterResponse instanceof Unlimited) { return $next($request); } return $this->handleRequest( $request, $next, collect(Arr::wrap($limiterResponse))->map(function ($limit) use ($limiterName) { return (object) [ 'key' => md5($limiterName.$limit->key), 'maxAttempts' => $limit->maxAttempts, 'decayMinutes' => $limit->decayMinutes, 'responseCallback' => $limit->responseCallback, ]; })->all() ); } /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param array $limits * @return \Symfony\Component\HttpFoundation\Response * * @throws \Illuminate\Http\Exceptions\ThrottleRequestsException */ protected function handleRequest($request, Closure $next, array $limits) { foreach ($limits as $limit) { if ($this->limiter->tooManyAttempts($limit->key, $limit->maxAttempts)) { throw $this->buildException($request, $limit->key, $limit->maxAttempts, $limit->responseCallback); } $this->limiter->hit($limit->key, $limit->decayMinutes * 60); } $response = $next($request); foreach ($limits as $limit) { $response = $this->addHeaders( $response, $limit->maxAttempts, $this->calculateRemainingAttempts($limit->key, $limit->maxAttempts) ); } return $response; } /** * Resolve the number of attempts if the user is authenticated or not. * * @param \Illuminate\Http\Request $request * @param int|string $maxAttempts * @return int */ protected function resolveMaxAttempts($request, $maxAttempts) { if (str_contains($maxAttempts, '|')) { $maxAttempts = explode('|', $maxAttempts, 2)[$request->user() ? 1 : 0]; } if (! is_numeric($maxAttempts) && $request->user()) { $maxAttempts = $request->user()->{$maxAttempts}; } return (int) $maxAttempts; } /** * Resolve request signature. * * @param \Illuminate\Http\Request $request * @return string * * @throws \RuntimeException */ protected function resolveRequestSignature($request) { if ($user = $request->user()) { return sha1($user->getAuthIdentifier()); } elseif ($route = $request->route()) { return sha1($route->getDomain().'|'.$request->ip()); } throw new RuntimeException('Unable to generate the request signature. Route unavailable.'); } /** * Create a 'too many attempts' exception. * * @param \Illuminate\Http\Request $request * @param string $key * @param int $maxAttempts * @param callable|null $responseCallback * @return \Illuminate\Http\Exceptions\ThrottleRequestsException */ protected function buildException($request, $key, $maxAttempts, $responseCallback = null) { $retryAfter = $this->getTimeUntilNextRetry($key); $headers = $this->getHeaders( $maxAttempts, $this->calculateRemainingAttempts($key, $maxAttempts, $retryAfter), $retryAfter ); return is_callable($responseCallback) ? new HttpResponseException($responseCallback($request, $headers)) : new ThrottleRequestsException('Too Many Attempts.', null, $headers); } /** * Get the number of seconds until the next retry. * * @param string $key * @return int */ protected function getTimeUntilNextRetry($key) { return $this->limiter->availableIn($key); } /** * Add the limit header information to the given response. * * @param \Symfony\Component\HttpFoundation\Response $response * @param int $maxAttempts * @param int $remainingAttempts * @param int|null $retryAfter * @return \Symfony\Component\HttpFoundation\Response */ protected function addHeaders(Response $response, $maxAttempts, $remainingAttempts, $retryAfter = null) { $response->headers->add( $this->getHeaders($maxAttempts, $remainingAttempts, $retryAfter, $response) ); return $response; } /** * Get the limit headers information. * * @param int $maxAttempts * @param int $remainingAttempts * @param int|null $retryAfter * @param \Symfony\Component\HttpFoundation\Response|null $response * @return array */ protected function getHeaders($maxAttempts, $remainingAttempts, $retryAfter = null, ?Response $response = null) { if ($response && ! is_null($response->headers->get('X-RateLimit-Remaining')) && (int) $response->headers->get('X-RateLimit-Remaining') <= (int) $remainingAttempts) { return []; } $headers = [ 'X-RateLimit-Limit' => $maxAttempts, 'X-RateLimit-Remaining' => $remainingAttempts, ]; if (! is_null($retryAfter)) { $headers['Retry-After'] = $retryAfter; $headers['X-RateLimit-Reset'] = $this->availableAt($retryAfter); } return $headers; } /** * Calculate the number of remaining attempts. * * @param string $key * @param int $maxAttempts * @param int|null $retryAfter * @return int */ protected function calculateRemainingAttempts($key, $maxAttempts, $retryAfter = null) { return is_null($retryAfter) ? $this->limiter->retriesLeft($key, $maxAttempts) : 0; } } PKz Z.V?B4Illuminate/Routing/Middleware/SubstituteBindings.phpnuW+Arouter = $router; } /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { try { $this->router->substituteBindings($route = $request->route()); $this->router->substituteImplicitBindings($route); } catch (ModelNotFoundException $exception) { if ($route->getMissing()) { return $route->getMissing()($request, $exception); } throw $exception; } return $next($request); } } PKz Zh]_ ;Illuminate/Routing/Middleware/ThrottleRequestsWithRedis.phpnuW+Aredis = $redis; } /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param array $limits * @return \Symfony\Component\HttpFoundation\Response * * @throws \Illuminate\Http\Exceptions\ThrottleRequestsException */ protected function handleRequest($request, Closure $next, array $limits) { foreach ($limits as $limit) { if ($this->tooManyAttempts($limit->key, $limit->maxAttempts, $limit->decayMinutes)) { throw $this->buildException($request, $limit->key, $limit->maxAttempts, $limit->responseCallback); } } $response = $next($request); foreach ($limits as $limit) { $response = $this->addHeaders( $response, $limit->maxAttempts, $this->calculateRemainingAttempts($limit->key, $limit->maxAttempts) ); } return $response; } /** * Determine if the given key has been "accessed" too many times. * * @param string $key * @param int $maxAttempts * @param int $decayMinutes * @return mixed */ protected function tooManyAttempts($key, $maxAttempts, $decayMinutes) { $limiter = new DurationLimiter( $this->redis, $key, $maxAttempts, $decayMinutes * 60 ); return tap(! $limiter->acquire(), function () use ($key, $limiter) { [$this->decaysAt[$key], $this->remaining[$key]] = [ $limiter->decaysAt, $limiter->remaining, ]; }); } /** * Calculate the number of remaining attempts. * * @param string $key * @param int $maxAttempts * @param int|null $retryAfter * @return int */ protected function calculateRemainingAttempts($key, $maxAttempts, $retryAfter = null) { return is_null($retryAfter) ? $this->remaining[$key] : 0; } /** * Get the number of seconds until the lock is released. * * @param string $key * @return int */ protected function getTimeUntilNextRetry($key) { return $this->decaysAt[$key] - $this->currentTime(); } } PKz Z:I$$Illuminate/Routing/RouteUri.phpnuW+Auri = $uri; $this->bindingFields = $bindingFields; } /** * Parse the given URI. * * @param string $uri * @return static */ public static function parse($uri) { preg_match_all('/\{([\w\:]+?)\??\}/', $uri, $matches); $bindingFields = []; foreach ($matches[0] as $match) { if (! str_contains($match, ':')) { continue; } $segments = explode(':', trim($match, '{}?')); $bindingFields[$segments[0]] = $segments[1]; $uri = str_contains($match, '?') ? str_replace($match, '{'.$segments[0].'?}', $uri) : str_replace($match, '{'.$segments[0].'}', $uri); } return new static($uri, $bindingFields); } } PKz Z. . +Illuminate/Routing/RouteParameterBinder.phpnuW+Aroute = $route; } /** * Get the parameters for the route. * * @param \Illuminate\Http\Request $request * @return array */ public function parameters($request) { $parameters = $this->bindPathParameters($request); // If the route has a regular expression for the host part of the URI, we will // compile that and get the parameter matches for this domain. We will then // merge them into this parameters array so that this array is completed. if (! is_null($this->route->compiled->getHostRegex())) { $parameters = $this->bindHostParameters( $request, $parameters ); } return $this->replaceDefaults($parameters); } /** * Get the parameter matches for the path portion of the URI. * * @param \Illuminate\Http\Request $request * @return array */ protected function bindPathParameters($request) { $path = '/'.ltrim($request->decodedPath(), '/'); preg_match($this->route->compiled->getRegex(), $path, $matches); return $this->matchToKeys(array_slice($matches, 1)); } /** * Extract the parameter list from the host part of the request. * * @param \Illuminate\Http\Request $request * @param array $parameters * @return array */ protected function bindHostParameters($request, $parameters) { preg_match($this->route->compiled->getHostRegex(), $request->getHost(), $matches); return array_merge($this->matchToKeys(array_slice($matches, 1)), $parameters); } /** * Combine a set of parameter matches with the route's keys. * * @param array $matches * @return array */ protected function matchToKeys(array $matches) { if (empty($parameterNames = $this->route->parameterNames())) { return []; } $parameters = array_intersect_key($matches, array_flip($parameterNames)); return array_filter($parameters, function ($value) { return is_string($value) && strlen($value) > 0; }); } /** * Replace null parameters with their defaults. * * @param array $parameters * @return array */ protected function replaceDefaults(array $parameters) { foreach ($parameters as $key => $value) { $parameters[$key] = $value ?? Arr::get($this->route->defaults, $key); } foreach ($this->route->defaults as $key => $value) { if (! isset($parameters[$key])) { $parameters[$key] = $value; } } return $parameters; } } PKz ZY٤!!;Illuminate/Routing/PendingSingletonResourceRegistration.phpnuW+Aname = $name; $this->options = $options; $this->registrar = $registrar; $this->controller = $controller; } /** * Set the methods the controller should apply to. * * @param array|string|dynamic $methods * @return \Illuminate\Routing\PendingSingletonResourceRegistration */ public function only($methods) { $this->options['only'] = is_array($methods) ? $methods : func_get_args(); return $this; } /** * Set the methods the controller should exclude. * * @param array|string|dynamic $methods * @return \Illuminate\Routing\PendingSingletonResourceRegistration */ public function except($methods) { $this->options['except'] = is_array($methods) ? $methods : func_get_args(); return $this; } /** * Indicate that the resource should have creation and storage routes. * * @return $this */ public function creatable() { $this->options['creatable'] = true; return $this; } /** * Indicate that the resource should have a deletion route. * * @return $this */ public function destroyable() { $this->options['destroyable'] = true; return $this; } /** * Set the route names for controller actions. * * @param array|string $names * @return \Illuminate\Routing\PendingSingletonResourceRegistration */ public function names($names) { $this->options['names'] = $names; return $this; } /** * Set the route name for a controller action. * * @param string $method * @param string $name * @return \Illuminate\Routing\PendingSingletonResourceRegistration */ public function name($method, $name) { $this->options['names'][$method] = $name; return $this; } /** * Override the route parameter names. * * @param array|string $parameters * @return \Illuminate\Routing\PendingSingletonResourceRegistration */ public function parameters($parameters) { $this->options['parameters'] = $parameters; return $this; } /** * Override a route parameter's name. * * @param string $previous * @param string $new * @return \Illuminate\Routing\PendingSingletonResourceRegistration */ public function parameter($previous, $new) { $this->options['parameters'][$previous] = $new; return $this; } /** * Add middleware to the resource routes. * * @param mixed $middleware * @return \Illuminate\Routing\PendingSingletonResourceRegistration */ public function middleware($middleware) { $middleware = Arr::wrap($middleware); foreach ($middleware as $key => $value) { $middleware[$key] = (string) $value; } $this->options['middleware'] = $middleware; return $this; } /** * Specify middleware that should be removed from the resource routes. * * @param array|string $middleware * @return $this|array */ public function withoutMiddleware($middleware) { $this->options['excluded_middleware'] = array_merge( (array) ($this->options['excluded_middleware'] ?? []), Arr::wrap($middleware) ); return $this; } /** * Add "where" constraints to the resource routes. * * @param mixed $wheres * @return \Illuminate\Routing\PendingSingletonResourceRegistration */ public function where($wheres) { $this->options['wheres'] = $wheres; return $this; } /** * Register the singleton resource route. * * @return \Illuminate\Routing\RouteCollection */ public function register() { $this->registered = true; return $this->registrar->singleton( $this->name, $this->controller, $this->options ); } /** * Handle the object's destruction. * * @return void */ public function __destruct() { if (! $this->registered) { $this->register(); } } } PKz Z𰺈%Illuminate/Routing/Events/Routing.phpnuW+Arequest = $request; } } PKz ZQQ*Illuminate/Routing/Events/RouteMatched.phpnuW+Aroute = $route; $this->request = $request; } } PKz Z()ӫ !Illuminate/Routing/RouteGroup.phpnuW+A static::formatNamespace($new, $old), 'prefix' => static::formatPrefix($new, $old, $prependExistingPrefix), 'where' => static::formatWhere($new, $old), ]); return array_merge_recursive(Arr::except( $old, ['namespace', 'prefix', 'where', 'as'] ), $new); } /** * Format the namespace for the new group attributes. * * @param array $new * @param array $old * @return string|null */ protected static function formatNamespace($new, $old) { if (isset($new['namespace'])) { return isset($old['namespace']) && ! str_starts_with($new['namespace'], '\\') ? trim($old['namespace'], '\\').'\\'.trim($new['namespace'], '\\') : trim($new['namespace'], '\\'); } return $old['namespace'] ?? null; } /** * Format the prefix for the new group attributes. * * @param array $new * @param array $old * @param bool $prependExistingPrefix * @return string|null */ protected static function formatPrefix($new, $old, $prependExistingPrefix = true) { $old = $old['prefix'] ?? ''; if ($prependExistingPrefix) { return isset($new['prefix']) ? trim($old, '/').'/'.trim($new['prefix'], '/') : $old; } else { return isset($new['prefix']) ? trim($new['prefix'], '/').'/'.trim($old, '/') : $old; } } /** * Format the "wheres" for the new group attributes. * * @param array $new * @param array $old * @return array */ protected static function formatWhere($new, $old) { return array_merge( $old['where'] ?? [], $new['where'] ?? [] ); } /** * Format the "as" clause of the new group attributes. * * @param array $new * @param array $old * @return array */ protected static function formatAs($new, $old) { if (isset($old['as'])) { $new['as'] = $old['as'].($new['as'] ?? ''); } return $new; } } PKz Zd ?Illuminate/Routing/CreatesRegularExpressionRouteConstraints.phpnuW+AassignExpressionToParameters($parameters, '[a-zA-Z]+'); } /** * Specify that the given route parameters must be alphanumeric. * * @param array|string $parameters * @return $this */ public function whereAlphaNumeric($parameters) { return $this->assignExpressionToParameters($parameters, '[a-zA-Z0-9]+'); } /** * Specify that the given route parameters must be numeric. * * @param array|string $parameters * @return $this */ public function whereNumber($parameters) { return $this->assignExpressionToParameters($parameters, '[0-9]+'); } /** * Specify that the given route parameters must be ULIDs. * * @param array|string $parameters * @return $this */ public function whereUlid($parameters) { return $this->assignExpressionToParameters($parameters, '[0-7][0-9a-hjkmnp-tv-zA-HJKMNP-TV-Z]{25}'); } /** * Specify that the given route parameters must be UUIDs. * * @param array|string $parameters * @return $this */ public function whereUuid($parameters) { return $this->assignExpressionToParameters($parameters, '[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}'); } /** * Specify that the given route parameters must be one of the given values. * * @param array|string $parameters * @param array $values * @return $this */ public function whereIn($parameters, array $values) { return $this->assignExpressionToParameters($parameters, implode('|', $values)); } /** * Apply the given regular expression to the given parameters. * * @param array|string $parameters * @param string $expression * @return $this */ protected function assignExpressionToParameters($parameters, $expression) { return $this->where(collect(Arr::wrap($parameters)) ->mapWithKeys(fn ($parameter) => [$parameter => $expression]) ->all()); } } PKz Z')4Illuminate/Routing/Console/MiddlewareMakeCommand.phpnuW+AresolveStubPath('/stubs/middleware.stub'); } /** * Resolve the fully-qualified path to the stub. * * @param string $stub * @return string */ protected function resolveStubPath($stub) { return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) ? $customPath : __DIR__.$stub; } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return $rootNamespace.'\Http\Middleware'; } } PKz Z[v,v,4Illuminate/Routing/Console/ControllerMakeCommand.phpnuW+Aoption('type')) { $stub = "/stubs/controller.{$type}.stub"; } elseif ($this->option('parent')) { $stub = $this->option('singleton') ? '/stubs/controller.nested.singleton.stub' : '/stubs/controller.nested.stub'; } elseif ($this->option('model')) { $stub = '/stubs/controller.model.stub'; } elseif ($this->option('invokable')) { $stub = '/stubs/controller.invokable.stub'; } elseif ($this->option('singleton')) { $stub = '/stubs/controller.singleton.stub'; } elseif ($this->option('resource')) { $stub = '/stubs/controller.stub'; } if ($this->option('api') && is_null($stub)) { $stub = '/stubs/controller.api.stub'; } elseif ($this->option('api') && ! is_null($stub) && ! $this->option('invokable')) { $stub = str_replace('.stub', '.api.stub', $stub); } $stub ??= '/stubs/controller.plain.stub'; return $this->resolveStubPath($stub); } /** * Resolve the fully-qualified path to the stub. * * @param string $stub * @return string */ protected function resolveStubPath($stub) { return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) ? $customPath : __DIR__.$stub; } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return $rootNamespace.'\Http\Controllers'; } /** * Build the class with the given name. * * Remove the base controller import if we are already in the base namespace. * * @param string $name * @return string */ protected function buildClass($name) { $controllerNamespace = $this->getNamespace($name); $replace = []; if ($this->option('parent')) { $replace = $this->buildParentReplacements(); } if ($this->option('model')) { $replace = $this->buildModelReplacements($replace); } if ($this->option('creatable')) { $replace['abort(404);'] = '//'; } $replace["use {$controllerNamespace}\Controller;\n"] = ''; return str_replace( array_keys($replace), array_values($replace), parent::buildClass($name) ); } /** * Build the replacements for a parent controller. * * @return array */ protected function buildParentReplacements() { $parentModelClass = $this->parseModel($this->option('parent')); if (! class_exists($parentModelClass) && $this->components->confirm("A {$parentModelClass} model does not exist. Do you want to generate it?", true)) { $this->call('make:model', ['name' => $parentModelClass]); } return [ 'ParentDummyFullModelClass' => $parentModelClass, '{{ namespacedParentModel }}' => $parentModelClass, '{{namespacedParentModel}}' => $parentModelClass, 'ParentDummyModelClass' => class_basename($parentModelClass), '{{ parentModel }}' => class_basename($parentModelClass), '{{parentModel}}' => class_basename($parentModelClass), 'ParentDummyModelVariable' => lcfirst(class_basename($parentModelClass)), '{{ parentModelVariable }}' => lcfirst(class_basename($parentModelClass)), '{{parentModelVariable}}' => lcfirst(class_basename($parentModelClass)), ]; } /** * Build the model replacement values. * * @param array $replace * @return array */ protected function buildModelReplacements(array $replace) { $modelClass = $this->parseModel($this->option('model')); if (! class_exists($modelClass) && $this->components->confirm("A {$modelClass} model does not exist. Do you want to generate it?", true)) { $this->call('make:model', ['name' => $modelClass]); } $replace = $this->buildFormRequestReplacements($replace, $modelClass); return array_merge($replace, [ 'DummyFullModelClass' => $modelClass, '{{ namespacedModel }}' => $modelClass, '{{namespacedModel}}' => $modelClass, 'DummyModelClass' => class_basename($modelClass), '{{ model }}' => class_basename($modelClass), '{{model}}' => class_basename($modelClass), 'DummyModelVariable' => lcfirst(class_basename($modelClass)), '{{ modelVariable }}' => lcfirst(class_basename($modelClass)), '{{modelVariable}}' => lcfirst(class_basename($modelClass)), ]); } /** * Get the fully-qualified model class name. * * @param string $model * @return string * * @throws \InvalidArgumentException */ protected function parseModel($model) { if (preg_match('([^A-Za-z0-9_/\\\\])', $model)) { throw new InvalidArgumentException('Model name contains invalid characters.'); } return $this->qualifyModel($model); } /** * Build the model replacement values. * * @param array $replace * @param string $modelClass * @return array */ protected function buildFormRequestReplacements(array $replace, $modelClass) { [$namespace, $storeRequestClass, $updateRequestClass] = [ 'Illuminate\\Http', 'Request', 'Request', ]; if ($this->option('requests')) { $namespace = 'App\\Http\\Requests'; [$storeRequestClass, $updateRequestClass] = $this->generateFormRequests( $modelClass, $storeRequestClass, $updateRequestClass ); } $namespacedRequests = $namespace.'\\'.$storeRequestClass.';'; if ($storeRequestClass !== $updateRequestClass) { $namespacedRequests .= PHP_EOL.'use '.$namespace.'\\'.$updateRequestClass.';'; } return array_merge($replace, [ '{{ storeRequest }}' => $storeRequestClass, '{{storeRequest}}' => $storeRequestClass, '{{ updateRequest }}' => $updateRequestClass, '{{updateRequest}}' => $updateRequestClass, '{{ namespacedStoreRequest }}' => $namespace.'\\'.$storeRequestClass, '{{namespacedStoreRequest}}' => $namespace.'\\'.$storeRequestClass, '{{ namespacedUpdateRequest }}' => $namespace.'\\'.$updateRequestClass, '{{namespacedUpdateRequest}}' => $namespace.'\\'.$updateRequestClass, '{{ namespacedRequests }}' => $namespacedRequests, '{{namespacedRequests}}' => $namespacedRequests, ]); } /** * Generate the form requests for the given model and classes. * * @param string $modelClass * @param string $storeRequestClass * @param string $updateRequestClass * @return array */ protected function generateFormRequests($modelClass, $storeRequestClass, $updateRequestClass) { $storeRequestClass = 'Store'.class_basename($modelClass).'Request'; $this->call('make:request', [ 'name' => $storeRequestClass, ]); $updateRequestClass = 'Update'.class_basename($modelClass).'Request'; $this->call('make:request', [ 'name' => $updateRequestClass, ]); return [$storeRequestClass, $updateRequestClass]; } /** * Get the console command options. * * @return array */ protected function getOptions() { return [ ['api', null, InputOption::VALUE_NONE, 'Exclude the create and edit methods from the controller'], ['type', null, InputOption::VALUE_REQUIRED, 'Manually specify the controller stub file to use'], ['force', null, InputOption::VALUE_NONE, 'Create the class even if the controller already exists'], ['invokable', 'i', InputOption::VALUE_NONE, 'Generate a single method, invokable controller class'], ['model', 'm', InputOption::VALUE_OPTIONAL, 'Generate a resource controller for the given model'], ['parent', 'p', InputOption::VALUE_OPTIONAL, 'Generate a nested resource controller class'], ['resource', 'r', InputOption::VALUE_NONE, 'Generate a resource controller class'], ['requests', 'R', InputOption::VALUE_NONE, 'Generate FormRequest classes for store and update'], ['singleton', 's', InputOption::VALUE_NONE, 'Generate a singleton resource controller class'], ['creatable', null, InputOption::VALUE_NONE, 'Indicate that a singleton resource should be creatable'], ]; } /** * Interact further with the user if they were prompted for missing arguments. * * @param \Symfony\Component\Console\Input\InputInterface $input * @param \Symfony\Component\Console\Output\OutputInterface $output * @return void */ protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output) { if ($this->didReceiveOptions($input)) { return; } $type = $this->components->choice('Which type of controller would you like', [ 'empty', 'api', 'invokable', 'resource', 'singleton', ], default: 0); if ($type !== 'empty') { $input->setOption($type, true); } if (in_array($type, ['api', 'resource', 'singleton'])) { $model = $this->components->askWithCompletion( "What model should this $type controller be for?", $this->possibleModels(), 'none' ); if ($model && $model !== 'none') { $input->setOption('model', $model); } } } } PKz Z`Ma?0Illuminate/Routing/Console/stubs/middleware.stubnuW+AIlluminate/Routing/Console/stubs/controller.singleton.api.stubnuW+Amiddleware = $middleware; } /** * Specify the only controller methods the middleware should apply to. * * @param array|string $only * @return $this */ public function only(array|string $only) { $this->only = Arr::wrap($only); return $this; } /** * Specify the controller methods the middleware should not apply to. * * @param array|string $only * @return $this */ public function except(array|string $except) { $this->except = Arr::wrap($except); return $this; } } PKz Z']0Illuminate/Routing/Controllers/HasMiddleware.phpnuW+Agenerator = $generator; } /** * Create a new redirect response to the "home" route. * * @param int $status * @return \Illuminate\Http\RedirectResponse * * @deprecated Will be removed in a future Laravel version. */ public function home($status = 302) { return $this->to($this->generator->route('home'), $status); } /** * Create a new redirect response to the previous location. * * @param int $status * @param array $headers * @param mixed $fallback * @return \Illuminate\Http\RedirectResponse */ public function back($status = 302, $headers = [], $fallback = false) { return $this->createRedirect($this->generator->previous($fallback), $status, $headers); } /** * Create a new redirect response to the current URI. * * @param int $status * @param array $headers * @return \Illuminate\Http\RedirectResponse */ public function refresh($status = 302, $headers = []) { return $this->to($this->generator->getRequest()->path(), $status, $headers); } /** * Create a new redirect response, while putting the current URL in the session. * * @param string $path * @param int $status * @param array $headers * @param bool|null $secure * @return \Illuminate\Http\RedirectResponse */ public function guest($path, $status = 302, $headers = [], $secure = null) { $request = $this->generator->getRequest(); $intended = $request->isMethod('GET') && $request->route() && ! $request->expectsJson() ? $this->generator->full() : $this->generator->previous(); if ($intended) { $this->setIntendedUrl($intended); } return $this->to($path, $status, $headers, $secure); } /** * Create a new redirect response to the previously intended location. * * @param mixed $default * @param int $status * @param array $headers * @param bool|null $secure * @return \Illuminate\Http\RedirectResponse */ public function intended($default = '/', $status = 302, $headers = [], $secure = null) { $path = $this->session->pull('url.intended', $default); return $this->to($path, $status, $headers, $secure); } /** * Create a new redirect response to the given path. * * @param string $path * @param int $status * @param array $headers * @param bool|null $secure * @return \Illuminate\Http\RedirectResponse */ public function to($path, $status = 302, $headers = [], $secure = null) { return $this->createRedirect($this->generator->to($path, [], $secure), $status, $headers); } /** * Create a new redirect response to an external URL (no validation). * * @param string $path * @param int $status * @param array $headers * @return \Illuminate\Http\RedirectResponse */ public function away($path, $status = 302, $headers = []) { return $this->createRedirect($path, $status, $headers); } /** * Create a new redirect response to the given HTTPS path. * * @param string $path * @param int $status * @param array $headers * @return \Illuminate\Http\RedirectResponse */ public function secure($path, $status = 302, $headers = []) { return $this->to($path, $status, $headers, true); } /** * Create a new redirect response to a named route. * * @param string $route * @param mixed $parameters * @param int $status * @param array $headers * @return \Illuminate\Http\RedirectResponse */ public function route($route, $parameters = [], $status = 302, $headers = []) { return $this->to($this->generator->route($route, $parameters), $status, $headers); } /** * Create a new redirect response to a signed named route. * * @param string $route * @param mixed $parameters * @param \DateTimeInterface|\DateInterval|int|null $expiration * @param int $status * @param array $headers * @return \Illuminate\Http\RedirectResponse */ public function signedRoute($route, $parameters = [], $expiration = null, $status = 302, $headers = []) { return $this->to($this->generator->signedRoute($route, $parameters, $expiration), $status, $headers); } /** * Create a new redirect response to a signed named route. * * @param string $route * @param \DateTimeInterface|\DateInterval|int|null $expiration * @param mixed $parameters * @param int $status * @param array $headers * @return \Illuminate\Http\RedirectResponse */ public function temporarySignedRoute($route, $expiration, $parameters = [], $status = 302, $headers = []) { return $this->to($this->generator->temporarySignedRoute($route, $expiration, $parameters), $status, $headers); } /** * Create a new redirect response to a controller action. * * @param string|array $action * @param mixed $parameters * @param int $status * @param array $headers * @return \Illuminate\Http\RedirectResponse */ public function action($action, $parameters = [], $status = 302, $headers = []) { return $this->to($this->generator->action($action, $parameters), $status, $headers); } /** * Create a new redirect response. * * @param string $path * @param int $status * @param array $headers * @return \Illuminate\Http\RedirectResponse */ protected function createRedirect($path, $status, $headers) { return tap(new RedirectResponse($path, $status, $headers), function ($redirect) { if (isset($this->session)) { $redirect->setSession($this->session); } $redirect->setRequest($this->generator->getRequest()); }); } /** * Get the URL generator instance. * * @return \Illuminate\Routing\UrlGenerator */ public function getUrlGenerator() { return $this->generator; } /** * Set the active session store. * * @param \Illuminate\Session\Store $session * @return void */ public function setSession(SessionStore $session) { $this->session = $session; } /** * Get the "intended" URL from the session. * * @return string|null */ public function getIntendedUrl() { return $this->session->get('url.intended'); } /** * Set the "intended" URL in the session. * * @param string $url * @return $this */ public function setIntendedUrl($url) { $this->session->put('url.intended', $url); return $this; } } PKz ZSCC3Illuminate/Routing/RouteDependencyResolverTrait.phpnuW+AresolveMethodDependencies( $parameters, new ReflectionMethod($instance, $method) ); } /** * Resolve the given method's type-hinted dependencies. * * @param array $parameters * @param \ReflectionFunctionAbstract $reflector * @return array */ public function resolveMethodDependencies(array $parameters, ReflectionFunctionAbstract $reflector) { $instanceCount = 0; $values = array_values($parameters); $skippableValue = new stdClass; foreach ($reflector->getParameters() as $key => $parameter) { $instance = $this->transformDependency($parameter, $parameters, $skippableValue); if ($instance !== $skippableValue) { $instanceCount++; $this->spliceIntoParameters($parameters, $key, $instance); } elseif (! isset($values[$key - $instanceCount]) && $parameter->isDefaultValueAvailable()) { $this->spliceIntoParameters($parameters, $key, $parameter->getDefaultValue()); } } return $parameters; } /** * Attempt to transform the given parameter into a class instance. * * @param \ReflectionParameter $parameter * @param array $parameters * @param object $skippableValue * @return mixed */ protected function transformDependency(ReflectionParameter $parameter, $parameters, $skippableValue) { $className = Reflector::getParameterClassName($parameter); // If the parameter has a type-hinted class, we will check to see if it is already in // the list of parameters. If it is we will just skip it as it is probably a model // binding and we do not want to mess with those; otherwise, we resolve it here. if ($className && ! $this->alreadyInParameters($className, $parameters)) { $isEnum = method_exists(ReflectionClass::class, 'isEnum') && (new ReflectionClass($className))->isEnum(); return $parameter->isDefaultValueAvailable() ? ($isEnum ? $parameter->getDefaultValue() : null) : $this->container->make($className); } return $skippableValue; } /** * Determine if an object of the given class is in a list of parameters. * * @param string $class * @param array $parameters * @return bool */ protected function alreadyInParameters($class, array $parameters) { return ! is_null(Arr::first($parameters, fn ($value) => $value instanceof $class)); } /** * Splice the given value into the parameter list. * * @param array $parameters * @param string $offset * @param mixed $value * @return void */ protected function spliceIntoParameters(array &$parameters, $offset, $value) { array_splice( $parameters, $offset, 0, [$value] ); } } PKz Z\  2Illuminate/Routing/PendingResourceRegistration.phpnuW+Aname = $name; $this->options = $options; $this->registrar = $registrar; $this->controller = $controller; } /** * Set the methods the controller should apply to. * * @param array|string|dynamic $methods * @return \Illuminate\Routing\PendingResourceRegistration */ public function only($methods) { $this->options['only'] = is_array($methods) ? $methods : func_get_args(); return $this; } /** * Set the methods the controller should exclude. * * @param array|string|dynamic $methods * @return \Illuminate\Routing\PendingResourceRegistration */ public function except($methods) { $this->options['except'] = is_array($methods) ? $methods : func_get_args(); return $this; } /** * Set the route names for controller actions. * * @param array|string $names * @return \Illuminate\Routing\PendingResourceRegistration */ public function names($names) { $this->options['names'] = $names; return $this; } /** * Set the route name for a controller action. * * @param string $method * @param string $name * @return \Illuminate\Routing\PendingResourceRegistration */ public function name($method, $name) { $this->options['names'][$method] = $name; return $this; } /** * Override the route parameter names. * * @param array|string $parameters * @return \Illuminate\Routing\PendingResourceRegistration */ public function parameters($parameters) { $this->options['parameters'] = $parameters; return $this; } /** * Override a route parameter's name. * * @param string $previous * @param string $new * @return \Illuminate\Routing\PendingResourceRegistration */ public function parameter($previous, $new) { $this->options['parameters'][$previous] = $new; return $this; } /** * Add middleware to the resource routes. * * @param mixed $middleware * @return \Illuminate\Routing\PendingResourceRegistration */ public function middleware($middleware) { $middleware = Arr::wrap($middleware); foreach ($middleware as $key => $value) { $middleware[$key] = (string) $value; } $this->options['middleware'] = $middleware; return $this; } /** * Specify middleware that should be removed from the resource routes. * * @param array|string $middleware * @return $this|array */ public function withoutMiddleware($middleware) { $this->options['excluded_middleware'] = array_merge( (array) ($this->options['excluded_middleware'] ?? []), Arr::wrap($middleware) ); return $this; } /** * Add "where" constraints to the resource routes. * * @param mixed $wheres * @return \Illuminate\Routing\PendingResourceRegistration */ public function where($wheres) { $this->options['wheres'] = $wheres; return $this; } /** * Indicate that the resource routes should have "shallow" nesting. * * @param bool $shallow * @return \Illuminate\Routing\PendingResourceRegistration */ public function shallow($shallow = true) { $this->options['shallow'] = $shallow; return $this; } /** * Define the callable that should be invoked on a missing model exception. * * @param callable $callback * @return $this */ public function missing($callback) { $this->options['missing'] = $callback; return $this; } /** * Indicate that the resource routes should be scoped using the given binding fields. * * @param array $fields * @return \Illuminate\Routing\PendingResourceRegistration */ public function scoped(array $fields = []) { $this->options['bindingFields'] = $fields; return $this; } /** * Define which routes should allow "trashed" models to be retrieved when resolving implicit model bindings. * * @param array $methods * @return \Illuminate\Routing\PendingResourceRegistration */ public function withTrashed(array $methods = []) { $this->options['trashed'] = $methods; return $this; } /** * Register the resource route. * * @return \Illuminate\Routing\RouteCollection */ public function register() { $this->registered = true; return $this->registrar->register( $this->name, $this->controller, $this->options ); } /** * Handle the object's destruction. * * @return void */ public function __destruct() { if (! $this->registered) { $this->register(); } } } PKz Z|)5 #Illuminate/Routing/RouteBinding.phpnuW+Amake($class), $method]; return $callable($value, $route); }; } /** * Create a Route model binding for a model. * * @param \Illuminate\Container\Container $container * @param string $class * @param \Closure|null $callback * @return \Closure * * @throws \Illuminate\Database\Eloquent\ModelNotFoundException<\Illuminate\Database\Eloquent\Model> */ public static function forModel($container, $class, $callback = null) { return function ($value) use ($container, $class, $callback) { if (is_null($value)) { return; } // For model binders, we will attempt to retrieve the models using the first // method on the model instance. If we cannot retrieve the models we'll // throw a not found exception otherwise we will return the instance. $instance = $container->make($class); if ($model = $instance->resolveRouteBinding($value)) { return $model; } // If a callback was supplied to the method we will call that to determine // what we should do when the model is not found. This just gives these // developer a little greater flexibility to decide what will happen. if ($callback instanceof Closure) { return $callback($value); } throw (new ModelNotFoundException)->setModel($class); }; } } PKz ZO/Illuminate/Routing/Matching/MethodValidator.phpnuW+AgetMethod(), $route->methods()); } } PKz Z32Illuminate/Routing/Matching/ValidatorInterface.phpnuW+AgetPathInfo(), '/') ?: '/'; return preg_match($route->getCompiled()->getRegex(), rawurldecode($path)); } } PKz ZJPqq-Illuminate/Routing/Matching/HostValidator.phpnuW+AgetCompiled()->getHostRegex(); if (is_null($hostRegex)) { return true; } return preg_match($hostRegex, $request->getHost()); } } PKz Z()kk/Illuminate/Routing/Matching/SchemeValidator.phpnuW+AhttpOnly()) { return ! $request->secure(); } elseif ($route->secure()) { return $request->secure(); } return true; } } PKz Zܟf Illuminate/Routing/composer.jsonnuW+A{ "name": "illuminate/routing", "description": "The Illuminate Routing package.", "license": "MIT", "homepage": "https://laravel.com", "support": { "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, "authors": [ { "name": "Taylor Otwell", "email": "taylor@laravel.com" } ], "require": { "php": "^8.0.2", "ext-filter": "*", "ext-hash": "*", "illuminate/collections": "^9.0", "illuminate/container": "^9.0", "illuminate/contracts": "^9.0", "illuminate/http": "^9.0", "illuminate/macroable": "^9.0", "illuminate/pipeline": "^9.0", "illuminate/session": "^9.0", "illuminate/support": "^9.0", "symfony/http-foundation": "^6.0", "symfony/http-kernel": "^6.0", "symfony/routing": "^6.0" }, "autoload": { "psr-4": { "Illuminate\\Routing\\": "" } }, "extra": { "branch-alias": { "dev-master": "9.x-dev" } }, "suggest": { "illuminate/console": "Required to use the make commands (^9.0).", "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0)." }, "config": { "sort-packages": true }, "minimum-stability": "dev" } PKz Z>@rUrU#Illuminate/Routing/UrlGenerator.phpnuW+Aroutes = $routes; $this->assetRoot = $assetRoot; $this->setRequest($request); } /** * Get the full URL for the current request. * * @return string */ public function full() { return $this->request->fullUrl(); } /** * Get the current URL for the request. * * @return string */ public function current() { return $this->to($this->request->getPathInfo()); } /** * Get the URL for the previous request. * * @param mixed $fallback * @return string */ public function previous($fallback = false) { $referrer = $this->request->headers->get('referer'); $url = $referrer ? $this->to($referrer) : $this->getPreviousUrlFromSession(); if ($url) { return $url; } elseif ($fallback) { return $this->to($fallback); } return $this->to('/'); } /** * Get the previous path info for the request. * * @param mixed $fallback * @return string */ public function previousPath($fallback = false) { $previousPath = str_replace($this->to('/'), '', rtrim(preg_replace('/\?.*/', '', $this->previous($fallback)), '/')); return $previousPath === '' ? '/' : $previousPath; } /** * Get the previous URL from the session if possible. * * @return string|null */ protected function getPreviousUrlFromSession() { $session = $this->getSession(); return $session ? $session->previousUrl() : null; } /** * Generate an absolute URL to the given path. * * @param string $path * @param mixed $extra * @param bool|null $secure * @return string */ public function to($path, $extra = [], $secure = null) { // First we will check if the URL is already a valid URL. If it is we will not // try to generate a new one but will simply return the URL as is, which is // convenient since developers do not always have to check if it's valid. if ($this->isValidUrl($path)) { return $path; } $tail = implode('/', array_map( 'rawurlencode', (array) $this->formatParameters($extra)) ); // Once we have the scheme we will compile the "tail" by collapsing the values // into a single string delimited by slashes. This just makes it convenient // for passing the array of parameters to this URL as a list of segments. $root = $this->formatRoot($this->formatScheme($secure)); [$path, $query] = $this->extractQueryString($path); return $this->format( $root, '/'.trim($path.'/'.$tail, '/') ).$query; } /** * Generate a secure, absolute URL to the given path. * * @param string $path * @param array $parameters * @return string */ public function secure($path, $parameters = []) { return $this->to($path, $parameters, true); } /** * Generate the URL to an application asset. * * @param string $path * @param bool|null $secure * @return string */ public function asset($path, $secure = null) { if ($this->isValidUrl($path)) { return $path; } // Once we get the root URL, we will check to see if it contains an index.php // file in the paths. If it does, we will remove it since it is not needed // for asset paths, but only for routes to endpoints in the application. $root = $this->assetRoot ?: $this->formatRoot($this->formatScheme($secure)); return $this->removeIndex($root).'/'.trim($path, '/'); } /** * Generate the URL to a secure asset. * * @param string $path * @return string */ public function secureAsset($path) { return $this->asset($path, true); } /** * Generate the URL to an asset from a custom root domain such as CDN, etc. * * @param string $root * @param string $path * @param bool|null $secure * @return string */ public function assetFrom($root, $path, $secure = null) { // Once we get the root URL, we will check to see if it contains an index.php // file in the paths. If it does, we will remove it since it is not needed // for asset paths, but only for routes to endpoints in the application. $root = $this->formatRoot($this->formatScheme($secure), $root); return $this->removeIndex($root).'/'.trim($path, '/'); } /** * Remove the index.php file from a path. * * @param string $root * @return string */ protected function removeIndex($root) { $i = 'index.php'; return str_contains($root, $i) ? str_replace('/'.$i, '', $root) : $root; } /** * Get the default scheme for a raw URL. * * @param bool|null $secure * @return string */ public function formatScheme($secure = null) { if (! is_null($secure)) { return $secure ? 'https://' : 'http://'; } if (is_null($this->cachedScheme)) { $this->cachedScheme = $this->forceScheme ?: $this->request->getScheme().'://'; } return $this->cachedScheme; } /** * Create a signed route URL for a named route. * * @param string $name * @param mixed $parameters * @param \DateTimeInterface|\DateInterval|int|null $expiration * @param bool $absolute * @return string * * @throws \InvalidArgumentException */ public function signedRoute($name, $parameters = [], $expiration = null, $absolute = true) { $this->ensureSignedRouteParametersAreNotReserved( $parameters = Arr::wrap($parameters) ); if ($expiration) { $parameters = $parameters + ['expires' => $this->availableAt($expiration)]; } ksort($parameters); $key = call_user_func($this->keyResolver); return $this->route($name, $parameters + [ 'signature' => hash_hmac('sha256', $this->route($name, $parameters, $absolute), $key), ], $absolute); } /** * Ensure the given signed route parameters are not reserved. * * @param mixed $parameters * @return void */ protected function ensureSignedRouteParametersAreNotReserved($parameters) { if (array_key_exists('signature', $parameters)) { throw new InvalidArgumentException( '"Signature" is a reserved parameter when generating signed routes. Please rename your route parameter.' ); } if (array_key_exists('expires', $parameters)) { throw new InvalidArgumentException( '"Expires" is a reserved parameter when generating signed routes. Please rename your route parameter.' ); } } /** * Create a temporary signed route URL for a named route. * * @param string $name * @param \DateTimeInterface|\DateInterval|int $expiration * @param array $parameters * @param bool $absolute * @return string */ public function temporarySignedRoute($name, $expiration, $parameters = [], $absolute = true) { return $this->signedRoute($name, $parameters, $expiration, $absolute); } /** * Determine if the given request has a valid signature. * * @param \Illuminate\Http\Request $request * @param bool $absolute * @param array $ignoreQuery * @return bool */ public function hasValidSignature(Request $request, $absolute = true, array $ignoreQuery = []) { return $this->hasCorrectSignature($request, $absolute, $ignoreQuery) && $this->signatureHasNotExpired($request); } /** * Determine if the given request has a valid signature for a relative URL. * * @param \Illuminate\Http\Request $request * @param array $ignoreQuery * @return bool */ public function hasValidRelativeSignature(Request $request, array $ignoreQuery = []) { return $this->hasValidSignature($request, false, $ignoreQuery); } /** * Determine if the signature from the given request matches the URL. * * @param \Illuminate\Http\Request $request * @param bool $absolute * @param array $ignoreQuery * @return bool */ public function hasCorrectSignature(Request $request, $absolute = true, array $ignoreQuery = []) { $ignoreQuery[] = 'signature'; $url = $absolute ? $request->url() : '/'.$request->path(); $queryString = collect(explode('&', (string) $request->server->get('QUERY_STRING'))) ->reject(fn ($parameter) => in_array(Str::before($parameter, '='), $ignoreQuery)) ->join('&'); $original = rtrim($url.'?'.$queryString, '?'); $signature = hash_hmac('sha256', $original, call_user_func($this->keyResolver)); return hash_equals($signature, (string) $request->query('signature', '')); } /** * Determine if the expires timestamp from the given request is not from the past. * * @param \Illuminate\Http\Request $request * @return bool */ public function signatureHasNotExpired(Request $request) { $expires = $request->query('expires'); return ! ($expires && Carbon::now()->getTimestamp() > $expires); } /** * Get the URL to a named route. * * @param string $name * @param mixed $parameters * @param bool $absolute * @return string * * @throws \Symfony\Component\Routing\Exception\RouteNotFoundException */ public function route($name, $parameters = [], $absolute = true) { if (! is_null($route = $this->routes->getByName($name))) { return $this->toRoute($route, $parameters, $absolute); } throw new RouteNotFoundException("Route [{$name}] not defined."); } /** * Get the URL for a given route instance. * * @param \Illuminate\Routing\Route $route * @param mixed $parameters * @param bool $absolute * @return string * * @throws \Illuminate\Routing\Exceptions\UrlGenerationException */ public function toRoute($route, $parameters, $absolute) { $parameters = collect(Arr::wrap($parameters))->map(function ($value, $key) use ($route) { $value = $value instanceof UrlRoutable && $route->bindingFieldFor($key) ? $value->{$route->bindingFieldFor($key)} : $value; return function_exists('enum_exists') && $value instanceof BackedEnum ? $value->value : $value; })->all(); return $this->routeUrl()->to( $route, $this->formatParameters($parameters), $absolute ); } /** * Get the URL to a controller action. * * @param string|array $action * @param mixed $parameters * @param bool $absolute * @return string * * @throws \InvalidArgumentException */ public function action($action, $parameters = [], $absolute = true) { if (is_null($route = $this->routes->getByAction($action = $this->formatAction($action)))) { throw new InvalidArgumentException("Action {$action} not defined."); } return $this->toRoute($route, $parameters, $absolute); } /** * Format the given controller action. * * @param string|array $action * @return string */ protected function formatAction($action) { if (is_array($action)) { $action = '\\'.implode('@', $action); } if ($this->rootNamespace && ! str_starts_with($action, '\\')) { return $this->rootNamespace.'\\'.$action; } else { return trim($action, '\\'); } } /** * Format the array of URL parameters. * * @param mixed|array $parameters * @return array */ public function formatParameters($parameters) { $parameters = Arr::wrap($parameters); foreach ($parameters as $key => $parameter) { if ($parameter instanceof UrlRoutable) { $parameters[$key] = $parameter->getRouteKey(); } } return $parameters; } /** * Extract the query string from the given path. * * @param string $path * @return array */ protected function extractQueryString($path) { if (($queryPosition = strpos($path, '?')) !== false) { return [ substr($path, 0, $queryPosition), substr($path, $queryPosition), ]; } return [$path, '']; } /** * Get the base URL for the request. * * @param string $scheme * @param string|null $root * @return string */ public function formatRoot($scheme, $root = null) { if (is_null($root)) { if (is_null($this->cachedRoot)) { $this->cachedRoot = $this->forcedRoot ?: $this->request->root(); } $root = $this->cachedRoot; } $start = str_starts_with($root, 'http://') ? 'http://' : 'https://'; return preg_replace('~'.$start.'~', $scheme, $root, 1); } /** * Format the given URL segments into a single URL. * * @param string $root * @param string $path * @param \Illuminate\Routing\Route|null $route * @return string */ public function format($root, $path, $route = null) { $path = '/'.trim($path, '/'); if ($this->formatHostUsing) { $root = call_user_func($this->formatHostUsing, $root, $route); } if ($this->formatPathUsing) { $path = call_user_func($this->formatPathUsing, $path, $route); } return trim($root.$path, '/'); } /** * Determine if the given path is a valid URL. * * @param string $path * @return bool */ public function isValidUrl($path) { if (! preg_match('~^(#|//|https?://|(mailto|tel|sms):)~', $path)) { return filter_var($path, FILTER_VALIDATE_URL) !== false; } return true; } /** * Get the Route URL generator instance. * * @return \Illuminate\Routing\RouteUrlGenerator */ protected function routeUrl() { if (! $this->routeGenerator) { $this->routeGenerator = new RouteUrlGenerator($this, $this->request); } return $this->routeGenerator; } /** * Set the default named parameters used by the URL generator. * * @param array $defaults * @return void */ public function defaults(array $defaults) { $this->routeUrl()->defaults($defaults); } /** * Get the default named parameters used by the URL generator. * * @return array */ public function getDefaultParameters() { return $this->routeUrl()->defaultParameters; } /** * Force the scheme for URLs. * * @param string|null $scheme * @return void */ public function forceScheme($scheme) { $this->cachedScheme = null; $this->forceScheme = $scheme ? $scheme.'://' : null; } /** * Set the forced root URL. * * @param string|null $root * @return void */ public function forceRootUrl($root) { $this->forcedRoot = $root ? rtrim($root, '/') : null; $this->cachedRoot = null; } /** * Set a callback to be used to format the host of generated URLs. * * @param \Closure $callback * @return $this */ public function formatHostUsing(Closure $callback) { $this->formatHostUsing = $callback; return $this; } /** * Set a callback to be used to format the path of generated URLs. * * @param \Closure $callback * @return $this */ public function formatPathUsing(Closure $callback) { $this->formatPathUsing = $callback; return $this; } /** * Get the path formatter being used by the URL generator. * * @return \Closure */ public function pathFormatter() { return $this->formatPathUsing ?: function ($path) { return $path; }; } /** * Get the request instance. * * @return \Illuminate\Http\Request */ public function getRequest() { return $this->request; } /** * Set the current request instance. * * @param \Illuminate\Http\Request $request * @return void */ public function setRequest(Request $request) { $this->request = $request; $this->cachedRoot = null; $this->cachedScheme = null; tap(optional($this->routeGenerator)->defaultParameters ?: [], function ($defaults) { $this->routeGenerator = null; if (! empty($defaults)) { $this->defaults($defaults); } }); } /** * Set the route collection. * * @param \Illuminate\Routing\RouteCollectionInterface $routes * @return $this */ public function setRoutes(RouteCollectionInterface $routes) { $this->routes = $routes; return $this; } /** * Get the session implementation from the resolver. * * @return \Illuminate\Session\Store|null */ protected function getSession() { if ($this->sessionResolver) { return call_user_func($this->sessionResolver); } } /** * Set the session resolver for the generator. * * @param callable $sessionResolver * @return $this */ public function setSessionResolver(callable $sessionResolver) { $this->sessionResolver = $sessionResolver; return $this; } /** * Set the encryption key resolver. * * @param callable $keyResolver * @return $this */ public function setKeyResolver(callable $keyResolver) { $this->keyResolver = $keyResolver; return $this; } /** * Clone a new instance of the URL generator with a different encryption key resolver. * * @param callable $keyResolver * @return \Illuminate\Routing\UrlGenerator */ public function withKeyResolver(callable $keyResolver) { return (clone $this)->setKeyResolver($keyResolver); } /** * Get the root controller namespace. * * @return string */ public function getRootControllerNamespace() { return $this->rootNamespace; } /** * Set the root controller namespace. * * @param string $rootNamespace * @return $this */ public function setRootControllerNamespace($rootNamespace) { $this->rootNamespace = $rootNamespace; return $this; } } PKz Z|lYff/Illuminate/Routing/RouteSignatureParameters.phpnuW+AgetClosure() : $action['uses']; $parameters = is_string($callback) ? static::fromClassMethodString($callback) : (new ReflectionFunction($callback))->getParameters(); return match (true) { ! empty($conditions['subClass']) => array_filter($parameters, fn ($p) => Reflector::isParameterSubclassOf($p, $conditions['subClass'])), ! empty($conditions['backedEnum']) => array_filter($parameters, fn ($p) => Reflector::isParameterBackedEnumWithStringBackingType($p)), default => $parameters, }; } /** * Get the parameters for the given class / method by string. * * @param string $uses * @return array */ protected static function fromClassMethodString($uses) { [$class, $method] = Str::parseCallback($uses); if (! method_exists($class, $method) && Reflector::isCallable($class, $method)) { return []; } return (new ReflectionMethod($class, $method))->getParameters(); } } PKz ZZ VV3Illuminate/Routing/Contracts/CallableDispatcher.phpnuW+Aresponse = $response; } /** * Invoke the controller method. * * @param mixed ...$args * @return \Illuminate\Http\Response */ public function __invoke(...$args) { $routeParameters = array_filter($args, function ($key) { return ! in_array($key, ['view', 'data', 'status', 'headers']); }, ARRAY_FILTER_USE_KEY); $args['data'] = array_merge($args['data'], $routeParameters); return $this->response->view( $args['view'], $args['data'], $args['status'], $args['headers'] ); } /** * Execute an action on the controller. * * @param string $method * @param array $parameters * @return \Symfony\Component\HttpFoundation\Response */ public function callAction($method, $parameters) { return $this->{$method}(...$parameters); } } PKz Z+$Illuminate/Routing/Router.phpnuW+Aevents = $events; $this->routes = new RouteCollection; $this->container = $container ?: new Container; } /** * Register a new GET route with the router. * * @param string $uri * @param array|string|callable|null $action * @return \Illuminate\Routing\Route */ public function get($uri, $action = null) { return $this->addRoute(['GET', 'HEAD'], $uri, $action); } /** * Register a new POST route with the router. * * @param string $uri * @param array|string|callable|null $action * @return \Illuminate\Routing\Route */ public function post($uri, $action = null) { return $this->addRoute('POST', $uri, $action); } /** * Register a new PUT route with the router. * * @param string $uri * @param array|string|callable|null $action * @return \Illuminate\Routing\Route */ public function put($uri, $action = null) { return $this->addRoute('PUT', $uri, $action); } /** * Register a new PATCH route with the router. * * @param string $uri * @param array|string|callable|null $action * @return \Illuminate\Routing\Route */ public function patch($uri, $action = null) { return $this->addRoute('PATCH', $uri, $action); } /** * Register a new DELETE route with the router. * * @param string $uri * @param array|string|callable|null $action * @return \Illuminate\Routing\Route */ public function delete($uri, $action = null) { return $this->addRoute('DELETE', $uri, $action); } /** * Register a new OPTIONS route with the router. * * @param string $uri * @param array|string|callable|null $action * @return \Illuminate\Routing\Route */ public function options($uri, $action = null) { return $this->addRoute('OPTIONS', $uri, $action); } /** * Register a new route responding to all verbs. * * @param string $uri * @param array|string|callable|null $action * @return \Illuminate\Routing\Route */ public function any($uri, $action = null) { return $this->addRoute(self::$verbs, $uri, $action); } /** * Register a new Fallback route with the router. * * @param array|string|callable|null $action * @return \Illuminate\Routing\Route */ public function fallback($action) { $placeholder = 'fallbackPlaceholder'; return $this->addRoute( 'GET', "{{$placeholder}}", $action )->where($placeholder, '.*')->fallback(); } /** * Create a redirect from one URI to another. * * @param string $uri * @param string $destination * @param int $status * @return \Illuminate\Routing\Route */ public function redirect($uri, $destination, $status = 302) { return $this->any($uri, '\Illuminate\Routing\RedirectController') ->defaults('destination', $destination) ->defaults('status', $status); } /** * Create a permanent redirect from one URI to another. * * @param string $uri * @param string $destination * @return \Illuminate\Routing\Route */ public function permanentRedirect($uri, $destination) { return $this->redirect($uri, $destination, 301); } /** * Register a new route that returns a view. * * @param string $uri * @param string $view * @param array $data * @param int|array $status * @param array $headers * @return \Illuminate\Routing\Route */ public function view($uri, $view, $data = [], $status = 200, array $headers = []) { return $this->match(['GET', 'HEAD'], $uri, '\Illuminate\Routing\ViewController') ->setDefaults([ 'view' => $view, 'data' => $data, 'status' => is_array($status) ? 200 : $status, 'headers' => is_array($status) ? $status : $headers, ]); } /** * Register a new route with the given verbs. * * @param array|string $methods * @param string $uri * @param array|string|callable|null $action * @return \Illuminate\Routing\Route */ public function match($methods, $uri, $action = null) { return $this->addRoute(array_map('strtoupper', (array) $methods), $uri, $action); } /** * Register an array of resource controllers. * * @param array $resources * @param array $options * @return void */ public function resources(array $resources, array $options = []) { foreach ($resources as $name => $controller) { $this->resource($name, $controller, $options); } } /** * Route a resource to a controller. * * @param string $name * @param string $controller * @param array $options * @return \Illuminate\Routing\PendingResourceRegistration */ public function resource($name, $controller, array $options = []) { if ($this->container && $this->container->bound(ResourceRegistrar::class)) { $registrar = $this->container->make(ResourceRegistrar::class); } else { $registrar = new ResourceRegistrar($this); } return new PendingResourceRegistration( $registrar, $name, $controller, $options ); } /** * Register an array of API resource controllers. * * @param array $resources * @param array $options * @return void */ public function apiResources(array $resources, array $options = []) { foreach ($resources as $name => $controller) { $this->apiResource($name, $controller, $options); } } /** * Route an API resource to a controller. * * @param string $name * @param string $controller * @param array $options * @return \Illuminate\Routing\PendingResourceRegistration */ public function apiResource($name, $controller, array $options = []) { $only = ['index', 'show', 'store', 'update', 'destroy']; if (isset($options['except'])) { $only = array_diff($only, (array) $options['except']); } return $this->resource($name, $controller, array_merge([ 'only' => $only, ], $options)); } /** * Register an array of singleton resource controllers. * * @param array $singletons * @param array $options * @return void */ public function singletons(array $singletons, array $options = []) { foreach ($singletons as $name => $controller) { $this->singleton($name, $controller, $options); } } /** * Route a singleton resource to a controller. * * @param string $name * @param string $controller * @param array $options * @return \Illuminate\Routing\PendingSingletonResourceRegistration */ public function singleton($name, $controller, array $options = []) { if ($this->container && $this->container->bound(ResourceRegistrar::class)) { $registrar = $this->container->make(ResourceRegistrar::class); } else { $registrar = new ResourceRegistrar($this); } return new PendingSingletonResourceRegistration( $registrar, $name, $controller, $options ); } /** * Register an array of API singleton resource controllers. * * @param array $singletons * @param array $options * @return void */ public function apiSingletons(array $singletons, array $options = []) { foreach ($singletons as $name => $controller) { $this->apiSingleton($name, $controller, $options); } } /** * Route an API singleton resource to a controller. * * @param string $name * @param string $controller * @param array $options * @return \Illuminate\Routing\PendingSingletonResourceRegistration */ public function apiSingleton($name, $controller, array $options = []) { $only = ['show', 'update', 'destroy']; if (isset($options['except'])) { $only = array_diff($only, (array) $options['except']); } return $this->singleton($name, $controller, array_merge([ 'only' => $only, 'apiSingleton' => true, ], $options)); } /** * Create a route group with shared attributes. * * @param array $attributes * @param \Closure|array|string $routes * @return $this */ public function group(array $attributes, $routes) { foreach (Arr::wrap($routes) as $groupRoutes) { $this->updateGroupStack($attributes); // Once we have updated the group stack, we'll load the provided routes and // merge in the group's attributes when the routes are created. After we // have created the routes, we will pop the attributes off the stack. $this->loadRoutes($groupRoutes); array_pop($this->groupStack); } return $this; } /** * Update the group stack with the given attributes. * * @param array $attributes * @return void */ protected function updateGroupStack(array $attributes) { if ($this->hasGroupStack()) { $attributes = $this->mergeWithLastGroup($attributes); } $this->groupStack[] = $attributes; } /** * Merge the given array with the last group stack. * * @param array $new * @param bool $prependExistingPrefix * @return array */ public function mergeWithLastGroup($new, $prependExistingPrefix = true) { return RouteGroup::merge($new, end($this->groupStack), $prependExistingPrefix); } /** * Load the provided routes. * * @param \Closure|string $routes * @return void */ protected function loadRoutes($routes) { if ($routes instanceof Closure) { $routes($this); } else { (new RouteFileRegistrar($this))->register($routes); } } /** * Get the prefix from the last group on the stack. * * @return string */ public function getLastGroupPrefix() { if ($this->hasGroupStack()) { $last = end($this->groupStack); return $last['prefix'] ?? ''; } return ''; } /** * Add a route to the underlying route collection. * * @param array|string $methods * @param string $uri * @param array|string|callable|null $action * @return \Illuminate\Routing\Route */ public function addRoute($methods, $uri, $action) { return $this->routes->add($this->createRoute($methods, $uri, $action)); } /** * Create a new route instance. * * @param array|string $methods * @param string $uri * @param mixed $action * @return \Illuminate\Routing\Route */ protected function createRoute($methods, $uri, $action) { // If the route is routing to a controller we will parse the route action into // an acceptable array format before registering it and creating this route // instance itself. We need to build the Closure that will call this out. if ($this->actionReferencesController($action)) { $action = $this->convertToControllerAction($action); } $route = $this->newRoute( $methods, $this->prefix($uri), $action ); // If we have groups that need to be merged, we will merge them now after this // route has already been created and is ready to go. After we're done with // the merge we will be ready to return the route back out to the caller. if ($this->hasGroupStack()) { $this->mergeGroupAttributesIntoRoute($route); } $this->addWhereClausesToRoute($route); return $route; } /** * Determine if the action is routing to a controller. * * @param mixed $action * @return bool */ protected function actionReferencesController($action) { if (! $action instanceof Closure) { return is_string($action) || (isset($action['uses']) && is_string($action['uses'])); } return false; } /** * Add a controller based route action to the action array. * * @param array|string $action * @return array */ protected function convertToControllerAction($action) { if (is_string($action)) { $action = ['uses' => $action]; } // Here we'll merge any group "controller" and "uses" statements if necessary so that // the action has the proper clause for this property. Then, we can simply set the // name of this controller on the action plus return the action array for usage. if ($this->hasGroupStack()) { $action['uses'] = $this->prependGroupController($action['uses']); $action['uses'] = $this->prependGroupNamespace($action['uses']); } // Here we will set this controller name on the action array just so we always // have a copy of it for reference if we need it. This can be used while we // search for a controller name or do some other type of fetch operation. $action['controller'] = $action['uses']; return $action; } /** * Prepend the last group namespace onto the use clause. * * @param string $class * @return string */ protected function prependGroupNamespace($class) { $group = end($this->groupStack); return isset($group['namespace']) && ! str_starts_with($class, '\\') && ! str_starts_with($class, $group['namespace']) ? $group['namespace'].'\\'.$class : $class; } /** * Prepend the last group controller onto the use clause. * * @param string $class * @return string */ protected function prependGroupController($class) { $group = end($this->groupStack); if (! isset($group['controller'])) { return $class; } if (class_exists($class)) { return $class; } if (str_contains($class, '@')) { return $class; } return $group['controller'].'@'.$class; } /** * Create a new Route object. * * @param array|string $methods * @param string $uri * @param mixed $action * @return \Illuminate\Routing\Route */ public function newRoute($methods, $uri, $action) { return (new Route($methods, $uri, $action)) ->setRouter($this) ->setContainer($this->container); } /** * Prefix the given URI with the last prefix. * * @param string $uri * @return string */ protected function prefix($uri) { return trim(trim($this->getLastGroupPrefix(), '/').'/'.trim($uri, '/'), '/') ?: '/'; } /** * Add the necessary where clauses to the route based on its initial registration. * * @param \Illuminate\Routing\Route $route * @return \Illuminate\Routing\Route */ protected function addWhereClausesToRoute($route) { $route->where(array_merge( $this->patterns, $route->getAction()['where'] ?? [] )); return $route; } /** * Merge the group stack with the controller action. * * @param \Illuminate\Routing\Route $route * @return void */ protected function mergeGroupAttributesIntoRoute($route) { $route->setAction($this->mergeWithLastGroup( $route->getAction(), $prependExistingPrefix = false )); } /** * Return the response returned by the given route. * * @param string $name * @return \Symfony\Component\HttpFoundation\Response */ public function respondWithRoute($name) { $route = tap($this->routes->getByName($name))->bind($this->currentRequest); return $this->runRoute($this->currentRequest, $route); } /** * Dispatch the request to the application. * * @param \Illuminate\Http\Request $request * @return \Symfony\Component\HttpFoundation\Response */ public function dispatch(Request $request) { $this->currentRequest = $request; return $this->dispatchToRoute($request); } /** * Dispatch the request to a route and return the response. * * @param \Illuminate\Http\Request $request * @return \Symfony\Component\HttpFoundation\Response */ public function dispatchToRoute(Request $request) { return $this->runRoute($request, $this->findRoute($request)); } /** * Find the route matching a given request. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Routing\Route */ protected function findRoute($request) { $this->events->dispatch(new Routing($request)); $this->current = $route = $this->routes->match($request); $route->setContainer($this->container); $this->container->instance(Route::class, $route); return $route; } /** * Return the response for the given route. * * @param \Illuminate\Http\Request $request * @param \Illuminate\Routing\Route $route * @return \Symfony\Component\HttpFoundation\Response */ protected function runRoute(Request $request, Route $route) { $request->setRouteResolver(fn () => $route); $this->events->dispatch(new RouteMatched($route, $request)); return $this->prepareResponse($request, $this->runRouteWithinStack($route, $request) ); } /** * Run the given route within a Stack "onion" instance. * * @param \Illuminate\Routing\Route $route * @param \Illuminate\Http\Request $request * @return mixed */ protected function runRouteWithinStack(Route $route, Request $request) { $shouldSkipMiddleware = $this->container->bound('middleware.disable') && $this->container->make('middleware.disable') === true; $middleware = $shouldSkipMiddleware ? [] : $this->gatherRouteMiddleware($route); return (new Pipeline($this->container)) ->send($request) ->through($middleware) ->then(fn ($request) => $this->prepareResponse( $request, $route->run() )); } /** * Gather the middleware for the given route with resolved class names. * * @param \Illuminate\Routing\Route $route * @return array */ public function gatherRouteMiddleware(Route $route) { return $this->resolveMiddleware($route->gatherMiddleware(), $route->excludedMiddleware()); } /** * Resolve a flat array of middleware classes from the provided array. * * @param array $middleware * @param array $excluded * @return array */ public function resolveMiddleware(array $middleware, array $excluded = []) { $excluded = collect($excluded)->map(function ($name) { return (array) MiddlewareNameResolver::resolve($name, $this->middleware, $this->middlewareGroups); })->flatten()->values()->all(); $middleware = collect($middleware)->map(function ($name) { return (array) MiddlewareNameResolver::resolve($name, $this->middleware, $this->middlewareGroups); })->flatten()->reject(function ($name) use ($excluded) { if (empty($excluded)) { return false; } if ($name instanceof Closure) { return false; } if (in_array($name, $excluded, true)) { return true; } if (! class_exists($name)) { return false; } $reflection = new ReflectionClass($name); return collect($excluded)->contains( fn ($exclude) => class_exists($exclude) && $reflection->isSubclassOf($exclude) ); })->values(); return $this->sortMiddleware($middleware); } /** * Sort the given middleware by priority. * * @param \Illuminate\Support\Collection $middlewares * @return array */ protected function sortMiddleware(Collection $middlewares) { return (new SortedMiddleware($this->middlewarePriority, $middlewares))->all(); } /** * Create a response instance from the given value. * * @param \Symfony\Component\HttpFoundation\Request $request * @param mixed $response * @return \Symfony\Component\HttpFoundation\Response */ public function prepareResponse($request, $response) { return static::toResponse($request, $response); } /** * Static version of prepareResponse. * * @param \Symfony\Component\HttpFoundation\Request $request * @param mixed $response * @return \Symfony\Component\HttpFoundation\Response */ public static function toResponse($request, $response) { if ($response instanceof Responsable) { $response = $response->toResponse($request); } if ($response instanceof PsrResponseInterface) { $response = (new HttpFoundationFactory)->createResponse($response); } elseif ($response instanceof Model && $response->wasRecentlyCreated) { $response = new JsonResponse($response, 201); } elseif ($response instanceof Stringable) { $response = new Response($response->__toString(), 200, ['Content-Type' => 'text/html']); } elseif (! $response instanceof SymfonyResponse && ($response instanceof Arrayable || $response instanceof Jsonable || $response instanceof ArrayObject || $response instanceof JsonSerializable || $response instanceof stdClass || is_array($response))) { $response = new JsonResponse($response); } elseif (! $response instanceof SymfonyResponse) { $response = new Response($response, 200, ['Content-Type' => 'text/html']); } if ($response->getStatusCode() === Response::HTTP_NOT_MODIFIED) { $response->setNotModified(); } return $response->prepare($request); } /** * Substitute the route bindings onto the route. * * @param \Illuminate\Routing\Route $route * @return \Illuminate\Routing\Route * * @throws \Illuminate\Database\Eloquent\ModelNotFoundException<\Illuminate\Database\Eloquent\Model> * @throws \Illuminate\Routing\Exceptions\BackedEnumCaseNotFoundException */ public function substituteBindings($route) { foreach ($route->parameters() as $key => $value) { if (isset($this->binders[$key])) { $route->setParameter($key, $this->performBinding($key, $value, $route)); } } return $route; } /** * Substitute the implicit route bindings for the given route. * * @param \Illuminate\Routing\Route $route * @return void * * @throws \Illuminate\Database\Eloquent\ModelNotFoundException<\Illuminate\Database\Eloquent\Model> * @throws \Illuminate\Routing\Exceptions\BackedEnumCaseNotFoundException */ public function substituteImplicitBindings($route) { ImplicitRouteBinding::resolveForRoute($this->container, $route); } /** * Call the binding callback for the given key. * * @param string $key * @param string $value * @param \Illuminate\Routing\Route $route * @return mixed * * @throws \Illuminate\Database\Eloquent\ModelNotFoundException<\Illuminate\Database\Eloquent\Model> */ protected function performBinding($key, $value, $route) { return call_user_func($this->binders[$key], $value, $route); } /** * Register a route matched event listener. * * @param string|callable $callback * @return void */ public function matched($callback) { $this->events->listen(Events\RouteMatched::class, $callback); } /** * Get all of the defined middleware short-hand names. * * @return array */ public function getMiddleware() { return $this->middleware; } /** * Register a short-hand name for a middleware. * * @param string $name * @param string $class * @return $this */ public function aliasMiddleware($name, $class) { $this->middleware[$name] = $class; return $this; } /** * Check if a middlewareGroup with the given name exists. * * @param string $name * @return bool */ public function hasMiddlewareGroup($name) { return array_key_exists($name, $this->middlewareGroups); } /** * Get all of the defined middleware groups. * * @return array */ public function getMiddlewareGroups() { return $this->middlewareGroups; } /** * Register a group of middleware. * * @param string $name * @param array $middleware * @return $this */ public function middlewareGroup($name, array $middleware) { $this->middlewareGroups[$name] = $middleware; return $this; } /** * Add a middleware to the beginning of a middleware group. * * If the middleware is already in the group, it will not be added again. * * @param string $group * @param string $middleware * @return $this */ public function prependMiddlewareToGroup($group, $middleware) { if (isset($this->middlewareGroups[$group]) && ! in_array($middleware, $this->middlewareGroups[$group])) { array_unshift($this->middlewareGroups[$group], $middleware); } return $this; } /** * Add a middleware to the end of a middleware group. * * If the middleware is already in the group, it will not be added again. * * @param string $group * @param string $middleware * @return $this */ public function pushMiddlewareToGroup($group, $middleware) { if (! array_key_exists($group, $this->middlewareGroups)) { $this->middlewareGroups[$group] = []; } if (! in_array($middleware, $this->middlewareGroups[$group])) { $this->middlewareGroups[$group][] = $middleware; } return $this; } /** * Remove the given middleware from the specified group. * * @param string $group * @param string $middleware * @return $this */ public function removeMiddlewareFromGroup($group, $middleware) { if (! $this->hasMiddlewareGroup($group)) { return $this; } $reversedMiddlewaresArray = array_flip($this->middlewareGroups[$group]); if (! array_key_exists($middleware, $reversedMiddlewaresArray)) { return $this; } $middlewareKey = $reversedMiddlewaresArray[$middleware]; unset($this->middlewareGroups[$group][$middlewareKey]); return $this; } /** * Flush the router's middleware groups. * * @return $this */ public function flushMiddlewareGroups() { $this->middlewareGroups = []; return $this; } /** * Add a new route parameter binder. * * @param string $key * @param string|callable $binder * @return void */ public function bind($key, $binder) { $this->binders[str_replace('-', '_', $key)] = RouteBinding::forCallback( $this->container, $binder ); } /** * Register a model binder for a wildcard. * * @param string $key * @param string $class * @param \Closure|null $callback * @return void */ public function model($key, $class, Closure $callback = null) { $this->bind($key, RouteBinding::forModel($this->container, $class, $callback)); } /** * Get the binding callback for a given binding. * * @param string $key * @return \Closure|null */ public function getBindingCallback($key) { if (isset($this->binders[$key = str_replace('-', '_', $key)])) { return $this->binders[$key]; } } /** * Get the global "where" patterns. * * @return array */ public function getPatterns() { return $this->patterns; } /** * Set a global where pattern on all routes. * * @param string $key * @param string $pattern * @return void */ public function pattern($key, $pattern) { $this->patterns[$key] = $pattern; } /** * Set a group of global where patterns on all routes. * * @param array $patterns * @return void */ public function patterns($patterns) { foreach ($patterns as $key => $pattern) { $this->pattern($key, $pattern); } } /** * Determine if the router currently has a group stack. * * @return bool */ public function hasGroupStack() { return ! empty($this->groupStack); } /** * Get the current group stack for the router. * * @return array */ public function getGroupStack() { return $this->groupStack; } /** * Get a route parameter for the current route. * * @param string $key * @param string|null $default * @return mixed */ public function input($key, $default = null) { return $this->current()->parameter($key, $default); } /** * Get the request currently being dispatched. * * @return \Illuminate\Http\Request */ public function getCurrentRequest() { return $this->currentRequest; } /** * Get the currently dispatched route instance. * * @return \Illuminate\Routing\Route|null */ public function getCurrentRoute() { return $this->current(); } /** * Get the currently dispatched route instance. * * @return \Illuminate\Routing\Route|null */ public function current() { return $this->current; } /** * Check if a route with the given name exists. * * @param string|array $name * @return bool */ public function has($name) { $names = is_array($name) ? $name : func_get_args(); foreach ($names as $value) { if (! $this->routes->hasNamedRoute($value)) { return false; } } return true; } /** * Get the current route name. * * @return string|null */ public function currentRouteName() { return $this->current() ? $this->current()->getName() : null; } /** * Alias for the "currentRouteNamed" method. * * @param mixed ...$patterns * @return bool */ public function is(...$patterns) { return $this->currentRouteNamed(...$patterns); } /** * Determine if the current route matches a pattern. * * @param mixed ...$patterns * @return bool */ public function currentRouteNamed(...$patterns) { return $this->current() && $this->current()->named(...$patterns); } /** * Get the current route action. * * @return string|null */ public function currentRouteAction() { if ($this->current()) { return $this->current()->getAction()['controller'] ?? null; } } /** * Alias for the "currentRouteUses" method. * * @param array ...$patterns * @return bool */ public function uses(...$patterns) { foreach ($patterns as $pattern) { if (Str::is($pattern, $this->currentRouteAction())) { return true; } } return false; } /** * Determine if the current route action matches a given action. * * @param string $action * @return bool */ public function currentRouteUses($action) { return $this->currentRouteAction() == $action; } /** * Set the unmapped global resource parameters to singular. * * @param bool $singular * @return void */ public function singularResourceParameters($singular = true) { ResourceRegistrar::singularParameters($singular); } /** * Set the global resource parameter mapping. * * @param array $parameters * @return void */ public function resourceParameters(array $parameters = []) { ResourceRegistrar::setParameters($parameters); } /** * Get or set the verbs used in the resource URIs. * * @param array $verbs * @return array|null */ public function resourceVerbs(array $verbs = []) { return ResourceRegistrar::verbs($verbs); } /** * Get the underlying route collection. * * @return \Illuminate\Routing\RouteCollectionInterface */ public function getRoutes() { return $this->routes; } /** * Set the route collection instance. * * @param \Illuminate\Routing\RouteCollection $routes * @return void */ public function setRoutes(RouteCollection $routes) { foreach ($routes as $route) { $route->setRouter($this)->setContainer($this->container); } $this->routes = $routes; $this->container->instance('routes', $this->routes); } /** * Set the compiled route collection instance. * * @param array $routes * @return void */ public function setCompiledRoutes(array $routes) { $this->routes = (new CompiledRouteCollection($routes['compiled'], $routes['attributes'])) ->setRouter($this) ->setContainer($this->container); $this->container->instance('routes', $this->routes); } /** * Remove any duplicate middleware from the given array. * * @param array $middleware * @return array */ public static function uniqueMiddleware(array $middleware) { $seen = []; $result = []; foreach ($middleware as $value) { $key = \is_object($value) ? \spl_object_id($value) : $value; if (! isset($seen[$key])) { $seen[$key] = true; $result[] = $value; } } return $result; } /** * Set the container instance used by the router. * * @param \Illuminate\Container\Container $container * @return $this */ public function setContainer(Container $container) { $this->container = $container; return $this; } /** * Dynamically handle calls into the router instance. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { if (static::hasMacro($method)) { return $this->macroCall($method, $parameters); } if ($method === 'middleware') { return (new RouteRegistrar($this))->attribute($method, is_array($parameters[0]) ? $parameters[0] : $parameters); } if ($method !== 'where' && Str::startsWith($method, 'where')) { return (new RouteRegistrar($this))->{$method}(...$parameters); } return (new RouteRegistrar($this))->attribute($method, array_key_exists(0, $parameters) ? $parameters[0] : true); } } PKz Z> =,!,!%Illuminate/Routing/RouteRegistrar.phpnuW+A 'as', 'scopeBindings' => 'scope_bindings', 'withoutMiddleware' => 'excluded_middleware', ]; /** * Create a new route registrar instance. * * @param \Illuminate\Routing\Router $router * @return void */ public function __construct(Router $router) { $this->router = $router; } /** * Set the value for a given attribute. * * @param string $key * @param mixed $value * @return $this * * @throws \InvalidArgumentException */ public function attribute($key, $value) { if (! in_array($key, $this->allowedAttributes)) { throw new InvalidArgumentException("Attribute [{$key}] does not exist."); } if ($key === 'middleware') { foreach ($value as $index => $middleware) { $value[$index] = (string) $middleware; } } $attributeKey = Arr::get($this->aliases, $key, $key); if ($key === 'withoutMiddleware') { $value = array_merge( (array) ($this->attributes[$attributeKey] ?? []), Arr::wrap($value) ); } $this->attributes[$attributeKey] = $value; return $this; } /** * Route a resource to a controller. * * @param string $name * @param string $controller * @param array $options * @return \Illuminate\Routing\PendingResourceRegistration */ public function resource($name, $controller, array $options = []) { return $this->router->resource($name, $controller, $this->attributes + $options); } /** * Route an API resource to a controller. * * @param string $name * @param string $controller * @param array $options * @return \Illuminate\Routing\PendingResourceRegistration */ public function apiResource($name, $controller, array $options = []) { return $this->router->apiResource($name, $controller, $this->attributes + $options); } /** * Route a singleton resource to a controller. * * @param string $name * @param string $controller * @param array $options * @return \Illuminate\Routing\PendingSingletonResourceRegistration */ public function singleton($name, $controller, array $options = []) { return $this->router->singleton($name, $controller, $this->attributes + $options); } /** * Route an API singleton resource to a controller. * * @param string $name * @param string $controller * @param array $options * @return \Illuminate\Routing\PendingSingletonResourceRegistration */ public function apiSingleton($name, $controller, array $options = []) { return $this->router->apiSingleton($name, $controller, $this->attributes + $options); } /** * Create a route group with shared attributes. * * @param \Closure|array|string $callback * @return $this */ public function group($callback) { $this->router->group($this->attributes, $callback); return $this; } /** * Register a new route with the given verbs. * * @param array|string $methods * @param string $uri * @param \Closure|array|string|null $action * @return \Illuminate\Routing\Route */ public function match($methods, $uri, $action = null) { return $this->router->match($methods, $uri, $this->compileAction($action)); } /** * Register a new route with the router. * * @param string $method * @param string $uri * @param \Closure|array|string|null $action * @return \Illuminate\Routing\Route */ protected function registerRoute($method, $uri, $action = null) { if (! is_array($action)) { $action = array_merge($this->attributes, $action ? ['uses' => $action] : []); } return $this->router->{$method}($uri, $this->compileAction($action)); } /** * Compile the action into an array including the attributes. * * @param \Closure|array|string|null $action * @return array */ protected function compileAction($action) { if (is_null($action)) { return $this->attributes; } if (is_string($action) || $action instanceof Closure) { $action = ['uses' => $action]; } if (is_array($action) && ! Arr::isAssoc($action) && Reflector::isCallable($action)) { if (strncmp($action[0], '\\', 1)) { $action[0] = '\\'.$action[0]; } $action = [ 'uses' => $action[0].'@'.$action[1], 'controller' => $action[0].'@'.$action[1], ]; } return array_merge($this->attributes, $action); } /** * Dynamically handle calls into the route registrar. * * @param string $method * @param array $parameters * @return \Illuminate\Routing\Route|$this * * @throws \BadMethodCallException */ public function __call($method, $parameters) { if (in_array($method, $this->passthru)) { return $this->registerRoute($method, ...$parameters); } if (in_array($method, $this->allowedAttributes)) { if ($method === 'middleware') { return $this->attribute($method, is_array($parameters[0]) ? $parameters[0] : $parameters); } return $this->attribute($method, array_key_exists(0, $parameters) ? $parameters[0] : true); } throw new BadMethodCallException(sprintf( 'Method %s::%s does not exist.', static::class, $method )); } } PKz Z s s +Illuminate/Routing/ControllerDispatcher.phpnuW+Acontainer = $container; } /** * Dispatch a request to a given controller and method. * * @param \Illuminate\Routing\Route $route * @param mixed $controller * @param string $method * @return mixed */ public function dispatch(Route $route, $controller, $method) { $parameters = $this->resolveParameters($route, $controller, $method); if (method_exists($controller, 'callAction')) { return $controller->callAction($method, $parameters); } return $controller->{$method}(...array_values($parameters)); } /** * Resolve the parameters for the controller. * * @param \Illuminate\Routing\Route $route * @param mixed $controller * @param string $method * @return array */ protected function resolveParameters(Route $route, $controller, $method) { return $this->resolveClassMethodDependencies( $route->parametersWithoutNulls(), $controller, $method ); } /** * Get the middleware for the controller instance. * * @param \Illuminate\Routing\Controller $controller * @param string $method * @return array */ public function getMiddleware($controller, $method) { if (! method_exists($controller, 'getMiddleware')) { return []; } return collect($controller->getMiddleware())->reject(function ($data) use ($method) { return static::methodExcludedByOptions($method, $data['options']); })->pluck('middleware')->all(); } /** * Determine if the given options exclude a particular method. * * @param string $method * @param array $options * @return bool */ public static function methodExcludedByOptions($method, array $options) { return (isset($options['only']) && ! in_array($method, (array) $options['only'])) || (! empty($options['except']) && in_array($method, (array) $options['except'])); } } PKz Zv&Illuminate/Routing/RouteCollection.phpnuW+AaddToCollections($route); $this->addLookups($route); return $route; } /** * Add the given route to the arrays of routes. * * @param \Illuminate\Routing\Route $route * @return void */ protected function addToCollections($route) { $domainAndUri = $route->getDomain().$route->uri(); foreach ($route->methods() as $method) { $this->routes[$method][$domainAndUri] = $route; } $this->allRoutes[$method.$domainAndUri] = $route; } /** * Add the route to any look-up tables if necessary. * * @param \Illuminate\Routing\Route $route * @return void */ protected function addLookups($route) { // If the route has a name, we will add it to the name look-up table so that we // will quickly be able to find any route associate with a name and not have // to iterate through every route every time we need to perform a look-up. if ($name = $route->getName()) { $this->nameList[$name] = $route; } // When the route is routing to a controller we will also store the action that // is used by the route. This will let us reverse route to controllers while // processing a request and easily generate URLs to the given controllers. $action = $route->getAction(); if (isset($action['controller'])) { $this->addToActionList($action, $route); } } /** * Add a route to the controller action dictionary. * * @param array $action * @param \Illuminate\Routing\Route $route * @return void */ protected function addToActionList($action, $route) { $this->actionList[trim($action['controller'], '\\')] = $route; } /** * Refresh the name look-up table. * * This is done in case any names are fluently defined or if routes are overwritten. * * @return void */ public function refreshNameLookups() { $this->nameList = []; foreach ($this->allRoutes as $route) { if ($route->getName()) { $this->nameList[$route->getName()] = $route; } } } /** * Refresh the action look-up table. * * This is done in case any actions are overwritten with new controllers. * * @return void */ public function refreshActionLookups() { $this->actionList = []; foreach ($this->allRoutes as $route) { if (isset($route->getAction()['controller'])) { $this->addToActionList($route->getAction(), $route); } } } /** * Find the first route matching a given request. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Routing\Route * * @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ public function match(Request $request) { $routes = $this->get($request->getMethod()); // First, we will see if we can find a matching route for this current request // method. If we can, great, we can just return it so that it can be called // by the consumer. Otherwise we will check for routes with another verb. $route = $this->matchAgainstRoutes($routes, $request); return $this->handleMatchedRoute($request, $route); } /** * Get routes from the collection by method. * * @param string|null $method * @return \Illuminate\Routing\Route[] */ public function get($method = null) { return is_null($method) ? $this->getRoutes() : Arr::get($this->routes, $method, []); } /** * Determine if the route collection contains a given named route. * * @param string $name * @return bool */ public function hasNamedRoute($name) { return ! is_null($this->getByName($name)); } /** * Get a route instance by its name. * * @param string $name * @return \Illuminate\Routing\Route|null */ public function getByName($name) { return $this->nameList[$name] ?? null; } /** * Get a route instance by its controller action. * * @param string $action * @return \Illuminate\Routing\Route|null */ public function getByAction($action) { return $this->actionList[$action] ?? null; } /** * Get all of the routes in the collection. * * @return \Illuminate\Routing\Route[] */ public function getRoutes() { return array_values($this->allRoutes); } /** * Get all of the routes keyed by their HTTP verb / method. * * @return array */ public function getRoutesByMethod() { return $this->routes; } /** * Get all of the routes keyed by their name. * * @return \Illuminate\Routing\Route[] */ public function getRoutesByName() { return $this->nameList; } /** * Convert the collection to a Symfony RouteCollection instance. * * @return \Symfony\Component\Routing\RouteCollection */ public function toSymfonyRouteCollection() { $symfonyRoutes = parent::toSymfonyRouteCollection(); $this->refreshNameLookups(); return $symfonyRoutes; } /** * Convert the collection to a CompiledRouteCollection instance. * * @param \Illuminate\Routing\Router $router * @param \Illuminate\Container\Container $container * @return \Illuminate\Routing\CompiledRouteCollection */ public function toCompiledRouteCollection(Router $router, Container $container) { ['compiled' => $compiled, 'attributes' => $attributes] = $this->compile(); return (new CompiledRouteCollection($compiled, $attributes)) ->setRouter($router) ->setContainer($container); } } PKz Z; =Illuminate/View/Compilers/Concerns/CompilesAuthorizations.phpnuW+Acheck{$expression}): ?>"; } /** * Compile the cannot statements into valid PHP. * * @param string $expression * @return string */ protected function compileCannot($expression) { return "denies{$expression}): ?>"; } /** * Compile the canany statements into valid PHP. * * @param string $expression * @return string */ protected function compileCanany($expression) { return "any{$expression}): ?>"; } /** * Compile the else-can statements into valid PHP. * * @param string $expression * @return string */ protected function compileElsecan($expression) { return "check{$expression}): ?>"; } /** * Compile the else-cannot statements into valid PHP. * * @param string $expression * @return string */ protected function compileElsecannot($expression) { return "denies{$expression}): ?>"; } /** * Compile the else-canany statements into valid PHP. * * @param string $expression * @return string */ protected function compileElsecanany($expression) { return "any{$expression}): ?>"; } /** * Compile the end-can statements into valid PHP. * * @return string */ protected function compileEndcan() { return ''; } /** * Compile the end-cannot statements into valid PHP. * * @return string */ protected function compileEndcannot() { return ''; } /** * Compile the end-canany statements into valid PHP. * * @return string */ protected function compileEndcanany() { return ''; } } PKz ZTa>>6Illuminate/View/Compilers/Concerns/CompilesHelpers.phpnuW+A'; } /** * Compile the "dd" statements into valid PHP. * * @param string $arguments * @return string */ protected function compileDd($arguments) { return ""; } /** * Compile the "dump" statements into valid PHP. * * @param string $arguments * @return string */ protected function compileDump($arguments) { return ""; } /** * Compile the method statements into valid PHP. * * @param string $method * @return string */ protected function compileMethod($method) { return ""; } /** * Compile the "vite" statements into valid PHP. * * @param string|null $arguments * @return string */ protected function compileVite($arguments) { $arguments ??= '()'; $class = Vite::class; return ""; } /** * Compile the "viteReactRefresh" statements into valid PHP. * * @return string */ protected function compileViteReactRefresh() { $class = Vite::class; return "reactRefresh(); ?>"; } } PKz Z!8Illuminate/View/Compilers/Concerns/CompilesFragments.phpnuW+AlastFragment = trim($expression, "()'\" "); return "startFragment{$expression}; ?>"; } /** * Compile the end-fragment statements into valid PHP. * * @return string */ protected function compileEndfragment() { return 'stopFragment(); ?>'; } } PKz Zң7Illuminate/View/Compilers/Concerns/CompilesComments.phpnuW+AcontentTags[0], $this->contentTags[1]); return preg_replace($pattern, '', $value); } } PKz Z2&9Illuminate/View/Compilers/Concerns/CompilesInjections.phpnuW+A"; } } PKz Zf+ ?!?!;Illuminate/View/Compilers/Concerns/CompilesConditionals.phpnuW+Aguard{$guard}->check()): ?>"; } /** * Compile the else-auth statements into valid PHP. * * @param string|null $guard * @return string */ protected function compileElseAuth($guard = null) { $guard = is_null($guard) ? '()' : $guard; return "guard{$guard}->check()): ?>"; } /** * Compile the end-auth statements into valid PHP. * * @return string */ protected function compileEndAuth() { return ''; } /** * Compile the env statements into valid PHP. * * @param string $environments * @return string */ protected function compileEnv($environments) { return "environment{$environments}): ?>"; } /** * Compile the end-env statements into valid PHP. * * @return string */ protected function compileEndEnv() { return ''; } /** * Compile the production statements into valid PHP. * * @return string */ protected function compileProduction() { return "environment('production')): ?>"; } /** * Compile the end-production statements into valid PHP. * * @return string */ protected function compileEndProduction() { return ''; } /** * Compile the if-guest statements into valid PHP. * * @param string|null $guard * @return string */ protected function compileGuest($guard = null) { $guard = is_null($guard) ? '()' : $guard; return "guard{$guard}->guest()): ?>"; } /** * Compile the else-guest statements into valid PHP. * * @param string|null $guard * @return string */ protected function compileElseGuest($guard = null) { $guard = is_null($guard) ? '()' : $guard; return "guard{$guard}->guest()): ?>"; } /** * Compile the end-guest statements into valid PHP. * * @return string */ protected function compileEndGuest() { return ''; } /** * Compile the has-section statements into valid PHP. * * @param string $expression * @return string */ protected function compileHasSection($expression) { return "yieldContent{$expression}))): ?>"; } /** * Compile the section-missing statements into valid PHP. * * @param string $expression * @return string */ protected function compileSectionMissing($expression) { return "yieldContent{$expression}))): ?>"; } /** * Compile the if statements into valid PHP. * * @param string $expression * @return string */ protected function compileIf($expression) { return ""; } /** * Compile the unless statements into valid PHP. * * @param string $expression * @return string */ protected function compileUnless($expression) { return ""; } /** * Compile the else-if statements into valid PHP. * * @param string $expression * @return string */ protected function compileElseif($expression) { return ""; } /** * Compile the else statements into valid PHP. * * @return string */ protected function compileElse() { return ''; } /** * Compile the end-if statements into valid PHP. * * @return string */ protected function compileEndif() { return ''; } /** * Compile the end-unless statements into valid PHP. * * @return string */ protected function compileEndunless() { return ''; } /** * Compile the if-isset statements into valid PHP. * * @param string $expression * @return string */ protected function compileIsset($expression) { return ""; } /** * Compile the end-isset statements into valid PHP. * * @return string */ protected function compileEndIsset() { return ''; } /** * Compile the switch statements into valid PHP. * * @param string $expression * @return string */ protected function compileSwitch($expression) { $this->firstCaseInSwitch = true; return "firstCaseInSwitch) { $this->firstCaseInSwitch = false; return "case {$expression}: ?>"; } return ""; } /** * Compile the default statements in switch case into valid PHP. * * @return string */ protected function compileDefault() { return ''; } /** * Compile the end switch statements into valid PHP. * * @return string */ protected function compileEndSwitch() { return ''; } /** * Compile a once block into valid PHP. * * @param string|null $id * @return string */ protected function compileOnce($id = null) { $id = $id ? $this->stripParentheses($id) : "'".(string) Str::uuid()."'"; return 'hasRenderedOnce('.$id.')): $__env->markAsRenderedOnce('.$id.'); ?>'; } /** * Compile an end-once block into valid PHP. * * @return string */ public function compileEndOnce() { return ''; } /** * Compile a selected block into valid PHP. * * @param string $condition * @return string */ protected function compileSelected($condition) { return ""; } /** * Compile a checked block into valid PHP. * * @param string $condition * @return string */ protected function compileChecked($condition) { return ""; } /** * Compile a disabled block into valid PHP. * * @param string $condition * @return string */ protected function compileDisabled($condition) { return ""; } /** * Compile a required block into valid PHP. * * @param string $condition * @return string */ protected function compileRequired($condition) { return ""; } /** * Compile a readonly block into valid PHP. * * @param string $condition * @return string */ protected function compileReadonly($condition) { return ""; } /** * Compile the push statements into valid PHP. * * @param string $expression * @return string */ protected function compilePushIf($expression) { $parts = explode(',', $this->stripParentheses($expression), 2); return "startPush({$parts[1]}); ?>"; } /** * Compile the end-push statements into valid PHP. * * @return string */ protected function compileEndPushIf() { return 'stopPush(); endif; ?>'; } } PKz Z@F9Illuminate/View/Compilers/Concerns/CompilesComponents.phpnuW+AstartComponent{$expression}; ?>"; } /** * Get a new component hash for a component name. * * @param string $component * @return string */ public static function newComponentHash(string $component) { static::$componentHashStack[] = $hash = sha1($component); return $hash; } /** * Compile a class component opening. * * @param string $component * @param string $alias * @param string $data * @param string $hash * @return string */ public static function compileClassComponentOpening(string $component, string $alias, string $data, string $hash) { return implode("\n", [ '', 'getIterator() : [])); ?>', 'withName('.$alias.'); ?>', 'shouldRender()): ?>', 'startComponent($component->resolveView(), $component->data()); ?>', ]); } /** * Compile the end-component statements into valid PHP. * * @return string */ protected function compileEndComponent() { return 'renderComponent(); ?>'; } /** * Compile the end-component statements into valid PHP. * * @return string */ public function compileEndComponentClass() { $hash = array_pop(static::$componentHashStack); return $this->compileEndComponent()."\n".implode("\n", [ '', '', '', '', '', ]); } /** * Compile the slot statements into valid PHP. * * @param string $expression * @return string */ protected function compileSlot($expression) { return "slot{$expression}; ?>"; } /** * Compile the end-slot statements into valid PHP. * * @return string */ protected function compileEndSlot() { return 'endSlot(); ?>'; } /** * Compile the component-first statements into valid PHP. * * @param string $expression * @return string */ protected function compileComponentFirst($expression) { return "startComponentFirst{$expression}; ?>"; } /** * Compile the end-component-first statements into valid PHP. * * @return string */ protected function compileEndComponentFirst() { return $this->compileEndComponent(); } /** * Compile the prop statement into valid PHP. * * @param string $expression * @return string */ protected function compileProps($expression) { return " onlyProps{$expression} as \$__key => \$__value) { \$\$__key = \$\$__key ?? \$__value; } ?> exceptProps{$expression}; ?> \$__value) { \$\$__key = \$\$__key ?? \$__value; } ?> \$__value) { if (array_key_exists(\$__key, \$__defined_vars)) unset(\$\$__key); } ?> "; } /** * Compile the aware statement into valid PHP. * * @param string $expression * @return string */ protected function compileAware($expression) { return " \$__value) { \$__consumeVariable = is_string(\$__key) ? \$__key : \$__value; \$\$__consumeVariable = is_string(\$__key) ? \$__env->getConsumableComponentData(\$__key, \$__value) : \$__env->getConsumableComponentData(\$__value); } ?>"; } /** * Sanitize the given component attribute value. * * @param mixed $value * @return mixed */ public static function sanitizeComponentAttribute($value) { if ($value instanceof CanBeEscapedWhenCastToString) { return $value->escapeWhenCastingToString(); } return is_string($value) || (is_object($value) && ! $value instanceof ComponentAttributeBag && method_exists($value, '__toString')) ? e($value) : $value; } } PKz Z9:;Illuminate/View/Compilers/Concerns/CompilesTranslations.phpnuW+AstartTranslation(); ?>'; } elseif ($expression[1] === '[') { return "startTranslation{$expression}; ?>"; } return "get{$expression}; ?>"; } /** * Compile the end-lang statements into valid PHP. * * @return string */ protected function compileEndlang() { return 'renderTranslation(); ?>'; } /** * Compile the choice statements into valid PHP. * * @param string $expression * @return string */ protected function compileChoice($expression) { return "choice{$expression}; ?>"; } } PKz Z~r 6Illuminate/View/Compilers/Concerns/CompilesLayouts.phpnuW+AstripParentheses($expression); $echo = "make({$expression}, \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?>"; $this->footer[] = $echo; return ''; } /** * Compile the extends-first statements into valid PHP. * * @param string $expression * @return string */ protected function compileExtendsFirst($expression) { $expression = $this->stripParentheses($expression); $echo = "first({$expression}, \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?>"; $this->footer[] = $echo; return ''; } /** * Compile the section statements into valid PHP. * * @param string $expression * @return string */ protected function compileSection($expression) { $this->lastSection = trim($expression, "()'\" "); return "startSection{$expression}; ?>"; } /** * Replace the @parent directive to a placeholder. * * @return string */ protected function compileParent() { $escapedLastSection = strtr($this->lastSection, ['\\' => '\\\\', "'" => "\\'"]); return ""; } /** * Compile the yield statements into valid PHP. * * @param string $expression * @return string */ protected function compileYield($expression) { return "yieldContent{$expression}; ?>"; } /** * Compile the show statements into valid PHP. * * @return string */ protected function compileShow() { return 'yieldSection(); ?>'; } /** * Compile the append statements into valid PHP. * * @return string */ protected function compileAppend() { return 'appendSection(); ?>'; } /** * Compile the overwrite statements into valid PHP. * * @return string */ protected function compileOverwrite() { return 'stopSection(true); ?>'; } /** * Compile the stop statements into valid PHP. * * @return string */ protected function compileStop() { return 'stopSection(); ?>'; } /** * Compile the end-section statements into valid PHP. * * @return string */ protected function compileEndsection() { return 'stopSection(); ?>'; } } PKz Z̀1Illuminate/View/Compilers/Concerns/CompilesJs.phpnuW+AtoHtml() ?>", Js::class, $this->stripParentheses($expression) ); } } PKz Z$B5Illuminate/View/Compilers/Concerns/CompilesStyles.phpnuW+A\""; } } PKz ZfirstClosureParameterType($class), $class]; } $this->echoHandlers[$class] = $handler; } /** * Compile Blade echos into valid PHP. * * @param string $value * @return string */ public function compileEchos($value) { foreach ($this->getEchoMethods() as $method) { $value = $this->$method($value); } return $value; } /** * Get the echo methods in the proper order for compilation. * * @return array */ protected function getEchoMethods() { return [ 'compileRawEchos', 'compileEscapedEchos', 'compileRegularEchos', ]; } /** * Compile the "raw" echo statements. * * @param string $value * @return string */ protected function compileRawEchos($value) { $pattern = sprintf('/(@)?%s\s*(.+?)\s*%s(\r?\n)?/s', $this->rawTags[0], $this->rawTags[1]); $callback = function ($matches) { $whitespace = empty($matches[3]) ? '' : $matches[3].$matches[3]; return $matches[1] ? substr($matches[0], 1) : "wrapInEchoHandler($matches[2])}; ?>{$whitespace}"; }; return preg_replace_callback($pattern, $callback, $value); } /** * Compile the "regular" echo statements. * * @param string $value * @return string */ protected function compileRegularEchos($value) { $pattern = sprintf('/(@)?%s\s*(.+?)\s*%s(\r?\n)?/s', $this->contentTags[0], $this->contentTags[1]); $callback = function ($matches) { $whitespace = empty($matches[3]) ? '' : $matches[3].$matches[3]; $wrapped = sprintf($this->echoFormat, $this->wrapInEchoHandler($matches[2])); return $matches[1] ? substr($matches[0], 1) : "{$whitespace}"; }; return preg_replace_callback($pattern, $callback, $value); } /** * Compile the escaped echo statements. * * @param string $value * @return string */ protected function compileEscapedEchos($value) { $pattern = sprintf('/(@)?%s\s*(.+?)\s*%s(\r?\n)?/s', $this->escapedTags[0], $this->escapedTags[1]); $callback = function ($matches) { $whitespace = empty($matches[3]) ? '' : $matches[3].$matches[3]; return $matches[1] ? $matches[0] : "wrapInEchoHandler($matches[2])}); ?>{$whitespace}"; }; return preg_replace_callback($pattern, $callback, $value); } /** * Add an instance of the blade echo handler to the start of the compiled string. * * @param string $result * @return string */ protected function addBladeCompilerVariable($result) { return "".$result; } /** * Wrap the echoable value in an echo handler if applicable. * * @param string $value * @return string */ protected function wrapInEchoHandler($value) { $value = Str::of($value) ->trim() ->when(str_ends_with($value, ';'), function ($str) { return $str->beforeLast(';'); }); return empty($this->echoHandlers) ? $value : '$__bladeCompiler->applyEchoHandler('.$value.')'; } /** * Apply the echo handler for the value if it exists. * * @param string $value * @return string */ public function applyEchoHandler($value) { if (is_object($value) && isset($this->echoHandlers[get_class($value)])) { return call_user_func($this->echoHandlers[get_class($value)], $value); } return $value; } } PKz Z|74 5Illuminate/View/Compilers/Concerns/CompilesStacks.phpnuW+AyieldPushContent{$expression}; ?>"; } /** * Compile the push statements into valid PHP. * * @param string $expression * @return string */ protected function compilePush($expression) { return "startPush{$expression}; ?>"; } /** * Compile the push-once statements into valid PHP. * * @param string $expression * @return string */ protected function compilePushOnce($expression) { $parts = explode(',', $this->stripParentheses($expression), 2); [$stack, $id] = [$parts[0], $parts[1] ?? '']; $id = trim($id) ?: "'".(string) Str::uuid()."'"; return 'hasRenderedOnce('.$id.')): $__env->markAsRenderedOnce('.$id.'); $__env->startPush('.$stack.'); ?>'; } /** * Compile the end-push statements into valid PHP. * * @return string */ protected function compileEndpush() { return 'stopPush(); ?>'; } /** * Compile the end-push-once statements into valid PHP. * * @return string */ protected function compileEndpushOnce() { return 'stopPush(); endif; ?>'; } /** * Compile the prepend statements into valid PHP. * * @param string $expression * @return string */ protected function compilePrepend($expression) { return "startPrepend{$expression}; ?>"; } /** * Compile the prepend-once statements into valid PHP. * * @param string $expression * @return string */ protected function compilePrependOnce($expression) { $parts = explode(',', $this->stripParentheses($expression), 2); [$stack, $id] = [$parts[0], $parts[1] ?? '']; $id = trim($id) ?: "'".(string) Str::uuid()."'"; return 'hasRenderedOnce('.$id.')): $__env->markAsRenderedOnce('.$id.'); $__env->startPrepend('.$stack.'); ?>'; } /** * Compile the end-prepend statements into valid PHP. * * @return string */ protected function compileEndprepend() { return 'stopPrepend(); ?>'; } /** * Compile the end-prepend-once statements into valid PHP. * * @return string */ protected function compileEndprependOnce() { return 'stopPrepend(); endif; ?>'; } } PKz ZN3Illuminate/View/Compilers/Concerns/CompilesJson.phpnuW+AstripParentheses($expression)); $options = isset($parts[1]) ? trim($parts[1]) : $this->encodingOptions; $depth = isset($parts[2]) ? trim($parts[2]) : 512; return ""; } } PKz Z 5Illuminate/View/Compilers/Concerns/CompilesErrors.phpnuW+AstripParentheses($expression); return 'getBag($__errorArgs[1] ?? \'default\'); if ($__bag->has($__errorArgs[0])) : if (isset($message)) { $__messageOriginal = $message; } $message = $__bag->first($__errorArgs[0]); ?>'; } /** * Compile the enderror statements into valid PHP. * * @param string $expression * @return string */ protected function compileEnderror($expression) { return ''; } } PKz ZN6Illuminate/View/Compilers/Concerns/CompilesClasses.phpnuW+A\""; } } PKz Z.| 7Illuminate/View/Compilers/Concerns/CompilesIncludes.phpnuW+ArenderEach{$expression}; ?>"; } /** * Compile the include statements into valid PHP. * * @param string $expression * @return string */ protected function compileInclude($expression) { $expression = $this->stripParentheses($expression); return "make({$expression}, \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?>"; } /** * Compile the include-if statements into valid PHP. * * @param string $expression * @return string */ protected function compileIncludeIf($expression) { $expression = $this->stripParentheses($expression); return "exists({$expression})) echo \$__env->make({$expression}, \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?>"; } /** * Compile the include-when statements into valid PHP. * * @param string $expression * @return string */ protected function compileIncludeWhen($expression) { $expression = $this->stripParentheses($expression); return "renderWhen($expression, \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path'])); ?>"; } /** * Compile the include-unless statements into valid PHP. * * @param string $expression * @return string */ protected function compileIncludeUnless($expression) { $expression = $this->stripParentheses($expression); return "renderUnless($expression, \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path'])); ?>"; } /** * Compile the include-first statements into valid PHP. * * @param string $expression * @return string */ protected function compileIncludeFirst($expression) { $expression = $this->stripParentheses($expression); return "first({$expression}, \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?>"; } } PKz Z^994Illuminate/View/Compilers/Concerns/CompilesLoops.phpnuW+AforElseCounter; preg_match('/\( *(.+) +as +(.+)\)$/is', $expression ?? '', $matches); if (count($matches) === 0) { throw new ViewCompilationException('Malformed @forelse statement.'); } $iteratee = trim($matches[1]); $iteration = trim($matches[2]); $initLoop = "\$__currentLoopData = {$iteratee}; \$__env->addLoop(\$__currentLoopData);"; $iterateLoop = '$__env->incrementLoopIndices(); $loop = $__env->getLastLoop();'; return ""; } /** * Compile the for-else-empty and empty statements into valid PHP. * * @param string $expression * @return string */ protected function compileEmpty($expression) { if ($expression) { return ""; } $empty = '$__empty_'.$this->forElseCounter--; return "popLoop(); \$loop = \$__env->getLastLoop(); if ({$empty}): ?>"; } /** * Compile the end-for-else statements into valid PHP. * * @return string */ protected function compileEndforelse() { return ''; } /** * Compile the end-empty statements into valid PHP. * * @return string */ protected function compileEndEmpty() { return ''; } /** * Compile the for statements into valid PHP. * * @param string $expression * @return string */ protected function compileFor($expression) { return ""; } /** * Compile the for-each statements into valid PHP. * * @param string $expression * @return string * * @throws \Illuminate\Contracts\View\ViewCompilationException */ protected function compileForeach($expression) { preg_match('/\( *(.+) +as +(.*)\)$/is', $expression ?? '', $matches); if (count($matches) === 0) { throw new ViewCompilationException('Malformed @foreach statement.'); } $iteratee = trim($matches[1]); $iteration = trim($matches[2]); $initLoop = "\$__currentLoopData = {$iteratee}; \$__env->addLoop(\$__currentLoopData);"; $iterateLoop = '$__env->incrementLoopIndices(); $loop = $__env->getLastLoop();'; return ""; } /** * Compile the break statements into valid PHP. * * @param string $expression * @return string */ protected function compileBreak($expression) { if ($expression) { preg_match('/\(\s*(-?\d+)\s*\)$/', $expression, $matches); return $matches ? '' : ""; } return ''; } /** * Compile the continue statements into valid PHP. * * @param string $expression * @return string */ protected function compileContinue($expression) { if ($expression) { preg_match('/\(\s*(-?\d+)\s*\)$/', $expression, $matches); return $matches ? '' : ""; } return ''; } /** * Compile the end-for statements into valid PHP. * * @return string */ protected function compileEndfor() { return ''; } /** * Compile the end-for-each statements into valid PHP. * * @return string */ protected function compileEndforeach() { return 'popLoop(); $loop = $__env->getLastLoop(); ?>'; } /** * Compile the while statements into valid PHP. * * @param string $expression * @return string */ protected function compileWhile($expression) { return ""; } /** * Compile the end-while statements into valid PHP. * * @return string */ protected function compileEndwhile() { return ''; } } PKz ZNll5Illuminate/View/Compilers/Concerns/CompilesRawPhp.phpnuW+A"; } return '@php'; } /** * Compile the unset statements into valid PHP. * * @param string $expression * @return string */ protected function compileUnset($expression) { return ""; } } PKz Z`=00/Illuminate/View/Compilers/CompilerInterface.phpnuW+Afiles = $files; $this->cachePath = $cachePath; $this->basePath = $basePath; $this->shouldCache = $shouldCache; $this->compiledExtension = $compiledExtension; } /** * Get the path to the compiled version of a view. * * @param string $path * @return string */ public function getCompiledPath($path) { return $this->cachePath.'/'.sha1('v2'.Str::after($path, $this->basePath)).'.'.$this->compiledExtension; } /** * Determine if the view at the given path is expired. * * @param string $path * @return bool */ public function isExpired($path) { if (! $this->shouldCache) { return true; } $compiled = $this->getCompiledPath($path); // If the compiled file doesn't exist we will indicate that the view is expired // so that it can be re-compiled. Else, we will verify the last modification // of the views is less than the modification times of the compiled views. if (! $this->files->exists($compiled)) { return true; } return $this->files->lastModified($path) >= $this->files->lastModified($compiled); } /** * Create the compiled file directory if necessary. * * @param string $path * @return void */ protected function ensureCompiledDirectoryExists($path) { if (! $this->files->exists(dirname($path))) { $this->files->makeDirectory(dirname($path), 0777, true, true); } } } PKz Z ucuc2Illuminate/View/Compilers/ComponentTagCompiler.phpnuW+A * @author Taylor Otwell */ class ComponentTagCompiler { /** * The Blade compiler instance. * * @var \Illuminate\View\Compilers\BladeCompiler */ protected $blade; /** * The component class aliases. * * @var array */ protected $aliases = []; /** * The component class namespaces. * * @var array */ protected $namespaces = []; /** * The "bind:" attributes that have been compiled for the current component. * * @var array */ protected $boundAttributes = []; /** * Create a new component tag compiler. * * @param array $aliases * @param array $namespaces * @param \Illuminate\View\Compilers\BladeCompiler|null $blade * @return void */ public function __construct(array $aliases = [], array $namespaces = [], ?BladeCompiler $blade = null) { $this->aliases = $aliases; $this->namespaces = $namespaces; $this->blade = $blade ?: new BladeCompiler(new Filesystem, sys_get_temp_dir()); } /** * Compile the component and slot tags within the given string. * * @param string $value * @return string */ public function compile(string $value) { $value = $this->compileSlots($value); return $this->compileTags($value); } /** * Compile the tags within the given string. * * @param string $value * @return string * * @throws \InvalidArgumentException */ public function compileTags(string $value) { $value = $this->compileSelfClosingTags($value); $value = $this->compileOpeningTags($value); $value = $this->compileClosingTags($value); return $value; } /** * Compile the opening tags within the given string. * * @param string $value * @return string * * @throws \InvalidArgumentException */ protected function compileOpeningTags(string $value) { $pattern = "/ < \s* x[-\:]([\w\-\:\.]*) (? (?: \s+ (?: (?: @(?:class)(\( (?: (?>[^()]+) | (?-1) )* \)) ) | (?: @(?:style)(\( (?: (?>[^()]+) | (?-1) )* \)) ) | (?: \{\{\s*\\\$attributes(?:[^}]+?)?\s*\}\} ) | (?: (\:\\\$)(\w+) ) | (?: [\w\-:.@]+ ( = (?: \\\"[^\\\"]*\\\" | \'[^\']*\' | [^\'\\\"=<>]+ ) )? ) ) )* \s* ) (? /x"; return preg_replace_callback($pattern, function (array $matches) { $this->boundAttributes = []; $attributes = $this->getAttributesFromAttributeString($matches['attributes']); return $this->componentString($matches[1], $attributes); }, $value); } /** * Compile the self-closing tags within the given string. * * @param string $value * @return string * * @throws \InvalidArgumentException */ protected function compileSelfClosingTags(string $value) { $pattern = "/ < \s* x[-\:]([\w\-\:\.]*) \s* (? (?: \s+ (?: (?: @(?:class)(\( (?: (?>[^()]+) | (?-1) )* \)) ) | (?: @(?:style)(\( (?: (?>[^()]+) | (?-1) )* \)) ) | (?: \{\{\s*\\\$attributes(?:[^}]+?)?\s*\}\} ) | (?: (\:\\\$)(\w+) ) | (?: [\w\-:.@]+ ( = (?: \\\"[^\\\"]*\\\" | \'[^\']*\' | [^\'\\\"=<>]+ ) )? ) ) )* \s* ) \/> /x"; return preg_replace_callback($pattern, function (array $matches) { $this->boundAttributes = []; $attributes = $this->getAttributesFromAttributeString($matches['attributes']); return $this->componentString($matches[1], $attributes)."\n@endComponentClass##END-COMPONENT-CLASS##"; }, $value); } /** * Compile the Blade component string for the given component and attributes. * * @param string $component * @param array $attributes * @return string * * @throws \InvalidArgumentException */ protected function componentString(string $component, array $attributes) { $class = $this->componentClass($component); [$data, $attributes] = $this->partitionDataAndAttributes($class, $attributes); $data = $data->mapWithKeys(function ($value, $key) { return [Str::camel($key) => $value]; }); // If the component doesn't exist as a class, we'll assume it's a class-less // component and pass the component as a view parameter to the data so it // can be accessed within the component and we can render out the view. if (! class_exists($class)) { $view = Str::startsWith($component, 'mail::') ? "\$__env->getContainer()->make(Illuminate\\View\\Factory::class)->make('{$component}')" : "'$class'"; $parameters = [ 'view' => $view, 'data' => '['.$this->attributesToString($data->all(), $escapeBound = false).']', ]; $class = AnonymousComponent::class; } else { $parameters = $data->all(); } return "##BEGIN-COMPONENT-CLASS##@component('{$class}', '{$component}', [".$this->attributesToString($parameters, $escapeBound = false).']) getConstructor()): ?> except(collect($constructor->getParameters())->map->getName()->all()); ?> withAttributes(['.$this->attributesToString($attributes->all(), $escapeAttributes = $class !== DynamicComponent::class).']); ?>'; } /** * Get the component class for a given component alias. * * @param string $component * @return string * * @throws \InvalidArgumentException */ public function componentClass(string $component) { $viewFactory = Container::getInstance()->make(Factory::class); if (isset($this->aliases[$component])) { if (class_exists($alias = $this->aliases[$component])) { return $alias; } if ($viewFactory->exists($alias)) { return $alias; } throw new InvalidArgumentException( "Unable to locate class or view [{$alias}] for component [{$component}]." ); } if ($class = $this->findClassByComponent($component)) { return $class; } if (class_exists($class = $this->guessClassName($component))) { return $class; } if (! is_null($guess = $this->guessAnonymousComponentUsingNamespaces($viewFactory, $component)) || ! is_null($guess = $this->guessAnonymousComponentUsingPaths($viewFactory, $component))) { return $guess; } if (Str::startsWith($component, 'mail::')) { return $component; } throw new InvalidArgumentException( "Unable to locate a class or view for component [{$component}]." ); } /** * Attempt to find an anonymous component using the registered anonymous component paths. * * @param \Illuminate\Contracts\View\Factory $viewFactory * @param string $component * @return string|null */ protected function guessAnonymousComponentUsingPaths(Factory $viewFactory, string $component) { $delimiter = ViewFinderInterface::HINT_PATH_DELIMITER; foreach ($this->blade->getAnonymousComponentPaths() as $path) { try { if (str_contains($component, $delimiter) && ! str_starts_with($component, $path['prefix'].$delimiter)) { continue; } $formattedComponent = str_starts_with($component, $path['prefix'].$delimiter) ? Str::after($component, $delimiter) : $component; if (! is_null($guess = match (true) { $viewFactory->exists($guess = $path['prefixHash'].$delimiter.$formattedComponent) => $guess, $viewFactory->exists($guess = $path['prefixHash'].$delimiter.$formattedComponent.'.index') => $guess, default => null, })) { return $guess; } } catch (InvalidArgumentException $e) { // } } } /** * Attempt to find an anonymous component using the registered anonymous component namespaces. * * @param \Illuminate\Contracts\View\Factory $viewFactory * @param string $component * @return string|null */ protected function guessAnonymousComponentUsingNamespaces(Factory $viewFactory, string $component) { return collect($this->blade->getAnonymousComponentNamespaces()) ->filter(function ($directory, $prefix) use ($component) { return Str::startsWith($component, $prefix.'::'); }) ->prepend('components', $component) ->reduce(function ($carry, $directory, $prefix) use ($component, $viewFactory) { if (! is_null($carry)) { return $carry; } $componentName = Str::after($component, $prefix.'::'); if ($viewFactory->exists($view = $this->guessViewName($componentName, $directory))) { return $view; } if ($viewFactory->exists($view = $this->guessViewName($componentName, $directory).'.index')) { return $view; } }); } /** * Find the class for the given component using the registered namespaces. * * @param string $component * @return string|null */ public function findClassByComponent(string $component) { $segments = explode('::', $component); $prefix = $segments[0]; if (! isset($this->namespaces[$prefix], $segments[1])) { return; } if (class_exists($class = $this->namespaces[$prefix].'\\'.$this->formatClassName($segments[1]))) { return $class; } } /** * Guess the class name for the given component. * * @param string $component * @return string */ public function guessClassName(string $component) { $namespace = Container::getInstance() ->make(Application::class) ->getNamespace(); $class = $this->formatClassName($component); return $namespace.'View\\Components\\'.$class; } /** * Format the class name for the given component. * * @param string $component * @return string */ public function formatClassName(string $component) { $componentPieces = array_map(function ($componentPiece) { return ucfirst(Str::camel($componentPiece)); }, explode('.', $component)); return implode('\\', $componentPieces); } /** * Guess the view name for the given component. * * @param string $name * @param string $prefix * @return string */ public function guessViewName($name, $prefix = 'components.') { if (! Str::endsWith($prefix, '.')) { $prefix .= '.'; } $delimiter = ViewFinderInterface::HINT_PATH_DELIMITER; if (str_contains($name, $delimiter)) { return Str::replaceFirst($delimiter, $delimiter.$prefix, $name); } return $prefix.$name; } /** * Partition the data and extra attributes from the given array of attributes. * * @param string $class * @param array $attributes * @return array */ public function partitionDataAndAttributes($class, array $attributes) { // If the class doesn't exist, we'll assume it is a class-less component and // return all of the attributes as both data and attributes since we have // now way to partition them. The user can exclude attributes manually. if (! class_exists($class)) { return [collect($attributes), collect($attributes)]; } $constructor = (new ReflectionClass($class))->getConstructor(); $parameterNames = $constructor ? collect($constructor->getParameters())->map->getName()->all() : []; return collect($attributes)->partition(function ($value, $key) use ($parameterNames) { return in_array(Str::camel($key), $parameterNames); })->all(); } /** * Compile the closing tags within the given string. * * @param string $value * @return string */ protected function compileClosingTags(string $value) { return preg_replace("/<\/\s*x[-\:][\w\-\:\.]*\s*>/", ' @endComponentClass##END-COMPONENT-CLASS##', $value); } /** * Compile the slot tags within the given string. * * @param string $value * @return string */ public function compileSlots(string $value) { $pattern = "/ < \s* x[\-\:]slot (?:\:(?\w+(?:-\w+)*))? (?:\s+(:?)name=(?(\"[^\"]+\"|\\\'[^\\\']+\\\'|[^\s>]+)))? (? (?: \s+ (?: (?: @(?:class)(\( (?: (?>[^()]+) | (?-1) )* \)) ) | (?: @(?:style)(\( (?: (?>[^()]+) | (?-1) )* \)) ) | (?: \{\{\s*\\\$attributes(?:[^}]+?)?\s*\}\} ) | (?: [\w\-:.@]+ ( = (?: \\\"[^\\\"]*\\\" | \'[^\']*\' | [^\'\\\"=<>]+ ) )? ) ) )* \s* ) (? /x"; $value = preg_replace_callback($pattern, function ($matches) { $name = $this->stripQuotes($matches['inlineName'] ?: $matches['name']); if (Str::contains($name, '-') && ! empty($matches['inlineName'])) { $name = Str::camel($name); } if ($matches[2] !== ':') { $name = "'{$name}'"; } $this->boundAttributes = []; $attributes = $this->getAttributesFromAttributeString($matches['attributes']); return " @slot({$name}, null, [".$this->attributesToString($attributes).']) '; }, $value); return preg_replace('/<\/\s*x[\-\:]slot[^>]*>/', ' @endslot', $value); } /** * Get an array of attributes from the given attribute string. * * @param string $attributeString * @return array */ protected function getAttributesFromAttributeString(string $attributeString) { $attributeString = $this->parseShortAttributeSyntax($attributeString); $attributeString = $this->parseAttributeBag($attributeString); $attributeString = $this->parseComponentTagClassStatements($attributeString); $attributeString = $this->parseComponentTagStyleStatements($attributeString); $attributeString = $this->parseBindAttributes($attributeString); $pattern = '/ (?[\w\-:.@]+) ( = (? ( \"[^\"]+\" | \\\'[^\\\']+\\\' | [^\s>]+ ) ) )? /x'; if (! preg_match_all($pattern, $attributeString, $matches, PREG_SET_ORDER)) { return []; } return collect($matches)->mapWithKeys(function ($match) { $attribute = $match['attribute']; $value = $match['value'] ?? null; if (is_null($value)) { $value = 'true'; $attribute = Str::start($attribute, 'bind:'); } $value = $this->stripQuotes($value); if (str_starts_with($attribute, 'bind:')) { $attribute = Str::after($attribute, 'bind:'); $this->boundAttributes[$attribute] = true; } else { $value = "'".$this->compileAttributeEchos($value)."'"; } if (str_starts_with($attribute, '::')) { $attribute = substr($attribute, 1); } return [$attribute => $value]; })->toArray(); } /** * Parses a short attribute syntax like :$foo into a fully-qualified syntax like :foo="$foo". * * @param string $value * @return string */ protected function parseShortAttributeSyntax(string $value) { $pattern = "/\s\:\\\$(\w+)/x"; return preg_replace_callback($pattern, function (array $matches) { return " :{$matches[1]}=\"\${$matches[1]}\""; }, $value); } /** * Parse the attribute bag in a given attribute string into its fully-qualified syntax. * * @param string $attributeString * @return string */ protected function parseAttributeBag(string $attributeString) { $pattern = "/ (?:^|\s+) # start of the string or whitespace between attributes \{\{\s*(\\\$attributes(?:[^}]+?(?[^()]+) | (?2) )* \))/x', function ($match) { if ($match[1] === 'class') { $match[2] = str_replace('"', "'", $match[2]); return ":class=\"\Illuminate\Support\Arr::toCssClasses{$match[2]}\""; } return $match[0]; }, $attributeString ); } /** * Parse @style statements in a given attribute string into their fully-qualified syntax. * * @param string $attributeString * @return string */ protected function parseComponentTagStyleStatements(string $attributeString) { return preg_replace_callback( '/@(style)(\( ( (?>[^()]+) | (?2) )* \))/x', function ($match) { if ($match[1] === 'style') { $match[2] = str_replace('"', "'", $match[2]); return ":style=\"\Illuminate\Support\Arr::toCssStyles{$match[2]}\""; } return $match[0]; }, $attributeString ); } /** * Parse the "bind" attributes in a given attribute string into their fully-qualified syntax. * * @param string $attributeString * @return string */ protected function parseBindAttributes(string $attributeString) { $pattern = "/ (?:^|\s+) # start of the string or whitespace between attributes :(?!:) # attribute needs to start with a single colon ([\w\-:.@]+) # match the actual attribute name = # only match attributes that have a value /xm"; return preg_replace($pattern, ' bind:$1=', $attributeString); } /** * Compile any Blade echo statements that are present in the attribute string. * * These echo statements need to be converted to string concatenation statements. * * @param string $attributeString * @return string */ protected function compileAttributeEchos(string $attributeString) { $value = $this->blade->compileEchos($attributeString); $value = $this->escapeSingleQuotesOutsideOfPhpBlocks($value); $value = str_replace('', '.\'', $value); return $value; } /** * Escape the single quotes in the given string that are outside of PHP blocks. * * @param string $value * @return string */ protected function escapeSingleQuotesOutsideOfPhpBlocks(string $value) { return collect(token_get_all($value))->map(function ($token) { if (! is_array($token)) { return $token; } return $token[0] === T_INLINE_HTML ? str_replace("'", "\\'", $token[1]) : $token[1]; })->implode(''); } /** * Convert an array of attributes to a string. * * @param array $attributes * @param bool $escapeBound * @return string */ protected function attributesToString(array $attributes, $escapeBound = true) { return collect($attributes) ->map(function (string $value, string $attribute) use ($escapeBound) { return $escapeBound && isset($this->boundAttributes[$attribute]) && $value !== 'true' && ! is_numeric($value) ? "'{$attribute}' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute({$value})" : "'{$attribute}' => {$value}"; }) ->implode(','); } /** * Strip any quotes from the given string. * * @param string $value * @return string */ public function stripQuotes(string $value) { return Str::startsWith($value, ['"', '\'']) ? substr($value, 1, -1) : $value; } } PKz Z(ff+Illuminate/View/Compilers/BladeCompiler.phpnuW+AsetPath($path); } if (! is_null($this->cachePath)) { $contents = $this->compileString($this->files->get($this->getPath())); if (! empty($this->getPath())) { $contents = $this->appendFilePath($contents); } $this->ensureCompiledDirectoryExists( $compiledPath = $this->getCompiledPath($this->getPath()) ); $this->files->put($compiledPath, $contents); } } /** * Append the file path to the compiled string. * * @param string $contents * @return string */ protected function appendFilePath($contents) { $tokens = $this->getOpenAndClosingPhpTokens($contents); if ($tokens->isNotEmpty() && $tokens->last() !== T_CLOSE_TAG) { $contents .= ' ?>'; } return $contents."getPath()} ENDPATH**/ ?>"; } /** * Get the open and closing PHP tag tokens from the given string. * * @param string $contents * @return \Illuminate\Support\Collection */ protected function getOpenAndClosingPhpTokens($contents) { return collect(token_get_all($contents)) ->pluck(0) ->filter(function ($token) { return in_array($token, [T_OPEN_TAG, T_OPEN_TAG_WITH_ECHO, T_CLOSE_TAG]); }); } /** * Get the path currently being compiled. * * @return string */ public function getPath() { return $this->path; } /** * Set the path currently being compiled. * * @param string $path * @return void */ public function setPath($path) { $this->path = $path; } /** * Compile the given Blade template contents. * * @param string $value * @return string */ public function compileString($value) { [$this->footer, $result] = [[], '']; // First we will compile the Blade component tags. This is a precompile style // step which compiles the component Blade tags into @component directives // that may be used by Blade. Then we should call any other precompilers. $value = $this->compileComponentTags( $this->compileComments($this->storeUncompiledBlocks($value)) ); foreach ($this->precompilers as $precompiler) { $value = $precompiler($value); } // Here we will loop through all of the tokens returned by the Zend lexer and // parse each one into the corresponding valid PHP. We will then have this // template as the correctly rendered PHP that can be rendered natively. foreach (token_get_all($value) as $token) { $result .= is_array($token) ? $this->parseToken($token) : $token; } if (! empty($this->rawBlocks)) { $result = $this->restoreRawContent($result); } // If there are any footer lines that need to get added to a template we will // add them here at the end of the template. This gets used mainly for the // template inheritance via the extends keyword that should be appended. if (count($this->footer) > 0) { $result = $this->addFooters($result); } if (! empty($this->echoHandlers)) { $result = $this->addBladeCompilerVariable($result); } return str_replace( ['##BEGIN-COMPONENT-CLASS##', '##END-COMPONENT-CLASS##'], '', $result); } /** * Evaluate and render a Blade string to HTML. * * @param string $string * @param array $data * @param bool $deleteCachedView * @return string */ public static function render($string, $data = [], $deleteCachedView = false) { $component = new class($string) extends Component { protected $template; public function __construct($template) { $this->template = $template; } public function render() { return $this->template; } }; $view = Container::getInstance() ->make(ViewFactory::class) ->make($component->resolveView(), $data); return tap($view->render(), function () use ($view, $deleteCachedView) { if ($deleteCachedView) { unlink($view->getPath()); } }); } /** * Render a component instance to HTML. * * @param \Illuminate\View\Component $component * @return string */ public static function renderComponent(Component $component) { $data = $component->data(); $view = value($component->resolveView(), $data); if ($view instanceof View) { return $view->with($data)->render(); } elseif ($view instanceof Htmlable) { return $view->toHtml(); } else { return Container::getInstance() ->make(ViewFactory::class) ->make($view, $data) ->render(); } } /** * Store the blocks that do not receive compilation. * * @param string $value * @return string */ protected function storeUncompiledBlocks($value) { if (str_contains($value, '@verbatim')) { $value = $this->storeVerbatimBlocks($value); } if (str_contains($value, '@php')) { $value = $this->storePhpBlocks($value); } return $value; } /** * Store the verbatim blocks and replace them with a temporary placeholder. * * @param string $value * @return string */ protected function storeVerbatimBlocks($value) { return preg_replace_callback('/(?storeRawBlock($matches[1]); }, $value); } /** * Store the PHP blocks and replace them with a temporary placeholder. * * @param string $value * @return string */ protected function storePhpBlocks($value) { return preg_replace_callback('/(?storeRawBlock(""); }, $value); } /** * Store a raw block and return a unique raw placeholder. * * @param string $value * @return string */ protected function storeRawBlock($value) { return $this->getRawPlaceholder( array_push($this->rawBlocks, $value) - 1 ); } /** * Compile the component tags. * * @param string $value * @return string */ protected function compileComponentTags($value) { if (! $this->compilesComponentTags) { return $value; } return (new ComponentTagCompiler( $this->classComponentAliases, $this->classComponentNamespaces, $this ))->compile($value); } /** * Replace the raw placeholders with the original code stored in the raw blocks. * * @param string $result * @return string */ protected function restoreRawContent($result) { $result = preg_replace_callback('/'.$this->getRawPlaceholder('(\d+)').'/', function ($matches) { return $this->rawBlocks[$matches[1]]; }, $result); $this->rawBlocks = []; return $result; } /** * Get a placeholder to temporarily mark the position of raw blocks. * * @param int|string $replace * @return string */ protected function getRawPlaceholder($replace) { return str_replace('#', $replace, '@__raw_block_#__@'); } /** * Add the stored footers onto the given content. * * @param string $result * @return string */ protected function addFooters($result) { return ltrim($result, "\n") ."\n".implode("\n", array_reverse($this->footer)); } /** * Parse the tokens from the template. * * @param array $token * @return string */ protected function parseToken($token) { [$id, $content] = $token; if ($id == T_INLINE_HTML) { foreach ($this->compilers as $type) { $content = $this->{"compile{$type}"}($content); } } return $content; } /** * Execute the user defined extensions. * * @param string $value * @return string */ protected function compileExtensions($value) { foreach ($this->extensions as $compiler) { $value = $compiler($value, $this); } return $value; } /** * Compile Blade statements that start with "@". * * @param string $template * @return string */ protected function compileStatements($template) { preg_match_all('/\B@(@?\w+(?:::\w+)?)([ \t]*)(\( ( [\S\s]*? ) \))?/x', $template, $matches); $offset = 0; for ($i = 0; isset($matches[0][$i]); $i++) { $match = [ $matches[0][$i], $matches[1][$i], $matches[2][$i], $matches[3][$i] ?: null, $matches[4][$i] ?: null, ]; // Here we check to see if we have properly found the closing parenthesis by // regex pattern or not, and will recursively continue on to the next ")" // then check again until the tokenizer confirms we find the right one. while (isset($match[4]) && Str::endsWith($match[0], ')') && ! $this->hasEvenNumberOfParentheses($match[0])) { if (($after = Str::after($template, $match[0])) === $template) { break; } $rest = Str::before($after, ')'); if (isset($matches[0][$i + 1]) && Str::contains($rest.')', $matches[0][$i + 1])) { unset($matches[0][$i + 1]); $i++; } $match[0] = $match[0].$rest.')'; $match[3] = $match[3].$rest.')'; $match[4] = $match[4].$rest; } [$template, $offset] = $this->replaceFirstStatement( $match[0], $this->compileStatement($match), $template, $offset ); } return $template; } /** * Replace the first match for a statement compilation operation. * * @param string $search * @param string $replace * @param string $subject * @param int $offset * @return array */ protected function replaceFirstStatement($search, $replace, $subject, $offset) { $search = (string) $search; if ($search === '') { return $subject; } $position = strpos($subject, $search, $offset); if ($position !== false) { return [ substr_replace($subject, $replace, $position, strlen($search)), $position + strlen($replace), ]; } return [$subject, 0]; } /** * Determine if the given expression has the same number of opening and closing parentheses. * * @param string $expression * @return bool */ protected function hasEvenNumberOfParentheses(string $expression) { $tokens = token_get_all('customDirectives[$match[1]])) { $match[0] = $this->callCustomDirective($match[1], Arr::get($match, 3)); } elseif (method_exists($this, $method = 'compile'.ucfirst($match[1]))) { $match[0] = $this->$method(Arr::get($match, 3)); } else { return $match[0]; } return isset($match[3]) ? $match[0] : $match[0].$match[2]; } /** * Call the given directive with the given value. * * @param string $name * @param string|null $value * @return string */ protected function callCustomDirective($name, $value) { $value ??= ''; if (str_starts_with($value, '(') && str_ends_with($value, ')')) { $value = Str::substr($value, 1, -1); } return call_user_func($this->customDirectives[$name], trim($value)); } /** * Strip the parentheses from the given expression. * * @param string $expression * @return string */ public function stripParentheses($expression) { if (Str::startsWith($expression, '(')) { $expression = substr($expression, 1, -1); } return $expression; } /** * Register a custom Blade compiler. * * @param callable $compiler * @return void */ public function extend(callable $compiler) { $this->extensions[] = $compiler; } /** * Get the extensions used by the compiler. * * @return array */ public function getExtensions() { return $this->extensions; } /** * Register an "if" statement directive. * * @param string $name * @param callable $callback * @return void */ public function if($name, callable $callback) { $this->conditions[$name] = $callback; $this->directive($name, function ($expression) use ($name) { return $expression !== '' ? "" : ""; }); $this->directive('unless'.$name, function ($expression) use ($name) { return $expression !== '' ? "" : ""; }); $this->directive('else'.$name, function ($expression) use ($name) { return $expression !== '' ? "" : ""; }); $this->directive('end'.$name, function () { return ''; }); } /** * Check the result of a condition. * * @param string $name * @param mixed ...$parameters * @return bool */ public function check($name, ...$parameters) { return call_user_func($this->conditions[$name], ...$parameters); } /** * Register a class-based component alias directive. * * @param string $class * @param string|null $alias * @param string $prefix * @return void */ public function component($class, $alias = null, $prefix = '') { if (! is_null($alias) && str_contains($alias, '\\')) { [$class, $alias] = [$alias, $class]; } if (is_null($alias)) { $alias = str_contains($class, '\\View\\Components\\') ? collect(explode('\\', Str::after($class, '\\View\\Components\\')))->map(function ($segment) { return Str::kebab($segment); })->implode(':') : Str::kebab(class_basename($class)); } if (! empty($prefix)) { $alias = $prefix.'-'.$alias; } $this->classComponentAliases[$alias] = $class; } /** * Register an array of class-based components. * * @param array $components * @param string $prefix * @return void */ public function components(array $components, $prefix = '') { foreach ($components as $key => $value) { if (is_numeric($key)) { $this->component($value, null, $prefix); } else { $this->component($key, $value, $prefix); } } } /** * Get the registered class component aliases. * * @return array */ public function getClassComponentAliases() { return $this->classComponentAliases; } /** * Register a new anonymous component path. * * @param string $path * @param string|null $prefix * @return void */ public function anonymousComponentPath(string $path, string $prefix = null) { $prefixHash = md5($prefix ?: $path); $this->anonymousComponentPaths[] = [ 'path' => $path, 'prefix' => $prefix, 'prefixHash' => $prefixHash, ]; Container::getInstance() ->make(ViewFactory::class) ->addNamespace($prefixHash, $path); } /** * Register an anonymous component namespace. * * @param string $directory * @param string|null $prefix * @return void */ public function anonymousComponentNamespace(string $directory, string $prefix = null) { $prefix ??= $directory; $this->anonymousComponentNamespaces[$prefix] = Str::of($directory) ->replace('/', '.') ->trim('. ') ->toString(); } /** * Register a class-based component namespace. * * @param string $namespace * @param string $prefix * @return void */ public function componentNamespace($namespace, $prefix) { $this->classComponentNamespaces[$prefix] = $namespace; } /** * Get the registered anonymous component paths. * * @return array */ public function getAnonymousComponentPaths() { return $this->anonymousComponentPaths; } /** * Get the registered anonymous component namespaces. * * @return array */ public function getAnonymousComponentNamespaces() { return $this->anonymousComponentNamespaces; } /** * Get the registered class component namespaces. * * @return array */ public function getClassComponentNamespaces() { return $this->classComponentNamespaces; } /** * Register a component alias directive. * * @param string $path * @param string|null $alias * @return void */ public function aliasComponent($path, $alias = null) { $alias = $alias ?: Arr::last(explode('.', $path)); $this->directive($alias, function ($expression) use ($path) { return $expression ? "startComponent('{$path}', {$expression}); ?>" : "startComponent('{$path}'); ?>"; }); $this->directive('end'.$alias, function ($expression) { return 'renderComponent(); ?>'; }); } /** * Register an include alias directive. * * @param string $path * @param string|null $alias * @return void */ public function include($path, $alias = null) { $this->aliasInclude($path, $alias); } /** * Register an include alias directive. * * @param string $path * @param string|null $alias * @return void */ public function aliasInclude($path, $alias = null) { $alias = $alias ?: Arr::last(explode('.', $path)); $this->directive($alias, function ($expression) use ($path) { $expression = $this->stripParentheses($expression) ?: '[]'; return "make('{$path}', {$expression}, \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?>"; }); } /** * Register a handler for custom directives. * * @param string $name * @param callable $handler * @return void * * @throws \InvalidArgumentException */ public function directive($name, callable $handler) { if (! preg_match('/^\w+(?:::\w+)?$/x', $name)) { throw new InvalidArgumentException("The directive name [{$name}] is not valid. Directive names must only contain alphanumeric characters and underscores."); } $this->customDirectives[$name] = $handler; } /** * Get the list of custom directives. * * @return array */ public function getCustomDirectives() { return $this->customDirectives; } /** * Register a new precompiler. * * @param callable $precompiler * @return void */ public function precompiler(callable $precompiler) { $this->precompilers[] = $precompiler; } /** * Set the echo format to be used by the compiler. * * @param string $format * @return void */ public function setEchoFormat($format) { $this->echoFormat = $format; } /** * Set the "echo" format to double encode entities. * * @return void */ public function withDoubleEncoding() { $this->setEchoFormat('e(%s, true)'); } /** * Set the "echo" format to not double encode entities. * * @return void */ public function withoutDoubleEncoding() { $this->setEchoFormat('e(%s, false)'); } /** * Indicate that component tags should not be compiled. * * @return void */ public function withoutComponentTags() { $this->compilesComponentTags = false; } } PKz Zj++Illuminate/View/View.phpnuW+Aview = $view; $this->path = $path; $this->engine = $engine; $this->factory = $factory; $this->data = $data instanceof Arrayable ? $data->toArray() : (array) $data; } /** * Get the evaluated contents of a given fragment. * * @param string $fragment * @return string */ public function fragment($fragment) { return $this->render(function () use ($fragment) { return $this->factory->getFragment($fragment); }); } /** * Get the evaluated contents for a given array of fragments. * * @param array $fragments * @return string */ public function fragments(array $fragments) { return collect($fragments)->map(fn ($f) => $this->fragment($f))->implode(''); } /** * Get the evaluated contents of a given fragment if the given condition is true. * * @param bool $boolean * @param string $fragment * @return string */ public function fragmentIf($boolean, $fragment) { if (value($boolean)) { return $this->fragment($fragment); } return $this->render(); } /** * Get the evaluated contents for a given array of fragments if the given condition is true. * * @param bool $boolean * @param array $fragments * @return string */ public function fragmentsIf($boolean, array $fragments) { if (value($boolean)) { return $this->fragments($fragments); } return $this->render(); } /** * Get the string contents of the view. * * @param callable|null $callback * @return string * * @throws \Throwable */ public function render(callable $callback = null) { try { $contents = $this->renderContents(); $response = isset($callback) ? $callback($this, $contents) : null; // Once we have the contents of the view, we will flush the sections if we are // done rendering all views so that there is nothing left hanging over when // another view gets rendered in the future by the application developer. $this->factory->flushStateIfDoneRendering(); return ! is_null($response) ? $response : $contents; } catch (Throwable $e) { $this->factory->flushState(); throw $e; } } /** * Get the contents of the view instance. * * @return string */ protected function renderContents() { // We will keep track of the number of views being rendered so we can flush // the section after the complete rendering operation is done. This will // clear out the sections for any separate views that may be rendered. $this->factory->incrementRender(); $this->factory->callComposer($this); $contents = $this->getContents(); // Once we've finished rendering the view, we'll decrement the render count // so that each section gets flushed out next time a view is created and // no old sections are staying around in the memory of an environment. $this->factory->decrementRender(); return $contents; } /** * Get the evaluated contents of the view. * * @return string */ protected function getContents() { return $this->engine->get($this->path, $this->gatherData()); } /** * Get the data bound to the view instance. * * @return array */ public function gatherData() { $data = array_merge($this->factory->getShared(), $this->data); foreach ($data as $key => $value) { if ($value instanceof Renderable) { $data[$key] = $value->render(); } } return $data; } /** * Get the sections of the rendered view. * * @return array * * @throws \Throwable */ public function renderSections() { return $this->render(function () { return $this->factory->getSections(); }); } /** * Add a piece of data to the view. * * @param string|array $key * @param mixed $value * @return $this */ public function with($key, $value = null) { if (is_array($key)) { $this->data = array_merge($this->data, $key); } else { $this->data[$key] = $value; } return $this; } /** * Add a view instance to the view data. * * @param string $key * @param string $view * @param array $data * @return $this */ public function nest($key, $view, array $data = []) { return $this->with($key, $this->factory->make($view, $data)); } /** * Add validation errors to the view. * * @param \Illuminate\Contracts\Support\MessageProvider|array $provider * @param string $bag * @return $this */ public function withErrors($provider, $bag = 'default') { return $this->with('errors', (new ViewErrorBag)->put( $bag, $this->formatErrors($provider) )); } /** * Parse the given errors into an appropriate value. * * @param \Illuminate\Contracts\Support\MessageProvider|array|string $provider * @return \Illuminate\Support\MessageBag */ protected function formatErrors($provider) { return $provider instanceof MessageProvider ? $provider->getMessageBag() : new MessageBag((array) $provider); } /** * Get the name of the view. * * @return string */ public function name() { return $this->getName(); } /** * Get the name of the view. * * @return string */ public function getName() { return $this->view; } /** * Get the array of view data. * * @return array */ public function getData() { return $this->data; } /** * Get the path to the view file. * * @return string */ public function getPath() { return $this->path; } /** * Set the path to the view. * * @param string $path * @return void */ public function setPath($path) { $this->path = $path; } /** * Get the view factory instance. * * @return \Illuminate\View\Factory */ public function getFactory() { return $this->factory; } /** * Get the view's rendering engine. * * @return \Illuminate\Contracts\View\Engine */ public function getEngine() { return $this->engine; } /** * Determine if a piece of data is bound. * * @param string $key * @return bool */ public function offsetExists($key): bool { return array_key_exists($key, $this->data); } /** * Get a piece of bound data to the view. * * @param string $key * @return mixed */ public function offsetGet($key): mixed { return $this->data[$key]; } /** * Set a piece of data on the view. * * @param string $key * @param mixed $value * @return void */ public function offsetSet($key, $value): void { $this->with($key, $value); } /** * Unset a piece of data from the view. * * @param string $key * @return void */ public function offsetUnset($key): void { unset($this->data[$key]); } /** * Get a piece of data from the view. * * @param string $key * @return mixed */ public function &__get($key) { return $this->data[$key]; } /** * Set a piece of data on the view. * * @param string $key * @param mixed $value * @return void */ public function __set($key, $value) { $this->with($key, $value); } /** * Check if a piece of data is bound to the view. * * @param string $key * @return bool */ public function __isset($key) { return isset($this->data[$key]); } /** * Remove a piece of bound data from the view. * * @param string $key * @return void */ public function __unset($key) { unset($this->data[$key]); } /** * Dynamically bind parameters to the view. * * @param string $method * @param array $parameters * @return \Illuminate\View\View * * @throws \BadMethodCallException */ public function __call($method, $parameters) { if (static::hasMacro($method)) { return $this->macroCall($method, $parameters); } if (! str_starts_with($method, 'with')) { throw new BadMethodCallException(sprintf( 'Method %s::%s does not exist.', static::class, $method )); } return $this->with(Str::camel(substr($method, 4)), $parameters[0]); } /** * Get content as a string of HTML. * * @return string */ public function toHtml() { return $this->render(); } /** * Get the string contents of the view. * * @return string * * @throws \Throwable */ public function __toString() { return $this->render(); } } PKz ZYY%Illuminate/View/Engines/PhpEngine.phpnuW+Afiles = $files; } /** * Get the evaluated contents of the view. * * @param string $path * @param array $data * @return string */ public function get($path, array $data = []) { return $this->evaluatePath($path, $data); } /** * Get the evaluated contents of the view at the given path. * * @param string $path * @param array $data * @return string */ protected function evaluatePath($path, $data) { $obLevel = ob_get_level(); ob_start(); // We'll evaluate the contents of the view inside a try/catch block so we can // flush out any stray output that might get out before an error occurs or // an exception is thrown. This prevents any partial views from leaking. try { $this->files->getRequire($path, $data); } catch (Throwable $e) { $this->handleViewException($e, $obLevel); } return ltrim(ob_get_clean()); } /** * Handle a view exception. * * @param \Throwable $e * @param int $obLevel * @return void * * @throws \Throwable */ protected function handleViewException(Throwable $e, $obLevel) { while (ob_get_level() > $obLevel) { ob_end_clean(); } throw $e; } } PKz Z%*Illuminate/View/Engines/EngineResolver.phpnuW+Aforget($engine); $this->resolvers[$engine] = $resolver; } /** * Resolve an engine instance by name. * * @param string $engine * @return \Illuminate\Contracts\View\Engine * * @throws \InvalidArgumentException */ public function resolve($engine) { if (isset($this->resolved[$engine])) { return $this->resolved[$engine]; } if (isset($this->resolvers[$engine])) { return $this->resolved[$engine] = call_user_func($this->resolvers[$engine]); } throw new InvalidArgumentException("Engine [{$engine}] not found."); } /** * Remove a resolved engine. * * @param string $engine * @return void */ public function forget($engine) { unset($this->resolved[$engine]); } } PKz Z׌~&Illuminate/View/Engines/FileEngine.phpnuW+Afiles = $files; } /** * Get the evaluated contents of the view. * * @param string $path * @param array $data * @return string */ public function get($path, array $data = []) { return $this->files->get($path); } } PKz ZrVo*Illuminate/View/Engines/CompilerEngine.phpnuW+A */ protected $compiledOrNotExpired = []; /** * Create a new compiler engine instance. * * @param \Illuminate\View\Compilers\CompilerInterface $compiler * @param \Illuminate\Filesystem\Filesystem|null $files * @return void */ public function __construct(CompilerInterface $compiler, Filesystem $files = null) { parent::__construct($files ?: new Filesystem); $this->compiler = $compiler; } /** * Get the evaluated contents of the view. * * @param string $path * @param array $data * @return string */ public function get($path, array $data = []) { $this->lastCompiled[] = $path; // If this given view has expired, which means it has simply been edited since // it was last compiled, we will re-compile the views so we can evaluate a // fresh copy of the view. We'll pass the compiler the path of the view. if (! isset($this->compiledOrNotExpired[$path]) && $this->compiler->isExpired($path)) { $this->compiler->compile($path); } // Once we have the path to the compiled file, we will evaluate the paths with // typical PHP just like any other templates. We also keep a stack of views // which have been rendered for right exception messages to be generated. try { $results = $this->evaluatePath($this->compiler->getCompiledPath($path), $data); } catch (ViewException $e) { if (! str($e->getMessage())->contains(['No such file or directory', 'File does not exist at path'])) { throw $e; } if (! isset($this->compiledOrNotExpired[$path])) { throw $e; } $this->compiler->compile($path); $results = $this->evaluatePath($this->compiler->getCompiledPath($path), $data); } $this->compiledOrNotExpired[$path] = true; array_pop($this->lastCompiled); return $results; } /** * Handle a view exception. * * @param \Throwable $e * @param int $obLevel * @return void * * @throws \Throwable */ protected function handleViewException(Throwable $e, $obLevel) { $e = new ViewException($this->getMessage($e), 0, 1, $e->getFile(), $e->getLine(), $e); parent::handleViewException($e, $obLevel); } /** * Get the exception message for an exception. * * @param \Throwable $e * @return string */ protected function getMessage(Throwable $e) { return $e->getMessage().' (View: '.realpath(last($this->lastCompiled)).')'; } /** * Get the compiler implementation. * * @return \Illuminate\View\Compilers\CompilerInterface */ public function getCompiler() { return $this->compiler; } /** * Clear the cache of views that were compiled or not expired. * * @return void */ public function forgetCompiledOrNotExpired() { $this->compiledOrNotExpired = []; } } PKz Z+g jj"Illuminate/View/Engines/Engine.phpnuW+AlastRendered; } } PKz ZsF?  )Illuminate/View/Concerns/ManagesLoops.phpnuW+AloopsStack); $this->loopsStack[] = [ 'iteration' => 0, 'index' => 0, 'remaining' => $length ?? null, 'count' => $length, 'first' => true, 'last' => isset($length) ? $length == 1 : null, 'odd' => false, 'even' => true, 'depth' => count($this->loopsStack) + 1, 'parent' => $parent ? (object) $parent : null, ]; } /** * Increment the top loop's indices. * * @return void */ public function incrementLoopIndices() { $loop = $this->loopsStack[$index = count($this->loopsStack) - 1]; $this->loopsStack[$index] = array_merge($this->loopsStack[$index], [ 'iteration' => $loop['iteration'] + 1, 'index' => $loop['iteration'], 'first' => $loop['iteration'] == 0, 'odd' => ! $loop['odd'], 'even' => ! $loop['even'], 'remaining' => isset($loop['count']) ? $loop['remaining'] - 1 : null, 'last' => isset($loop['count']) ? $loop['iteration'] == $loop['count'] - 1 : null, ]); } /** * Pop a loop from the top of the loop stack. * * @return void */ public function popLoop() { array_pop($this->loopsStack); } /** * Get an instance of the last loop in the stack. * * @return \stdClass|null */ public function getLastLoop() { if ($last = Arr::last($this->loopsStack)) { return (object) $last; } } /** * Get the entire loop stack. * * @return array */ public function getLoopStack() { return $this->loopsStack; } } PKz Z(!60Illuminate/View/Concerns/ManagesTranslations.phpnuW+AtranslationReplacements = $replacements; } /** * Render the current translation. * * @return string */ public function renderTranslation() { return $this->container->make('translator')->get( trim(ob_get_clean()), $this->translationReplacements ); } } PKz ZJss.Illuminate/View/Concerns/ManagesComponents.phpnuW+AcomponentStack[] = $view; $this->componentData[$this->currentComponent()] = $data; $this->slots[$this->currentComponent()] = []; } } /** * Get the first view that actually exists from the given list, and start a component. * * @param array $names * @param array $data * @return void */ public function startComponentFirst(array $names, array $data = []) { $name = Arr::first($names, function ($item) { return $this->exists($item); }); $this->startComponent($name, $data); } /** * Render the current component. * * @return string */ public function renderComponent() { $view = array_pop($this->componentStack); $this->currentComponentData = array_merge( $previousComponentData = $this->currentComponentData, $data = $this->componentData() ); try { $view = value($view, $data); if ($view instanceof View) { return $view->with($data)->render(); } elseif ($view instanceof Htmlable) { return $view->toHtml(); } else { return $this->make($view, $data)->render(); } } finally { $this->currentComponentData = $previousComponentData; } } /** * Get the data for the given component. * * @return array */ protected function componentData() { $defaultSlot = new HtmlString(trim(ob_get_clean())); $slots = array_merge([ '__default' => $defaultSlot, ], $this->slots[count($this->componentStack)]); return array_merge( $this->componentData[count($this->componentStack)], ['slot' => $defaultSlot], $this->slots[count($this->componentStack)], ['__laravel_slots' => $slots] ); } /** * Get an item from the component data that exists above the current component. * * @param string $key * @param mixed $default * @return mixed|null */ public function getConsumableComponentData($key, $default = null) { if (array_key_exists($key, $this->currentComponentData)) { return $this->currentComponentData[$key]; } $currentComponent = count($this->componentStack); if ($currentComponent === 0) { return value($default); } for ($i = $currentComponent - 1; $i >= 0; $i--) { $data = $this->componentData[$i] ?? []; if (array_key_exists($key, $data)) { return $data[$key]; } } return value($default); } /** * Start the slot rendering process. * * @param string $name * @param string|null $content * @param array $attributes * @return void */ public function slot($name, $content = null, $attributes = []) { if (func_num_args() === 2 || $content !== null) { $this->slots[$this->currentComponent()][$name] = $content; } elseif (ob_start()) { $this->slots[$this->currentComponent()][$name] = ''; $this->slotStack[$this->currentComponent()][] = [$name, $attributes]; } } /** * Save the slot content for rendering. * * @return void */ public function endSlot() { last($this->componentStack); $currentSlot = array_pop( $this->slotStack[$this->currentComponent()] ); [$currentName, $currentAttributes] = $currentSlot; $this->slots[$this->currentComponent()][$currentName] = new ComponentSlot( trim(ob_get_clean()), $currentAttributes ); } /** * Get the index for the current component. * * @return int */ protected function currentComponent() { return count($this->componentStack) - 1; } /** * Flush all of the component state. * * @return void */ protected function flushComponents() { $this->componentStack = []; $this->componentData = []; $this->currentComponentData = []; } } PKz Zhcr+Illuminate/View/Concerns/ManagesLayouts.phpnuW+AsectionStack[] = $section; } } else { $this->extendSection($section, $content instanceof View ? $content : e($content)); } } /** * Inject inline content into a section. * * @param string $section * @param string $content * @return void */ public function inject($section, $content) { $this->startSection($section, $content); } /** * Stop injecting content into a section and return its contents. * * @return string */ public function yieldSection() { if (empty($this->sectionStack)) { return ''; } return $this->yieldContent($this->stopSection()); } /** * Stop injecting content into a section. * * @param bool $overwrite * @return string * * @throws \InvalidArgumentException */ public function stopSection($overwrite = false) { if (empty($this->sectionStack)) { throw new InvalidArgumentException('Cannot end a section without first starting one.'); } $last = array_pop($this->sectionStack); if ($overwrite) { $this->sections[$last] = ob_get_clean(); } else { $this->extendSection($last, ob_get_clean()); } return $last; } /** * Stop injecting content into a section and append it. * * @return string * * @throws \InvalidArgumentException */ public function appendSection() { if (empty($this->sectionStack)) { throw new InvalidArgumentException('Cannot end a section without first starting one.'); } $last = array_pop($this->sectionStack); if (isset($this->sections[$last])) { $this->sections[$last] .= ob_get_clean(); } else { $this->sections[$last] = ob_get_clean(); } return $last; } /** * Append content to a given section. * * @param string $section * @param string $content * @return void */ protected function extendSection($section, $content) { if (isset($this->sections[$section])) { $content = str_replace(static::parentPlaceholder($section), $content, $this->sections[$section]); } $this->sections[$section] = $content; } /** * Get the string contents of a section. * * @param string $section * @param string $default * @return string */ public function yieldContent($section, $default = '') { $sectionContent = $default instanceof View ? $default : e($default); if (isset($this->sections[$section])) { $sectionContent = $this->sections[$section]; } $sectionContent = str_replace('@@parent', '--parent--holder--', $sectionContent); return str_replace( '--parent--holder--', '@parent', str_replace(static::parentPlaceholder($section), '', $sectionContent) ); } /** * Get the parent placeholder for the current request. * * @param string $section * @return string */ public static function parentPlaceholder($section = '') { if (! isset(static::$parentPlaceholder[$section])) { $salt = static::parentPlaceholderSalt(); static::$parentPlaceholder[$section] = '##parent-placeholder-'.sha1($salt.$section).'##'; } return static::$parentPlaceholder[$section]; } /** * Get the parent placeholder salt. * * @return string */ protected static function parentPlaceholderSalt() { if (! static::$parentPlaceholderSalt) { return static::$parentPlaceholderSalt = Str::random(40); } return static::$parentPlaceholderSalt; } /** * Check if section exists. * * @param string $name * @return bool */ public function hasSection($name) { return array_key_exists($name, $this->sections); } /** * Check if section does not exist. * * @param string $name * @return bool */ public function sectionMissing($name) { return ! $this->hasSection($name); } /** * Get the contents of a section. * * @param string $name * @param string|null $default * @return mixed */ public function getSection($name, $default = null) { return $this->getSections()[$name] ?? $default; } /** * Get the entire array of sections. * * @return array */ public function getSections() { return $this->sections; } /** * Flush all of the sections. * * @return void */ public function flushSections() { $this->sections = []; $this->sectionStack = []; } } PKz Z7*Illuminate/View/Concerns/ManagesStacks.phpnuW+ApushStack[] = $section; } } else { $this->extendPush($section, $content); } } /** * Stop injecting content into a push section. * * @return string * * @throws \InvalidArgumentException */ public function stopPush() { if (empty($this->pushStack)) { throw new InvalidArgumentException('Cannot end a push stack without first starting one.'); } return tap(array_pop($this->pushStack), function ($last) { $this->extendPush($last, ob_get_clean()); }); } /** * Append content to a given push section. * * @param string $section * @param string $content * @return void */ protected function extendPush($section, $content) { if (! isset($this->pushes[$section])) { $this->pushes[$section] = []; } if (! isset($this->pushes[$section][$this->renderCount])) { $this->pushes[$section][$this->renderCount] = $content; } else { $this->pushes[$section][$this->renderCount] .= $content; } } /** * Start prepending content into a push section. * * @param string $section * @param string $content * @return void */ public function startPrepend($section, $content = '') { if ($content === '') { if (ob_start()) { $this->pushStack[] = $section; } } else { $this->extendPrepend($section, $content); } } /** * Stop prepending content into a push section. * * @return string * * @throws \InvalidArgumentException */ public function stopPrepend() { if (empty($this->pushStack)) { throw new InvalidArgumentException('Cannot end a prepend operation without first starting one.'); } return tap(array_pop($this->pushStack), function ($last) { $this->extendPrepend($last, ob_get_clean()); }); } /** * Prepend content to a given stack. * * @param string $section * @param string $content * @return void */ protected function extendPrepend($section, $content) { if (! isset($this->prepends[$section])) { $this->prepends[$section] = []; } if (! isset($this->prepends[$section][$this->renderCount])) { $this->prepends[$section][$this->renderCount] = $content; } else { $this->prepends[$section][$this->renderCount] = $content.$this->prepends[$section][$this->renderCount]; } } /** * Get the string contents of a push section. * * @param string $section * @param string $default * @return string */ public function yieldPushContent($section, $default = '') { if (! isset($this->pushes[$section]) && ! isset($this->prepends[$section])) { return $default; } $output = ''; if (isset($this->prepends[$section])) { $output .= implode(array_reverse($this->prepends[$section])); } if (isset($this->pushes[$section])) { $output .= implode($this->pushes[$section]); } return $output; } /** * Flush all of the stacks. * * @return void */ public function flushStacks() { $this->pushes = []; $this->prepends = []; $this->pushStack = []; } } PKz ZƢ3bb*Illuminate/View/Concerns/ManagesEvents.phpnuW+AaddViewEvent($view, $callback, 'creating: '); } return $creators; } /** * Register multiple view composers via an array. * * @param array $composers * @return array */ public function composers(array $composers) { $registered = []; foreach ($composers as $callback => $views) { $registered = array_merge($registered, $this->composer($views, $callback)); } return $registered; } /** * Register a view composer event. * * @param array|string $views * @param \Closure|string $callback * @return array */ public function composer($views, $callback) { $composers = []; foreach ((array) $views as $view) { $composers[] = $this->addViewEvent($view, $callback); } return $composers; } /** * Add an event for a given view. * * @param string $view * @param \Closure|string $callback * @param string $prefix * @return \Closure|null */ protected function addViewEvent($view, $callback, $prefix = 'composing: ') { $view = $this->normalizeName($view); if ($callback instanceof Closure) { $this->addEventListener($prefix.$view, $callback); return $callback; } elseif (is_string($callback)) { return $this->addClassEvent($view, $callback, $prefix); } } /** * Register a class based view composer. * * @param string $view * @param string $class * @param string $prefix * @return \Closure */ protected function addClassEvent($view, $class, $prefix) { $name = $prefix.$view; // When registering a class based view "composer", we will simply resolve the // classes from the application IoC container then call the compose method // on the instance. This allows for convenient, testable view composers. $callback = $this->buildClassEventCallback( $class, $prefix ); $this->addEventListener($name, $callback); return $callback; } /** * Build a class based container callback Closure. * * @param string $class * @param string $prefix * @return \Closure */ protected function buildClassEventCallback($class, $prefix) { [$class, $method] = $this->parseClassEvent($class, $prefix); // Once we have the class and method name, we can build the Closure to resolve // the instance out of the IoC container and call the method on it with the // given arguments that are passed to the Closure as the composer's data. return function () use ($class, $method) { return $this->container->make($class)->{$method}(...func_get_args()); }; } /** * Parse a class based composer name. * * @param string $class * @param string $prefix * @return array */ protected function parseClassEvent($class, $prefix) { return Str::parseCallback($class, $this->classEventMethodForPrefix($prefix)); } /** * Determine the class event method based on the given prefix. * * @param string $prefix * @return string */ protected function classEventMethodForPrefix($prefix) { return str_contains($prefix, 'composing') ? 'compose' : 'create'; } /** * Add a listener to the event dispatcher. * * @param string $name * @param \Closure $callback * @return void */ protected function addEventListener($name, $callback) { if (str_contains($name, '*')) { $callback = function ($name, array $data) use ($callback) { return $callback($data[0]); }; } $this->events->listen($name, $callback); } /** * Call the composer for a given view. * * @param \Illuminate\Contracts\View\View $view * @return void */ public function callComposer(ViewContract $view) { $this->events->dispatch('composing: '.$view->name(), [$view]); } /** * Call the creator for a given view. * * @param \Illuminate\Contracts\View\View $view * @return void */ public function callCreator(ViewContract $view) { $this->events->dispatch('creating: '.$view->name(), [$view]); } } PKz Z6-Illuminate/View/Concerns/ManagesFragments.phpnuW+AfragmentStack[] = $fragment; } } /** * Stop injecting content into a fragment. * * @return string * * @throws \InvalidArgumentException */ public function stopFragment() { if (empty($this->fragmentStack)) { throw new InvalidArgumentException('Cannot end a fragment without first starting one.'); } $last = array_pop($this->fragmentStack); $this->fragments[$last] = ob_get_clean(); return $this->fragments[$last]; } /** * Get the contents of a fragment. * * @param string $name * @param string|null $default * @return mixed */ public function getFragment($name, $default = null) { return $this->getFragments()[$name] ?? $default; } /** * Get the entire array of rendered fragments. * * @return array */ public function getFragments() { return $this->fragments; } /** * Flush all of the fragments. * * @return void */ public function flushFragments() { $this->fragments = []; $this->fragmentStack = []; } } PKz Zα33Illuminate/View/LICENSE.mdnuW+AThe MIT License (MIT) Copyright (c) Taylor Otwell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PKz Z,q@@!Illuminate/View/ComponentSlot.phpnuW+Acontents = $contents; $this->withAttributes($attributes); } /** * Set the extra attributes that the slot should make available. * * @param array $attributes * @return $this */ public function withAttributes(array $attributes) { $this->attributes = new ComponentAttributeBag($attributes); return $this; } /** * Get the slot's HTML string. * * @return string */ public function toHtml() { return $this->contents; } /** * Determine if the slot is empty. * * @return bool */ public function isEmpty() { return $this->contents === ''; } /** * Determine if the slot is not empty. * * @return bool */ public function isNotEmpty() { return ! $this->isEmpty(); } /** * Get the slot's HTML string. * * @return string */ public function __toString() { return $this->toHtml(); } } PKz Ziqq'Illuminate/View/ViewServiceProvider.phpnuW+AregisterFactory(); $this->registerViewFinder(); $this->registerBladeCompiler(); $this->registerEngineResolver(); $this->app->terminating(static function () { Component::flushCache(); }); } /** * Register the view environment. * * @return void */ public function registerFactory() { $this->app->singleton('view', function ($app) { // Next we need to grab the engine resolver instance that will be used by the // environment. The resolver will be used by an environment to get each of // the various engine implementations such as plain PHP or Blade engine. $resolver = $app['view.engine.resolver']; $finder = $app['view.finder']; $factory = $this->createFactory($resolver, $finder, $app['events']); // We will also set the container instance on this view environment since the // view composers may be classes registered in the container, which allows // for great testable, flexible composers for the application developer. $factory->setContainer($app); $factory->share('app', $app); $app->terminating(static function () { Component::forgetFactory(); }); return $factory; }); } /** * Create a new Factory Instance. * * @param \Illuminate\View\Engines\EngineResolver $resolver * @param \Illuminate\View\ViewFinderInterface $finder * @param \Illuminate\Contracts\Events\Dispatcher $events * @return \Illuminate\View\Factory */ protected function createFactory($resolver, $finder, $events) { return new Factory($resolver, $finder, $events); } /** * Register the view finder implementation. * * @return void */ public function registerViewFinder() { $this->app->bind('view.finder', function ($app) { return new FileViewFinder($app['files'], $app['config']['view.paths']); }); } /** * Register the Blade compiler implementation. * * @return void */ public function registerBladeCompiler() { $this->app->singleton('blade.compiler', function ($app) { return tap(new BladeCompiler( $app['files'], $app['config']['view.compiled'], $app['config']->get('view.relative_hash', false) ? $app->basePath() : '', $app['config']->get('view.cache', true), $app['config']->get('view.compiled_extension', 'php'), ), function ($blade) { $blade->component('dynamic-component', DynamicComponent::class); }); }); } /** * Register the engine resolver instance. * * @return void */ public function registerEngineResolver() { $this->app->singleton('view.engine.resolver', function () { $resolver = new EngineResolver; // Next, we will register the various view engines with the resolver so that the // environment will resolve the engines needed for various views based on the // extension of view file. We call a method for each of the view's engines. foreach (['file', 'php', 'blade'] as $engine) { $this->{'register'.ucfirst($engine).'Engine'}($resolver); } return $resolver; }); } /** * Register the file engine implementation. * * @param \Illuminate\View\Engines\EngineResolver $resolver * @return void */ public function registerFileEngine($resolver) { $resolver->register('file', function () { return new FileEngine($this->app['files']); }); } /** * Register the PHP engine implementation. * * @param \Illuminate\View\Engines\EngineResolver $resolver * @return void */ public function registerPhpEngine($resolver) { $resolver->register('php', function () { return new PhpEngine($this->app['files']); }); } /** * Register the Blade engine implementation. * * @param \Illuminate\View\Engines\EngineResolver $resolver * @return void */ public function registerBladeEngine($resolver) { $resolver->register('blade', function () { $compiler = new CompilerEngine($this->app['blade.compiler'], $this->app['files']); $this->app->terminating(static function () use ($compiler) { $compiler->forgetCompiledOrNotExpired(); }); return $compiler; }); } } PKz Z\$Illuminate/View/DynamicComponent.phpnuW+Acomponent = $component; } /** * Get the view / contents that represent the component. * * @return \Illuminate\Contracts\View\View|string */ public function render() { $template = <<<'EOF' getAttributes())->mapWithKeys(function ($value, $key) { return [Illuminate\Support\Str::camel(str_replace([':', '.'], ' ', $key)) => $value]; })->all(), EXTR_SKIP); ?> {{ props }} {{ slots }} {{ defaultSlot }} EOF; return function ($data) use ($template) { $bindings = $this->bindings($class = $this->classForComponent()); return str_replace( [ '{{ component }}', '{{ props }}', '{{ bindings }}', '{{ attributes }}', '{{ slots }}', '{{ defaultSlot }}', ], [ $this->component, $this->compileProps($bindings), $this->compileBindings($bindings), class_exists($class) ? '{{ $attributes }}' : '', $this->compileSlots($data['__laravel_slots']), '{{ $slot ?? "" }}', ], $template ); }; } /** * Compile the @props directive for the component. * * @param array $bindings * @return string */ protected function compileProps(array $bindings) { if (empty($bindings)) { return ''; } return '@props('.'[\''.implode('\',\'', collect($bindings)->map(function ($dataKey) { return Str::camel($dataKey); })->all()).'\']'.')'; } /** * Compile the bindings for the component. * * @param array $bindings * @return string */ protected function compileBindings(array $bindings) { return collect($bindings)->map(function ($key) { return ':'.$key.'="$'.Str::camel(str_replace([':', '.'], ' ', $key)).'"'; })->implode(' '); } /** * Compile the slots for the component. * * @param array $slots * @return string */ protected function compileSlots(array $slots) { return collect($slots)->map(function ($slot, $name) { return $name === '__default' ? null : 'attributes).'>{{ $'.$name.' }}'; })->filter()->implode(PHP_EOL); } /** * Get the class for the current component. * * @return string */ protected function classForComponent() { if (isset(static::$componentClasses[$this->component])) { return static::$componentClasses[$this->component]; } return static::$componentClasses[$this->component] = $this->compiler()->componentClass($this->component); } /** * Get the names of the variables that should be bound to the component. * * @param string $class * @return array */ protected function bindings(string $class) { [$data, $attributes] = $this->compiler()->partitionDataAndAttributes($class, $this->attributes->getAttributes()); return array_keys($data->all()); } /** * Get an instance of the Blade tag compiler. * * @return \Illuminate\View\Compilers\ComponentTagCompiler */ protected function compiler() { if (! static::$compiler) { static::$compiler = new ComponentTagCompiler( Container::getInstance()->make('blade.compiler')->getClassComponentAliases(), Container::getInstance()->make('blade.compiler')->getClassComponentNamespaces(), Container::getInstance()->make('blade.compiler') ); } return static::$compiler; } } PKz Z<+q]]"Illuminate/View/FileViewFinder.phpnuW+Afiles = $files; $this->paths = array_map([$this, 'resolvePath'], $paths); if (isset($extensions)) { $this->extensions = $extensions; } } /** * Get the fully qualified location of the view. * * @param string $name * @return string */ public function find($name) { if (isset($this->views[$name])) { return $this->views[$name]; } if ($this->hasHintInformation($name = trim($name))) { return $this->views[$name] = $this->findNamespacedView($name); } return $this->views[$name] = $this->findInPaths($name, $this->paths); } /** * Get the path to a template with a named path. * * @param string $name * @return string */ protected function findNamespacedView($name) { [$namespace, $view] = $this->parseNamespaceSegments($name); return $this->findInPaths($view, $this->hints[$namespace]); } /** * Get the segments of a template with a named path. * * @param string $name * @return array * * @throws \InvalidArgumentException */ protected function parseNamespaceSegments($name) { $segments = explode(static::HINT_PATH_DELIMITER, $name); if (count($segments) !== 2) { throw new InvalidArgumentException("View [{$name}] has an invalid name."); } if (! isset($this->hints[$segments[0]])) { throw new InvalidArgumentException("No hint path defined for [{$segments[0]}]."); } return $segments; } /** * Find the given view in the list of paths. * * @param string $name * @param array $paths * @return string * * @throws \InvalidArgumentException */ protected function findInPaths($name, $paths) { foreach ((array) $paths as $path) { foreach ($this->getPossibleViewFiles($name) as $file) { if ($this->files->exists($viewPath = $path.'/'.$file)) { return $viewPath; } } } throw new InvalidArgumentException("View [{$name}] not found."); } /** * Get an array of possible view files. * * @param string $name * @return array */ protected function getPossibleViewFiles($name) { return array_map(fn ($extension) => str_replace('.', '/', $name).'.'.$extension, $this->extensions); } /** * Add a location to the finder. * * @param string $location * @return void */ public function addLocation($location) { $this->paths[] = $this->resolvePath($location); } /** * Prepend a location to the finder. * * @param string $location * @return void */ public function prependLocation($location) { array_unshift($this->paths, $this->resolvePath($location)); } /** * Resolve the path. * * @param string $path * @return string */ protected function resolvePath($path) { return realpath($path) ?: $path; } /** * Add a namespace hint to the finder. * * @param string $namespace * @param string|array $hints * @return void */ public function addNamespace($namespace, $hints) { $hints = (array) $hints; if (isset($this->hints[$namespace])) { $hints = array_merge($this->hints[$namespace], $hints); } $this->hints[$namespace] = $hints; } /** * Prepend a namespace hint to the finder. * * @param string $namespace * @param string|array $hints * @return void */ public function prependNamespace($namespace, $hints) { $hints = (array) $hints; if (isset($this->hints[$namespace])) { $hints = array_merge($hints, $this->hints[$namespace]); } $this->hints[$namespace] = $hints; } /** * Replace the namespace hints for the given namespace. * * @param string $namespace * @param string|array $hints * @return void */ public function replaceNamespace($namespace, $hints) { $this->hints[$namespace] = (array) $hints; } /** * Register an extension with the view finder. * * @param string $extension * @return void */ public function addExtension($extension) { if (($index = array_search($extension, $this->extensions)) !== false) { unset($this->extensions[$index]); } array_unshift($this->extensions, $extension); } /** * Returns whether or not the view name has any hint information. * * @param string $name * @return bool */ public function hasHintInformation($name) { return strpos($name, static::HINT_PATH_DELIMITER) > 0; } /** * Flush the cache of located views. * * @return void */ public function flush() { $this->views = []; } /** * Get the filesystem instance. * * @return \Illuminate\Filesystem\Filesystem */ public function getFilesystem() { return $this->files; } /** * Set the active view paths. * * @param array $paths * @return $this */ public function setPaths($paths) { $this->paths = $paths; return $this; } /** * Get the active view paths. * * @return array */ public function getPaths() { return $this->paths; } /** * Get the views that have been located. * * @return array */ public function getViews() { return $this->views; } /** * Get the namespace to file path hints. * * @return array */ public function getHints() { return $this->hints; } /** * Get registered extensions. * * @return array */ public function getExtensions() { return $this->extensions; } } PKz ZѠc!Illuminate/View/ViewException.phpnuW+AgetPrevious(); if (Reflector::isCallable($reportCallable = [$exception, 'report'])) { return Container::getInstance()->call($reportCallable); } return false; } /** * Render the exception into an HTTP response. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response|null */ public function render($request) { $exception = $this->getPrevious(); if ($exception && method_exists($exception, 'render')) { return $exception->render($request); } } } PKz ZHt;'y:y:Illuminate/View/Factory.phpnuW+A 'blade', 'php' => 'php', 'css' => 'file', 'html' => 'file', ]; /** * The view composer events. * * @var array */ protected $composers = []; /** * The number of active rendering operations. * * @var int */ protected $renderCount = 0; /** * The "once" block IDs that have been rendered. * * @var array */ protected $renderedOnce = []; /** * Create a new view factory instance. * * @param \Illuminate\View\Engines\EngineResolver $engines * @param \Illuminate\View\ViewFinderInterface $finder * @param \Illuminate\Contracts\Events\Dispatcher $events * @return void */ public function __construct(EngineResolver $engines, ViewFinderInterface $finder, Dispatcher $events) { $this->finder = $finder; $this->events = $events; $this->engines = $engines; $this->share('__env', $this); } /** * Get the evaluated view contents for the given view. * * @param string $path * @param \Illuminate\Contracts\Support\Arrayable|array $data * @param array $mergeData * @return \Illuminate\Contracts\View\View */ public function file($path, $data = [], $mergeData = []) { $data = array_merge($mergeData, $this->parseData($data)); return tap($this->viewInstance($path, $path, $data), function ($view) { $this->callCreator($view); }); } /** * Get the evaluated view contents for the given view. * * @param string $view * @param \Illuminate\Contracts\Support\Arrayable|array $data * @param array $mergeData * @return \Illuminate\Contracts\View\View */ public function make($view, $data = [], $mergeData = []) { $path = $this->finder->find( $view = $this->normalizeName($view) ); // Next, we will create the view instance and call the view creator for the view // which can set any data, etc. Then we will return the view instance back to // the caller for rendering or performing other view manipulations on this. $data = array_merge($mergeData, $this->parseData($data)); return tap($this->viewInstance($view, $path, $data), function ($view) { $this->callCreator($view); }); } /** * Get the first view that actually exists from the given list. * * @param array $views * @param \Illuminate\Contracts\Support\Arrayable|array $data * @param array $mergeData * @return \Illuminate\Contracts\View\View * * @throws \InvalidArgumentException */ public function first(array $views, $data = [], $mergeData = []) { $view = Arr::first($views, function ($view) { return $this->exists($view); }); if (! $view) { throw new InvalidArgumentException('None of the views in the given array exist.'); } return $this->make($view, $data, $mergeData); } /** * Get the rendered content of the view based on a given condition. * * @param bool $condition * @param string $view * @param \Illuminate\Contracts\Support\Arrayable|array $data * @param array $mergeData * @return string */ public function renderWhen($condition, $view, $data = [], $mergeData = []) { if (! $condition) { return ''; } return $this->make($view, $this->parseData($data), $mergeData)->render(); } /** * Get the rendered content of the view based on the negation of a given condition. * * @param bool $condition * @param string $view * @param \Illuminate\Contracts\Support\Arrayable|array $data * @param array $mergeData * @return string */ public function renderUnless($condition, $view, $data = [], $mergeData = []) { return $this->renderWhen(! $condition, $view, $data, $mergeData); } /** * Get the rendered contents of a partial from a loop. * * @param string $view * @param array $data * @param string $iterator * @param string $empty * @return string */ public function renderEach($view, $data, $iterator, $empty = 'raw|') { $result = ''; // If is actually data in the array, we will loop through the data and append // an instance of the partial view to the final result HTML passing in the // iterated value of this data array, allowing the views to access them. if (count($data) > 0) { foreach ($data as $key => $value) { $result .= $this->make( $view, ['key' => $key, $iterator => $value] )->render(); } } // If there is no data in the array, we will render the contents of the empty // view. Alternatively, the "empty view" could be a raw string that begins // with "raw|" for convenience and to let this know that it is a string. else { $result = str_starts_with($empty, 'raw|') ? substr($empty, 4) : $this->make($empty)->render(); } return $result; } /** * Normalize a view name. * * @param string $name * @return string */ protected function normalizeName($name) { return ViewName::normalize($name); } /** * Parse the given data into a raw array. * * @param mixed $data * @return array */ protected function parseData($data) { return $data instanceof Arrayable ? $data->toArray() : $data; } /** * Create a new view instance from the given arguments. * * @param string $view * @param string $path * @param \Illuminate\Contracts\Support\Arrayable|array $data * @return \Illuminate\Contracts\View\View */ protected function viewInstance($view, $path, $data) { return new View($this, $this->getEngineFromPath($path), $view, $path, $data); } /** * Determine if a given view exists. * * @param string $view * @return bool */ public function exists($view) { try { $this->finder->find($view); } catch (InvalidArgumentException $e) { return false; } return true; } /** * Get the appropriate view engine for the given path. * * @param string $path * @return \Illuminate\Contracts\View\Engine * * @throws \InvalidArgumentException */ public function getEngineFromPath($path) { if (! $extension = $this->getExtension($path)) { throw new InvalidArgumentException("Unrecognized extension in file: {$path}."); } $engine = $this->extensions[$extension]; return $this->engines->resolve($engine); } /** * Get the extension used by the view file. * * @param string $path * @return string|null */ protected function getExtension($path) { $extensions = array_keys($this->extensions); return Arr::first($extensions, function ($value) use ($path) { return str_ends_with($path, '.'.$value); }); } /** * Add a piece of shared data to the environment. * * @param array|string $key * @param mixed|null $value * @return mixed */ public function share($key, $value = null) { $keys = is_array($key) ? $key : [$key => $value]; foreach ($keys as $key => $value) { $this->shared[$key] = $value; } return $value; } /** * Increment the rendering counter. * * @return void */ public function incrementRender() { $this->renderCount++; } /** * Decrement the rendering counter. * * @return void */ public function decrementRender() { $this->renderCount--; } /** * Check if there are no active render operations. * * @return bool */ public function doneRendering() { return $this->renderCount == 0; } /** * Determine if the given once token has been rendered. * * @param string $id * @return bool */ public function hasRenderedOnce(string $id) { return isset($this->renderedOnce[$id]); } /** * Mark the given once token as having been rendered. * * @param string $id * @return void */ public function markAsRenderedOnce(string $id) { $this->renderedOnce[$id] = true; } /** * Add a location to the array of view locations. * * @param string $location * @return void */ public function addLocation($location) { $this->finder->addLocation($location); } /** * Add a new namespace to the loader. * * @param string $namespace * @param string|array $hints * @return $this */ public function addNamespace($namespace, $hints) { $this->finder->addNamespace($namespace, $hints); return $this; } /** * Prepend a new namespace to the loader. * * @param string $namespace * @param string|array $hints * @return $this */ public function prependNamespace($namespace, $hints) { $this->finder->prependNamespace($namespace, $hints); return $this; } /** * Replace the namespace hints for the given namespace. * * @param string $namespace * @param string|array $hints * @return $this */ public function replaceNamespace($namespace, $hints) { $this->finder->replaceNamespace($namespace, $hints); return $this; } /** * Register a valid view extension and its engine. * * @param string $extension * @param string $engine * @param \Closure|null $resolver * @return void */ public function addExtension($extension, $engine, $resolver = null) { $this->finder->addExtension($extension); if (isset($resolver)) { $this->engines->register($engine, $resolver); } unset($this->extensions[$extension]); $this->extensions = array_merge([$extension => $engine], $this->extensions); } /** * Flush all of the factory state like sections and stacks. * * @return void */ public function flushState() { $this->renderCount = 0; $this->renderedOnce = []; $this->flushSections(); $this->flushStacks(); $this->flushComponents(); $this->flushFragments(); } /** * Flush all of the section contents if done rendering. * * @return void */ public function flushStateIfDoneRendering() { if ($this->doneRendering()) { $this->flushState(); } } /** * Get the extension to engine bindings. * * @return array */ public function getExtensions() { return $this->extensions; } /** * Get the engine resolver instance. * * @return \Illuminate\View\Engines\EngineResolver */ public function getEngineResolver() { return $this->engines; } /** * Get the view finder instance. * * @return \Illuminate\View\ViewFinderInterface */ public function getFinder() { return $this->finder; } /** * Set the view finder instance. * * @param \Illuminate\View\ViewFinderInterface $finder * @return void */ public function setFinder(ViewFinderInterface $finder) { $this->finder = $finder; } /** * Flush the cache of views located by the finder. * * @return void */ public function flushFinderCache() { $this->getFinder()->flush(); } /** * Get the event dispatcher instance. * * @return \Illuminate\Contracts\Events\Dispatcher */ public function getDispatcher() { return $this->events; } /** * Set the event dispatcher instance. * * @param \Illuminate\Contracts\Events\Dispatcher $events * @return void */ public function setDispatcher(Dispatcher $events) { $this->events = $events; } /** * Get the IoC container instance. * * @return \Illuminate\Contracts\Container\Container */ public function getContainer() { return $this->container; } /** * Set the IoC container instance. * * @param \Illuminate\Contracts\Container\Container $container * @return void */ public function setContainer(Container $container) { $this->container = $container; } /** * Get an item from the shared data. * * @param string $key * @param mixed $default * @return mixed */ public function shared($key, $default = null) { return Arr::get($this->shared, $key, $default); } /** * Get all of the shared data for the environment. * * @return array */ public function getShared() { return $this->shared; } } PKz ZzU++)Illuminate/View/ComponentAttributeBag.phpnuW+Aattributes = $attributes; } /** * Get the first attribute's value. * * @param mixed $default * @return mixed */ public function first($default = null) { return $this->getIterator()->current() ?? value($default); } /** * Get a given attribute from the attribute array. * * @param string $key * @param mixed $default * @return mixed */ public function get($key, $default = null) { return $this->attributes[$key] ?? value($default); } /** * Determine if a given attribute exists in the attribute array. * * @param string $key * @return bool */ public function has($key) { return array_key_exists($key, $this->attributes); } /** * Determine if a given attribute is missing from the attribute array. * * @param string $key * @return bool */ public function missing($key) { return ! $this->has($key, $this->attributes); } /** * Only include the given attribute from the attribute array. * * @param mixed $keys * @return static */ public function only($keys) { if (is_null($keys)) { $values = $this->attributes; } else { $keys = Arr::wrap($keys); $values = Arr::only($this->attributes, $keys); } return new static($values); } /** * Exclude the given attribute from the attribute array. * * @param mixed|array $keys * @return static */ public function except($keys) { if (is_null($keys)) { $values = $this->attributes; } else { $keys = Arr::wrap($keys); $values = Arr::except($this->attributes, $keys); } return new static($values); } /** * Filter the attributes, returning a bag of attributes that pass the filter. * * @param callable $callback * @return static */ public function filter($callback) { return new static(collect($this->attributes)->filter($callback)->all()); } /** * Return a bag of attributes that have keys starting with the given value / pattern. * * @param string|string[] $needles * @return static */ public function whereStartsWith($needles) { return $this->filter(function ($value, $key) use ($needles) { return Str::startsWith($key, $needles); }); } /** * Return a bag of attributes with keys that do not start with the given value / pattern. * * @param string|string[] $needles * @return static */ public function whereDoesntStartWith($needles) { return $this->filter(function ($value, $key) use ($needles) { return ! Str::startsWith($key, $needles); }); } /** * Return a bag of attributes that have keys starting with the given value / pattern. * * @param string|string[] $needles * @return static */ public function thatStartWith($needles) { return $this->whereStartsWith($needles); } /** * Only include the given attribute from the attribute array. * * @param mixed|array $keys * @return static */ public function onlyProps($keys) { return $this->only($this->extractPropNames($keys)); } /** * Exclude the given attribute from the attribute array. * * @param mixed|array $keys * @return static */ public function exceptProps($keys) { return $this->except($this->extractPropNames($keys)); } /** * Extract prop names from given keys. * * @param mixed|array $keys * @return array */ protected function extractPropNames($keys) { $props = []; foreach ($keys as $key => $defaultValue) { $key = is_numeric($key) ? $defaultValue : $key; $props[] = $key; $props[] = Str::kebab($key); } return $props; } /** * Conditionally merge classes into the attribute bag. * * @param mixed|array $classList * @return static */ public function class($classList) { $classList = Arr::wrap($classList); return $this->merge(['class' => Arr::toCssClasses($classList)]); } /** * Conditionally merge styles into the attribute bag. * * @param mixed|array $styleList * @return static */ public function style($styleList) { $styleList = Arr::wrap($styleList); return $this->merge(['style' => Arr::toCssStyles($styleList)]); } /** * Merge additional attributes / values into the attribute bag. * * @param array $attributeDefaults * @param bool $escape * @return static */ public function merge(array $attributeDefaults = [], $escape = true) { $attributeDefaults = array_map(function ($value) use ($escape) { return $this->shouldEscapeAttributeValue($escape, $value) ? e($value) : $value; }, $attributeDefaults); [$appendableAttributes, $nonAppendableAttributes] = collect($this->attributes) ->partition(function ($value, $key) use ($attributeDefaults) { return $key === 'class' || $key === 'style' || ( isset($attributeDefaults[$key]) && $attributeDefaults[$key] instanceof AppendableAttributeValue ); }); $attributes = $appendableAttributes->mapWithKeys(function ($value, $key) use ($attributeDefaults, $escape) { $defaultsValue = isset($attributeDefaults[$key]) && $attributeDefaults[$key] instanceof AppendableAttributeValue ? $this->resolveAppendableAttributeDefault($attributeDefaults, $key, $escape) : ($attributeDefaults[$key] ?? ''); if ($key === 'style') { $value = Str::finish($value, ';'); } return [$key => implode(' ', array_unique(array_filter([$defaultsValue, $value])))]; })->merge($nonAppendableAttributes)->all(); return new static(array_merge($attributeDefaults, $attributes)); } /** * Determine if the specific attribute value should be escaped. * * @param bool $escape * @param mixed $value * @return bool */ protected function shouldEscapeAttributeValue($escape, $value) { if (! $escape) { return false; } return ! is_object($value) && ! is_null($value) && ! is_bool($value); } /** * Create a new appendable attribute value. * * @param mixed $value * @return \Illuminate\View\AppendableAttributeValue */ public function prepends($value) { return new AppendableAttributeValue($value); } /** * Resolve an appendable attribute value default value. * * @param array $attributeDefaults * @param string $key * @param bool $escape * @return mixed */ protected function resolveAppendableAttributeDefault($attributeDefaults, $key, $escape) { if ($this->shouldEscapeAttributeValue($escape, $value = $attributeDefaults[$key]->value)) { $value = e($value); } return $value; } /** * Get all of the raw attributes. * * @return array */ public function getAttributes() { return $this->attributes; } /** * Set the underlying attributes. * * @param array $attributes * @return void */ public function setAttributes(array $attributes) { if (isset($attributes['attributes']) && $attributes['attributes'] instanceof self) { $parentBag = $attributes['attributes']; unset($attributes['attributes']); $attributes = $parentBag->merge($attributes, $escape = false)->getAttributes(); } $this->attributes = $attributes; } /** * Get content as a string of HTML. * * @return string */ public function toHtml() { return (string) $this; } /** * Merge additional attributes / values into the attribute bag. * * @param array $attributeDefaults * @return \Illuminate\Support\HtmlString */ public function __invoke(array $attributeDefaults = []) { return new HtmlString((string) $this->merge($attributeDefaults)); } /** * Determine if the given offset exists. * * @param string $offset * @return bool */ public function offsetExists($offset): bool { return isset($this->attributes[$offset]); } /** * Get the value at the given offset. * * @param string $offset * @return mixed */ public function offsetGet($offset): mixed { return $this->get($offset); } /** * Set the value at a given offset. * * @param string $offset * @param mixed $value * @return void */ public function offsetSet($offset, $value): void { $this->attributes[$offset] = $value; } /** * Remove the value at the given offset. * * @param string $offset * @return void */ public function offsetUnset($offset): void { unset($this->attributes[$offset]); } /** * Get an iterator for the items. * * @return \ArrayIterator */ public function getIterator(): Traversable { return new ArrayIterator($this->attributes); } /** * Implode the attributes into a single HTML ready string. * * @return string */ public function __toString() { $string = ''; foreach ($this->attributes as $key => $value) { if ($value === false || is_null($value)) { continue; } if ($value === true) { $value = $key; } $string .= ' '.$key.'="'.str_replace('"', '\\"', trim($value)).'"'; } return trim($string); } } PKz ZgxQ..Illuminate/View/Component.phpnuW+A */ protected static $bladeViewCache = []; /** * The cache of public property names, keyed by class. * * @var array */ protected static $propertyCache = []; /** * The cache of public method names, keyed by class. * * @var array */ protected static $methodCache = []; /** * The cache of constructor parameters, keyed by class. * * @var array> */ protected static $constructorParametersCache = []; /** * Get the view / view contents that represent the component. * * @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\Support\Htmlable|\Closure|string */ abstract public function render(); /** * Resolve the component instance with the given data. * * @param array $data * @return static */ public static function resolve($data) { if (static::$componentsResolver) { return call_user_func(static::$componentsResolver, static::class, $data); } $parameters = static::extractConstructorParameters(); $dataKeys = array_keys($data); if (empty(array_diff($parameters, $dataKeys))) { return new static(...array_intersect_key($data, array_flip($parameters))); } return Container::getInstance()->make(static::class, $data); } /** * Extract the constructor parameters for the component. * * @return array */ protected static function extractConstructorParameters() { if (! isset(static::$constructorParametersCache[static::class])) { $class = new ReflectionClass(static::class); $constructor = $class->getConstructor(); static::$constructorParametersCache[static::class] = $constructor ? collect($constructor->getParameters())->map->getName()->all() : []; } return static::$constructorParametersCache[static::class]; } /** * Resolve the Blade view or view file that should be used when rendering the component. * * @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\Support\Htmlable|\Closure|string */ public function resolveView() { $view = $this->render(); if ($view instanceof ViewContract) { return $view; } if ($view instanceof Htmlable) { return $view; } $resolver = function ($view) { return $this->extractBladeViewFromString($view); }; return $view instanceof Closure ? function (array $data = []) use ($view, $resolver) { return $resolver($view($data)); } : $resolver($view); } /** * Create a Blade view with the raw component string content. * * @param string $contents * @return string */ protected function extractBladeViewFromString($contents) { $key = sprintf('%s::%s', static::class, $contents); if (isset(static::$bladeViewCache[$key])) { return static::$bladeViewCache[$key]; } if (strlen($contents) <= PHP_MAXPATHLEN && $this->factory()->exists($contents)) { return static::$bladeViewCache[$key] = $contents; } return static::$bladeViewCache[$key] = $this->createBladeViewFromString($this->factory(), $contents); } /** * Create a Blade view with the raw component string content. * * @param \Illuminate\Contracts\View\Factory $factory * @param string $contents * @return string */ protected function createBladeViewFromString($factory, $contents) { $factory->addNamespace( '__components', $directory = Container::getInstance()['config']->get('view.compiled') ); if (! is_file($viewFile = $directory.'/'.sha1($contents).'.blade.php')) { if (! is_dir($directory)) { mkdir($directory, 0755, true); } file_put_contents($viewFile, $contents); } return '__components::'.basename($viewFile, '.blade.php'); } /** * Get the data that should be supplied to the view. * * @author Freek Van der Herten * @author Brent Roose * * @return array */ public function data() { $this->attributes = $this->attributes ?: $this->newAttributeBag(); return array_merge($this->extractPublicProperties(), $this->extractPublicMethods()); } /** * Extract the public properties for the component. * * @return array */ protected function extractPublicProperties() { $class = get_class($this); if (! isset(static::$propertyCache[$class])) { $reflection = new ReflectionClass($this); static::$propertyCache[$class] = collect($reflection->getProperties(ReflectionProperty::IS_PUBLIC)) ->reject(function (ReflectionProperty $property) { return $property->isStatic(); }) ->reject(function (ReflectionProperty $property) { return $this->shouldIgnore($property->getName()); }) ->map(function (ReflectionProperty $property) { return $property->getName(); })->all(); } $values = []; foreach (static::$propertyCache[$class] as $property) { $values[$property] = $this->{$property}; } return $values; } /** * Extract the public methods for the component. * * @return array */ protected function extractPublicMethods() { $class = get_class($this); if (! isset(static::$methodCache[$class])) { $reflection = new ReflectionClass($this); static::$methodCache[$class] = collect($reflection->getMethods(ReflectionMethod::IS_PUBLIC)) ->reject(function (ReflectionMethod $method) { return $this->shouldIgnore($method->getName()); }) ->map(function (ReflectionMethod $method) { return $method->getName(); }); } $values = []; foreach (static::$methodCache[$class] as $method) { $values[$method] = $this->createVariableFromMethod(new ReflectionMethod($this, $method)); } return $values; } /** * Create a callable variable from the given method. * * @param \ReflectionMethod $method * @return mixed */ protected function createVariableFromMethod(ReflectionMethod $method) { return $method->getNumberOfParameters() === 0 ? $this->createInvokableVariable($method->getName()) : Closure::fromCallable([$this, $method->getName()]); } /** * Create an invokable, toStringable variable for the given component method. * * @param string $method * @return \Illuminate\View\InvokableComponentVariable */ protected function createInvokableVariable(string $method) { return new InvokableComponentVariable(function () use ($method) { return $this->{$method}(); }); } /** * Determine if the given property / method should be ignored. * * @param string $name * @return bool */ protected function shouldIgnore($name) { return str_starts_with($name, '__') || in_array($name, $this->ignoredMethods()); } /** * Get the methods that should be ignored. * * @return array */ protected function ignoredMethods() { return array_merge([ 'data', 'render', 'resolveView', 'shouldRender', 'view', 'withName', 'withAttributes', ], $this->except); } /** * Set the component alias name. * * @param string $name * @return $this */ public function withName($name) { $this->componentName = $name; return $this; } /** * Set the extra attributes that the component should make available. * * @param array $attributes * @return $this */ public function withAttributes(array $attributes) { $this->attributes = $this->attributes ?: $this->newAttributeBag(); $this->attributes->setAttributes($attributes); return $this; } /** * Get a new attribute bag instance. * * @param array $attributes * @return \Illuminate\View\ComponentAttributeBag */ protected function newAttributeBag(array $attributes = []) { return new ComponentAttributeBag($attributes); } /** * Determine if the component should be rendered. * * @return bool */ public function shouldRender() { return true; } /** * Get the evaluated view contents for the given view. * * @param string|null $view * @param \Illuminate\Contracts\Support\Arrayable|array $data * @param array $mergeData * @return \Illuminate\Contracts\View\View */ public function view($view, $data = [], $mergeData = []) { return $this->factory()->make($view, $data, $mergeData); } /** * Get the view factory instance. * * @return \Illuminate\Contracts\View\Factory */ protected function factory() { if (is_null(static::$factory)) { static::$factory = Container::getInstance()->make('view'); } return static::$factory; } /** * Flush the component's cached state. * * @return void */ public static function flushCache() { static::$bladeViewCache = []; static::$constructorParametersCache = []; static::$methodCache = []; static::$propertyCache = []; } /** * Forget the component's factory instance. * * @return void */ public static function forgetFactory() { static::$factory = null; } /** * Forget the component's resolver callback. * * @return void * * @internal */ public static function forgetComponentsResolver() { static::$componentsResolver = null; } /** * Set the callback that should be used to resolve components within views. * * @param \Closure(string $component, array $data): Component $resolver * @return void * * @internal */ public static function resolveComponentsUsing($resolver) { static::$componentsResolver = $resolver; } } PKz Z(5Illuminate/View/Middleware/ShareErrorsFromSession.phpnuW+Aview = $view; } /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { // If the current session has an "errors" variable bound to it, we will share // its value with all view instances so the views can easily access errors // without having to bind. An empty bag is set when there aren't errors. $this->view->share( 'errors', $request->session()->get('errors') ?: new ViewErrorBag ); // Putting the errors in the view for every view allows the developer to just // assume that some errors are always available, which is convenient since // they don't have to continually run checks for the presence of errors. return $next($request); } } PKz ZXј.Illuminate/View/InvokableComponentVariable.phpnuW+Acallable = $callable; } /** * Resolve the displayable value that the class is deferring. * * @return \Illuminate\Contracts\Support\Htmlable|string */ public function resolveDisplayableValue() { return $this->__invoke(); } /** * Get an interator instance for the variable. * * @return \ArrayIterator */ public function getIterator(): Traversable { $result = $this->__invoke(); return new ArrayIterator($result instanceof Enumerable ? $result->all() : $result); } /** * Dynamically proxy attribute access to the variable. * * @param string $key * @return mixed */ public function __get($key) { return $this->__invoke()->{$key}; } /** * Dynamically proxy method access to the variable. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { return $this->__invoke()->{$method}(...$parameters); } /** * Resolve the variable. * * @return mixed */ public function __invoke() { return call_user_func($this->callable); } /** * Resolve the variable as a string. * * @return mixed */ public function __toString() { return (string) $this->__invoke(); } } PKz Z:&Illuminate/View/AnonymousComponent.phpnuW+Aview = $view; $this->data = $data; } /** * Get the view / view contents that represent the component. * * @return string */ public function render() { return $this->view; } /** * Get the data that should be supplied to the view. * * @return array */ public function data() { $this->attributes = $this->attributes ?: $this->newAttributeBag(); return array_merge( ($this->data['attributes'] ?? null)?->getAttributes() ?: [], $this->attributes->getAttributes(), $this->data, ['attributes' => $this->attributes] ); } } PKz ZGjIlluminate/View/composer.jsonnuW+A{ "name": "illuminate/view", "description": "The Illuminate View package.", "license": "MIT", "homepage": "https://laravel.com", "support": { "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, "authors": [ { "name": "Taylor Otwell", "email": "taylor@laravel.com" } ], "require": { "php": "^8.0.2", "ext-tokenizer": "*", "illuminate/collections": "^9.0", "illuminate/container": "^9.0", "illuminate/contracts": "^9.0", "illuminate/events": "^9.0", "illuminate/filesystem": "^9.0", "illuminate/macroable": "^9.0", "illuminate/support": "^9.0" }, "autoload": { "psr-4": { "Illuminate\\View\\": "" } }, "extra": { "branch-alias": { "dev-master": "9.x-dev" } }, "config": { "sort-packages": true }, "minimum-stability": "dev" } PKz ZHUC,Illuminate/View/AppendableAttributeValue.phpnuW+Avalue = $value; } /** * Get the string value. * * @return string */ public function __toString() { return (string) $this->value; } } PKz ZI  Illuminate/View/ViewName.phpnuW+Aapp->singleton( PipelineHubContract::class, Hub::class ); } /** * Get the services provided by the provider. * * @return array */ public function provides() { return [ PipelineHubContract::class, ]; } } PKz Zα33Illuminate/Pipeline/LICENSE.mdnuW+AThe MIT License (MIT) Copyright (c) Taylor Otwell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PKz ZRCCIlluminate/Pipeline/Hub.phpnuW+Acontainer = $container; } /** * Define the default named pipeline. * * @param \Closure $callback * @return void */ public function defaults(Closure $callback) { return $this->pipeline('default', $callback); } /** * Define a new named pipeline. * * @param string $name * @param \Closure $callback * @return void */ public function pipeline($name, Closure $callback) { $this->pipelines[$name] = $callback; } /** * Send an object through one of the available pipelines. * * @param mixed $object * @param string|null $pipeline * @return mixed */ public function pipe($object, $pipeline = null) { $pipeline = $pipeline ?: 'default'; return call_user_func( $this->pipelines[$pipeline], new Pipeline($this->container), $object ); } /** * Get the container instance used by the hub. * * @return \Illuminate\Contracts\Container\Container */ public function getContainer() { return $this->container; } /** * Set the container instance used by the hub. * * @param \Illuminate\Contracts\Container\Container $container * @return $this */ public function setContainer(Container $container) { $this->container = $container; return $this; } } PKz Zk Illuminate/Pipeline/Pipeline.phpnuW+Acontainer = $container; } /** * Set the object being sent through the pipeline. * * @param mixed $passable * @return $this */ public function send($passable) { $this->passable = $passable; return $this; } /** * Set the array of pipes. * * @param array|mixed $pipes * @return $this */ public function through($pipes) { $this->pipes = is_array($pipes) ? $pipes : func_get_args(); return $this; } /** * Push additional pipes onto the pipeline. * * @param array|mixed $pipes * @return $this */ public function pipe($pipes) { array_push($this->pipes, ...(is_array($pipes) ? $pipes : func_get_args())); return $this; } /** * Set the method to call on the pipes. * * @param string $method * @return $this */ public function via($method) { $this->method = $method; return $this; } /** * Run the pipeline with a final destination callback. * * @param \Closure $destination * @return mixed */ public function then(Closure $destination) { $pipeline = array_reduce( array_reverse($this->pipes()), $this->carry(), $this->prepareDestination($destination) ); return $pipeline($this->passable); } /** * Run the pipeline and return the result. * * @return mixed */ public function thenReturn() { return $this->then(function ($passable) { return $passable; }); } /** * Get the final piece of the Closure onion. * * @param \Closure $destination * @return \Closure */ protected function prepareDestination(Closure $destination) { return function ($passable) use ($destination) { try { return $destination($passable); } catch (Throwable $e) { return $this->handleException($passable, $e); } }; } /** * Get a Closure that represents a slice of the application onion. * * @return \Closure */ protected function carry() { return function ($stack, $pipe) { return function ($passable) use ($stack, $pipe) { try { if (is_callable($pipe)) { // If the pipe is a callable, then we will call it directly, but otherwise we // will resolve the pipes out of the dependency container and call it with // the appropriate method and arguments, returning the results back out. return $pipe($passable, $stack); } elseif (! is_object($pipe)) { [$name, $parameters] = $this->parsePipeString($pipe); // If the pipe is a string we will parse the string and resolve the class out // of the dependency injection container. We can then build a callable and // execute the pipe function giving in the parameters that are required. $pipe = $this->getContainer()->make($name); $parameters = array_merge([$passable, $stack], $parameters); } else { // If the pipe is already an object we'll just make a callable and pass it to // the pipe as-is. There is no need to do any extra parsing and formatting // since the object we're given was already a fully instantiated object. $parameters = [$passable, $stack]; } $carry = method_exists($pipe, $this->method) ? $pipe->{$this->method}(...$parameters) : $pipe(...$parameters); return $this->handleCarry($carry); } catch (Throwable $e) { return $this->handleException($passable, $e); } }; }; } /** * Parse full pipe string to get name and parameters. * * @param string $pipe * @return array */ protected function parsePipeString($pipe) { [$name, $parameters] = array_pad(explode(':', $pipe, 2), 2, []); if (is_string($parameters)) { $parameters = explode(',', $parameters); } return [$name, $parameters]; } /** * Get the array of configured pipes. * * @return array */ protected function pipes() { return $this->pipes; } /** * Get the container instance. * * @return \Illuminate\Contracts\Container\Container * * @throws \RuntimeException */ protected function getContainer() { if (! $this->container) { throw new RuntimeException('A container instance has not been passed to the Pipeline.'); } return $this->container; } /** * Set the container instance. * * @param \Illuminate\Contracts\Container\Container $container * @return $this */ public function setContainer(Container $container) { $this->container = $container; return $this; } /** * Handle the value returned from each pipe before passing it to the next. * * @param mixed $carry * @return mixed */ protected function handleCarry($carry) { return $carry; } /** * Handle the given exception. * * @param mixed $passable * @param \Throwable $e * @return mixed * * @throws \Throwable */ protected function handleException($passable, Throwable $e) { throw $e; } } PKz Z77!Illuminate/Pipeline/composer.jsonnuW+A{ "name": "illuminate/pipeline", "description": "The Illuminate Pipeline package.", "license": "MIT", "homepage": "https://laravel.com", "support": { "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, "authors": [ { "name": "Taylor Otwell", "email": "taylor@laravel.com" } ], "require": { "php": "^8.0.2", "illuminate/contracts": "^9.0", "illuminate/support": "^9.0" }, "autoload": { "psr-4": { "Illuminate\\Pipeline\\": "" } }, "extra": { "branch-alias": { "dev-master": "9.x-dev" } }, "config": { "sort-packages": true }, "minimum-stability": "dev" } PKz ZKIlluminate/Foundation/Testing/Concerns/InteractsWithDeprecationHandling.phpnuW+AoriginalDeprecationHandler) { set_error_handler(tap($this->originalDeprecationHandler, function () { $this->originalDeprecationHandler = null; })); } return $this; } /** * Disable deprecation handling for the test. * * @return $this */ protected function withoutDeprecationHandling() { if ($this->originalDeprecationHandler == null) { $this->originalDeprecationHandler = set_error_handler(function ($level, $message, $file = '', $line = 0) { if (in_array($level, [E_DEPRECATED, E_USER_DEPRECATED]) || (error_reporting() & $level)) { throw new ErrorException($message, 0, $level, $file, $line); } }); } return $this; } } PKz Z} =Illuminate/Foundation/Testing/Concerns/InteractsWithRedis.phpnuW+AmarkTestSkipped('The redis extension is not installed. Please install the extension to enable '.__CLASS__); } if (static::$connectionFailedOnceWithDefaultsSkip) { $this->markTestSkipped('Trying default host/port failed, please set environment variable REDIS_HOST & REDIS_PORT to enable '.__CLASS__); } $app = $this->app ?? new Application; $host = Env::get('REDIS_HOST', '127.0.0.1'); $port = Env::get('REDIS_PORT', 6379); foreach ($this->redisDriverProvider() as $driver) { $this->redis[$driver[0]] = new RedisManager($app, $driver[0], [ 'cluster' => false, 'options' => [ 'prefix' => 'test_', ], 'default' => [ 'host' => $host, 'port' => $port, 'database' => 5, 'timeout' => 0.5, 'name' => 'default', ], ]); } try { $this->redis['phpredis']->connection()->flushdb(); } catch (Exception $e) { if ($host === '127.0.0.1' && $port === 6379 && Env::get('REDIS_HOST') === null) { static::$connectionFailedOnceWithDefaultsSkip = true; $this->markTestSkipped('Trying default host/port failed, please set environment variable REDIS_HOST & REDIS_PORT to enable '.__CLASS__); } } } /** * Teardown redis connection. * * @return void */ public function tearDownRedis() { if (isset($this->redis['phpredis'])) { $this->redis['phpredis']->connection()->flushdb(); } foreach ($this->redisDriverProvider() as $driver) { if (isset($this->redis[$driver[0]])) { $this->redis[$driver[0]]->connection()->disconnect(); } } } /** * Get redis driver provider. * * @return array */ public function redisDriverProvider() { return [ ['predis'], ['phpredis'], ]; } /** * Run test if redis is available. * * @param callable $callback * @return void */ public function ifRedisAvailable($callback) { $this->setUpRedis(); $callback(); $this->tearDownRedis(); } } PKz Z!!IIlluminate/Foundation/Testing/Concerns/InteractsWithExceptionHandling.phpnuW+AoriginalExceptionHandler) { $this->app->instance(ExceptionHandler::class, $this->originalExceptionHandler); } return $this; } /** * Only handle the given exceptions via the exception handler. * * @param array $exceptions * @return $this */ protected function handleExceptions(array $exceptions) { return $this->withoutExceptionHandling($exceptions); } /** * Only handle validation exceptions via the exception handler. * * @return $this */ protected function handleValidationExceptions() { return $this->handleExceptions([ValidationException::class]); } /** * Disable exception handling for the test. * * @param array $except * @return $this */ protected function withoutExceptionHandling(array $except = []) { if ($this->originalExceptionHandler == null) { $this->originalExceptionHandler = app(ExceptionHandler::class); } $this->app->instance(ExceptionHandler::class, new class($this->originalExceptionHandler, $except) implements ExceptionHandler { protected $except; protected $originalHandler; /** * Create a new class instance. * * @param \Illuminate\Contracts\Debug\ExceptionHandler $originalHandler * @param array $except * @return void */ public function __construct($originalHandler, $except = []) { $this->except = $except; $this->originalHandler = $originalHandler; } /** * Report or log an exception. * * @param \Throwable $e * @return void * * @throws \Exception */ public function report(Throwable $e) { // } /** * Determine if the exception should be reported. * * @param \Throwable $e * @return bool */ public function shouldReport(Throwable $e) { return false; } /** * Render an exception into an HTTP response. * * @param \Illuminate\Http\Request $request * @param \Throwable $e * @return \Symfony\Component\HttpFoundation\Response * * @throws \Throwable */ public function render($request, Throwable $e) { foreach ($this->except as $class) { if ($e instanceof $class) { return $this->originalHandler->render($request, $e); } } if ($e instanceof NotFoundHttpException) { throw new NotFoundHttpException( "{$request->method()} {$request->url()}", $e, is_int($e->getCode()) ? $e->getCode() : 0 ); } throw $e; } /** * Render an exception to the console. * * @param \Symfony\Component\Console\Output\OutputInterface $output * @param \Throwable $e * @return void */ public function renderForConsole($output, Throwable $e) { (new ConsoleApplication)->renderThrowable($e, $output); } }); return $this; } /** * Assert that the given callback throws an exception with the given message when invoked. * * @param \Closure $test * @param class-string<\Throwable> $expectedClass * @param string|null $expectedMessage * @return $this */ protected function assertThrows(Closure $test, string $expectedClass = Throwable::class, ?string $expectedMessage = null) { try { $test(); $thrown = false; } catch (Throwable $exception) { $thrown = $exception instanceof $expectedClass; $actualMessage = $exception->getMessage(); } Assert::assertTrue( $thrown, sprintf('Failed asserting that exception of type "%s" was thrown.', $expectedClass) ); if (isset($expectedMessage)) { if (! isset($actualMessage)) { Assert::fail( sprintf( 'Failed asserting that exception of type "%s" with message "%s" was thrown.', $expectedClass, $expectedMessage ) ); } else { Assert::assertStringContainsString($expectedMessage, $actualMessage); } } return $this; } } PKz Z`VAIlluminate/Foundation/Testing/Concerns/InteractsWithContainer.phpnuW+Ainstance($abstract, $instance); } /** * Register an instance of an object in the container. * * @param string $abstract * @param object $instance * @return object */ protected function instance($abstract, $instance) { $this->app->instance($abstract, $instance); return $instance; } /** * Mock an instance of an object in the container. * * @param string $abstract * @param \Closure|null $mock * @return \Mockery\MockInterface */ protected function mock($abstract, Closure $mock = null) { return $this->instance($abstract, Mockery::mock(...array_filter(func_get_args()))); } /** * Mock a partial instance of an object in the container. * * @param string $abstract * @param \Closure|null $mock * @return \Mockery\MockInterface */ protected function partialMock($abstract, Closure $mock = null) { return $this->instance($abstract, Mockery::mock(...array_filter(func_get_args()))->makePartial()); } /** * Spy an instance of an object in the container. * * @param string $abstract * @param \Closure|null $mock * @return \Mockery\MockInterface */ protected function spy($abstract, Closure $mock = null) { return $this->instance($abstract, Mockery::spy(...array_filter(func_get_args()))); } /** * Instruct the container to forget a previously mocked / spied instance of an object. * * @param string $abstract * @return $this */ protected function forgetMock($abstract) { $this->app->forgetInstance($abstract); return $this; } /** * Register an empty handler for Vite in the container. * * @return $this */ protected function withoutVite() { if ($this->originalVite == null) { $this->originalVite = app(Vite::class); } $this->swap(Vite::class, new class { public function __invoke() { return ''; } public function __call($name, $arguments) { return ''; } public function __toString() { return ''; } public function useIntegrityKey() { return $this; } public function useBuildDirectory() { return $this; } public function useHotFile() { return $this; } public function withEntryPoints() { return $this; } public function useScriptTagAttributes() { return $this; } public function useStyleTagAttributes() { return $this; } public function preloadedAssets() { return []; } }); return $this; } /** * Restore Vite in the container. * * @return $this */ protected function withVite() { if ($this->originalVite) { $this->app->instance(Vite::class, $this->originalVite); } return $this; } /** * Register an empty handler for Laravel Mix in the container. * * @return $this */ protected function withoutMix() { if ($this->originalMix == null) { $this->originalMix = app(Mix::class); } $this->swap(Mix::class, function () { return new HtmlString(''); }); return $this; } /** * Restore Laravel Mix in the container. * * @return $this */ protected function withMix() { if ($this->originalMix) { $this->app->instance(Mix::class, $this->originalMix); } return $this; } } PKz Z ~##@Illuminate/Foundation/Testing/Concerns/InteractsWithDatabase.phpnuW+AassertThat( $this->getTable($table), new HasInDatabase($this->getConnection($connection, $table), $data) ); return $this; } /** * Assert that a given where condition does not exist in the database. * * @param \Illuminate\Database\Eloquent\Model|string $table * @param array $data * @param string|null $connection * @return $this */ protected function assertDatabaseMissing($table, array $data, $connection = null) { $constraint = new ReverseConstraint( new HasInDatabase($this->getConnection($connection, $table), $data) ); $this->assertThat($this->getTable($table), $constraint); return $this; } /** * Assert the count of table entries. * * @param \Illuminate\Database\Eloquent\Model|string $table * @param int $count * @param string|null $connection * @return $this */ protected function assertDatabaseCount($table, int $count, $connection = null) { $this->assertThat( $this->getTable($table), new CountInDatabase($this->getConnection($connection, $table), $count) ); return $this; } /** * Assert that the given table has no entries. * * @param \Illuminate\Database\Eloquent\Model|string $table * @param string|null $connection * @return $this */ protected function assertDatabaseEmpty($table, $connection = null) { $this->assertThat( $this->getTable($table), new CountInDatabase($this->getConnection($connection, $table), 0) ); return $this; } /** * Assert the given record has been "soft deleted". * * @param \Illuminate\Database\Eloquent\Model|string $table * @param array $data * @param string|null $connection * @param string|null $deletedAtColumn * @return $this */ protected function assertSoftDeleted($table, array $data = [], $connection = null, $deletedAtColumn = 'deleted_at') { if ($this->isSoftDeletableModel($table)) { return $this->assertSoftDeleted( $table->getTable(), array_merge($data, [$table->getKeyName() => $table->getKey()]), $table->getConnectionName(), $table->getDeletedAtColumn() ); } $this->assertThat( $this->getTable($table), new SoftDeletedInDatabase($this->getConnection($connection, $table), $data, $deletedAtColumn) ); return $this; } /** * Assert the given record has not been "soft deleted". * * @param \Illuminate\Database\Eloquent\Model|string $table * @param array $data * @param string|null $connection * @param string|null $deletedAtColumn * @return $this */ protected function assertNotSoftDeleted($table, array $data = [], $connection = null, $deletedAtColumn = 'deleted_at') { if ($this->isSoftDeletableModel($table)) { return $this->assertNotSoftDeleted( $table->getTable(), array_merge($data, [$table->getKeyName() => $table->getKey()]), $table->getConnectionName(), $table->getDeletedAtColumn() ); } $this->assertThat( $this->getTable($table), new NotSoftDeletedInDatabase($this->getConnection($connection, $table), $data, $deletedAtColumn) ); return $this; } /** * Assert the given model exists in the database. * * @param \Illuminate\Database\Eloquent\Model $model * @return $this */ protected function assertModelExists($model) { return $this->assertDatabaseHas( $model->getTable(), [$model->getKeyName() => $model->getKey()], $model->getConnectionName() ); } /** * Assert the given model does not exist in the database. * * @param \Illuminate\Database\Eloquent\Model $model * @return $this */ protected function assertModelMissing($model) { return $this->assertDatabaseMissing( $model->getTable(), [$model->getKeyName() => $model->getKey()], $model->getConnectionName() ); } /** * Specify the number of database queries that should occur throughout the test. * * @param int $expected * @param string|null $connection * @return $this */ public function expectsDatabaseQueryCount($expected, $connection = null) { with($this->getConnection($connection), function ($connectionInstance) use ($expected, $connection) { $actual = 0; $connectionInstance->listen(function (QueryExecuted $event) use (&$actual, $connectionInstance, $connection) { if (is_null($connection) || $connectionInstance === $event->connection) { $actual++; } }); $this->beforeApplicationDestroyed(function () use (&$actual, $expected, $connectionInstance) { $this->assertSame( $actual, $expected, "Expected {$expected} database queries on the [{$connectionInstance->getName()}] connection. {$actual} occurred." ); }); }); return $this; } /** * Determine if the argument is a soft deletable model. * * @param mixed $model * @return bool */ protected function isSoftDeletableModel($model) { return $model instanceof Model && in_array(SoftDeletes::class, class_uses_recursive($model)); } /** * Cast a JSON string to a database compatible type. * * @param array|object|string $value * @return \Illuminate\Database\Query\Expression */ public function castAsJson($value) { if ($value instanceof Jsonable) { $value = $value->toJson(); } elseif (is_array($value) || is_object($value)) { $value = json_encode($value); } $value = DB::connection()->getPdo()->quote($value); return DB::raw( DB::connection()->getQueryGrammar()->compileJsonValueCast($value) ); } /** * Get the database connection. * * @param string|null $connection * @param string|null $table * @return \Illuminate\Database\Connection */ protected function getConnection($connection = null, $table = null) { $database = $this->app->make('db'); $connection = $connection ?: $this->getTableConnection($table) ?: $database->getDefaultConnection(); return $database->connection($connection); } /** * Get the table name from the given model or string. * * @param \Illuminate\Database\Eloquent\Model|string $table * @return string */ protected function getTable($table) { return $this->newModelFor($table)?->getTable() ?: $table; } /** * Get the table connection specified in the given model. * * @param \Illuminate\Database\Eloquent\Model|string $table * @return string|null */ protected function getTableConnection($table) { return $this->newModelFor($table)?->getConnectionName(); } /** * Get the model entity from the given model or string. * * @param \Illuminate\Database\Eloquent\Model|string $table * @return \Illuminate\Database\Eloquent\Model|null */ protected function newModelFor($table) { return is_subclass_of($table, Model::class) ? (new $table) : null; } /** * Seed a given database connection. * * @param array|string $class * @return $this */ public function seed($class = 'Database\\Seeders\\DatabaseSeeder') { foreach (Arr::wrap($class) as $class) { $this->artisan('db:seed', ['--class' => $class, '--no-interaction' => true]); } return $this; } } PKz ZT<Illuminate/Foundation/Testing/Concerns/InteractsWithTime.phpnuW+AtravelTo(Carbon::now(), $callback); } /** * Freeze time at the beginning of the current second. * * @param callable|null $callback * @return mixed */ public function freezeSecond($callback = null) { return $this->travelTo(Carbon::now()->startOfSecond(), $callback); } /** * Begin travelling to another time. * * @param int $value * @return \Illuminate\Foundation\Testing\Wormhole */ public function travel($value) { return new Wormhole($value); } /** * Travel to another time. * * @param \DateTimeInterface|\Closure|\Illuminate\Support\Carbon|string|bool|null $date * @param callable|null $callback * @return mixed */ public function travelTo($date, $callback = null) { Carbon::setTestNow($date); if ($callback) { return tap($callback($date), function () { Carbon::setTestNow(); }); } } /** * Travel back to the current time. * * @return \DateTimeInterface */ public function travelBack() { return Wormhole::back(); } } PKz ZCFIlluminate/Foundation/Testing/Concerns/InteractsWithAuthentication.phpnuW+Abe($user, $guard); } /** * Set the currently logged in user for the application. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param string|null $guard * @return $this */ public function be(UserContract $user, $guard = null) { if (isset($user->wasRecentlyCreated) && $user->wasRecentlyCreated) { $user->wasRecentlyCreated = false; } $this->app['auth']->guard($guard)->setUser($user); $this->app['auth']->shouldUse($guard); return $this; } /** * Assert that the user is authenticated. * * @param string|null $guard * @return $this */ public function assertAuthenticated($guard = null) { $this->assertTrue($this->isAuthenticated($guard), 'The user is not authenticated'); return $this; } /** * Assert that the user is not authenticated. * * @param string|null $guard * @return $this */ public function assertGuest($guard = null) { $this->assertFalse($this->isAuthenticated($guard), 'The user is authenticated'); return $this; } /** * Return true if the user is authenticated, false otherwise. * * @param string|null $guard * @return bool */ protected function isAuthenticated($guard = null) { return $this->app->make('auth')->guard($guard)->check(); } /** * Assert that the user is authenticated as the given user. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param string|null $guard * @return $this */ public function assertAuthenticatedAs($user, $guard = null) { $expected = $this->app->make('auth')->guard($guard)->user(); $this->assertNotNull($expected, 'The current user is not authenticated.'); $this->assertInstanceOf( get_class($expected), $user, 'The currently authenticated user is not who was expected' ); $this->assertSame( $expected->getAuthIdentifier(), $user->getAuthIdentifier(), 'The currently authenticated user is not who was expected' ); return $this; } /** * Assert that the given credentials are valid. * * @param array $credentials * @param string|null $guard * @return $this */ public function assertCredentials(array $credentials, $guard = null) { $this->assertTrue( $this->hasCredentials($credentials, $guard), 'The given credentials are invalid.' ); return $this; } /** * Assert that the given credentials are invalid. * * @param array $credentials * @param string|null $guard * @return $this */ public function assertInvalidCredentials(array $credentials, $guard = null) { $this->assertFalse( $this->hasCredentials($credentials, $guard), 'The given credentials are valid.' ); return $this; } /** * Return true if the credentials are valid, false otherwise. * * @param array $credentials * @param string|null $guard * @return bool */ protected function hasCredentials(array $credentials, $guard = null) { $provider = $this->app->make('auth')->guard($guard)->getProvider(); $user = $provider->retrieveByCredentials($credentials); return $user && $provider->validateCredentials($user, $credentials); } } PKz Z0)}~~?Illuminate/Foundation/Testing/Concerns/InteractsWithSession.phpnuW+Asession($data); return $this; } /** * Set the session to the given array. * * @param array $data * @return $this */ public function session(array $data) { $this->startSession(); foreach ($data as $key => $value) { $this->app['session']->put($key, $value); } return $this; } /** * Start the session for the application. * * @return $this */ protected function startSession() { if (! $this->app['session']->isStarted()) { $this->app['session']->start(); } return $this; } /** * Flush all of the current session data. * * @return $this */ public function flushSession() { $this->startSession(); $this->app['session']->flush(); return $this; } } PKz Z|Z Z =Illuminate/Foundation/Testing/Concerns/InteractsWithViews.phpnuW+AgetPaths())) { ViewFacade::addLocation(sys_get_temp_dir()); } $tempFileInfo = pathinfo(tempnam($tempDirectory, 'laravel-blade')); $tempFile = $tempFileInfo['dirname'].'/'.$tempFileInfo['filename'].'.blade.php'; file_put_contents($tempFile, $template); return new TestView(view($tempFileInfo['filename'], $data)); } /** * Render the given view component. * * @param string $componentClass * @param \Illuminate\Contracts\Support\Arrayable|array $data * @return \Illuminate\Testing\TestComponent */ protected function component(string $componentClass, $data = []) { $component = $this->app->make($componentClass, $data); $view = value($component->resolveView(), $data); $view = $view instanceof View ? $view->with($component->data()) : view($view, $component->data()); return new TestComponent($component, $view); } /** * Populate the shared view error bag with the given errors. * * @param array $errors * @param string $key * @return $this */ protected function withViewErrors(array $errors, $key = 'default') { ViewFacade::share('errors', (new ViewErrorBag)->put($key, new MessageBag($errors))); return $this; } } PKz ZP6CIlluminate/Foundation/Testing/Concerns/MocksApplicationServices.phpnuW+AwithoutEvents(); $this->beforeApplicationDestroyed(function () use ($events) { $fired = $this->getFiredEvents($events); $this->assertEmpty( $eventsNotFired = array_diff($events, $fired), 'These expected events were not fired: ['.implode(', ', $eventsNotFired).']' ); }); return $this; } /** * Specify a list of events that should not be fired for the given operation. * * These events will be mocked, so that handlers will not actually be executed. * * @param array|string $events * @return $this */ public function doesntExpectEvents($events) { $events = is_array($events) ? $events : func_get_args(); $this->withoutEvents(); $this->beforeApplicationDestroyed(function () use ($events) { $this->assertEmpty( $fired = $this->getFiredEvents($events), 'These unexpected events were fired: ['.implode(', ', $fired).']' ); }); return $this; } /** * Mock the event dispatcher so all events are silenced and collected. * * @return $this */ protected function withoutEvents() { $mock = Mockery::mock(EventsDispatcherContract::class)->shouldIgnoreMissing(); $mock->shouldReceive('dispatch', 'until')->andReturnUsing(function ($called) { $this->firedEvents[] = $called; }); Event::clearResolvedInstances(); $this->app->instance('events', $mock); return $this; } /** * Filter the given events against the fired events. * * @param array $events * @return array */ protected function getFiredEvents(array $events) { return $this->getDispatched($events, $this->firedEvents); } /** * Specify a list of jobs that should be dispatched for the given operation. * * These jobs will be mocked, so that handlers will not actually be executed. * * @param array|string $jobs * @return $this */ protected function expectsJobs($jobs) { $jobs = is_array($jobs) ? $jobs : func_get_args(); $this->withoutJobs(); $this->beforeApplicationDestroyed(function () use ($jobs) { $dispatched = $this->getDispatchedJobs($jobs); $this->assertEmpty( $jobsNotDispatched = array_diff($jobs, $dispatched), 'These expected jobs were not dispatched: ['.implode(', ', $jobsNotDispatched).']' ); }); return $this; } /** * Specify a list of jobs that should not be dispatched for the given operation. * * These jobs will be mocked, so that handlers will not actually be executed. * * @param array|string $jobs * @return $this */ protected function doesntExpectJobs($jobs) { $jobs = is_array($jobs) ? $jobs : func_get_args(); $this->withoutJobs(); $this->beforeApplicationDestroyed(function () use ($jobs) { $this->assertEmpty( $dispatched = $this->getDispatchedJobs($jobs), 'These unexpected jobs were dispatched: ['.implode(', ', $dispatched).']' ); }); return $this; } /** * Mock the job dispatcher so all jobs are silenced and collected. * * @return $this */ protected function withoutJobs() { $mock = Mockery::mock(BusDispatcherContract::class)->shouldIgnoreMissing(); $mock->shouldReceive('dispatch', 'dispatchNow')->andReturnUsing(function ($dispatched) { $this->dispatchedJobs[] = $dispatched; }); $this->app->instance( BusDispatcherContract::class, $mock ); return $this; } /** * Filter the given jobs against the dispatched jobs. * * @param array $jobs * @return array */ protected function getDispatchedJobs(array $jobs) { return $this->getDispatched($jobs, $this->dispatchedJobs); } /** * Filter the given classes against an array of dispatched classes. * * @param array $classes * @param array $dispatched * @return array */ protected function getDispatched(array $classes, array $dispatched) { return array_filter($classes, function ($class) use ($dispatched) { return $this->wasDispatched($class, $dispatched); }); } /** * Check if the given class exists in an array of dispatched classes. * * @param string $needle * @param array $haystack * @return bool */ protected function wasDispatched($needle, array $haystack) { foreach ($haystack as $dispatched) { if ((is_string($dispatched) && ($dispatched === $needle || is_subclass_of($dispatched, $needle))) || $dispatched instanceof $needle) { return true; } } return false; } /** * Mock the notification dispatcher so all notifications are silenced. * * @return $this */ protected function withoutNotifications() { $mock = Mockery::mock(NotificationDispatcher::class); $mock->shouldReceive('send')->andReturnUsing(function ($notifiable, $instance, $channels = []) { $this->dispatchedNotifications[] = compact( 'notifiable', 'instance', 'channels' ); }); $this->app->instance(NotificationDispatcher::class, $mock); return $this; } /** * Specify a notification that is expected to be dispatched. * * @param mixed $notifiable * @param string $notification * @return $this */ protected function expectsNotification($notifiable, $notification) { $this->withoutNotifications(); $this->beforeApplicationDestroyed(function () use ($notifiable, $notification) { foreach ($this->dispatchedNotifications as $dispatched) { $notified = $dispatched['notifiable']; if (($notified === $notifiable || $notified->getKey() == $notifiable->getKey()) && get_class($dispatched['instance']) === $notification ) { return $this; } } $this->fail('The following expected notification were not dispatched: ['.$notification.']'); }); return $this; } } PKz Zt?Illuminate/Foundation/Testing/Concerns/InteractsWithConsole.phpnuW+AmockConsoleOutput) { return $this->app[Kernel::class]->call($command, $parameters); } return new PendingCommand($this, $this->app, $command, $parameters); } /** * Disable mocking the console output. * * @return $this */ protected function withoutMockingConsoleOutput() { $this->mockConsoleOutput = false; $this->app->offsetUnset(OutputStyle::class); return $this; } } PKz ZGG<Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.phpnuW+AdefaultHeaders = array_merge($this->defaultHeaders, $headers); return $this; } /** * Add a header to be sent with the request. * * @param string $name * @param string $value * @return $this */ public function withHeader(string $name, string $value) { $this->defaultHeaders[$name] = $value; return $this; } /** * Add an authorization token for the request. * * @param string $token * @param string $type * @return $this */ public function withToken(string $token, string $type = 'Bearer') { return $this->withHeader('Authorization', $type.' '.$token); } /** * Add a basic authentication header to the request with the given credentials. * * @param string $username * @param string $password * @return $this */ public function withBasicAuth(string $username, string $password) { return $this->withToken(base64_encode("$username:$password"), 'Basic'); } /** * Remove the authorization token from the request. * * @return $this */ public function withoutToken() { unset($this->defaultHeaders['Authorization']); return $this; } /** * Flush all the configured headers. * * @return $this */ public function flushHeaders() { $this->defaultHeaders = []; return $this; } /** * Define a set of server variables to be sent with the requests. * * @param array $server * @return $this */ public function withServerVariables(array $server) { $this->serverVariables = $server; return $this; } /** * Disable middleware for the test. * * @param string|array|null $middleware * @return $this */ public function withoutMiddleware($middleware = null) { if (is_null($middleware)) { $this->app->instance('middleware.disable', true); return $this; } foreach ((array) $middleware as $abstract) { $this->app->instance($abstract, new class { public function handle($request, $next) { return $next($request); } }); } return $this; } /** * Enable the given middleware for the test. * * @param string|array|null $middleware * @return $this */ public function withMiddleware($middleware = null) { if (is_null($middleware)) { unset($this->app['middleware.disable']); return $this; } foreach ((array) $middleware as $abstract) { unset($this->app[$abstract]); } return $this; } /** * Define additional cookies to be sent with the request. * * @param array $cookies * @return $this */ public function withCookies(array $cookies) { $this->defaultCookies = array_merge($this->defaultCookies, $cookies); return $this; } /** * Add a cookie to be sent with the request. * * @param string $name * @param string $value * @return $this */ public function withCookie(string $name, string $value) { $this->defaultCookies[$name] = $value; return $this; } /** * Define additional cookies will not be encrypted before sending with the request. * * @param array $cookies * @return $this */ public function withUnencryptedCookies(array $cookies) { $this->unencryptedCookies = array_merge($this->unencryptedCookies, $cookies); return $this; } /** * Add a cookie will not be encrypted before sending with the request. * * @param string $name * @param string $value * @return $this */ public function withUnencryptedCookie(string $name, string $value) { $this->unencryptedCookies[$name] = $value; return $this; } /** * Automatically follow any redirects returned from the response. * * @return $this */ public function followingRedirects() { $this->followRedirects = true; return $this; } /** * Include cookies and authorization headers for JSON requests. * * @return $this */ public function withCredentials() { $this->withCredentials = true; return $this; } /** * Disable automatic encryption of cookie values. * * @return $this */ public function disableCookieEncryption() { $this->encryptCookies = false; return $this; } /** * Set the referer header and previous URL session value in order to simulate a previous request. * * @param string $url * @return $this */ public function from(string $url) { $this->app['session']->setPreviousUrl($url); return $this->withHeader('referer', $url); } /** * Visit the given URI with a GET request. * * @param string $uri * @param array $headers * @return \Illuminate\Testing\TestResponse */ public function get($uri, array $headers = []) { $server = $this->transformHeadersToServerVars($headers); $cookies = $this->prepareCookiesForRequest(); return $this->call('GET', $uri, [], $cookies, [], $server); } /** * Visit the given URI with a GET request, expecting a JSON response. * * @param string $uri * @param array $headers * @return \Illuminate\Testing\TestResponse */ public function getJson($uri, array $headers = []) { return $this->json('GET', $uri, [], $headers); } /** * Visit the given URI with a POST request. * * @param string $uri * @param array $data * @param array $headers * @return \Illuminate\Testing\TestResponse */ public function post($uri, array $data = [], array $headers = []) { $server = $this->transformHeadersToServerVars($headers); $cookies = $this->prepareCookiesForRequest(); return $this->call('POST', $uri, $data, $cookies, [], $server); } /** * Visit the given URI with a POST request, expecting a JSON response. * * @param string $uri * @param array $data * @param array $headers * @return \Illuminate\Testing\TestResponse */ public function postJson($uri, array $data = [], array $headers = []) { return $this->json('POST', $uri, $data, $headers); } /** * Visit the given URI with a PUT request. * * @param string $uri * @param array $data * @param array $headers * @return \Illuminate\Testing\TestResponse */ public function put($uri, array $data = [], array $headers = []) { $server = $this->transformHeadersToServerVars($headers); $cookies = $this->prepareCookiesForRequest(); return $this->call('PUT', $uri, $data, $cookies, [], $server); } /** * Visit the given URI with a PUT request, expecting a JSON response. * * @param string $uri * @param array $data * @param array $headers * @return \Illuminate\Testing\TestResponse */ public function putJson($uri, array $data = [], array $headers = []) { return $this->json('PUT', $uri, $data, $headers); } /** * Visit the given URI with a PATCH request. * * @param string $uri * @param array $data * @param array $headers * @return \Illuminate\Testing\TestResponse */ public function patch($uri, array $data = [], array $headers = []) { $server = $this->transformHeadersToServerVars($headers); $cookies = $this->prepareCookiesForRequest(); return $this->call('PATCH', $uri, $data, $cookies, [], $server); } /** * Visit the given URI with a PATCH request, expecting a JSON response. * * @param string $uri * @param array $data * @param array $headers * @return \Illuminate\Testing\TestResponse */ public function patchJson($uri, array $data = [], array $headers = []) { return $this->json('PATCH', $uri, $data, $headers); } /** * Visit the given URI with a DELETE request. * * @param string $uri * @param array $data * @param array $headers * @return \Illuminate\Testing\TestResponse */ public function delete($uri, array $data = [], array $headers = []) { $server = $this->transformHeadersToServerVars($headers); $cookies = $this->prepareCookiesForRequest(); return $this->call('DELETE', $uri, $data, $cookies, [], $server); } /** * Visit the given URI with a DELETE request, expecting a JSON response. * * @param string $uri * @param array $data * @param array $headers * @return \Illuminate\Testing\TestResponse */ public function deleteJson($uri, array $data = [], array $headers = []) { return $this->json('DELETE', $uri, $data, $headers); } /** * Visit the given URI with an OPTIONS request. * * @param string $uri * @param array $data * @param array $headers * @return \Illuminate\Testing\TestResponse */ public function options($uri, array $data = [], array $headers = []) { $server = $this->transformHeadersToServerVars($headers); $cookies = $this->prepareCookiesForRequest(); return $this->call('OPTIONS', $uri, $data, $cookies, [], $server); } /** * Visit the given URI with an OPTIONS request, expecting a JSON response. * * @param string $uri * @param array $data * @param array $headers * @return \Illuminate\Testing\TestResponse */ public function optionsJson($uri, array $data = [], array $headers = []) { return $this->json('OPTIONS', $uri, $data, $headers); } /** * Visit the given URI with a HEAD request. * * @param string $uri * @param array $headers * @return \Illuminate\Testing\TestResponse */ public function head($uri, array $headers = []) { $server = $this->transformHeadersToServerVars($headers); $cookies = $this->prepareCookiesForRequest(); return $this->call('HEAD', $uri, [], $cookies, [], $server); } /** * Call the given URI with a JSON request. * * @param string $method * @param string $uri * @param array $data * @param array $headers * @return \Illuminate\Testing\TestResponse */ public function json($method, $uri, array $data = [], array $headers = []) { $files = $this->extractFilesFromDataArray($data); $content = json_encode($data); $headers = array_merge([ 'CONTENT_LENGTH' => mb_strlen($content, '8bit'), 'CONTENT_TYPE' => 'application/json', 'Accept' => 'application/json', ], $headers); return $this->call( $method, $uri, [], $this->prepareCookiesForJsonRequest(), $files, $this->transformHeadersToServerVars($headers), $content ); } /** * Call the given URI and return the Response. * * @param string $method * @param string $uri * @param array $parameters * @param array $cookies * @param array $files * @param array $server * @param string|null $content * @return \Illuminate\Testing\TestResponse */ public function call($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null) { $kernel = $this->app->make(HttpKernel::class); $files = array_merge($files, $this->extractFilesFromDataArray($parameters)); $symfonyRequest = SymfonyRequest::create( $this->prepareUrlForRequest($uri), $method, $parameters, $cookies, $files, array_replace($this->serverVariables, $server), $content ); $response = $kernel->handle( $request = Request::createFromBase($symfonyRequest) ); $kernel->terminate($request, $response); if ($this->followRedirects) { $response = $this->followRedirects($response); } return static::$latestResponse = $this->createTestResponse($response); } /** * Turn the given URI into a fully qualified URL. * * @param string $uri * @return string */ protected function prepareUrlForRequest($uri) { if (str_starts_with($uri, '/')) { $uri = substr($uri, 1); } return trim(url($uri), '/'); } /** * Transform headers array to array of $_SERVER vars with HTTP_* format. * * @param array $headers * @return array */ protected function transformHeadersToServerVars(array $headers) { return collect(array_merge($this->defaultHeaders, $headers))->mapWithKeys(function ($value, $name) { $name = strtr(strtoupper($name), '-', '_'); return [$this->formatServerHeaderKey($name) => $value]; })->all(); } /** * Format the header name for the server array. * * @param string $name * @return string */ protected function formatServerHeaderKey($name) { if (! str_starts_with($name, 'HTTP_') && $name !== 'CONTENT_TYPE' && $name !== 'REMOTE_ADDR') { return 'HTTP_'.$name; } return $name; } /** * Extract the file uploads from the given data array. * * @param array $data * @return array */ protected function extractFilesFromDataArray(&$data) { $files = []; foreach ($data as $key => $value) { if ($value instanceof SymfonyUploadedFile) { $files[$key] = $value; unset($data[$key]); } if (is_array($value)) { $files[$key] = $this->extractFilesFromDataArray($value); $data[$key] = $value; } } return $files; } /** * If enabled, encrypt cookie values for request. * * @return array */ protected function prepareCookiesForRequest() { if (! $this->encryptCookies) { return array_merge($this->defaultCookies, $this->unencryptedCookies); } return collect($this->defaultCookies)->map(function ($value, $key) { return encrypt(CookieValuePrefix::create($key, app('encrypter')->getKey()).$value, false); })->merge($this->unencryptedCookies)->all(); } /** * If enabled, add cookies for JSON requests. * * @return array */ protected function prepareCookiesForJsonRequest() { return $this->withCredentials ? $this->prepareCookiesForRequest() : []; } /** * Follow a redirect chain until a non-redirect is received. * * @param \Illuminate\Http\Response $response * @return \Illuminate\Http\Response|\Illuminate\Testing\TestResponse */ protected function followRedirects($response) { $this->followRedirects = false; while ($response->isRedirect()) { $response = $this->get($response->headers->get('Location')); } return $response; } /** * Create the test response instance from the given response. * * @param \Illuminate\Http\Response $response * @return \Illuminate\Testing\TestResponse */ protected function createTestResponse($response) { return tap(TestResponse::fromBaseResponse($response), function ($response) { $response->withExceptions( $this->app->bound(LoggedExceptionCollection::class) ? $this->app->make(LoggedExceptionCollection::class) : new LoggedExceptionCollection ); }); } } PKz Z*Illuminate/Foundation/Testing/TestCase.phpnuW+Aapp) { $this->refreshApplication(); ParallelTesting::callSetUpTestCaseCallbacks($this); } $this->setUpTraits(); foreach ($this->afterApplicationCreatedCallbacks as $callback) { $callback(); } Model::setEventDispatcher($this->app['events']); $this->setUpHasRun = true; } /** * Refresh the application instance. * * @return void */ protected function refreshApplication() { $this->app = $this->createApplication(); } /** * Boot the testing helper traits. * * @return array */ protected function setUpTraits() { $uses = array_flip(class_uses_recursive(static::class)); if (isset($uses[RefreshDatabase::class])) { $this->refreshDatabase(); } if (isset($uses[DatabaseMigrations::class])) { $this->runDatabaseMigrations(); } if (isset($uses[DatabaseTruncation::class])) { $this->truncateDatabaseTables(); } if (isset($uses[DatabaseTransactions::class])) { $this->beginDatabaseTransaction(); } if (isset($uses[WithoutMiddleware::class])) { $this->disableMiddlewareForAllTests(); } if (isset($uses[WithoutEvents::class])) { $this->disableEventsForAllTests(); } if (isset($uses[WithFaker::class])) { $this->setUpFaker(); } foreach ($uses as $trait) { if (method_exists($this, $method = 'setUp'.class_basename($trait))) { $this->{$method}(); } if (method_exists($this, $method = 'tearDown'.class_basename($trait))) { $this->beforeApplicationDestroyed(fn () => $this->{$method}()); } } return $uses; } /** * Clean up the testing environment before the next test. * * @return void * * @throws \Mockery\Exception\InvalidCountException */ protected function tearDown(): void { if ($this->app) { $this->callBeforeApplicationDestroyedCallbacks(); ParallelTesting::callTearDownTestCaseCallbacks($this); $this->app->flush(); $this->app = null; } $this->setUpHasRun = false; if (property_exists($this, 'serverVariables')) { $this->serverVariables = []; } if (property_exists($this, 'defaultHeaders')) { $this->defaultHeaders = []; } if (class_exists('Mockery')) { if ($container = Mockery::getContainer()) { $this->addToAssertionCount($container->mockery_getExpectationCount()); } try { Mockery::close(); } catch (InvalidCountException $e) { if (! Str::contains($e->getMethodName(), ['doWrite', 'askQuestion'])) { throw $e; } } } if (class_exists(Carbon::class)) { Carbon::setTestNow(); } if (class_exists(CarbonImmutable::class)) { CarbonImmutable::setTestNow(); } $this->afterApplicationCreatedCallbacks = []; $this->beforeApplicationDestroyedCallbacks = []; $this->originalExceptionHandler = null; $this->originalDeprecationHandler = null; Artisan::forgetBootstrappers(); Component::flushCache(); Component::forgetComponentsResolver(); Component::forgetFactory(); Queue::createPayloadUsing(null); HandleExceptions::forgetApp(); if ($this->callbackException) { throw $this->callbackException; } } /** * Clean up the testing environment before the next test case. * * @return void */ public static function tearDownAfterClass(): void { static::$latestResponse = null; (function () { $this->classDocBlocks = []; $this->methodDocBlocks = []; })->call(Registry::getInstance()); } /** * Register a callback to be run after the application is created. * * @param callable $callback * @return void */ public function afterApplicationCreated(callable $callback) { $this->afterApplicationCreatedCallbacks[] = $callback; if ($this->setUpHasRun) { $callback(); } } /** * Register a callback to be run before the application is destroyed. * * @param callable $callback * @return void */ protected function beforeApplicationDestroyed(callable $callback) { $this->beforeApplicationDestroyedCallbacks[] = $callback; } /** * Execute the application's pre-destruction callbacks. * * @return void */ protected function callBeforeApplicationDestroyedCallbacks() { foreach ($this->beforeApplicationDestroyedCallbacks as $callback) { try { $callback(); } catch (Throwable $e) { if (! $this->callbackException) { $this->callbackException = $e; } } } } /** * This method is called when a test method did not execute successfully. * * @param \Throwable $exception * @return void */ protected function onNotSuccessfulTest(Throwable $exception): void { parent::onNotSuccessfulTest( is_null(static::$latestResponse) ? $exception : static::$latestResponse->transformNotSuccessfulException($exception) ); } } PKz ZMee6Illuminate/Foundation/Testing/RefreshDatabaseState.phpnuW+AwithoutMiddleware(); } else { throw new Exception('Unable to disable middleware. MakesHttpRequests trait not used.'); } } } PKz Z+M/Illuminate/Foundation/Testing/WithoutEvents.phpnuW+AwithoutEvents(); } else { throw new Exception('Unable to disable events. ApplicationTrait not used.'); } } } PKz Z-N<<1Illuminate/Foundation/Testing/RefreshDatabase.phpnuW+AbeforeRefreshingDatabase(); $this->usingInMemoryDatabase() ? $this->refreshInMemoryDatabase() : $this->refreshTestDatabase(); $this->afterRefreshingDatabase(); } /** * Determine if an in-memory database is being used. * * @return bool */ protected function usingInMemoryDatabase() { $default = config('database.default'); return config("database.connections.$default.database") === ':memory:'; } /** * Refresh the in-memory database. * * @return void */ protected function refreshInMemoryDatabase() { $this->artisan('migrate', $this->migrateUsing()); $this->app[Kernel::class]->setArtisan(null); } /** * The parameters that should be used when running "migrate". * * @return array */ protected function migrateUsing() { return [ '--seed' => $this->shouldSeed(), '--seeder' => $this->seeder(), ]; } /** * Refresh a conventional test database. * * @return void */ protected function refreshTestDatabase() { if (! RefreshDatabaseState::$migrated) { $this->artisan('migrate:fresh', $this->migrateFreshUsing()); $this->app[Kernel::class]->setArtisan(null); RefreshDatabaseState::$migrated = true; } $this->beginDatabaseTransaction(); } /** * Begin a database transaction on the testing database. * * @return void */ public function beginDatabaseTransaction() { $database = $this->app->make('db'); foreach ($this->connectionsToTransact() as $name) { $connection = $database->connection($name); $dispatcher = $connection->getEventDispatcher(); $connection->unsetEventDispatcher(); $connection->beginTransaction(); $connection->setEventDispatcher($dispatcher); if ($this->app->resolved('db.transactions')) { $this->app->make('db.transactions')->callbacksShouldIgnore( $this->app->make('db.transactions')->getTransactions()->first() ); } } $this->beforeApplicationDestroyed(function () use ($database) { foreach ($this->connectionsToTransact() as $name) { $connection = $database->connection($name); $dispatcher = $connection->getEventDispatcher(); $connection->unsetEventDispatcher(); $connection->rollBack(); $connection->setEventDispatcher($dispatcher); $connection->disconnect(); } }); } /** * The database connections that should have transactions. * * @return array */ protected function connectionsToTransact() { return property_exists($this, 'connectionsToTransact') ? $this->connectionsToTransact : [null]; } /** * Perform any work that should take place before the database has started refreshing. * * @return void */ protected function beforeRefreshingDatabase() { // ... } /** * Perform any work that should take place once the database has finished refreshing. * * @return void */ protected function afterRefreshingDatabase() { // ... } } PKz Zw34Illuminate/Foundation/Testing/DatabaseMigrations.phpnuW+Aartisan('migrate:fresh', $this->migrateFreshUsing()); $this->app[Kernel::class]->setArtisan(null); $this->beforeApplicationDestroyed(function () { $this->artisan('migrate:rollback'); RefreshDatabaseState::$migrated = false; }); } } PKz Z@6Illuminate/Foundation/Testing/DatabaseTransactions.phpnuW+Aapp->make('db'); foreach ($this->connectionsToTransact() as $name) { $connection = $database->connection($name); $dispatcher = $connection->getEventDispatcher(); $connection->unsetEventDispatcher(); $connection->beginTransaction(); $connection->setEventDispatcher($dispatcher); if ($this->app->resolved('db.transactions')) { $this->app->make('db.transactions')->callbacksShouldIgnore( $this->app->make('db.transactions')->getTransactions()->first() ); } } $this->beforeApplicationDestroyed(function () use ($database) { foreach ($this->connectionsToTransact() as $name) { $connection = $database->connection($name); $dispatcher = $connection->getEventDispatcher(); $connection->unsetEventDispatcher(); $connection->rollBack(); $connection->setEventDispatcher($dispatcher); $connection->disconnect(); } }); } /** * The database connections that should have transactions. * * @return array */ protected function connectionsToTransact() { return property_exists($this, 'connectionsToTransact') ? $this->connectionsToTransact : [null]; } } PKz Z.7Illuminate/Foundation/Testing/LazilyRefreshDatabase.phpnuW+Aapp->make('db'); $database->beforeExecuting(function () { if (RefreshDatabaseState::$lazilyRefreshed) { return; } RefreshDatabaseState::$lazilyRefreshed = true; $this->baseRefreshDatabase(); }); $this->beforeApplicationDestroyed(function () { RefreshDatabaseState::$lazilyRefreshed = false; }); } } PKz Z?:+Illuminate/Foundation/Testing/WithFaker.phpnuW+Afaker = $this->makeFaker(); } /** * Get the default Faker instance for a given locale. * * @param string|null $locale * @return \Faker\Generator */ protected function faker($locale = null) { return is_null($locale) ? $this->faker : $this->makeFaker($locale); } /** * Create a Faker instance for the given locale. * * @param string|null $locale * @return \Faker\Generator */ protected function makeFaker($locale = null) { if (isset($this->app)) { $locale ??= $this->app->make('config')->get('app.faker_locale', Factory::DEFAULT_LOCALE); if ($this->app->bound(Generator::class)) { return $this->app->make(Generator::class, ['locale' => $locale]); } } return Factory::create($locale ?? Factory::DEFAULT_LOCALE); } } PKz Z2FIlluminate/Foundation/Testing/Traits/CanConfigureMigrationCommands.phpnuW+Aseeder(); return array_merge( [ '--drop-views' => $this->shouldDropViews(), '--drop-types' => $this->shouldDropTypes(), ], $seeder ? ['--seeder' => $seeder] : ['--seed' => $this->shouldSeed()] ); } /** * Determine if views should be dropped when refreshing the database. * * @return bool */ protected function shouldDropViews() { return property_exists($this, 'dropViews') ? $this->dropViews : false; } /** * Determine if types should be dropped when refreshing the database. * * @return bool */ protected function shouldDropTypes() { return property_exists($this, 'dropTypes') ? $this->dropTypes : false; } /** * Determine if the seed task should be run when refreshing the database. * * @return bool */ protected function shouldSeed() { return property_exists($this, 'seed') ? $this->seed : false; } /** * Determine the specific seeder class that should be used when refreshing the database. * * @return mixed */ protected function seeder() { return property_exists($this, 'seeder') ? $this->seeder : false; } } PKz Zإ*Illuminate/Foundation/Testing/Wormhole.phpnuW+Avalue = $value; } /** * Travel forward the given number of milliseconds. * * @param callable|null $callback * @return mixed */ public function millisecond($callback = null) { return $this->milliseconds($callback); } /** * Travel forward the given number of milliseconds. * * @param callable|null $callback * @return mixed */ public function milliseconds($callback = null) { Carbon::setTestNow(Carbon::now()->addMilliseconds($this->value)); return $this->handleCallback($callback); } /** * Travel forward the given number of seconds. * * @param callable|null $callback * @return mixed */ public function second($callback = null) { return $this->seconds($callback); } /** * Travel forward the given number of seconds. * * @param callable|null $callback * @return mixed */ public function seconds($callback = null) { Carbon::setTestNow(Carbon::now()->addSeconds($this->value)); return $this->handleCallback($callback); } /** * Travel forward the given number of minutes. * * @param callable|null $callback * @return mixed */ public function minute($callback = null) { return $this->minutes($callback); } /** * Travel forward the given number of minutes. * * @param callable|null $callback * @return mixed */ public function minutes($callback = null) { Carbon::setTestNow(Carbon::now()->addMinutes($this->value)); return $this->handleCallback($callback); } /** * Travel forward the given number of hours. * * @param callable|null $callback * @return mixed */ public function hour($callback = null) { return $this->hours($callback); } /** * Travel forward the given number of hours. * * @param callable|null $callback * @return mixed */ public function hours($callback = null) { Carbon::setTestNow(Carbon::now()->addHours($this->value)); return $this->handleCallback($callback); } /** * Travel forward the given number of days. * * @param callable|null $callback * @return mixed */ public function day($callback = null) { return $this->days($callback); } /** * Travel forward the given number of days. * * @param callable|null $callback * @return mixed */ public function days($callback = null) { Carbon::setTestNow(Carbon::now()->addDays($this->value)); return $this->handleCallback($callback); } /** * Travel forward the given number of weeks. * * @param callable|null $callback * @return mixed */ public function week($callback = null) { return $this->weeks($callback); } /** * Travel forward the given number of weeks. * * @param callable|null $callback * @return mixed */ public function weeks($callback = null) { Carbon::setTestNow(Carbon::now()->addWeeks($this->value)); return $this->handleCallback($callback); } /** * Travel forward the given number of months. * * @param callable|null $callback * @return mixed */ public function month($callback = null) { return $this->months($callback); } /** * Travel forward the given number of months. * * @param callable|null $callback * @return mixed */ public function months($callback = null) { Carbon::setTestNow(Carbon::now()->addMonths($this->value)); return $this->handleCallback($callback); } /** * Travel forward the given number of years. * * @param callable|null $callback * @return mixed */ public function year($callback = null) { return $this->years($callback); } /** * Travel forward the given number of years. * * @param callable|null $callback * @return mixed */ public function years($callback = null) { Carbon::setTestNow(Carbon::now()->addYears($this->value)); return $this->handleCallback($callback); } /** * Travel back to the current time. * * @return \DateTimeInterface */ public static function back() { Carbon::setTestNow(); return Carbon::now(); } /** * Handle the given optional execution callback. * * @param callable|null $callback * @return mixed */ protected function handleCallback($callback) { if ($callback) { return tap($callback(), function () { Carbon::setTestNow(); }); } } } PKz Z04Illuminate/Foundation/Testing/DatabaseTruncation.phpnuW+Aartisan('migrate:fresh', $this->migrateFreshUsing()); $this->app[Kernel::class]->setArtisan(null); RefreshDatabaseState::$migrated = true; return; } // Always clear any test data on subsequent runs... $this->truncateTablesForAllConnections(); if ($seeder = $this->seeder()) { // Use a specific seeder class... $this->artisan('db:seed', ['--class' => $seeder]); } elseif ($this->shouldSeed()) { // Use the default seeder class... $this->artisan('db:seed'); } } /** * Truncate the database tables for all configured connections. * * @return void */ protected function truncateTablesForAllConnections(): void { $database = $this->app->make('db'); collect($this->connectionsToTruncate()) ->each(function ($name) use ($database) { $connection = $database->connection($name); $connection->getSchemaBuilder()->withoutForeignKeyConstraints( fn () => $this->truncateTablesForConnection($connection, $name) ); }); } /** * Truncate the database tables for the given database connection. * * @param \Illuminate\Database\ConnectionInterface $connection * @param string|null $name * @return void */ protected function truncateTablesForConnection(ConnectionInterface $connection, ?string $name): void { $dispatcher = $connection->getEventDispatcher(); $connection->unsetEventDispatcher(); collect(static::$allTables[$name] ??= $connection->getDoctrineSchemaManager()->listTableNames()) ->when( property_exists($this, 'tablesToTruncate'), fn ($tables) => $tables->intersect($this->tablesToTruncate), fn ($tables) => $tables->diff($this->exceptTables($name)) ) ->filter(fn ($table) => $connection->table($table)->exists()) ->each(fn ($table) => $connection->table($table)->truncate()); $connection->setEventDispatcher($dispatcher); } /** * The database connections that should have their tables truncated. * * @return array */ protected function connectionsToTruncate(): array { return property_exists($this, 'connectionsToTruncate') ? $this->connectionsToTruncate : [null]; } /** * Get the tables that should not be truncated. * * @param string|null $connectionName * @return array */ protected function exceptTables(?string $connectionName): array { if (property_exists($this, 'exceptTables')) { return array_merge( $this->exceptTables[$connectionName] ?? [], [$this->app['config']->get('database.migrations')] ); } return [$this->app['config']->get('database.migrations')]; } } PKz Z,&Illuminate/Foundation/Precognition.phpnuW+Amessages()->isEmpty() && $request->headers->has('Precognition-Validate-Only')) { abort(204); } }; } } PKz Zem8Illuminate/Foundation/Auth/Access/AuthorizesRequests.phpnuW+AparseAbilityAndArguments($ability, $arguments); return app(Gate::class)->authorize($ability, $arguments); } /** * Authorize a given action for a user. * * @param \Illuminate\Contracts\Auth\Authenticatable|mixed $user * @param mixed $ability * @param mixed|array $arguments * @return \Illuminate\Auth\Access\Response * * @throws \Illuminate\Auth\Access\AuthorizationException */ public function authorizeForUser($user, $ability, $arguments = []) { [$ability, $arguments] = $this->parseAbilityAndArguments($ability, $arguments); return app(Gate::class)->forUser($user)->authorize($ability, $arguments); } /** * Guesses the ability's name if it wasn't provided. * * @param mixed $ability * @param mixed|array $arguments * @return array */ protected function parseAbilityAndArguments($ability, $arguments) { if (is_string($ability) && ! str_contains($ability, '\\')) { return [$ability, $arguments]; } $method = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]['function']; return [$this->normalizeGuessedAbilityName($method), $ability]; } /** * Normalize the ability name that has been guessed from the method name. * * @param string $ability * @return string */ protected function normalizeGuessedAbilityName($ability) { $map = $this->resourceAbilityMap(); return $map[$ability] ?? $ability; } /** * Authorize a resource action based on the incoming request. * * @param string|array $model * @param string|array|null $parameter * @param array $options * @param \Illuminate\Http\Request|null $request * @return void */ public function authorizeResource($model, $parameter = null, array $options = [], $request = null) { $model = is_array($model) ? implode(',', $model) : $model; $parameter = is_array($parameter) ? implode(',', $parameter) : $parameter; $parameter = $parameter ?: Str::snake(class_basename($model)); $middleware = []; foreach ($this->resourceAbilityMap() as $method => $ability) { $modelName = in_array($method, $this->resourceMethodsWithoutModels()) ? $model : $parameter; $middleware["can:{$ability},{$modelName}"][] = $method; } foreach ($middleware as $middlewareName => $methods) { $this->middleware($middlewareName, $options)->only($methods); } } /** * Get the map of resource methods to ability names. * * @return array */ protected function resourceAbilityMap() { return [ 'index' => 'viewAny', 'show' => 'view', 'create' => 'create', 'store' => 'create', 'edit' => 'update', 'update' => 'update', 'destroy' => 'delete', ]; } /** * Get the list of resource methods which do not have model parameters. * * @return array */ protected function resourceMethodsWithoutModels() { return ['index', 'create', 'store']; } } PKz ZO||2Illuminate/Foundation/Auth/Access/Authorizable.phpnuW+AforUser($this)->check($abilities, $arguments); } /** * Determine if the entity has any of the given abilities. * * @param iterable|string $abilities * @param array|mixed $arguments * @return bool */ public function canAny($abilities, $arguments = []) { return app(Gate::class)->forUser($this)->any($abilities, $arguments); } /** * Determine if the entity does not have the given abilities. * * @param iterable|string $abilities * @param array|mixed $arguments * @return bool */ public function cant($abilities, $arguments = []) { return ! $this->can($abilities, $arguments); } /** * Determine if the entity does not have the given abilities. * * @param iterable|string $abilities * @param array|mixed $arguments * @return bool */ public function cannot($abilities, $arguments = []) { return $this->cant($abilities, $arguments); } } PKz Z/#Illuminate/Foundation/Auth/User.phpnuW+Auser()->getKey(), (string) $this->route('id'))) { return false; } if (! hash_equals(sha1($this->user()->getEmailForVerification()), (string) $this->route('hash'))) { return false; } return true; } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ // ]; } /** * Fulfill the email verification request. * * @return void */ public function fulfill() { if (! $this->user()->hasVerifiedEmail()) { $this->user()->markEmailAsVerified(); event(new Verified($this->user())); } } /** * Configure the validator instance. * * @param \Illuminate\Validation\Validator $validator * @return void */ public function withValidator($validator) { return $validator; } } PKz Z ;4"nn5Illuminate/Foundation/Concerns/ResolvesDumpSource.phpnuW+A */ protected $editorHrefs = [ 'atom' => 'atom://core/open/file?filename={file}&line={line}', 'emacs' => 'emacs://open?url=file://{file}&line={line}', 'idea' => 'idea://open?file={file}&line={line}', 'macvim' => 'mvim://open/?url=file://{file}&line={line}', 'netbeans' => 'netbeans://open/?f={file}:{line}', 'nova' => 'nova://core/open/file?filename={file}&line={line}', 'phpstorm' => 'phpstorm://open?file={file}&line={line}', 'sublime' => 'subl://open?url=file://{file}&line={line}', 'textmate' => 'txmt://open?url=file://{file}&line={line}', 'vscode' => 'vscode://file/{file}:{line}', 'vscode-insiders' => 'vscode-insiders://file/{file}:{line}', 'vscode-insiders-remote' => 'vscode-insiders://vscode-remote/{file}:{line}', 'vscode-remote' => 'vscode://vscode-remote/{file}:{line}', 'vscodium' => 'vscodium://file/{file}:{line}', 'xdebug' => 'xdebug://{file}@{line}', ]; /** * Files that require special trace handling and their levels. * * @var array */ protected static $adjustableTraces = [ 'symfony/var-dumper/Resources/functions/dump.php' => 1, 'Illuminate/Collections/Traits/EnumeratesValues.php' => 4, ]; /** * The source resolver. * * @var (callable(): (array{0: string, 1: string, 2: int|null}|null))|null|false */ protected static $dumpSourceResolver; /** * Resolve the source of the dump call. * * @return array{0: string, 1: string, 2: int|null}|null */ public function resolveDumpSource() { if (static::$dumpSourceResolver === false) { return null; } if (static::$dumpSourceResolver) { return call_user_func(static::$dumpSourceResolver); } $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 20); $sourceKey = null; foreach ($trace as $traceKey => $traceFile) { if (! isset($traceFile['file'])) { continue; } foreach (self::$adjustableTraces as $name => $key) { if (str_ends_with( $traceFile['file'], str_replace('/', DIRECTORY_SEPARATOR, $name) )) { $sourceKey = $traceKey + $key; break; } } if (! is_null($sourceKey)) { break; } } if (is_null($sourceKey)) { return; } $file = $trace[$sourceKey]['file'] ?? null; $line = $trace[$sourceKey]['line'] ?? null; if (is_null($file) || is_null($line)) { return; } $relativeFile = $file; if ($this->isCompiledViewFile($file)) { $file = $this->getOriginalFileForCompiledView($file); $line = null; } if (str_starts_with($file, $this->basePath)) { $relativeFile = substr($file, strlen($this->basePath) + 1); } return [$file, $relativeFile, $line]; } /** * Determine if the given file is a view compiled. * * @param string $file * @return bool */ protected function isCompiledViewFile($file) { return str_starts_with($file, $this->compiledViewPath); } /** * Get the original view compiled file by the given compiled file. * * @param string $file * @return string */ protected function getOriginalFileForCompiledView($file) { preg_match('/\/\*\*PATH\s(.*)\sENDPATH/', file_get_contents($file), $matches); if (isset($matches[1])) { $file = $matches[1]; } return $file; } /** * Resolve the source href, if possible. * * @param string $file * @param int|null $line * @return string|null */ protected function resolveSourceHref($file, $line) { try { $editor = config('app.editor'); } catch (Throwable $e) { // .. } if (! isset($editor)) { return; } $href = is_array($editor) && isset($editor['href']) ? $editor['href'] : ($this->editorHrefs[$editor['name'] ?? $editor] ?? sprintf('%s://open?file={file}&line={line}', $editor['name'] ?? $editor)); if ($basePath = $editor['base_path'] ?? false) { $file = str_replace($this->basePath, $basePath, $file); } $href = str_replace( ['{file}', '{line}'], [$file, is_null($line) ? 1 : $line], $href, ); return $href; } /** * Set the resolver that resolves the source of the dump call. * * @param (callable(): (array{0: string, 1: string, 2: int|null}|null))|null $callable * @return void */ public static function resolveDumpSourceUsing($callable) { static::$dumpSourceResolver = $callable; } /** * Don't include the location / file of the dump in dumps. * * @return void */ public static function dontIncludeSource() { static::$dumpSourceResolver = false; } } PKz ZEkF F @Illuminate/Foundation/Support/Providers/RouteServiceProvider.phpnuW+Abooted(function () { $this->setRootControllerNamespace(); if ($this->routesAreCached()) { $this->loadCachedRoutes(); } else { $this->loadRoutes(); $this->app->booted(function () { $this->app['router']->getRoutes()->refreshNameLookups(); $this->app['router']->getRoutes()->refreshActionLookups(); }); } }); } /** * Bootstrap any application services. * * @return void */ public function boot() { // } /** * Register the callback that will be used to load the application's routes. * * @param \Closure $routesCallback * @return $this */ protected function routes(Closure $routesCallback) { $this->loadRoutesUsing = $routesCallback; return $this; } /** * Set the root controller namespace for the application. * * @return void */ protected function setRootControllerNamespace() { if (! is_null($this->namespace)) { $this->app[UrlGenerator::class]->setRootControllerNamespace($this->namespace); } } /** * Determine if the application routes are cached. * * @return bool */ protected function routesAreCached() { return $this->app->routesAreCached(); } /** * Load the cached routes for the application. * * @return void */ protected function loadCachedRoutes() { $this->app->booted(function () { require $this->app->getCachedRoutesPath(); }); } /** * Load the application routes. * * @return void */ protected function loadRoutes() { if (! is_null($this->loadRoutesUsing)) { $this->app->call($this->loadRoutesUsing); } elseif (method_exists($this, 'map')) { $this->app->call([$this, 'map']); } } /** * Pass dynamic methods onto the router instance. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { return $this->forwardCallTo( $this->app->make(Router::class), $method, $parameters ); } } PKz Z*h@?Illuminate/Foundation/Support/Providers/AuthServiceProvider.phpnuW+A */ protected $policies = []; /** * Register the application's policies. * * @return void */ public function registerPolicies() { foreach ($this->policies() as $model => $policy) { Gate::policy($model, $policy); } } /** * Get the policies defined on the provider. * * @return array */ public function policies() { return $this->policies; } } PKz Z55@Illuminate/Foundation/Support/Providers/EventServiceProvider.phpnuW+A> */ protected $listen = []; /** * The subscribers to register. * * @var array */ protected $subscribe = []; /** * The model observers to register. * * @var array */ protected $observers = []; /** * Register the application's event listeners. * * @return void */ public function register() { $this->booting(function () { $events = $this->getEvents(); foreach ($events as $event => $listeners) { foreach (array_unique($listeners, SORT_REGULAR) as $listener) { Event::listen($event, $listener); } } foreach ($this->subscribe as $subscriber) { Event::subscribe($subscriber); } foreach ($this->observers as $model => $observers) { $model::observe($observers); } }); } /** * Boot any application services. * * @return void */ public function boot() { // } /** * Get the events and handlers. * * @return array */ public function listens() { return $this->listen; } /** * Get the discovered events and listeners for the application. * * @return array */ public function getEvents() { if ($this->app->eventsAreCached()) { $cache = require $this->app->getCachedEventsPath(); return $cache[get_class($this)] ?? []; } else { return array_merge_recursive( $this->discoveredEvents(), $this->listens() ); } } /** * Get the discovered events for the application. * * @return array */ protected function discoveredEvents() { return $this->shouldDiscoverEvents() ? $this->discoverEvents() : []; } /** * Determine if events and listeners should be automatically discovered. * * @return bool */ public function shouldDiscoverEvents() { return false; } /** * Discover the events and listeners for the application. * * @return array */ public function discoverEvents() { return collect($this->discoverEventsWithin()) ->reject(function ($directory) { return ! is_dir($directory); }) ->reduce(function ($discovered, $directory) { return array_merge_recursive( $discovered, DiscoverEvents::within($directory, $this->eventDiscoveryBasePath()) ); }, []); } /** * Get the listener directories that should be used to discover events. * * @return array */ protected function discoverEventsWithin() { return [ $this->app->path('Listeners'), ]; } /** * Get the base path to be used during event discovery. * * @return string */ protected function eventDiscoveryBasePath() { return base_path(); } } PKz Zqk22#Illuminate/Foundation/Inspiring.phpnuW+A> .~)>> .~))))>>> .~))>> ___ .~))>>)))>> .-~))>> .~)))))>> .-~))>>)> .~)))>>))))>> .-~)>>)> ) .~))>>))))>> .-~)))))>>)> ( )@@*) //)>)))))) .-~))))>>)> ).@(@@ //))>>))) .-~))>>)))))>>)> (( @.@). //))))) .-~)>>)))))>>)> )) )@@*.@@ ) //)>))) //))))))>>))))>>)> (( ((@@@.@@ |/))))) //)))))>>)))>>)> )) @@*. )@@ ) (\_(\-\b |))>)) //)))>>)))))))>>)> (( @@@(.@(@ . _/`-` ~|b |>))) //)>>)))))))>>)> )* @@@ )@* (@) (@) /\b|))) //))))))>>))))>> (( @. )@( @ . _/ / / \b)) //))>>)))))>>>_._ )@@ (@@*)@@. (6///6)- / ^ \b)//))))))>>)))>> ~~-. ( @jgs@@. @@@.*@_ VvvvvV// ^ \b/)>>))))>> _. `bb ((@@ @@@*.(@@ . - | o |' \ ( ^ \b)))>> .' b`, ((@@).*@@ )@ ) \^^^/ (( ^ ~)_ \ / b `, (@@. (@@ ). `-' ((( ^ `\ \ \ \ \| b `. (*.@* / (((( \| | | \ . b `. / / ((((( \ \ / _.-~\ Y, b ; / / / (((((( \ \.-~ _.`" _.-~`, b ; / / `(((((() ) (((((~ `, b ; _/ _/ `"""/ /' ; b ; _.-~_.-~ / /' _.'~bb _.' ((((~~ / /' _.'~bb.--~ (((( __.-~bb.-~ .' b .~~ :bb ,' ~~~~ */ class Inspiring { /** * Get an inspiring quote. * * Taylor & Dayle made this commit from Jungfraujoch. (11,333 ft.) * * May McGinnis always control the board. #LaraconUS2015 * * RIP Charlie - Feb 6, 2018 * * @return string */ public static function quote() { return static::quotes() ->map(fn ($quote) => static::formatForConsole($quote)) ->random(); } /** * Get the collection of inspiring quotes. * * @return \Illuminate\Support\Collection */ public static function quotes() { return Collection::make([ 'Act only according to that maxim whereby you can, at the same time, will that it should become a universal law. - Immanuel Kant', 'An unexamined life is not worth living. - Socrates', 'Be present above all else. - Naval Ravikant', 'Do what you can, with what you have, where you are. - Theodore Roosevelt', 'Happiness is not something readymade. It comes from your own actions. - Dalai Lama', 'He who is contented is rich. - Laozi', 'I begin to speak only when I am certain what I will say is not better left unsaid. - Cato the Younger', 'I have not failed. I\'ve just found 10,000 ways that won\'t work. - Thomas Edison', 'If you do not have a consistent goal in life, you can not live it in a consistent way. - Marcus Aurelius', 'It is never too late to be what you might have been. - George Eliot', 'It is not the man who has too little, but the man who craves more, that is poor. - Seneca', 'It is quality rather than quantity that matters. - Lucius Annaeus Seneca', 'Knowing is not enough; we must apply. Being willing is not enough; we must do. - Leonardo da Vinci', 'Let all your things have their places; let each part of your business have its time. - Benjamin Franklin', 'Live as if you were to die tomorrow. Learn as if you were to live forever. - Mahatma Gandhi', 'No surplus words or unnecessary actions. - Marcus Aurelius', 'Nothing worth having comes easy. - Theodore Roosevelt', 'Order your soul. Reduce your wants. - Augustine', 'People find pleasure in different ways. I find it in keeping my mind clear. - Marcus Aurelius', 'Simplicity is an acquired taste. - Katharine Gerould', 'Simplicity is the consequence of refined emotions. - Jean D\'Alembert', 'Simplicity is the essence of happiness. - Cedric Bledsoe', 'Simplicity is the ultimate sophistication. - Leonardo da Vinci', 'Smile, breathe, and go slowly. - Thich Nhat Hanh', 'The only way to do great work is to love what you do. - Steve Jobs', 'The whole future lies in uncertainty: live immediately. - Seneca', 'Very little is needed to make a happy life. - Marcus Aurelius', 'Waste no more time arguing what a good man should be, be one. - Marcus Aurelius', 'Well begun is half done. - Aristotle', 'When there is no desire, all things are at peace. - Laozi', 'Walk as if you are kissing the Earth with your feet. - Thich Nhat Hanh', 'Because you are alive, everything is possible. - Thich Nhat Hanh', 'Breathing in, I calm body and mind. Breathing out, I smile. - Thich Nhat Hanh', 'Life is available only in the present moment. - Thich Nhat Hanh', 'The best way to take care of the future is to take care of the present moment. - Thich Nhat Hanh', 'Nothing in life is to be feared, it is only to be understood. Now is the time to understand more, so that we may fear less. - Marie Curie', 'The biggest battle is the war against ignorance. - Mustafa Kemal Atatürk', 'Always remember that you are absolutely unique. Just like everyone else. - Margaret Mead', 'You must be the change you wish to see in the world. - Mahatma Gandhi', ]); } /** * Formats the given quote for a pretty console output. * * @param string $quote * @return string */ protected static function formatForConsole($quote) { [$text, $author] = str($quote)->explode('-'); return sprintf( "\n “ %s ”\n — %s\n", trim($text), trim($author), ); } } PKz ZH]BIlluminate/Foundation/Routing/PrecognitionControllerDispatcher.phpnuW+AensureMethodExists($controller, $method); $this->resolveParameters($route, $controller, $method); abort(204); } /** * Ensure that the given method exists on the controller. * * @param object $controller * @param string $method * @return $this */ protected function ensureMethodExists($controller, $method) { if (method_exists($controller, $method)) { return $this; } $class = $controller::class; throw new RuntimeException("Attempting to predict the outcome of the [{$class}::{$method}()] method but the method is not defined."); } } PKz ZY@Illuminate/Foundation/Routing/PrecognitionCallableDispatcher.phpnuW+AresolveParameters($route, $callable); abort(204); } } PKz ZhX0Illuminate/Foundation/MaintenanceModeManager.phpnuW+Acontainer->make('cache'), $this->config->get('app.maintenance.store') ?: $this->config->get('cache.default'), 'illuminate:foundation:down' ); } /** * Get the default driver name. * * @return string */ public function getDefaultDriver(): string { return $this->config->get('app.maintenance.driver', 'file'); } } PKz ZA2Illuminate/Foundation/FileBasedMaintenanceMode.phpnuW+Apath(), json_encode($payload, JSON_PRETTY_PRINT) ); } /** * Take the application out of maintenance. * * @return void */ public function deactivate(): void { if ($this->active()) { unlink($this->path()); } } /** * Determine if the application is currently down for maintenance. * * @return bool */ public function active(): bool { return file_exists($this->path()); } /** * Get the data array which was provided when the application was placed into maintenance. * * @return array */ public function data(): array { return json_decode(file_get_contents($this->path()), true); } /** * Get the path where the file is stored that signals that the application is down for maintenance. * * @return string */ protected function path(): string { return storage_path('framework/down'); } } PKz Zwq- 6Illuminate/Foundation/Validation/ValidatesRequests.phpnuW+AgetValidationFactory()->make($request->all(), $validator); } if ($request->isPrecognitive()) { $validator->after(Precognition::afterValidationHook($request)) ->setRules( $request->filterPrecognitiveRules($validator->getRulesWithoutPlaceholders()) ); } return $validator->validate(); } /** * Validate the given request with the given rules. * * @param \Illuminate\Http\Request $request * @param array $rules * @param array $messages * @param array $customAttributes * @return array * * @throws \Illuminate\Validation\ValidationException */ public function validate(Request $request, array $rules, array $messages = [], array $customAttributes = []) { $validator = $this->getValidationFactory()->make( $request->all(), $rules, $messages, $customAttributes ); if ($request->isPrecognitive()) { $validator->after(Precognition::afterValidationHook($request)) ->setRules( $request->filterPrecognitiveRules($validator->getRulesWithoutPlaceholders()) ); } return $validator->validate(); } /** * Validate the given request with the given rules. * * @param string $errorBag * @param \Illuminate\Http\Request $request * @param array $rules * @param array $messages * @param array $customAttributes * @return array * * @throws \Illuminate\Validation\ValidationException */ public function validateWithBag($errorBag, Request $request, array $rules, array $messages = [], array $customAttributes = []) { try { return $this->validate($request, $rules, $messages, $customAttributes); } catch (ValidationException $e) { $e->errorBag = $errorBag; throw $e; } } /** * Get a validation factory instance. * * @return \Illuminate\Contracts\Validation\Factory */ protected function getValidationFactory() { return app(Factory::class); } } PKz ZH ;Illuminate/Foundation/Exceptions/RegisterErrorViewPaths.phpnuW+Amap(function ($path) { return "{$path}/errors"; })->push(__DIR__.'/views')->all()); } } PKz Z17Illuminate/Foundation/Exceptions/views/layout.blade.phpnuW+A @yield('title')
@yield('message')
PKz Z7^4Illuminate/Foundation/Exceptions/views/401.blade.phpnuW+A@extends('errors::minimal') @section('title', __('Unauthorized')) @section('code', '401') @section('message', __('Unauthorized')) PKz Z{Ճ4Illuminate/Foundation/Exceptions/views/419.blade.phpnuW+A@extends('errors::minimal') @section('title', __('Page Expired')) @section('code', '419') @section('message', __('Page Expired')) PKz Z:4Illuminate/Foundation/Exceptions/views/500.blade.phpnuW+A@extends('errors::minimal') @section('title', __('Server Error')) @section('code', '500') @section('message', __('Server Error')) PKz Z&U4Illuminate/Foundation/Exceptions/views/429.blade.phpnuW+A@extends('errors::minimal') @section('title', __('Too Many Requests')) @section('code', '429') @section('message', __('Too Many Requests')) PKz Z6!4Illuminate/Foundation/Exceptions/views/503.blade.phpnuW+A@extends('errors::minimal') @section('title', __('Service Unavailable')) @section('code', '503') @section('message', __('Service Unavailable')) PKz Z}}4Illuminate/Foundation/Exceptions/views/404.blade.phpnuW+A@extends('errors::minimal') @section('title', __('Not Found')) @section('code', '404') @section('message', __('Not Found')) PKz Zh8Illuminate/Foundation/Exceptions/views/minimal.blade.phpnuW+A @yield('title')
@yield('code')
@yield('message')
PKz Z)4Illuminate/Foundation/Exceptions/views/403.blade.phpnuW+A@extends('errors::minimal') @section('title', __('Forbidden')) @section('code', '403') @section('message', __($exception->getMessage() ?: 'Forbidden')) PKz Z:E4Illuminate/Foundation/Exceptions/views/402.blade.phpnuW+A@extends('errors::minimal') @section('title', __('Payment Required')) @section('code', '402') @section('message', __('Payment Required')) PKz Z=Ҍ6Illuminate/Foundation/Exceptions/ReportableHandler.phpnuW+Acallback = $callback; } /** * Invoke the handler. * * @param \Throwable $e * @return bool */ public function __invoke(Throwable $e) { $result = call_user_func($this->callback, $e); if ($result === false) { return false; } return ! $this->shouldStop; } /** * Determine if the callback handles the given exception. * * @param \Throwable $e * @return bool */ public function handles(Throwable $e) { foreach ($this->firstClosureParameterTypes($this->callback) as $type) { if (is_a($e, $type)) { return true; } } return false; } /** * Indicate that report handling should stop after invoking this callback. * * @return $this */ public function stop() { $this->shouldStop = true; return $this; } } PKz ZXX,Illuminate/Foundation/Exceptions/Handler.phpnuW+A> */ protected $dontReport = []; /** * The callbacks that should be used during reporting. * * @var \Illuminate\Foundation\Exceptions\ReportableHandler[] */ protected $reportCallbacks = []; /** * A map of exceptions with their corresponding custom log levels. * * @var array, \Psr\Log\LogLevel::*> */ protected $levels = []; /** * The callbacks that should be used during rendering. * * @var \Closure[] */ protected $renderCallbacks = []; /** * The registered exception mappings. * * @var array */ protected $exceptionMap = []; /** * A list of the internal exception types that should not be reported. * * @var array> */ protected $internalDontReport = [ AuthenticationException::class, AuthorizationException::class, BackedEnumCaseNotFoundException::class, HttpException::class, HttpResponseException::class, ModelNotFoundException::class, MultipleRecordsFoundException::class, RecordsNotFoundException::class, SuspiciousOperationException::class, TokenMismatchException::class, ValidationException::class, ]; /** * A list of the inputs that are never flashed for validation exceptions. * * @var array */ protected $dontFlash = [ 'current_password', 'password', 'password_confirmation', ]; /** * Create a new exception handler instance. * * @param \Illuminate\Contracts\Container\Container $container * @return void */ public function __construct(Container $container) { $this->container = $container; $this->register(); } /** * Register the exception handling callbacks for the application. * * @return void */ public function register() { // } /** * Register a reportable callback. * * @param callable $reportUsing * @return \Illuminate\Foundation\Exceptions\ReportableHandler */ public function reportable(callable $reportUsing) { if (! $reportUsing instanceof Closure) { $reportUsing = Closure::fromCallable($reportUsing); } return tap(new ReportableHandler($reportUsing), function ($callback) { $this->reportCallbacks[] = $callback; }); } /** * Register a renderable callback. * * @param callable $renderUsing * @return $this */ public function renderable(callable $renderUsing) { if (! $renderUsing instanceof Closure) { $renderUsing = Closure::fromCallable($renderUsing); } $this->renderCallbacks[] = $renderUsing; return $this; } /** * Register a new exception mapping. * * @param \Closure|string $from * @param \Closure|string|null $to * @return $this * * @throws \InvalidArgumentException */ public function map($from, $to = null) { if (is_string($to)) { $to = fn ($exception) => new $to('', 0, $exception); } if (is_callable($from) && is_null($to)) { $from = $this->firstClosureParameterType($to = $from); } if (! is_string($from) || ! $to instanceof Closure) { throw new InvalidArgumentException('Invalid exception mapping.'); } $this->exceptionMap[$from] = $to; return $this; } /** * Indicate that the given exception type should not be reported. * * @param string $class * @return $this */ public function ignore(string $class) { $this->dontReport[] = $class; return $this; } /** * Set the log level for the given exception type. * * @param class-string<\Throwable> $type * @param \Psr\Log\LogLevel::* $level * @return $this */ public function level($type, $level) { $this->levels[$type] = $level; return $this; } /** * Report or log an exception. * * @param \Throwable $e * @return void * * @throws \Throwable */ public function report(Throwable $e) { $e = $this->mapException($e); if ($this->shouldntReport($e)) { return; } if (Reflector::isCallable($reportCallable = [$e, 'report']) && $this->container->call($reportCallable) !== false) { return; } foreach ($this->reportCallbacks as $reportCallback) { if ($reportCallback->handles($e) && $reportCallback($e) === false) { return; } } try { $logger = $this->container->make(LoggerInterface::class); } catch (Exception $ex) { throw $e; } $level = Arr::first( $this->levels, fn ($level, $type) => $e instanceof $type, LogLevel::ERROR ); $context = $this->buildExceptionContext($e); method_exists($logger, $level) ? $logger->{$level}($e->getMessage(), $context) : $logger->log($level, $e->getMessage(), $context); } /** * Determine if the exception should be reported. * * @param \Throwable $e * @return bool */ public function shouldReport(Throwable $e) { return ! $this->shouldntReport($e); } /** * Determine if the exception is in the "do not report" list. * * @param \Throwable $e * @return bool */ protected function shouldntReport(Throwable $e) { $dontReport = array_merge($this->dontReport, $this->internalDontReport); return ! is_null(Arr::first($dontReport, fn ($type) => $e instanceof $type)); } /** * Create the context array for logging the given exception. * * @param \Throwable $e * @return array */ protected function buildExceptionContext(Throwable $e) { return array_merge( $this->exceptionContext($e), $this->context(), ['exception' => $e] ); } /** * Get the default exception context variables for logging. * * @param \Throwable $e * @return array */ protected function exceptionContext(Throwable $e) { if (method_exists($e, 'context')) { return $e->context(); } return []; } /** * Get the default context variables for logging. * * @return array */ protected function context() { try { return array_filter([ 'userId' => Auth::id(), ]); } catch (Throwable $e) { return []; } } /** * Render an exception into an HTTP response. * * @param \Illuminate\Http\Request $request * @param \Throwable $e * @return \Symfony\Component\HttpFoundation\Response * * @throws \Throwable */ public function render($request, Throwable $e) { if (method_exists($e, 'render') && $response = $e->render($request)) { return Router::toResponse($request, $response); } if ($e instanceof Responsable) { return $e->toResponse($request); } $e = $this->prepareException($this->mapException($e)); if ($response = $this->renderViaCallbacks($request, $e)) { return $response; } return match (true) { $e instanceof HttpResponseException => $e->getResponse(), $e instanceof AuthenticationException => $this->unauthenticated($request, $e), $e instanceof ValidationException => $this->convertValidationExceptionToResponse($e, $request), default => $this->renderExceptionResponse($request, $e), }; } /** * Prepare exception for rendering. * * @param \Throwable $e * @return \Throwable */ protected function prepareException(Throwable $e) { return match (true) { $e instanceof BackedEnumCaseNotFoundException => new NotFoundHttpException($e->getMessage(), $e), $e instanceof ModelNotFoundException => new NotFoundHttpException($e->getMessage(), $e), $e instanceof AuthorizationException && $e->hasStatus() => new HttpException( $e->status(), $e->response()?->message() ?: (Response::$statusTexts[$e->status()] ?? 'Whoops, looks like something went wrong.'), $e ), $e instanceof AuthorizationException && ! $e->hasStatus() => new AccessDeniedHttpException($e->getMessage(), $e), $e instanceof TokenMismatchException => new HttpException(419, $e->getMessage(), $e), $e instanceof SuspiciousOperationException => new NotFoundHttpException('Bad hostname provided.', $e), $e instanceof RecordsNotFoundException => new NotFoundHttpException('Not found.', $e), default => $e, }; } /** * Map the exception using a registered mapper if possible. * * @param \Throwable $e * @return \Throwable */ protected function mapException(Throwable $e) { if (method_exists($e, 'getInnerException') && ($inner = $e->getInnerException()) instanceof Throwable) { return $inner; } foreach ($this->exceptionMap as $class => $mapper) { if (is_a($e, $class)) { return $mapper($e); } } return $e; } /** * Try to render a response from request and exception via render callbacks. * * @param \Illuminate\Http\Request $request * @param \Throwable $e * @return mixed * * @throws \ReflectionException */ protected function renderViaCallbacks($request, Throwable $e) { foreach ($this->renderCallbacks as $renderCallback) { foreach ($this->firstClosureParameterTypes($renderCallback) as $type) { if (is_a($e, $type)) { $response = $renderCallback($e, $request); if (! is_null($response)) { return $response; } } } } } /** * Render a default exception response if any. * * @param \Illuminate\Http\Request $request * @param \Throwable $e * @return \Symfony\Component\HttpFoundation\Response */ protected function renderExceptionResponse($request, Throwable $e) { return $this->shouldReturnJson($request, $e) ? $this->prepareJsonResponse($request, $e) : $this->prepareResponse($request, $e); } /** * Convert an authentication exception into a response. * * @param \Illuminate\Http\Request $request * @param \Illuminate\Auth\AuthenticationException $exception * @return \Symfony\Component\HttpFoundation\Response */ protected function unauthenticated($request, AuthenticationException $exception) { return $this->shouldReturnJson($request, $exception) ? response()->json(['message' => $exception->getMessage()], 401) : redirect()->guest($exception->redirectTo() ?? route('login')); } /** * Create a response object from the given validation exception. * * @param \Illuminate\Validation\ValidationException $e * @param \Illuminate\Http\Request $request * @return \Symfony\Component\HttpFoundation\Response */ protected function convertValidationExceptionToResponse(ValidationException $e, $request) { if ($e->response) { return $e->response; } return $this->shouldReturnJson($request, $e) ? $this->invalidJson($request, $e) : $this->invalid($request, $e); } /** * Convert a validation exception into a response. * * @param \Illuminate\Http\Request $request * @param \Illuminate\Validation\ValidationException $exception * @return \Illuminate\Http\Response */ protected function invalid($request, ValidationException $exception) { return redirect($exception->redirectTo ?? url()->previous()) ->withInput(Arr::except($request->input(), $this->dontFlash)) ->withErrors($exception->errors(), $request->input('_error_bag', $exception->errorBag)); } /** * Convert a validation exception into a JSON response. * * @param \Illuminate\Http\Request $request * @param \Illuminate\Validation\ValidationException $exception * @return \Illuminate\Http\JsonResponse */ protected function invalidJson($request, ValidationException $exception) { return response()->json([ 'message' => $exception->getMessage(), 'errors' => $exception->errors(), ], $exception->status); } /** * Determine if the exception handler response should be JSON. * * @param \Illuminate\Http\Request $request * @param \Throwable $e * @return bool */ protected function shouldReturnJson($request, Throwable $e) { return $request->expectsJson(); } /** * Prepare a response for the given exception. * * @param \Illuminate\Http\Request $request * @param \Throwable $e * @return \Symfony\Component\HttpFoundation\Response */ protected function prepareResponse($request, Throwable $e) { if (! $this->isHttpException($e) && config('app.debug')) { return $this->toIlluminateResponse($this->convertExceptionToResponse($e), $e)->prepare($request); } if (! $this->isHttpException($e)) { $e = new HttpException(500, $e->getMessage(), $e); } return $this->toIlluminateResponse( $this->renderHttpException($e), $e )->prepare($request); } /** * Create a Symfony response for the given exception. * * @param \Throwable $e * @return \Symfony\Component\HttpFoundation\Response */ protected function convertExceptionToResponse(Throwable $e) { return new SymfonyResponse( $this->renderExceptionContent($e), $this->isHttpException($e) ? $e->getStatusCode() : 500, $this->isHttpException($e) ? $e->getHeaders() : [] ); } /** * Get the response content for the given exception. * * @param \Throwable $e * @return string */ protected function renderExceptionContent(Throwable $e) { try { return config('app.debug') && app()->has(ExceptionRenderer::class) ? $this->renderExceptionWithCustomRenderer($e) : $this->renderExceptionWithSymfony($e, config('app.debug')); } catch (Throwable $e) { return $this->renderExceptionWithSymfony($e, config('app.debug')); } } /** * Render an exception to a string using the registered `ExceptionRenderer`. * * @param \Throwable $e * @return string */ protected function renderExceptionWithCustomRenderer(Throwable $e) { return app(ExceptionRenderer::class)->render($e); } /** * Render an exception to a string using Symfony. * * @param \Throwable $e * @param bool $debug * @return string */ protected function renderExceptionWithSymfony(Throwable $e, $debug) { $renderer = new HtmlErrorRenderer($debug); return $renderer->render($e)->getAsString(); } /** * Render the given HttpException. * * @param \Symfony\Component\HttpKernel\Exception\HttpExceptionInterface $e * @return \Symfony\Component\HttpFoundation\Response */ protected function renderHttpException(HttpExceptionInterface $e) { $this->registerErrorViewPaths(); if ($view = $this->getHttpExceptionView($e)) { return response()->view($view, [ 'errors' => new ViewErrorBag, 'exception' => $e, ], $e->getStatusCode(), $e->getHeaders()); } return $this->convertExceptionToResponse($e); } /** * Register the error template hint paths. * * @return void */ protected function registerErrorViewPaths() { (new RegisterErrorViewPaths)(); } /** * Get the view used to render HTTP exceptions. * * @param \Symfony\Component\HttpKernel\Exception\HttpExceptionInterface $e * @return string|null */ protected function getHttpExceptionView(HttpExceptionInterface $e) { $view = 'errors::'.$e->getStatusCode(); if (view()->exists($view)) { return $view; } $view = substr($view, 0, -2).'xx'; if (view()->exists($view)) { return $view; } return null; } /** * Map the given exception into an Illuminate response. * * @param \Symfony\Component\HttpFoundation\Response $response * @param \Throwable $e * @return \Illuminate\Http\Response */ protected function toIlluminateResponse($response, Throwable $e) { if ($response instanceof SymfonyRedirectResponse) { $response = new RedirectResponse( $response->getTargetUrl(), $response->getStatusCode(), $response->headers->all() ); } else { $response = new Response( $response->getContent(), $response->getStatusCode(), $response->headers->all() ); } return $response->withException($e); } /** * Prepare a JSON response for the given exception. * * @param \Illuminate\Http\Request $request * @param \Throwable $e * @return \Illuminate\Http\JsonResponse */ protected function prepareJsonResponse($request, Throwable $e) { return new JsonResponse( $this->convertExceptionToArray($e), $this->isHttpException($e) ? $e->getStatusCode() : 500, $this->isHttpException($e) ? $e->getHeaders() : [], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ); } /** * Convert the given exception to an array. * * @param \Throwable $e * @return array */ protected function convertExceptionToArray(Throwable $e) { return config('app.debug') ? [ 'message' => $e->getMessage(), 'exception' => get_class($e), 'file' => $e->getFile(), 'line' => $e->getLine(), 'trace' => collect($e->getTrace())->map(fn ($trace) => Arr::except($trace, ['args']))->all(), ] : [ 'message' => $this->isHttpException($e) ? $e->getMessage() : 'Server Error', ]; } /** * Render an exception to the console. * * @param \Symfony\Component\Console\Output\OutputInterface $output * @param \Throwable $e * @return void * * @internal This method is not meant to be used or overwritten outside the framework. */ public function renderForConsole($output, Throwable $e) { if ($e instanceof CommandNotFoundException) { $message = str($e->getMessage())->explode('.')->first(); if (! empty($alternatives = $e->getAlternatives())) { $message .= '. Did you mean one of these?'; with(new Error($output))->render($message); with(new BulletList($output))->render($e->getAlternatives()); $output->writeln(''); } else { with(new Error($output))->render($message); } return; } (new ConsoleApplication)->renderThrowable($e, $output); } /** * Determine if the given exception is an HTTP exception. * * @param \Throwable $e * @return bool */ protected function isHttpException(Throwable $e) { return $e instanceof HttpExceptionInterface; } } PKz Z!SSCIlluminate/Foundation/Exceptions/Whoops/WhoopsExceptionRenderer.phpnuW+AappendHandler($this->whoopsHandler()); $whoops->writeToOutput(false); $whoops->allowQuit(false); })->handleException($throwable); } /** * Get the Whoops handler for the application. * * @return \Whoops\Handler\Handler */ protected function whoopsHandler() { return (new WhoopsHandler)->forDebug(); } } PKz Z( 339Illuminate/Foundation/Exceptions/Whoops/WhoopsHandler.phpnuW+AhandleUnconditionally(true); $this->registerApplicationPaths($handler) ->registerBlacklist($handler) ->registerEditor($handler); }); } /** * Register the application paths with the handler. * * @param \Whoops\Handler\PrettyPageHandler $handler * @return $this */ protected function registerApplicationPaths($handler) { $handler->setApplicationPaths( array_flip($this->directoriesExceptVendor()) ); return $this; } /** * Get the application paths except for the "vendor" directory. * * @return array */ protected function directoriesExceptVendor() { return Arr::except( array_flip((new Filesystem)->directories(base_path())), [base_path('vendor')] ); } /** * Register the blacklist with the handler. * * @param \Whoops\Handler\PrettyPageHandler $handler * @return $this */ protected function registerBlacklist($handler) { foreach (config('app.debug_blacklist', config('app.debug_hide', [])) as $key => $secrets) { foreach ($secrets as $secret) { $handler->blacklist($key, $secret); } } return $this; } /** * Register the editor with the handler. * * @param \Whoops\Handler\PrettyPageHandler $handler * @return $this */ protected function registerEditor($handler) { if (config('app.editor', false)) { $handler->setEditor(config('app.editor')); } return $this; } } PKz Z ˡA995Illuminate/Foundation/Bootstrap/LoadConfiguration.phpnuW+AgetCachedConfigPath())) { $items = require $cached; $loadedFromCache = true; } // Next we will spin through all of the configuration files in the configuration // directory and load each one into the repository. This will make all of the // options available to the developer for use in various parts of this app. $app->instance('config', $config = new Repository($items)); if (! isset($loadedFromCache)) { $this->loadConfigurationFiles($app, $config); } // Finally, we will set the application's environment based on the configuration // values that were loaded. We will pass a callback which will be used to get // the environment in a web context where an "--env" switch is not present. $app->detectEnvironment(fn () => $config->get('app.env', 'production')); date_default_timezone_set($config->get('app.timezone', 'UTC')); mb_internal_encoding('UTF-8'); } /** * Load the configuration items from all of the files. * * @param \Illuminate\Contracts\Foundation\Application $app * @param \Illuminate\Contracts\Config\Repository $repository * @return void * * @throws \Exception */ protected function loadConfigurationFiles(Application $app, RepositoryContract $repository) { $files = $this->getConfigurationFiles($app); if (! isset($files['app'])) { throw new Exception('Unable to load the "app" configuration file.'); } foreach ($files as $key => $path) { $repository->set($key, require $path); } } /** * Get all of the configuration files for the application. * * @param \Illuminate\Contracts\Foundation\Application $app * @return array */ protected function getConfigurationFiles(Application $app) { $files = []; $configPath = realpath($app->configPath()); foreach (Finder::create()->files()->name('*.php')->in($configPath) as $file) { $directory = $this->getNestedDirectory($file, $configPath); $files[$directory.basename($file->getRealPath(), '.php')] = $file->getRealPath(); } ksort($files, SORT_NATURAL); return $files; } /** * Get the configuration file nesting path. * * @param \SplFileInfo $file * @param string $configPath * @return string */ protected function getNestedDirectory(SplFileInfo $file, $configPath) { $directory = $file->getPath(); if ($nested = trim(str_replace($configPath, '', $directory), DIRECTORY_SEPARATOR)) { $nested = str_replace(DIRECTORY_SEPARATOR, '.', $nested).'.'; } return $nested; } } PKz ZGxkEOO8Illuminate/Foundation/Bootstrap/SetRequestForConsole.phpnuW+Amake('config')->get('app.url', 'http://localhost'); $components = parse_url($uri); $server = $_SERVER; if (isset($components['path'])) { $server = array_merge($server, [ 'SCRIPT_FILENAME' => $components['path'], 'SCRIPT_NAME' => $components['path'], ]); } $app->instance('request', Request::create( $uri, 'GET', [], [], [], $server )); } } PKz Z 4Illuminate/Foundation/Bootstrap/HandleExceptions.phpnuW+AforwardsTo('handleError')); set_exception_handler($this->forwardsTo('handleException')); register_shutdown_function($this->forwardsTo('handleShutdown')); if (! $app->environment('testing')) { ini_set('display_errors', 'Off'); } } /** * Report PHP deprecations, or convert PHP errors to ErrorException instances. * * @param int $level * @param string $message * @param string $file * @param int $line * @param array $context * @return void * * @throws \ErrorException */ public function handleError($level, $message, $file = '', $line = 0, $context = []) { if ($this->isDeprecation($level)) { $this->handleDeprecationError($message, $file, $line, $level); } elseif (error_reporting() & $level) { throw new ErrorException($message, 0, $level, $file, $line); } } /** * Reports a deprecation to the "deprecations" logger. * * @param string $message * @param string $file * @param int $line * @return void * * @deprecated Use handleDeprecationError instead. */ public function handleDeprecation($message, $file, $line) { $this->handleDeprecationError($message, $file, $line); } /** * Reports a deprecation to the "deprecations" logger. * * @param string $message * @param string $file * @param int $line * @param int $level * @return void */ public function handleDeprecationError($message, $file, $line, $level = E_DEPRECATED) { if ($this->shouldIgnoreDeprecationErrors()) { return; } try { $logger = static::$app->make(LogManager::class); } catch (Exception $e) { return; } $this->ensureDeprecationLoggerIsConfigured(); $options = static::$app['config']->get('logging.deprecations') ?? []; with($logger->channel('deprecations'), function ($log) use ($message, $file, $line, $level, $options) { if ($options['trace'] ?? false) { $log->warning((string) new ErrorException($message, 0, $level, $file, $line)); } else { $log->warning(sprintf('%s in %s on line %s', $message, $file, $line )); } }); } /** * Determine if deprecation errors should be ignored. * * @return bool */ protected function shouldIgnoreDeprecationErrors() { return ! class_exists(LogManager::class) || ! static::$app->hasBeenBootstrapped() || static::$app->runningUnitTests(); } /** * Ensure the "deprecations" logger is configured. * * @return void */ protected function ensureDeprecationLoggerIsConfigured() { with(static::$app['config'], function ($config) { if ($config->get('logging.channels.deprecations')) { return; } $this->ensureNullLogDriverIsConfigured(); if (is_array($options = $config->get('logging.deprecations'))) { $driver = $options['channel'] ?? 'null'; } else { $driver = $options ?? 'null'; } $config->set('logging.channels.deprecations', $config->get("logging.channels.{$driver}")); }); } /** * Ensure the "null" log driver is configured. * * @return void */ protected function ensureNullLogDriverIsConfigured() { with(static::$app['config'], function ($config) { if ($config->get('logging.channels.null')) { return; } $config->set('logging.channels.null', [ 'driver' => 'monolog', 'handler' => NullHandler::class, ]); }); } /** * Handle an uncaught exception from the application. * * Note: Most exceptions can be handled via the try / catch block in * the HTTP and Console kernels. But, fatal error exceptions must * be handled differently since they are not normal exceptions. * * @param \Throwable $e * @return void */ public function handleException(Throwable $e) { self::$reservedMemory = null; try { $this->getExceptionHandler()->report($e); } catch (Exception $e) { $exceptionHandlerFailed = true; } if (static::$app->runningInConsole()) { $this->renderForConsole($e); if ($exceptionHandlerFailed ?? false) { exit(1); } } else { $this->renderHttpResponse($e); } } /** * Render an exception to the console. * * @param \Throwable $e * @return void */ protected function renderForConsole(Throwable $e) { $this->getExceptionHandler()->renderForConsole(new ConsoleOutput, $e); } /** * Render an exception as an HTTP response and send it. * * @param \Throwable $e * @return void */ protected function renderHttpResponse(Throwable $e) { $this->getExceptionHandler()->render(static::$app['request'], $e)->send(); } /** * Handle the PHP shutdown event. * * @return void */ public function handleShutdown() { self::$reservedMemory = null; if (! is_null($error = error_get_last()) && $this->isFatal($error['type'])) { $this->handleException($this->fatalErrorFromPhpError($error, 0)); } } /** * Create a new fatal error instance from an error array. * * @param array $error * @param int|null $traceOffset * @return \Symfony\Component\ErrorHandler\Error\FatalError */ protected function fatalErrorFromPhpError(array $error, $traceOffset = null) { return new FatalError($error['message'], 0, $error, $traceOffset); } /** * Forward a method call to the given method if an application instance exists. * * @return callable */ protected function forwardsTo($method) { return fn (...$arguments) => static::$app ? $this->{$method}(...$arguments) : false; } /** * Determine if the error level is a deprecation. * * @param int $level * @return bool */ protected function isDeprecation($level) { return in_array($level, [E_DEPRECATED, E_USER_DEPRECATED]); } /** * Determine if the error type is fatal. * * @param int $type * @return bool */ protected function isFatal($type) { return in_array($type, [E_COMPILE_ERROR, E_CORE_ERROR, E_ERROR, E_PARSE]); } /** * Get an instance of the exception handler. * * @return \Illuminate\Contracts\Debug\ExceptionHandler */ protected function getExceptionHandler() { return static::$app->make(ExceptionHandler::class); } /** * Clear the local application instance from memory. * * @return void */ public static function forgetApp() { static::$app = null; } } PKz Zh <Illuminate/Foundation/Bootstrap/LoadEnvironmentVariables.phpnuW+AconfigurationIsCached()) { return; } $this->checkForSpecificEnvironmentFile($app); try { $this->createDotenv($app)->safeLoad(); } catch (InvalidFileException $e) { $this->writeErrorAndDie($e); } } /** * Detect if a custom environment file matching the APP_ENV exists. * * @param \Illuminate\Contracts\Foundation\Application $app * @return void */ protected function checkForSpecificEnvironmentFile($app) { if ($app->runningInConsole() && ($input = new ArgvInput)->hasParameterOption('--env') && $this->setEnvironmentFilePath($app, $app->environmentFile().'.'.$input->getParameterOption('--env'))) { return; } $environment = Env::get('APP_ENV'); if (! $environment) { return; } $this->setEnvironmentFilePath( $app, $app->environmentFile().'.'.$environment ); } /** * Load a custom environment file. * * @param \Illuminate\Contracts\Foundation\Application $app * @param string $file * @return bool */ protected function setEnvironmentFilePath($app, $file) { if (is_file($app->environmentPath().'/'.$file)) { $app->loadEnvironmentFrom($file); return true; } return false; } /** * Create a Dotenv instance. * * @param \Illuminate\Contracts\Foundation\Application $app * @return \Dotenv\Dotenv */ protected function createDotenv($app) { return Dotenv::create( Env::getRepository(), $app->environmentPath(), $app->environmentFile() ); } /** * Write the error information to the screen and exit. * * @param \Dotenv\Exception\InvalidFileException $e * @return void */ protected function writeErrorAndDie(InvalidFileException $e) { $output = (new ConsoleOutput)->getErrorOutput(); $output->writeln('The environment file is invalid!'); $output->writeln($e->getMessage()); http_response_code(500); exit(1); } } PKz ZmJB3Illuminate/Foundation/Bootstrap/RegisterFacades.phpnuW+Amake('config')->get('app.aliases', []), $app->make(PackageManifest::class)->aliases() ))->register(); } } PKz ZN5Illuminate/Foundation/Bootstrap/RegisterProviders.phpnuW+AregisterConfiguredProviders(); } } PKz ZDdd1Illuminate/Foundation/Bootstrap/BootProviders.phpnuW+Aboot(); } } PKz ZUvv%Illuminate/Foundation/Application.phpnuW+AsetBasePath($basePath); } $this->registerBaseBindings(); $this->registerBaseServiceProviders(); $this->registerCoreContainerAliases(); } /** * Get the version number of the application. * * @return string */ public function version() { return static::VERSION; } /** * Register the basic bindings into the container. * * @return void */ protected function registerBaseBindings() { static::setInstance($this); $this->instance('app', $this); $this->instance(Container::class, $this); $this->singleton(Mix::class); $this->singleton(PackageManifest::class, function () { return new PackageManifest( new Filesystem, $this->basePath(), $this->getCachedPackagesPath() ); }); } /** * Register all of the base service providers. * * @return void */ protected function registerBaseServiceProviders() { $this->register(new EventServiceProvider($this)); $this->register(new LogServiceProvider($this)); $this->register(new RoutingServiceProvider($this)); } /** * Run the given array of bootstrap classes. * * @param string[] $bootstrappers * @return void */ public function bootstrapWith(array $bootstrappers) { $this->hasBeenBootstrapped = true; foreach ($bootstrappers as $bootstrapper) { $this['events']->dispatch('bootstrapping: '.$bootstrapper, [$this]); $this->make($bootstrapper)->bootstrap($this); $this['events']->dispatch('bootstrapped: '.$bootstrapper, [$this]); } } /** * Register a callback to run after loading the environment. * * @param \Closure $callback * @return void */ public function afterLoadingEnvironment(Closure $callback) { $this->afterBootstrapping( LoadEnvironmentVariables::class, $callback ); } /** * Register a callback to run before a bootstrapper. * * @param string $bootstrapper * @param \Closure $callback * @return void */ public function beforeBootstrapping($bootstrapper, Closure $callback) { $this['events']->listen('bootstrapping: '.$bootstrapper, $callback); } /** * Register a callback to run after a bootstrapper. * * @param string $bootstrapper * @param \Closure $callback * @return void */ public function afterBootstrapping($bootstrapper, Closure $callback) { $this['events']->listen('bootstrapped: '.$bootstrapper, $callback); } /** * Determine if the application has been bootstrapped before. * * @return bool */ public function hasBeenBootstrapped() { return $this->hasBeenBootstrapped; } /** * Set the base path for the application. * * @param string $basePath * @return $this */ public function setBasePath($basePath) { $this->basePath = rtrim($basePath, '\/'); $this->bindPathsInContainer(); return $this; } /** * Bind all of the application paths in the container. * * @return void */ protected function bindPathsInContainer() { $this->instance('path', $this->path()); $this->instance('path.base', $this->basePath()); $this->instance('path.config', $this->configPath()); $this->instance('path.public', $this->publicPath()); $this->instance('path.storage', $this->storagePath()); $this->instance('path.database', $this->databasePath()); $this->instance('path.resources', $this->resourcePath()); $this->instance('path.bootstrap', $this->bootstrapPath()); $this->useLangPath(value(function () { if (is_dir($directory = $this->resourcePath('lang'))) { return $directory; } return $this->basePath('lang'); })); } /** * Get the path to the application "app" directory. * * @param string $path * @return string */ public function path($path = '') { $appPath = $this->appPath ?: $this->basePath.DIRECTORY_SEPARATOR.'app'; return $appPath.($path != '' ? DIRECTORY_SEPARATOR.$path : ''); } /** * Set the application directory. * * @param string $path * @return $this */ public function useAppPath($path) { $this->appPath = $path; $this->instance('path', $path); return $this; } /** * Get the base path of the Laravel installation. * * @param string $path * @return string */ public function basePath($path = '') { return $this->basePath.($path != '' ? DIRECTORY_SEPARATOR.$path : ''); } /** * Get the path to the bootstrap directory. * * @param string $path * @return string */ public function bootstrapPath($path = '') { return $this->basePath.DIRECTORY_SEPARATOR.'bootstrap'.($path != '' ? DIRECTORY_SEPARATOR.$path : ''); } /** * Get the path to the application configuration files. * * @param string $path * @return string */ public function configPath($path = '') { return $this->basePath.DIRECTORY_SEPARATOR.'config'.($path != '' ? DIRECTORY_SEPARATOR.$path : ''); } /** * Get the path to the database directory. * * @param string $path * @return string */ public function databasePath($path = '') { return ($this->databasePath ?: $this->basePath.DIRECTORY_SEPARATOR.'database').($path != '' ? DIRECTORY_SEPARATOR.$path : ''); } /** * Set the database directory. * * @param string $path * @return $this */ public function useDatabasePath($path) { $this->databasePath = $path; $this->instance('path.database', $path); return $this; } /** * Get the path to the language files. * * @param string $path * @return string */ public function langPath($path = '') { return $this->langPath.($path != '' ? DIRECTORY_SEPARATOR.$path : ''); } /** * Set the language file directory. * * @param string $path * @return $this */ public function useLangPath($path) { $this->langPath = $path; $this->instance('path.lang', $path); return $this; } /** * Get the path to the public / web directory. * * @return string */ public function publicPath() { return $this->basePath.DIRECTORY_SEPARATOR.'public'; } /** * Get the path to the storage directory. * * @param string $path * @return string */ public function storagePath($path = '') { return ($this->storagePath ?: $this->basePath.DIRECTORY_SEPARATOR.'storage') .($path != '' ? DIRECTORY_SEPARATOR.$path : ''); } /** * Set the storage directory. * * @param string $path * @return $this */ public function useStoragePath($path) { $this->storagePath = $path; $this->instance('path.storage', $path); return $this; } /** * Get the path to the resources directory. * * @param string $path * @return string */ public function resourcePath($path = '') { return $this->basePath.DIRECTORY_SEPARATOR.'resources'.($path != '' ? DIRECTORY_SEPARATOR.$path : ''); } /** * Get the path to the views directory. * * This method returns the first configured path in the array of view paths. * * @param string $path * @return string */ public function viewPath($path = '') { $basePath = $this['config']->get('view.paths')[0]; return rtrim($basePath, DIRECTORY_SEPARATOR).($path != '' ? DIRECTORY_SEPARATOR.$path : ''); } /** * Get the path to the environment file directory. * * @return string */ public function environmentPath() { return $this->environmentPath ?: $this->basePath; } /** * Set the directory for the environment file. * * @param string $path * @return $this */ public function useEnvironmentPath($path) { $this->environmentPath = $path; return $this; } /** * Set the environment file to be loaded during bootstrapping. * * @param string $file * @return $this */ public function loadEnvironmentFrom($file) { $this->environmentFile = $file; return $this; } /** * Get the environment file the application is using. * * @return string */ public function environmentFile() { return $this->environmentFile ?: '.env'; } /** * Get the fully qualified path to the environment file. * * @return string */ public function environmentFilePath() { return $this->environmentPath().DIRECTORY_SEPARATOR.$this->environmentFile(); } /** * Get or check the current application environment. * * @param string|array ...$environments * @return string|bool */ public function environment(...$environments) { if (count($environments) > 0) { $patterns = is_array($environments[0]) ? $environments[0] : $environments; return Str::is($patterns, $this['env']); } return $this['env']; } /** * Determine if the application is in the local environment. * * @return bool */ public function isLocal() { return $this['env'] === 'local'; } /** * Determine if the application is in the production environment. * * @return bool */ public function isProduction() { return $this['env'] === 'production'; } /** * Detect the application's current environment. * * @param \Closure $callback * @return string */ public function detectEnvironment(Closure $callback) { $args = $_SERVER['argv'] ?? null; return $this['env'] = (new EnvironmentDetector)->detect($callback, $args); } /** * Determine if the application is running in the console. * * @return bool */ public function runningInConsole() { if ($this->isRunningInConsole === null) { $this->isRunningInConsole = Env::get('APP_RUNNING_IN_CONSOLE') ?? (\PHP_SAPI === 'cli' || \PHP_SAPI === 'phpdbg'); } return $this->isRunningInConsole; } /** * Determine if the application is running unit tests. * * @return bool */ public function runningUnitTests() { return $this->bound('env') && $this['env'] === 'testing'; } /** * Determine if the application is running with debug mode enabled. * * @return bool */ public function hasDebugModeEnabled() { return (bool) $this['config']->get('app.debug'); } /** * Register all of the configured providers. * * @return void */ public function registerConfiguredProviders() { $providers = Collection::make($this->make('config')->get('app.providers')) ->partition(fn ($provider) => str_starts_with($provider, 'Illuminate\\')); $providers->splice(1, 0, [$this->make(PackageManifest::class)->providers()]); (new ProviderRepository($this, new Filesystem, $this->getCachedServicesPath())) ->load($providers->collapse()->toArray()); } /** * Register a service provider with the application. * * @param \Illuminate\Support\ServiceProvider|string $provider * @param bool $force * @return \Illuminate\Support\ServiceProvider */ public function register($provider, $force = false) { if (($registered = $this->getProvider($provider)) && ! $force) { return $registered; } // If the given "provider" is a string, we will resolve it, passing in the // application instance automatically for the developer. This is simply // a more convenient way of specifying your service provider classes. if (is_string($provider)) { $provider = $this->resolveProvider($provider); } $provider->register(); // If there are bindings / singletons set as properties on the provider we // will spin through them and register them with the application, which // serves as a convenience layer while registering a lot of bindings. if (property_exists($provider, 'bindings')) { foreach ($provider->bindings as $key => $value) { $this->bind($key, $value); } } if (property_exists($provider, 'singletons')) { foreach ($provider->singletons as $key => $value) { $key = is_int($key) ? $value : $key; $this->singleton($key, $value); } } $this->markAsRegistered($provider); // If the application has already booted, we will call this boot method on // the provider class so it has an opportunity to do its boot logic and // will be ready for any usage by this developer's application logic. if ($this->isBooted()) { $this->bootProvider($provider); } return $provider; } /** * Get the registered service provider instance if it exists. * * @param \Illuminate\Support\ServiceProvider|string $provider * @return \Illuminate\Support\ServiceProvider|null */ public function getProvider($provider) { return array_values($this->getProviders($provider))[0] ?? null; } /** * Get the registered service provider instances if any exist. * * @param \Illuminate\Support\ServiceProvider|string $provider * @return array */ public function getProviders($provider) { $name = is_string($provider) ? $provider : get_class($provider); return Arr::where($this->serviceProviders, fn ($value) => $value instanceof $name); } /** * Resolve a service provider instance from the class name. * * @param string $provider * @return \Illuminate\Support\ServiceProvider */ public function resolveProvider($provider) { return new $provider($this); } /** * Mark the given provider as registered. * * @param \Illuminate\Support\ServiceProvider $provider * @return void */ protected function markAsRegistered($provider) { $this->serviceProviders[] = $provider; $this->loadedProviders[get_class($provider)] = true; } /** * Load and boot all of the remaining deferred providers. * * @return void */ public function loadDeferredProviders() { // We will simply spin through each of the deferred providers and register each // one and boot them if the application has booted. This should make each of // the remaining services available to this application for immediate use. foreach ($this->deferredServices as $service => $provider) { $this->loadDeferredProvider($service); } $this->deferredServices = []; } /** * Load the provider for a deferred service. * * @param string $service * @return void */ public function loadDeferredProvider($service) { if (! $this->isDeferredService($service)) { return; } $provider = $this->deferredServices[$service]; // If the service provider has not already been loaded and registered we can // register it with the application and remove the service from this list // of deferred services, since it will already be loaded on subsequent. if (! isset($this->loadedProviders[$provider])) { $this->registerDeferredProvider($provider, $service); } } /** * Register a deferred provider and service. * * @param string $provider * @param string|null $service * @return void */ public function registerDeferredProvider($provider, $service = null) { // Once the provider that provides the deferred service has been registered we // will remove it from our local list of the deferred services with related // providers so that this container does not try to resolve it out again. if ($service) { unset($this->deferredServices[$service]); } $this->register($instance = new $provider($this)); if (! $this->isBooted()) { $this->booting(function () use ($instance) { $this->bootProvider($instance); }); } } /** * Resolve the given type from the container. * * @param string $abstract * @param array $parameters * @return mixed */ public function make($abstract, array $parameters = []) { $this->loadDeferredProviderIfNeeded($abstract = $this->getAlias($abstract)); return parent::make($abstract, $parameters); } /** * Resolve the given type from the container. * * @param string $abstract * @param array $parameters * @param bool $raiseEvents * @return mixed */ protected function resolve($abstract, $parameters = [], $raiseEvents = true) { $this->loadDeferredProviderIfNeeded($abstract = $this->getAlias($abstract)); return parent::resolve($abstract, $parameters, $raiseEvents); } /** * Load the deferred provider if the given type is a deferred service and the instance has not been loaded. * * @param string $abstract * @return void */ protected function loadDeferredProviderIfNeeded($abstract) { if ($this->isDeferredService($abstract) && ! isset($this->instances[$abstract])) { $this->loadDeferredProvider($abstract); } } /** * Determine if the given abstract type has been bound. * * @param string $abstract * @return bool */ public function bound($abstract) { return $this->isDeferredService($abstract) || parent::bound($abstract); } /** * Determine if the application has booted. * * @return bool */ public function isBooted() { return $this->booted; } /** * Boot the application's service providers. * * @return void */ public function boot() { if ($this->isBooted()) { return; } // Once the application has booted we will also fire some "booted" callbacks // for any listeners that need to do work after this initial booting gets // finished. This is useful when ordering the boot-up processes we run. $this->fireAppCallbacks($this->bootingCallbacks); array_walk($this->serviceProviders, function ($p) { $this->bootProvider($p); }); $this->booted = true; $this->fireAppCallbacks($this->bootedCallbacks); } /** * Boot the given service provider. * * @param \Illuminate\Support\ServiceProvider $provider * @return void */ protected function bootProvider(ServiceProvider $provider) { $provider->callBootingCallbacks(); if (method_exists($provider, 'boot')) { $this->call([$provider, 'boot']); } $provider->callBootedCallbacks(); } /** * Register a new boot listener. * * @param callable $callback * @return void */ public function booting($callback) { $this->bootingCallbacks[] = $callback; } /** * Register a new "booted" listener. * * @param callable $callback * @return void */ public function booted($callback) { $this->bootedCallbacks[] = $callback; if ($this->isBooted()) { $callback($this); } } /** * Call the booting callbacks for the application. * * @param callable[] $callbacks * @return void */ protected function fireAppCallbacks(array &$callbacks) { $index = 0; while ($index < count($callbacks)) { $callbacks[$index]($this); $index++; } } /** * {@inheritdoc} * * @return \Symfony\Component\HttpFoundation\Response */ public function handle(SymfonyRequest $request, int $type = self::MAIN_REQUEST, bool $catch = true): SymfonyResponse { return $this[HttpKernelContract::class]->handle(Request::createFromBase($request)); } /** * Determine if middleware has been disabled for the application. * * @return bool */ public function shouldSkipMiddleware() { return $this->bound('middleware.disable') && $this->make('middleware.disable') === true; } /** * Get the path to the cached services.php file. * * @return string */ public function getCachedServicesPath() { return $this->normalizeCachePath('APP_SERVICES_CACHE', 'cache/services.php'); } /** * Get the path to the cached packages.php file. * * @return string */ public function getCachedPackagesPath() { return $this->normalizeCachePath('APP_PACKAGES_CACHE', 'cache/packages.php'); } /** * Determine if the application configuration is cached. * * @return bool */ public function configurationIsCached() { return is_file($this->getCachedConfigPath()); } /** * Get the path to the configuration cache file. * * @return string */ public function getCachedConfigPath() { return $this->normalizeCachePath('APP_CONFIG_CACHE', 'cache/config.php'); } /** * Determine if the application routes are cached. * * @return bool */ public function routesAreCached() { return $this['files']->exists($this->getCachedRoutesPath()); } /** * Get the path to the routes cache file. * * @return string */ public function getCachedRoutesPath() { return $this->normalizeCachePath('APP_ROUTES_CACHE', 'cache/routes-v7.php'); } /** * Determine if the application events are cached. * * @return bool */ public function eventsAreCached() { return $this['files']->exists($this->getCachedEventsPath()); } /** * Get the path to the events cache file. * * @return string */ public function getCachedEventsPath() { return $this->normalizeCachePath('APP_EVENTS_CACHE', 'cache/events.php'); } /** * Normalize a relative or absolute path to a cache file. * * @param string $key * @param string $default * @return string */ protected function normalizeCachePath($key, $default) { if (is_null($env = Env::get($key))) { return $this->bootstrapPath($default); } return Str::startsWith($env, $this->absoluteCachePathPrefixes) ? $env : $this->basePath($env); } /** * Add new prefix to list of absolute path prefixes. * * @param string $prefix * @return $this */ public function addAbsoluteCachePathPrefix($prefix) { $this->absoluteCachePathPrefixes[] = $prefix; return $this; } /** * Get an instance of the maintenance mode manager implementation. * * @return \Illuminate\Contracts\Foundation\MaintenanceMode */ public function maintenanceMode() { return $this->make(MaintenanceModeContract::class); } /** * Determine if the application is currently down for maintenance. * * @return bool */ public function isDownForMaintenance() { return $this->maintenanceMode()->active(); } /** * Throw an HttpException with the given data. * * @param int $code * @param string $message * @param array $headers * @return never * * @throws \Symfony\Component\HttpKernel\Exception\HttpException * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ public function abort($code, $message = '', array $headers = []) { if ($code == 404) { throw new NotFoundHttpException($message); } throw new HttpException($code, $message, null, $headers); } /** * Register a terminating callback with the application. * * @param callable|string $callback * @return $this */ public function terminating($callback) { $this->terminatingCallbacks[] = $callback; return $this; } /** * Terminate the application. * * @return void */ public function terminate() { $index = 0; while ($index < count($this->terminatingCallbacks)) { $this->call($this->terminatingCallbacks[$index]); $index++; } } /** * Get the service providers that have been loaded. * * @return array */ public function getLoadedProviders() { return $this->loadedProviders; } /** * Determine if the given service provider is loaded. * * @param string $provider * @return bool */ public function providerIsLoaded(string $provider) { return isset($this->loadedProviders[$provider]); } /** * Get the application's deferred services. * * @return array */ public function getDeferredServices() { return $this->deferredServices; } /** * Set the application's deferred services. * * @param array $services * @return void */ public function setDeferredServices(array $services) { $this->deferredServices = $services; } /** * Add an array of services to the application's deferred services. * * @param array $services * @return void */ public function addDeferredServices(array $services) { $this->deferredServices = array_merge($this->deferredServices, $services); } /** * Determine if the given service is a deferred service. * * @param string $service * @return bool */ public function isDeferredService($service) { return isset($this->deferredServices[$service]); } /** * Configure the real-time facade namespace. * * @param string $namespace * @return void */ public function provideFacades($namespace) { AliasLoader::setFacadeNamespace($namespace); } /** * Get the current application locale. * * @return string */ public function getLocale() { return $this['config']->get('app.locale'); } /** * Get the current application locale. * * @return string */ public function currentLocale() { return $this->getLocale(); } /** * Get the current application fallback locale. * * @return string */ public function getFallbackLocale() { return $this['config']->get('app.fallback_locale'); } /** * Set the current application locale. * * @param string $locale * @return void */ public function setLocale($locale) { $this['config']->set('app.locale', $locale); $this['translator']->setLocale($locale); $this['events']->dispatch(new LocaleUpdated($locale)); } /** * Set the current application fallback locale. * * @param string $fallbackLocale * @return void */ public function setFallbackLocale($fallbackLocale) { $this['config']->set('app.fallback_locale', $fallbackLocale); $this['translator']->setFallback($fallbackLocale); } /** * Determine if the application locale is the given locale. * * @param string $locale * @return bool */ public function isLocale($locale) { return $this->getLocale() == $locale; } /** * Register the core class aliases in the container. * * @return void */ public function registerCoreContainerAliases() { foreach ([ 'app' => [self::class, \Illuminate\Contracts\Container\Container::class, \Illuminate\Contracts\Foundation\Application::class, \Psr\Container\ContainerInterface::class], 'auth' => [\Illuminate\Auth\AuthManager::class, \Illuminate\Contracts\Auth\Factory::class], 'auth.driver' => [\Illuminate\Contracts\Auth\Guard::class], 'blade.compiler' => [\Illuminate\View\Compilers\BladeCompiler::class], 'cache' => [\Illuminate\Cache\CacheManager::class, \Illuminate\Contracts\Cache\Factory::class], 'cache.store' => [\Illuminate\Cache\Repository::class, \Illuminate\Contracts\Cache\Repository::class, \Psr\SimpleCache\CacheInterface::class], 'cache.psr6' => [\Symfony\Component\Cache\Adapter\Psr16Adapter::class, \Symfony\Component\Cache\Adapter\AdapterInterface::class, \Psr\Cache\CacheItemPoolInterface::class], 'config' => [\Illuminate\Config\Repository::class, \Illuminate\Contracts\Config\Repository::class], 'cookie' => [\Illuminate\Cookie\CookieJar::class, \Illuminate\Contracts\Cookie\Factory::class, \Illuminate\Contracts\Cookie\QueueingFactory::class], 'db' => [\Illuminate\Database\DatabaseManager::class, \Illuminate\Database\ConnectionResolverInterface::class], 'db.connection' => [\Illuminate\Database\Connection::class, \Illuminate\Database\ConnectionInterface::class], 'db.schema' => [\Illuminate\Database\Schema\Builder::class], 'encrypter' => [\Illuminate\Encryption\Encrypter::class, \Illuminate\Contracts\Encryption\Encrypter::class, \Illuminate\Contracts\Encryption\StringEncrypter::class], 'events' => [\Illuminate\Events\Dispatcher::class, \Illuminate\Contracts\Events\Dispatcher::class], 'files' => [\Illuminate\Filesystem\Filesystem::class], 'filesystem' => [\Illuminate\Filesystem\FilesystemManager::class, \Illuminate\Contracts\Filesystem\Factory::class], 'filesystem.disk' => [\Illuminate\Contracts\Filesystem\Filesystem::class], 'filesystem.cloud' => [\Illuminate\Contracts\Filesystem\Cloud::class], 'hash' => [\Illuminate\Hashing\HashManager::class], 'hash.driver' => [\Illuminate\Contracts\Hashing\Hasher::class], 'translator' => [\Illuminate\Translation\Translator::class, \Illuminate\Contracts\Translation\Translator::class], 'log' => [\Illuminate\Log\LogManager::class, \Psr\Log\LoggerInterface::class], 'mail.manager' => [\Illuminate\Mail\MailManager::class, \Illuminate\Contracts\Mail\Factory::class], 'mailer' => [\Illuminate\Mail\Mailer::class, \Illuminate\Contracts\Mail\Mailer::class, \Illuminate\Contracts\Mail\MailQueue::class], 'auth.password' => [\Illuminate\Auth\Passwords\PasswordBrokerManager::class, \Illuminate\Contracts\Auth\PasswordBrokerFactory::class], 'auth.password.broker' => [\Illuminate\Auth\Passwords\PasswordBroker::class, \Illuminate\Contracts\Auth\PasswordBroker::class], 'queue' => [\Illuminate\Queue\QueueManager::class, \Illuminate\Contracts\Queue\Factory::class, \Illuminate\Contracts\Queue\Monitor::class], 'queue.connection' => [\Illuminate\Contracts\Queue\Queue::class], 'queue.failer' => [\Illuminate\Queue\Failed\FailedJobProviderInterface::class], 'redirect' => [\Illuminate\Routing\Redirector::class], 'redis' => [\Illuminate\Redis\RedisManager::class, \Illuminate\Contracts\Redis\Factory::class], 'redis.connection' => [\Illuminate\Redis\Connections\Connection::class, \Illuminate\Contracts\Redis\Connection::class], 'request' => [\Illuminate\Http\Request::class, \Symfony\Component\HttpFoundation\Request::class], 'router' => [\Illuminate\Routing\Router::class, \Illuminate\Contracts\Routing\Registrar::class, \Illuminate\Contracts\Routing\BindingRegistrar::class], 'session' => [\Illuminate\Session\SessionManager::class], 'session.store' => [\Illuminate\Session\Store::class, \Illuminate\Contracts\Session\Session::class], 'url' => [\Illuminate\Routing\UrlGenerator::class, \Illuminate\Contracts\Routing\UrlGenerator::class], 'validator' => [\Illuminate\Validation\Factory::class, \Illuminate\Contracts\Validation\Factory::class], 'view' => [\Illuminate\View\Factory::class, \Illuminate\Contracts\View\Factory::class], ] as $key => $aliases) { foreach ($aliases as $alias) { $this->alias($key, $alias); } } } /** * Flush the container of all bindings and resolved instances. * * @return void */ public function flush() { parent::flush(); $this->buildStack = []; $this->loadedProviders = []; $this->bootedCallbacks = []; $this->bootingCallbacks = []; $this->deferredServices = []; $this->reboundCallbacks = []; $this->serviceProviders = []; $this->resolvingCallbacks = []; $this->terminatingCallbacks = []; $this->beforeResolvingCallbacks = []; $this->afterResolvingCallbacks = []; $this->globalBeforeResolvingCallbacks = []; $this->globalResolvingCallbacks = []; $this->globalAfterResolvingCallbacks = []; } /** * Get the application namespace. * * @return string * * @throws \RuntimeException */ public function getNamespace() { if (! is_null($this->namespace)) { return $this->namespace; } $composer = json_decode(file_get_contents($this->basePath('composer.json')), true); foreach ((array) data_get($composer, 'autoload.psr-4') as $namespace => $path) { foreach ((array) $path as $pathChoice) { if (realpath($this->path()) === realpath($this->basePath($pathChoice))) { return $this->namespace = $namespace; } } } throw new RuntimeException('Unable to detect application namespace.'); } } PKz Z)NNIlluminate/Foundation/Vite.phpnuW+ApreloadedAssets; } /** * Get the Content Security Policy nonce applied to all generated tags. * * @return string|null */ public function cspNonce() { return $this->nonce; } /** * Generate or set a Content Security Policy nonce to apply to all generated tags. * * @param string|null $nonce * @return string */ public function useCspNonce($nonce = null) { return $this->nonce = $nonce ?? Str::random(40); } /** * Use the given key to detect integrity hashes in the manifest. * * @param string|false $key * @return $this */ public function useIntegrityKey($key) { $this->integrityKey = $key; return $this; } /** * Set the Vite entry points. * * @param array $entryPoints * @return $this */ public function withEntryPoints($entryPoints) { $this->entryPoints = $entryPoints; return $this; } /** * Set the filename for the manifest file. * * @param string $filename * @return $this */ public function useManifestFilename($filename) { $this->manifestFilename = $filename; return $this; } /** * Get the Vite "hot" file path. * * @return string */ public function hotFile() { return $this->hotFile ?? public_path('/hot'); } /** * Set the Vite "hot" file path. * * @param string $path * @return $this */ public function useHotFile($path) { $this->hotFile = $path; return $this; } /** * Set the Vite build directory. * * @param string $path * @return $this */ public function useBuildDirectory($path) { $this->buildDirectory = $path; return $this; } /** * Use the given callback to resolve attributes for script tags. * * @param (callable(string, string, ?array, ?array): array)|array $attributes * @return $this */ public function useScriptTagAttributes($attributes) { if (! is_callable($attributes)) { $attributes = fn () => $attributes; } $this->scriptTagAttributesResolvers[] = $attributes; return $this; } /** * Use the given callback to resolve attributes for style tags. * * @param (callable(string, string, ?array, ?array): array)|array $attributes * @return $this */ public function useStyleTagAttributes($attributes) { if (! is_callable($attributes)) { $attributes = fn () => $attributes; } $this->styleTagAttributesResolvers[] = $attributes; return $this; } /** * Use the given callback to resolve attributes for preload tags. * * @param (callable(string, string, ?array, ?array): (array|false))|array|false $attributes * @return $this */ public function usePreloadTagAttributes($attributes) { if (! is_callable($attributes)) { $attributes = fn () => $attributes; } $this->preloadTagAttributesResolvers[] = $attributes; return $this; } /** * Generate Vite tags for an entrypoint. * * @param string|string[] $entrypoints * @param string|null $buildDirectory * @return \Illuminate\Support\HtmlString * * @throws \Exception */ public function __invoke($entrypoints, $buildDirectory = null) { $entrypoints = collect($entrypoints); $buildDirectory ??= $this->buildDirectory; if ($this->isRunningHot()) { return new HtmlString( $entrypoints ->prepend('@vite/client') ->map(fn ($entrypoint) => $this->makeTagForChunk($entrypoint, $this->hotAsset($entrypoint), null, null)) ->join('') ); } $manifest = $this->manifest($buildDirectory); $tags = collect(); $preloads = collect(); foreach ($entrypoints as $entrypoint) { $chunk = $this->chunk($manifest, $entrypoint); $preloads->push([ $chunk['src'], $this->assetPath("{$buildDirectory}/{$chunk['file']}"), $chunk, $manifest, ]); foreach ($chunk['imports'] ?? [] as $import) { $preloads->push([ $import, $this->assetPath("{$buildDirectory}/{$manifest[$import]['file']}"), $manifest[$import], $manifest, ]); foreach ($manifest[$import]['css'] ?? [] as $css) { $partialManifest = Collection::make($manifest)->where('file', $css); $preloads->push([ $partialManifest->keys()->first(), $this->assetPath("{$buildDirectory}/{$css}"), $partialManifest->first(), $manifest, ]); $tags->push($this->makeTagForChunk( $partialManifest->keys()->first(), $this->assetPath("{$buildDirectory}/{$css}"), $partialManifest->first(), $manifest )); } } $tags->push($this->makeTagForChunk( $entrypoint, $this->assetPath("{$buildDirectory}/{$chunk['file']}"), $chunk, $manifest )); foreach ($chunk['css'] ?? [] as $css) { $partialManifest = Collection::make($manifest)->where('file', $css); $preloads->push([ $partialManifest->keys()->first(), $this->assetPath("{$buildDirectory}/{$css}"), $partialManifest->first(), $manifest, ]); $tags->push($this->makeTagForChunk( $partialManifest->keys()->first(), $this->assetPath("{$buildDirectory}/{$css}"), $partialManifest->first(), $manifest )); } } [$stylesheets, $scripts] = $tags->unique()->partition(fn ($tag) => str_starts_with($tag, 'unique() ->sortByDesc(fn ($args) => $this->isCssPath($args[1])) ->map(fn ($args) => $this->makePreloadTagForChunk(...$args)); return new HtmlString($preloads->join('').$stylesheets->join('').$scripts->join('')); } /** * Make tag for the given chunk. * * @param string $src * @param string $url * @param array|null $chunk * @param array|null $manifest * @return string */ protected function makeTagForChunk($src, $url, $chunk, $manifest) { if ( $this->nonce === null && $this->integrityKey !== false && ! array_key_exists($this->integrityKey, $chunk ?? []) && $this->scriptTagAttributesResolvers === [] && $this->styleTagAttributesResolvers === []) { return $this->makeTag($url); } if ($this->isCssPath($url)) { return $this->makeStylesheetTagWithAttributes( $url, $this->resolveStylesheetTagAttributes($src, $url, $chunk, $manifest) ); } return $this->makeScriptTagWithAttributes( $url, $this->resolveScriptTagAttributes($src, $url, $chunk, $manifest) ); } /** * Make a preload tag for the given chunk. * * @param string $src * @param string $url * @param array $chunk * @param array $manifest * @return string */ protected function makePreloadTagForChunk($src, $url, $chunk, $manifest) { $attributes = $this->resolvePreloadTagAttributes($src, $url, $chunk, $manifest); if ($attributes === false) { return ''; } $this->preloadedAssets[$url] = $this->parseAttributes( Collection::make($attributes)->forget('href')->all() ); return 'parseAttributes($attributes)).' />'; } /** * Resolve the attributes for the chunks generated script tag. * * @param string $src * @param string $url * @param array|null $chunk * @param array|null $manifest * @return array */ protected function resolveScriptTagAttributes($src, $url, $chunk, $manifest) { $attributes = $this->integrityKey !== false ? ['integrity' => $chunk[$this->integrityKey] ?? false] : []; foreach ($this->scriptTagAttributesResolvers as $resolver) { $attributes = array_merge($attributes, $resolver($src, $url, $chunk, $manifest)); } return $attributes; } /** * Resolve the attributes for the chunks generated stylesheet tag. * * @param string $src * @param string $url * @param array|null $chunk * @param array|null $manifest * @return array */ protected function resolveStylesheetTagAttributes($src, $url, $chunk, $manifest) { $attributes = $this->integrityKey !== false ? ['integrity' => $chunk[$this->integrityKey] ?? false] : []; foreach ($this->styleTagAttributesResolvers as $resolver) { $attributes = array_merge($attributes, $resolver($src, $url, $chunk, $manifest)); } return $attributes; } /** * Resolve the attributes for the chunks generated preload tag. * * @param string $src * @param string $url * @param array $chunk * @param array $manifest * @return array|false */ protected function resolvePreloadTagAttributes($src, $url, $chunk, $manifest) { $attributes = $this->isCssPath($url) ? [ 'rel' => 'preload', 'as' => 'style', 'href' => $url, 'nonce' => $this->nonce ?? false, 'crossorigin' => $this->resolveStylesheetTagAttributes($src, $url, $chunk, $manifest)['crossorigin'] ?? false, ] : [ 'rel' => 'modulepreload', 'href' => $url, 'nonce' => $this->nonce ?? false, 'crossorigin' => $this->resolveScriptTagAttributes($src, $url, $chunk, $manifest)['crossorigin'] ?? false, ]; $attributes = $this->integrityKey !== false ? array_merge($attributes, ['integrity' => $chunk[$this->integrityKey] ?? false]) : $attributes; foreach ($this->preloadTagAttributesResolvers as $resolver) { if (false === ($resolvedAttributes = $resolver($src, $url, $chunk, $manifest))) { return false; } $attributes = array_merge($attributes, $resolvedAttributes); } return $attributes; } /** * Generate an appropriate tag for the given URL in HMR mode. * * @deprecated Will be removed in a future Laravel version. * * @param string $url * @return string */ protected function makeTag($url) { if ($this->isCssPath($url)) { return $this->makeStylesheetTag($url); } return $this->makeScriptTag($url); } /** * Generate a script tag for the given URL. * * @deprecated Will be removed in a future Laravel version. * * @param string $url * @return string */ protected function makeScriptTag($url) { return $this->makeScriptTagWithAttributes($url, []); } /** * Generate a stylesheet tag for the given URL in HMR mode. * * @deprecated Will be removed in a future Laravel version. * * @param string $url * @return string */ protected function makeStylesheetTag($url) { return $this->makeStylesheetTagWithAttributes($url, []); } /** * Generate a script tag with attributes for the given URL. * * @param string $url * @param array $attributes * @return string */ protected function makeScriptTagWithAttributes($url, $attributes) { $attributes = $this->parseAttributes(array_merge([ 'type' => 'module', 'src' => $url, 'nonce' => $this->nonce ?? false, ], $attributes)); return ''; } /** * Generate a link tag with attributes for the given URL. * * @param string $url * @param array $attributes * @return string */ protected function makeStylesheetTagWithAttributes($url, $attributes) { $attributes = $this->parseAttributes(array_merge([ 'rel' => 'stylesheet', 'href' => $url, 'nonce' => $this->nonce ?? false, ], $attributes)); return ''; } /** * Determine whether the given path is a CSS file. * * @param string $path * @return bool */ protected function isCssPath($path) { return preg_match('/\.(css|less|sass|scss|styl|stylus|pcss|postcss)$/', $path) === 1; } /** * Parse the attributes into key="value" strings. * * @param array $attributes * @return array */ protected function parseAttributes($attributes) { return Collection::make($attributes) ->reject(fn ($value, $key) => in_array($value, [false, null], true)) ->flatMap(fn ($value, $key) => $value === true ? [$key] : [$key => $value]) ->map(fn ($value, $key) => is_int($key) ? $value : $key.'="'.$value.'"') ->values() ->all(); } /** * Generate React refresh runtime script. * * @return \Illuminate\Support\HtmlString|void */ public function reactRefresh() { if (! $this->isRunningHot()) { return; } $attributes = $this->parseAttributes([ 'nonce' => $this->cspNonce(), ]); return new HtmlString( sprintf( <<<'HTML' HTML, implode(' ', $attributes), $this->hotAsset('@react-refresh') ) ); } /** * Get the path to a given asset when running in HMR mode. * * @return string */ protected function hotAsset($asset) { return rtrim(file_get_contents($this->hotFile())).'/'.$asset; } /** * Get the URL for an asset. * * @param string $asset * @param string|null $buildDirectory * @return string */ public function asset($asset, $buildDirectory = null) { $buildDirectory ??= $this->buildDirectory; if ($this->isRunningHot()) { return $this->hotAsset($asset); } $chunk = $this->chunk($this->manifest($buildDirectory), $asset); return $this->assetPath($buildDirectory.'/'.$chunk['file']); } /** * Generate an asset path for the application. * * @param string $path * @param bool|null $secure * @return string */ protected function assetPath($path, $secure = null) { return asset($path, $secure); } /** * Get the the manifest file for the given build directory. * * @param string $buildDirectory * @return array * * @throws \Exception */ protected function manifest($buildDirectory) { $path = $this->manifestPath($buildDirectory); if (! isset(static::$manifests[$path])) { if (! is_file($path)) { throw new Exception("Vite manifest not found at: {$path}"); } static::$manifests[$path] = json_decode(file_get_contents($path), true); } return static::$manifests[$path]; } /** * Get the path to the manifest file for the given build directory. * * @param string $buildDirectory * @return string */ protected function manifestPath($buildDirectory) { return public_path($buildDirectory.'/'.$this->manifestFilename); } /** * Get a unique hash representing the current manifest, or null if there is no manifest. * * @param string|null $buildDirectory * @return string|null */ public function manifestHash($buildDirectory = null) { $buildDirectory ??= $this->buildDirectory; if ($this->isRunningHot()) { return null; } if (! is_file($path = $this->manifestPath($buildDirectory))) { return null; } return md5_file($path) ?: null; } /** * Get the chunk for the given entry point / asset. * * @param array $manifest * @param string $file * @return array * * @throws \Exception */ protected function chunk($manifest, $file) { if (! isset($manifest[$file])) { throw new Exception("Unable to locate file in Vite manifest: {$file}."); } return $manifest[$file]; } /** * Determine if the HMR server is running. * * @return bool */ public function isRunningHot() { return is_file($this->hotFile()); } /** * Get the Vite tag content as a string of HTML. * * @return string */ public function toHtml() { return $this->__invoke($this->entryPoints)->toHtml(); } } PKz ZW<AIlluminate/Foundation/Providers/ConsoleSupportServiceProvider.phpnuW+AIlluminate/Foundation/Providers/FormRequestServiceProvider.phpnuW+Aapp->afterResolving(ValidatesWhenResolved::class, function ($resolved) { $resolved->validateResolved(); }); $this->app->resolving(FormRequest::class, function ($request, $app) { $request = FormRequest::createFrom($app['request'], $request); $request->setContainer($app)->setRedirector($app->make(Redirector::class)); }); } } PKz Z2k77=Illuminate/Foundation/Providers/FoundationServiceProvider.phpnuW+A Vite::class, ]; /** * Boot the service provider. * * @return void */ public function boot() { if ($this->app->runningInConsole()) { $this->publishes([ __DIR__.'/../Exceptions/views' => $this->app->resourcePath('views/errors/'), ], 'laravel-errors'); } } /** * Register the service provider. * * @return void */ public function register() { parent::register(); $this->registerDumper(); $this->registerRequestValidation(); $this->registerRequestSignatureValidation(); $this->registerExceptionTracking(); $this->registerMaintenanceModeManager(); } /** * Register an var dumper (with source) to debug variables. * * @return void */ public function registerDumper() { AbstractCloner::$defaultCasters[ConnectionInterface::class] = [StubCaster::class, 'cutInternals']; AbstractCloner::$defaultCasters[Container::class] = [StubCaster::class, 'cutInternals']; AbstractCloner::$defaultCasters[Dispatcher::class] = [StubCaster::class, 'cutInternals']; AbstractCloner::$defaultCasters[Factory::class] = [StubCaster::class, 'cutInternals']; AbstractCloner::$defaultCasters[Grammar::class] = [StubCaster::class, 'cutInternals']; $basePath = $this->app->basePath(); $compiledViewPath = $this->app['config']->get('view.compiled'); $format = $_SERVER['VAR_DUMPER_FORMAT'] ?? null; match (true) { 'html' == $format => HtmlDumper::register($basePath, $compiledViewPath), 'cli' == $format => CliDumper::register($basePath, $compiledViewPath), 'server' == $format => null, $format && 'tcp' == parse_url($format, PHP_URL_SCHEME) => null, default => in_array(PHP_SAPI, ['cli', 'phpdbg']) ? CliDumper::register($basePath, $compiledViewPath) : HtmlDumper::register($basePath, $compiledViewPath), }; } /** * Register the "validate" macro on the request. * * @return void * * @throws \Illuminate\Validation\ValidationException */ public function registerRequestValidation() { Request::macro('validate', function (array $rules, ...$params) { return tap(validator($this->all(), $rules, ...$params), function ($validator) { if ($this->isPrecognitive()) { $validator->after(Precognition::afterValidationHook($this)) ->setRules( $this->filterPrecognitiveRules($validator->getRulesWithoutPlaceholders()) ); } })->validate(); }); Request::macro('validateWithBag', function (string $errorBag, array $rules, ...$params) { try { return $this->validate($rules, ...$params); } catch (ValidationException $e) { $e->errorBag = $errorBag; throw $e; } }); } /** * Register the "hasValidSignature" macro on the request. * * @return void */ public function registerRequestSignatureValidation() { Request::macro('hasValidSignature', function ($absolute = true) { return URL::hasValidSignature($this, $absolute); }); Request::macro('hasValidRelativeSignature', function () { return URL::hasValidSignature($this, $absolute = false); }); Request::macro('hasValidSignatureWhileIgnoring', function ($ignoreQuery = [], $absolute = true) { return URL::hasValidSignature($this, $absolute, $ignoreQuery); }); } /** * Register an event listener to track logged exceptions. * * @return void */ protected function registerExceptionTracking() { if (! $this->app->runningUnitTests()) { return; } $this->app->instance( LoggedExceptionCollection::class, new LoggedExceptionCollection ); $this->app->make('events')->listen(MessageLogged::class, function ($event) { if (isset($event->context['exception'])) { $this->app->make(LoggedExceptionCollection::class) ->push($event->context['exception']); } }); } /** * Register the maintenance mode manager service. * * @return void */ public function registerMaintenanceModeManager() { $this->app->singleton(MaintenanceModeManager::class); $this->app->bind( MaintenanceModeContract::class, fn () => $this->app->make(MaintenanceModeManager::class)->driver() ); } } PKz Z}%~__:Illuminate/Foundation/Providers/ArtisanServiceProvider.phpnuW+A AboutCommand::class, 'CacheClear' => CacheClearCommand::class, 'CacheForget' => CacheForgetCommand::class, 'ClearCompiled' => ClearCompiledCommand::class, 'ClearResets' => ClearResetsCommand::class, 'ConfigCache' => ConfigCacheCommand::class, 'ConfigClear' => ConfigClearCommand::class, 'Db' => DbCommand::class, 'DbMonitor' => DatabaseMonitorCommand::class, 'DbPrune' => PruneCommand::class, 'DbShow' => ShowCommand::class, 'DbTable' => DatabaseTableCommand::class, 'DbWipe' => WipeCommand::class, 'Down' => DownCommand::class, 'Environment' => EnvironmentCommand::class, 'EnvironmentDecrypt' => EnvironmentDecryptCommand::class, 'EnvironmentEncrypt' => EnvironmentEncryptCommand::class, 'EventCache' => EventCacheCommand::class, 'EventClear' => EventClearCommand::class, 'EventList' => EventListCommand::class, 'KeyGenerate' => KeyGenerateCommand::class, 'Optimize' => OptimizeCommand::class, 'OptimizeClear' => OptimizeClearCommand::class, 'PackageDiscover' => PackageDiscoverCommand::class, 'QueueClear' => QueueClearCommand::class, 'QueueFailed' => ListFailedQueueCommand::class, 'QueueFlush' => FlushFailedQueueCommand::class, 'QueueForget' => ForgetFailedQueueCommand::class, 'QueueListen' => QueueListenCommand::class, 'QueueMonitor' => QueueMonitorCommand::class, 'QueuePruneBatches' => QueuePruneBatchesCommand::class, 'QueuePruneFailedJobs' => QueuePruneFailedJobsCommand::class, 'QueueRestart' => QueueRestartCommand::class, 'QueueRetry' => QueueRetryCommand::class, 'QueueRetryBatch' => QueueRetryBatchCommand::class, 'QueueWork' => QueueWorkCommand::class, 'RouteCache' => RouteCacheCommand::class, 'RouteClear' => RouteClearCommand::class, 'RouteList' => RouteListCommand::class, 'SchemaDump' => DumpCommand::class, 'Seed' => SeedCommand::class, 'ScheduleFinish' => ScheduleFinishCommand::class, 'ScheduleList' => ScheduleListCommand::class, 'ScheduleRun' => ScheduleRunCommand::class, 'ScheduleClearCache' => ScheduleClearCacheCommand::class, 'ScheduleTest' => ScheduleTestCommand::class, 'ScheduleWork' => ScheduleWorkCommand::class, 'ShowModel' => ShowModelCommand::class, 'StorageLink' => StorageLinkCommand::class, 'Up' => UpCommand::class, 'ViewCache' => ViewCacheCommand::class, 'ViewClear' => ViewClearCommand::class, ]; /** * The commands to be registered. * * @var array */ protected $devCommands = [ 'CacheTable' => CacheTableCommand::class, 'CastMake' => CastMakeCommand::class, 'ChannelMake' => ChannelMakeCommand::class, 'ComponentMake' => ComponentMakeCommand::class, 'ConsoleMake' => ConsoleMakeCommand::class, 'ControllerMake' => ControllerMakeCommand::class, 'Docs' => DocsCommand::class, 'EventGenerate' => EventGenerateCommand::class, 'EventMake' => EventMakeCommand::class, 'ExceptionMake' => ExceptionMakeCommand::class, 'FactoryMake' => FactoryMakeCommand::class, 'JobMake' => JobMakeCommand::class, 'ListenerMake' => ListenerMakeCommand::class, 'MailMake' => MailMakeCommand::class, 'MiddlewareMake' => MiddlewareMakeCommand::class, 'ModelMake' => ModelMakeCommand::class, 'NotificationMake' => NotificationMakeCommand::class, 'NotificationTable' => NotificationTableCommand::class, 'ObserverMake' => ObserverMakeCommand::class, 'PolicyMake' => PolicyMakeCommand::class, 'ProviderMake' => ProviderMakeCommand::class, 'QueueFailedTable' => FailedTableCommand::class, 'QueueTable' => TableCommand::class, 'QueueBatchesTable' => BatchesTableCommand::class, 'RequestMake' => RequestMakeCommand::class, 'ResourceMake' => ResourceMakeCommand::class, 'RuleMake' => RuleMakeCommand::class, 'ScopeMake' => ScopeMakeCommand::class, 'SeederMake' => SeederMakeCommand::class, 'SessionTable' => SessionTableCommand::class, 'Serve' => ServeCommand::class, 'StubPublish' => StubPublishCommand::class, 'TestMake' => TestMakeCommand::class, 'VendorPublish' => VendorPublishCommand::class, ]; /** * Register the service provider. * * @return void */ public function register() { $this->registerCommands(array_merge( $this->commands, $this->devCommands )); Signals::resolveAvailabilityUsing(function () { return $this->app->runningInConsole() && ! $this->app->runningUnitTests() && extension_loaded('pcntl'); }); } /** * Register the given commands. * * @param array $commands * @return void */ protected function registerCommands(array $commands) { foreach ($commands as $commandName => $command) { $method = "register{$commandName}Command"; if (method_exists($this, $method)) { $this->{$method}(); } else { $this->app->singleton($command); } } $this->commands(array_values($commands)); } /** * Register the command. * * @return void */ protected function registerAboutCommand() { $this->app->singleton(AboutCommand::class, function ($app) { return new AboutCommand($app['composer']); }); } /** * Register the command. * * @return void */ protected function registerCacheClearCommand() { $this->app->singleton(CacheClearCommand::class, function ($app) { return new CacheClearCommand($app['cache'], $app['files']); }); } /** * Register the command. * * @return void */ protected function registerCacheForgetCommand() { $this->app->singleton(CacheForgetCommand::class, function ($app) { return new CacheForgetCommand($app['cache']); }); } /** * Register the command. * * @return void */ protected function registerCacheTableCommand() { $this->app->singleton(CacheTableCommand::class, function ($app) { return new CacheTableCommand($app['files'], $app['composer']); }); } /** * Register the command. * * @return void */ protected function registerCastMakeCommand() { $this->app->singleton(CastMakeCommand::class, function ($app) { return new CastMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerChannelMakeCommand() { $this->app->singleton(ChannelMakeCommand::class, function ($app) { return new ChannelMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerComponentMakeCommand() { $this->app->singleton(ComponentMakeCommand::class, function ($app) { return new ComponentMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerConfigCacheCommand() { $this->app->singleton(ConfigCacheCommand::class, function ($app) { return new ConfigCacheCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerConfigClearCommand() { $this->app->singleton(ConfigClearCommand::class, function ($app) { return new ConfigClearCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerConsoleMakeCommand() { $this->app->singleton(ConsoleMakeCommand::class, function ($app) { return new ConsoleMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerControllerMakeCommand() { $this->app->singleton(ControllerMakeCommand::class, function ($app) { return new ControllerMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerEventMakeCommand() { $this->app->singleton(EventMakeCommand::class, function ($app) { return new EventMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerExceptionMakeCommand() { $this->app->singleton(ExceptionMakeCommand::class, function ($app) { return new ExceptionMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerFactoryMakeCommand() { $this->app->singleton(FactoryMakeCommand::class, function ($app) { return new FactoryMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerEventClearCommand() { $this->app->singleton(EventClearCommand::class, function ($app) { return new EventClearCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerJobMakeCommand() { $this->app->singleton(JobMakeCommand::class, function ($app) { return new JobMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerListenerMakeCommand() { $this->app->singleton(ListenerMakeCommand::class, function ($app) { return new ListenerMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerMailMakeCommand() { $this->app->singleton(MailMakeCommand::class, function ($app) { return new MailMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerMiddlewareMakeCommand() { $this->app->singleton(MiddlewareMakeCommand::class, function ($app) { return new MiddlewareMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerModelMakeCommand() { $this->app->singleton(ModelMakeCommand::class, function ($app) { return new ModelMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerNotificationMakeCommand() { $this->app->singleton(NotificationMakeCommand::class, function ($app) { return new NotificationMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerNotificationTableCommand() { $this->app->singleton(NotificationTableCommand::class, function ($app) { return new NotificationTableCommand($app['files'], $app['composer']); }); } /** * Register the command. * * @return void */ protected function registerObserverMakeCommand() { $this->app->singleton(ObserverMakeCommand::class, function ($app) { return new ObserverMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerPolicyMakeCommand() { $this->app->singleton(PolicyMakeCommand::class, function ($app) { return new PolicyMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerProviderMakeCommand() { $this->app->singleton(ProviderMakeCommand::class, function ($app) { return new ProviderMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerQueueForgetCommand() { $this->app->singleton(ForgetFailedQueueCommand::class); } /** * Register the command. * * @return void */ protected function registerQueueListenCommand() { $this->app->singleton(QueueListenCommand::class, function ($app) { return new QueueListenCommand($app['queue.listener']); }); } /** * Register the command. * * @return void */ protected function registerQueueMonitorCommand() { $this->app->singleton(QueueMonitorCommand::class, function ($app) { return new QueueMonitorCommand($app['queue'], $app['events']); }); } /** * Register the command. * * @return void */ protected function registerQueuePruneBatchesCommand() { $this->app->singleton(QueuePruneBatchesCommand::class, function () { return new QueuePruneBatchesCommand; }); } /** * Register the command. * * @return void */ protected function registerQueuePruneFailedJobsCommand() { $this->app->singleton(QueuePruneFailedJobsCommand::class, function () { return new QueuePruneFailedJobsCommand; }); } /** * Register the command. * * @return void */ protected function registerQueueRestartCommand() { $this->app->singleton(QueueRestartCommand::class, function ($app) { return new QueueRestartCommand($app['cache.store']); }); } /** * Register the command. * * @return void */ protected function registerQueueWorkCommand() { $this->app->singleton(QueueWorkCommand::class, function ($app) { return new QueueWorkCommand($app['queue.worker'], $app['cache.store']); }); } /** * Register the command. * * @return void */ protected function registerQueueFailedTableCommand() { $this->app->singleton(FailedTableCommand::class, function ($app) { return new FailedTableCommand($app['files'], $app['composer']); }); } /** * Register the command. * * @return void */ protected function registerQueueTableCommand() { $this->app->singleton(TableCommand::class, function ($app) { return new TableCommand($app['files'], $app['composer']); }); } /** * Register the command. * * @return void */ protected function registerQueueBatchesTableCommand() { $this->app->singleton(BatchesTableCommand::class, function ($app) { return new BatchesTableCommand($app['files'], $app['composer']); }); } /** * Register the command. * * @return void */ protected function registerRequestMakeCommand() { $this->app->singleton(RequestMakeCommand::class, function ($app) { return new RequestMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerResourceMakeCommand() { $this->app->singleton(ResourceMakeCommand::class, function ($app) { return new ResourceMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerRuleMakeCommand() { $this->app->singleton(RuleMakeCommand::class, function ($app) { return new RuleMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerScopeMakeCommand() { $this->app->singleton(ScopeMakeCommand::class, function ($app) { return new ScopeMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerSeederMakeCommand() { $this->app->singleton(SeederMakeCommand::class, function ($app) { return new SeederMakeCommand($app['files'], $app['composer']); }); } /** * Register the command. * * @return void */ protected function registerSessionTableCommand() { $this->app->singleton(SessionTableCommand::class, function ($app) { return new SessionTableCommand($app['files'], $app['composer']); }); } /** * Register the command. * * @return void */ protected function registerRouteCacheCommand() { $this->app->singleton(RouteCacheCommand::class, function ($app) { return new RouteCacheCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerRouteClearCommand() { $this->app->singleton(RouteClearCommand::class, function ($app) { return new RouteClearCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerRouteListCommand() { $this->app->singleton(RouteListCommand::class, function ($app) { return new RouteListCommand($app['router']); }); } /** * Register the command. * * @return void */ protected function registerSeedCommand() { $this->app->singleton(SeedCommand::class, function ($app) { return new SeedCommand($app['db']); }); } /** * Register the command. * * @return void */ protected function registerTestMakeCommand() { $this->app->singleton(TestMakeCommand::class, function ($app) { return new TestMakeCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerVendorPublishCommand() { $this->app->singleton(VendorPublishCommand::class, function ($app) { return new VendorPublishCommand($app['files']); }); } /** * Register the command. * * @return void */ protected function registerViewClearCommand() { $this->app->singleton(ViewClearCommand::class, function ($app) { return new ViewClearCommand($app['files']); }); } /** * Get the services provided by the provider. * * @return array */ public function provides() { return array_merge(array_values($this->commands), array_values($this->devCommands)); } } PKz Z[8q;Illuminate/Foundation/Providers/ComposerServiceProvider.phpnuW+Aapp->singleton('composer', function ($app) { return new Composer($app['files'], $app->basePath()); }); } /** * Get the services provided by the provider. * * @return array */ public function provides() { return ['composer']; } } PKz Z'XX7Illuminate/Foundation/Events/MaintenanceModeEnabled.phpnuW+Afiles()->in($listenerPath), $basePath )); $discoveredEvents = []; foreach ($listeners as $listener => $events) { foreach ($events as $event) { if (! isset($discoveredEvents[$event])) { $discoveredEvents[$event] = []; } $discoveredEvents[$event][] = $listener; } } return $discoveredEvents; } /** * Get all of the listeners and their corresponding events. * * @param iterable $listeners * @param string $basePath * @return array */ protected static function getListenerEvents($listeners, $basePath) { $listenerEvents = []; foreach ($listeners as $listener) { try { $listener = new ReflectionClass( static::classFromFile($listener, $basePath) ); } catch (ReflectionException $e) { continue; } if (! $listener->isInstantiable()) { continue; } foreach ($listener->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { if ((! Str::is('handle*', $method->name) && ! Str::is('__invoke', $method->name)) || ! isset($method->getParameters()[0])) { continue; } $listenerEvents[$listener->name.'@'.$method->name] = Reflector::getParameterClassNames($method->getParameters()[0]); } } return array_filter($listenerEvents); } /** * Extract the class name from the given file path. * * @param \SplFileInfo $file * @param string $basePath * @return string */ protected static function classFromFile(SplFileInfo $file, $basePath) { $class = trim(Str::replaceFirst($basePath, '', $file->getRealPath()), DIRECTORY_SEPARATOR); return str_replace( [DIRECTORY_SEPARATOR, ucfirst(basename(app()->path())).'\\'], ['\\', app()->getNamespace()], ucfirst(Str::replaceLast('.php', '', $class)) ); } } PKz Z b-Illuminate/Foundation/Events/Dispatchable.phpnuW+Atag = $tag; $this->paths = $paths; } } PKz Zuwmbb.Illuminate/Foundation/Events/LocaleUpdated.phpnuW+Alocale = $locale; } } PKz Z0Illuminate/Foundation/Events/PublishingStubs.phpnuW+Astubs = $stubs; } /** * Add a new stub to be published. * * @param string $path * @param string $name * @return $this */ public function add(string $path, string $name) { $this->stubs[$path] = $name; return $this; } } PKz Z{Ktt4Illuminate/Foundation/Bus/PendingClosureDispatch.phpnuW+Ajob->onFailure($callback); return $this; } } PKz Zu4-Illuminate/Foundation/Bus/PendingDispatch.phpnuW+Ajob = $job; } /** * Set the desired connection for the job. * * @param string|null $connection * @return $this */ public function onConnection($connection) { $this->job->onConnection($connection); return $this; } /** * Set the desired queue for the job. * * @param string|null $queue * @return $this */ public function onQueue($queue) { $this->job->onQueue($queue); return $this; } /** * Set the desired connection for the chain. * * @param string|null $connection * @return $this */ public function allOnConnection($connection) { $this->job->allOnConnection($connection); return $this; } /** * Set the desired queue for the chain. * * @param string|null $queue * @return $this */ public function allOnQueue($queue) { $this->job->allOnQueue($queue); return $this; } /** * Set the desired delay in seconds for the job. * * @param \DateTimeInterface|\DateInterval|int|null $delay * @return $this */ public function delay($delay) { $this->job->delay($delay); return $this; } /** * Indicate that the job should be dispatched after all database transactions have committed. * * @return $this */ public function afterCommit() { $this->job->afterCommit(); return $this; } /** * Indicate that the job should not wait until database transactions have been committed before dispatching. * * @return $this */ public function beforeCommit() { $this->job->beforeCommit(); return $this; } /** * Set the jobs that should run if this job is successful. * * @param array $chain * @return $this */ public function chain($chain) { $this->job->chain($chain); return $this; } /** * Indicate that the job should be dispatched after the response is sent to the browser. * * @return $this */ public function afterResponse() { $this->afterResponse = true; return $this; } /** * Determine if the job should be dispatched. * * @return bool */ protected function shouldDispatch() { if (! $this->job instanceof ShouldBeUnique) { return true; } return (new UniqueLock(Container::getInstance()->make(Cache::class))) ->acquire($this->job); } /** * Dynamically proxy methods to the underlying job. * * @param string $method * @param array $parameters * @return $this */ public function __call($method, $parameters) { $this->job->{$method}(...$parameters); return $this; } /** * Handle the object's destruction. * * @return void */ public function __destruct() { if (! $this->shouldDispatch()) { return; } elseif ($this->afterResponse) { app(Dispatcher::class)->dispatchAfterResponse($this->job); } else { app(Dispatcher::class)->dispatch($this->job); } } } PKz ZT;|U U *Illuminate/Foundation/Bus/Dispatchable.phpnuW+AdispatchSync(new static(...$arguments)); } /** * Dispatch a command to its appropriate handler in the current process. * * @return mixed * * @deprecated Will be removed in a future Laravel version. */ public static function dispatchNow(...$arguments) { return app(Dispatcher::class)->dispatchNow(new static(...$arguments)); } /** * Dispatch a command to its appropriate handler after the current process. * * @param mixed ...$arguments * @return mixed */ public static function dispatchAfterResponse(...$arguments) { return self::dispatch(...$arguments)->afterResponse(); } /** * Set the jobs that should run if this job is successful. * * @param array $chain * @return \Illuminate\Foundation\Bus\PendingChain */ public static function withChain($chain) { return new PendingChain(static::class, $chain); } } PKz Zh/,Illuminate/Foundation/Bus/DispatchesJobs.phpnuW+Adispatch($job); } /** * Dispatch a job to its appropriate handler in the current process. * * @param mixed $job * @return mixed * * @deprecated Will be removed in a future Laravel version. */ public function dispatchNow($job) { return app(Dispatcher::class)->dispatchNow($job); } /** * Dispatch a job to its appropriate handler in the current process. * * Queueable jobs will be dispatched to the "sync" queue. * * @param mixed $job * @return mixed */ public function dispatchSync($job) { return app(Dispatcher::class)->dispatchSync($job); } } PKz Z''*Illuminate/Foundation/Bus/PendingChain.phpnuW+Ajob = $job; $this->chain = $chain; } /** * Set the desired connection for the job. * * @param string|null $connection * @return $this */ public function onConnection($connection) { $this->connection = $connection; return $this; } /** * Set the desired queue for the job. * * @param string|null $queue * @return $this */ public function onQueue($queue) { $this->queue = $queue; return $this; } /** * Set the desired delay in seconds for the chain. * * @param \DateTimeInterface|\DateInterval|int|null $delay * @return $this */ public function delay($delay) { $this->delay = $delay; return $this; } /** * Add a callback to be executed on job failure. * * @param callable $callback * @return $this */ public function catch($callback) { $this->catchCallbacks[] = $callback instanceof Closure ? new SerializableClosure($callback) : $callback; return $this; } /** * Get the "catch" callbacks that have been registered. * * @return array */ public function catchCallbacks() { return $this->catchCallbacks ?? []; } /** * Dispatch the job with the given arguments. * * @return \Illuminate\Foundation\Bus\PendingDispatch */ public function dispatch() { if (is_string($this->job)) { $firstJob = new $this->job(...func_get_args()); } elseif ($this->job instanceof Closure) { $firstJob = CallQueuedClosure::create($this->job); } else { $firstJob = $this->job; } if ($this->connection) { $firstJob->chainConnection = $this->connection; $firstJob->connection = $firstJob->connection ?: $this->connection; } if ($this->queue) { $firstJob->chainQueue = $this->queue; $firstJob->queue = $firstJob->queue ?: $this->queue; } if ($this->delay) { $firstJob->delay = ! is_null($firstJob->delay) ? $firstJob->delay : $this->delay; } $firstJob->chain($this->chain); $firstJob->chainCatchCallbacks = $this->catchCallbacks(); return app(Dispatcher::class)->dispatch($firstJob); } } PKz Z:O mm)Illuminate/Foundation/ComposerScripts.phpnuW+AgetComposer()->getConfig()->get('vendor-dir').'/autoload.php'; static::clearCompiled(); } /** * Handle the post-update Composer event. * * @param \Composer\Script\Event $event * @return void */ public static function postUpdate(Event $event) { require_once $event->getComposer()->getConfig()->get('vendor-dir').'/autoload.php'; static::clearCompiled(); } /** * Handle the post-autoload-dump Composer event. * * @param \Composer\Script\Event $event * @return void */ public static function postAutoloadDump(Event $event) { require_once $event->getComposer()->getConfig()->get('vendor-dir').'/autoload.php'; static::clearCompiled(); } /** * Clear the cached Laravel bootstrapping files. * * @return void */ protected static function clearCompiled() { $laravel = new Application(getcwd()); if (is_file($configPath = $laravel->getCachedConfigPath())) { @unlink($configPath); } if (is_file($servicesPath = $laravel->getCachedServicesPath())) { @unlink($servicesPath); } if (is_file($packagesPath = $laravel->getCachedPackagesPath())) { @unlink($packagesPath); } } } PKz ZZ::Illuminate/Foundation/Mix.phpnuW+Aget('app.mix_hot_proxy_url'); if (! empty($customUrl)) { return new HtmlString("{$customUrl}{$path}"); } if (Str::startsWith($url, ['http://', 'https://'])) { return new HtmlString(Str::after($url, ':').$path); } return new HtmlString("//localhost:8080{$path}"); } $manifestPath = public_path($manifestDirectory.'/mix-manifest.json'); if (! isset($manifests[$manifestPath])) { if (! is_file($manifestPath)) { throw new Exception("Mix manifest not found at: {$manifestPath}"); } $manifests[$manifestPath] = json_decode(file_get_contents($manifestPath), true); } $manifest = $manifests[$manifestPath]; if (! isset($manifest[$path])) { $exception = new Exception("Unable to locate Mix file: {$path}."); if (! app('config')->get('app.debug')) { report($exception); return $path; } else { throw $exception; } } return new HtmlString(app('config')->get('app.mix_url').$manifestDirectory.$manifest[$path]); } } PKz ZzEE'Illuminate/Foundation/stubs/facade.stubnuW+AtoResponse(request())); } app()->abort($code, $message, $headers); } } if (! function_exists('abort_if')) { /** * Throw an HttpException with the given data if the given condition is true. * * @param bool $boolean * @param \Symfony\Component\HttpFoundation\Response|\Illuminate\Contracts\Support\Responsable|int $code * @param string $message * @param array $headers * @return void * * @throws \Symfony\Component\HttpKernel\Exception\HttpException * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ function abort_if($boolean, $code, $message = '', array $headers = []) { if ($boolean) { abort($code, $message, $headers); } } } if (! function_exists('abort_unless')) { /** * Throw an HttpException with the given data unless the given condition is true. * * @param bool $boolean * @param \Symfony\Component\HttpFoundation\Response|\Illuminate\Contracts\Support\Responsable|int $code * @param string $message * @param array $headers * @return void * * @throws \Symfony\Component\HttpKernel\Exception\HttpException * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ function abort_unless($boolean, $code, $message = '', array $headers = []) { if (! $boolean) { abort($code, $message, $headers); } } } if (! function_exists('action')) { /** * Generate the URL to a controller action. * * @param string|array $name * @param mixed $parameters * @param bool $absolute * @return string */ function action($name, $parameters = [], $absolute = true) { return app('url')->action($name, $parameters, $absolute); } } if (! function_exists('app')) { /** * Get the available container instance. * * @param string|null $abstract * @param array $parameters * @return mixed|\Illuminate\Contracts\Foundation\Application */ function app($abstract = null, array $parameters = []) { if (is_null($abstract)) { return Container::getInstance(); } return Container::getInstance()->make($abstract, $parameters); } } if (! function_exists('app_path')) { /** * Get the path to the application folder. * * @param string $path * @return string */ function app_path($path = '') { return app()->path($path); } } if (! function_exists('asset')) { /** * Generate an asset path for the application. * * @param string $path * @param bool|null $secure * @return string */ function asset($path, $secure = null) { return app('url')->asset($path, $secure); } } if (! function_exists('auth')) { /** * Get the available auth instance. * * @param string|null $guard * @return \Illuminate\Contracts\Auth\Factory|\Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard */ function auth($guard = null) { if (is_null($guard)) { return app(AuthFactory::class); } return app(AuthFactory::class)->guard($guard); } } if (! function_exists('back')) { /** * Create a new redirect response to the previous location. * * @param int $status * @param array $headers * @param mixed $fallback * @return \Illuminate\Http\RedirectResponse */ function back($status = 302, $headers = [], $fallback = false) { return app('redirect')->back($status, $headers, $fallback); } } if (! function_exists('base_path')) { /** * Get the path to the base of the install. * * @param string $path * @return string */ function base_path($path = '') { return app()->basePath($path); } } if (! function_exists('bcrypt')) { /** * Hash the given value against the bcrypt algorithm. * * @param string $value * @param array $options * @return string */ function bcrypt($value, $options = []) { return app('hash')->driver('bcrypt')->make($value, $options); } } if (! function_exists('broadcast')) { /** * Begin broadcasting an event. * * @param mixed|null $event * @return \Illuminate\Broadcasting\PendingBroadcast */ function broadcast($event = null) { return app(BroadcastFactory::class)->event($event); } } if (! function_exists('cache')) { /** * Get / set the specified cache value. * * If an array is passed, we'll assume you want to put to the cache. * * @param dynamic key|key,default|data,expiration|null * @return mixed|\Illuminate\Cache\CacheManager * * @throws \InvalidArgumentException */ function cache() { $arguments = func_get_args(); if (empty($arguments)) { return app('cache'); } if (is_string($arguments[0])) { return app('cache')->get(...$arguments); } if (! is_array($arguments[0])) { throw new InvalidArgumentException( 'When setting a value in the cache, you must pass an array of key / value pairs.' ); } return app('cache')->put(key($arguments[0]), reset($arguments[0]), $arguments[1] ?? null); } } if (! function_exists('config')) { /** * Get / set the specified configuration value. * * If an array is passed as the key, we will assume you want to set an array of values. * * @param array|string|null $key * @param mixed $default * @return mixed|\Illuminate\Config\Repository */ function config($key = null, $default = null) { if (is_null($key)) { return app('config'); } if (is_array($key)) { return app('config')->set($key); } return app('config')->get($key, $default); } } if (! function_exists('config_path')) { /** * Get the configuration path. * * @param string $path * @return string */ function config_path($path = '') { return app()->configPath($path); } } if (! function_exists('cookie')) { /** * Create a new cookie instance. * * @param string|null $name * @param string|null $value * @param int $minutes * @param string|null $path * @param string|null $domain * @param bool|null $secure * @param bool $httpOnly * @param bool $raw * @param string|null $sameSite * @return \Illuminate\Cookie\CookieJar|\Symfony\Component\HttpFoundation\Cookie */ function cookie($name = null, $value = null, $minutes = 0, $path = null, $domain = null, $secure = null, $httpOnly = true, $raw = false, $sameSite = null) { $cookie = app(CookieFactory::class); if (is_null($name)) { return $cookie; } return $cookie->make($name, $value, $minutes, $path, $domain, $secure, $httpOnly, $raw, $sameSite); } } if (! function_exists('csrf_field')) { /** * Generate a CSRF token form field. * * @return \Illuminate\Support\HtmlString */ function csrf_field() { return new HtmlString(''); } } if (! function_exists('csrf_token')) { /** * Get the CSRF token value. * * @return string * * @throws \RuntimeException */ function csrf_token() { $session = app('session'); if (isset($session)) { return $session->token(); } throw new RuntimeException('Application session store not set.'); } } if (! function_exists('database_path')) { /** * Get the database path. * * @param string $path * @return string */ function database_path($path = '') { return app()->databasePath($path); } } if (! function_exists('decrypt')) { /** * Decrypt the given value. * * @param string $value * @param bool $unserialize * @return mixed */ function decrypt($value, $unserialize = true) { return app('encrypter')->decrypt($value, $unserialize); } } if (! function_exists('dispatch')) { /** * Dispatch a job to its appropriate handler. * * @param mixed $job * @return \Illuminate\Foundation\Bus\PendingDispatch */ function dispatch($job) { return $job instanceof Closure ? new PendingClosureDispatch(CallQueuedClosure::create($job)) : new PendingDispatch($job); } } if (! function_exists('dispatch_sync')) { /** * Dispatch a command to its appropriate handler in the current process. * * Queueable jobs will be dispatched to the "sync" queue. * * @param mixed $job * @param mixed $handler * @return mixed */ function dispatch_sync($job, $handler = null) { return app(Dispatcher::class)->dispatchSync($job, $handler); } } if (! function_exists('dispatch_now')) { /** * Dispatch a command to its appropriate handler in the current process. * * @param mixed $job * @param mixed $handler * @return mixed * * @deprecated Will be removed in a future Laravel version. */ function dispatch_now($job, $handler = null) { return app(Dispatcher::class)->dispatchNow($job, $handler); } } if (! function_exists('encrypt')) { /** * Encrypt the given value. * * @param mixed $value * @param bool $serialize * @return string */ function encrypt($value, $serialize = true) { return app('encrypter')->encrypt($value, $serialize); } } if (! function_exists('event')) { /** * Dispatch an event and call the listeners. * * @param string|object $event * @param mixed $payload * @param bool $halt * @return array|null */ function event(...$args) { return app('events')->dispatch(...$args); } } if (! function_exists('fake') && class_exists(\Faker\Factory::class)) { /** * Get a faker instance. * * @param string|null $locale * @return \Faker\Generator */ function fake($locale = null) { if (app()->bound('config')) { $locale ??= app('config')->get('app.faker_locale'); } $locale ??= 'en_US'; $abstract = \Faker\Generator::class.':'.$locale; if (! app()->bound($abstract)) { app()->singleton($abstract, fn () => \Faker\Factory::create($locale)); } return app()->make($abstract); } } if (! function_exists('info')) { /** * Write some information to the log. * * @param string $message * @param array $context * @return void */ function info($message, $context = []) { app('log')->info($message, $context); } } if (! function_exists('logger')) { /** * Log a debug message to the logs. * * @param string|null $message * @param array $context * @return \Illuminate\Log\LogManager|null */ function logger($message = null, array $context = []) { if (is_null($message)) { return app('log'); } return app('log')->debug($message, $context); } } if (! function_exists('lang_path')) { /** * Get the path to the language folder. * * @param string $path * @return string */ function lang_path($path = '') { return app()->langPath($path); } } if (! function_exists('logs')) { /** * Get a log driver instance. * * @param string|null $driver * @return \Illuminate\Log\LogManager|\Psr\Log\LoggerInterface */ function logs($driver = null) { return $driver ? app('log')->driver($driver) : app('log'); } } if (! function_exists('method_field')) { /** * Generate a form field to spoof the HTTP verb used by forms. * * @param string $method * @return \Illuminate\Support\HtmlString */ function method_field($method) { return new HtmlString(''); } } if (! function_exists('mix')) { /** * Get the path to a versioned Mix file. * * @param string $path * @param string $manifestDirectory * @return \Illuminate\Support\HtmlString|string * * @throws \Exception */ function mix($path, $manifestDirectory = '') { return app(Mix::class)(...func_get_args()); } } if (! function_exists('now')) { /** * Create a new Carbon instance for the current time. * * @param \DateTimeZone|string|null $tz * @return \Illuminate\Support\Carbon */ function now($tz = null) { return Date::now($tz); } } if (! function_exists('old')) { /** * Retrieve an old input item. * * @param string|null $key * @param mixed $default * @return mixed */ function old($key = null, $default = null) { return app('request')->old($key, $default); } } if (! function_exists('policy')) { /** * Get a policy instance for a given class. * * @param object|string $class * @return mixed * * @throws \InvalidArgumentException */ function policy($class) { return app(Gate::class)->getPolicyFor($class); } } if (! function_exists('precognitive')) { /** * Handle a Precognition controller hook. * * @param null|callable $callable * @return mixed */ function precognitive($callable = null) { $callable ??= function () { // }; $payload = $callable(function ($default, $precognition = null) { $response = request()->isPrecognitive() ? ($precognition ?? $default) : $default; abort(Router::toResponse(request(), value($response))); }); if (request()->isPrecognitive()) { abort(204); } return $payload; } } if (! function_exists('public_path')) { /** * Get the path to the public folder. * * @param string $path * @return string */ function public_path($path = '') { return app()->make('path.public').($path ? DIRECTORY_SEPARATOR.ltrim($path, DIRECTORY_SEPARATOR) : $path); } } if (! function_exists('redirect')) { /** * Get an instance of the redirector. * * @param string|null $to * @param int $status * @param array $headers * @param bool|null $secure * @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse */ function redirect($to = null, $status = 302, $headers = [], $secure = null) { if (is_null($to)) { return app('redirect'); } return app('redirect')->to($to, $status, $headers, $secure); } } if (! function_exists('report')) { /** * Report an exception. * * @param \Throwable|string $exception * @return void */ function report($exception) { if (is_string($exception)) { $exception = new Exception($exception); } app(ExceptionHandler::class)->report($exception); } } if (! function_exists('report_if')) { /** * Report an exception if the given condition is true. * * @param bool $boolean * @param \Throwable|string $exception * @return void */ function report_if($boolean, $exception) { if ($boolean) { report($exception); } } } if (! function_exists('report_unless')) { /** * Report an exception unless the given condition is true. * * @param bool $boolean * @param \Throwable|string $exception * @return void */ function report_unless($boolean, $exception) { if (! $boolean) { report($exception); } } } if (! function_exists('request')) { /** * Get an instance of the current request or an input item from the request. * * @param array|string|null $key * @param mixed $default * @return mixed|\Illuminate\Http\Request|string|array|null */ function request($key = null, $default = null) { if (is_null($key)) { return app('request'); } if (is_array($key)) { return app('request')->only($key); } $value = app('request')->__get($key); return is_null($value) ? value($default) : $value; } } if (! function_exists('rescue')) { /** * Catch a potential exception and return a default value. * * @param callable $callback * @param mixed $rescue * @param bool|callable $report * @return mixed */ function rescue(callable $callback, $rescue = null, $report = true) { try { return $callback(); } catch (Throwable $e) { if (value($report, $e)) { report($e); } return value($rescue, $e); } } } if (! function_exists('resolve')) { /** * Resolve a service from the container. * * @param string $name * @param array $parameters * @return mixed */ function resolve($name, array $parameters = []) { return app($name, $parameters); } } if (! function_exists('resource_path')) { /** * Get the path to the resources folder. * * @param string $path * @return string */ function resource_path($path = '') { return app()->resourcePath($path); } } if (! function_exists('response')) { /** * Return a new response from the application. * * @param \Illuminate\Contracts\View\View|string|array|null $content * @param int $status * @param array $headers * @return \Illuminate\Http\Response|\Illuminate\Contracts\Routing\ResponseFactory */ function response($content = '', $status = 200, array $headers = []) { $factory = app(ResponseFactory::class); if (func_num_args() === 0) { return $factory; } return $factory->make($content, $status, $headers); } } if (! function_exists('route')) { /** * Generate the URL to a named route. * * @param array|string $name * @param mixed $parameters * @param bool $absolute * @return string */ function route($name, $parameters = [], $absolute = true) { return app('url')->route($name, $parameters, $absolute); } } if (! function_exists('secure_asset')) { /** * Generate an asset path for the application. * * @param string $path * @return string */ function secure_asset($path) { return asset($path, true); } } if (! function_exists('secure_url')) { /** * Generate a HTTPS url for the application. * * @param string $path * @param mixed $parameters * @return string */ function secure_url($path, $parameters = []) { return url($path, $parameters, true); } } if (! function_exists('session')) { /** * Get / set the specified session value. * * If an array is passed as the key, we will assume you want to set an array of values. * * @param array|string|null $key * @param mixed $default * @return mixed|\Illuminate\Session\Store|\Illuminate\Session\SessionManager */ function session($key = null, $default = null) { if (is_null($key)) { return app('session'); } if (is_array($key)) { return app('session')->put($key); } return app('session')->get($key, $default); } } if (! function_exists('storage_path')) { /** * Get the path to the storage folder. * * @param string $path * @return string */ function storage_path($path = '') { return app()->storagePath($path); } } if (! function_exists('to_route')) { /** * Create a new redirect response to a named route. * * @param string $route * @param mixed $parameters * @param int $status * @param array $headers * @return \Illuminate\Http\RedirectResponse */ function to_route($route, $parameters = [], $status = 302, $headers = []) { return redirect()->route($route, $parameters, $status, $headers); } } if (! function_exists('today')) { /** * Create a new Carbon instance for the current date. * * @param \DateTimeZone|string|null $tz * @return \Illuminate\Support\Carbon */ function today($tz = null) { return Date::today($tz); } } if (! function_exists('trans')) { /** * Translate the given message. * * @param string|null $key * @param array $replace * @param string|null $locale * @return \Illuminate\Contracts\Translation\Translator|string|array|null */ function trans($key = null, $replace = [], $locale = null) { if (is_null($key)) { return app('translator'); } return app('translator')->get($key, $replace, $locale); } } if (! function_exists('trans_choice')) { /** * Translates the given message based on a count. * * @param string $key * @param \Countable|int|array $number * @param array $replace * @param string|null $locale * @return string */ function trans_choice($key, $number, array $replace = [], $locale = null) { return app('translator')->choice($key, $number, $replace, $locale); } } if (! function_exists('__')) { /** * Translate the given message. * * @param string|null $key * @param array $replace * @param string|null $locale * @return string|array|null */ function __($key = null, $replace = [], $locale = null) { if (is_null($key)) { return $key; } return trans($key, $replace, $locale); } } if (! function_exists('url')) { /** * Generate a url for the application. * * @param string|null $path * @param mixed $parameters * @param bool|null $secure * @return \Illuminate\Contracts\Routing\UrlGenerator|string */ function url($path = null, $parameters = [], $secure = null) { if (is_null($path)) { return app(UrlGenerator::class); } return app(UrlGenerator::class)->to($path, $parameters, $secure); } } if (! function_exists('validator')) { /** * Create a new Validator instance. * * @param array $data * @param array $rules * @param array $messages * @param array $customAttributes * @return \Illuminate\Contracts\Validation\Validator|\Illuminate\Contracts\Validation\Factory */ function validator(array $data = [], array $rules = [], array $messages = [], array $customAttributes = []) { $factory = app(ValidationFactory::class); if (func_num_args() === 0) { return $factory; } return $factory->make($data, $rules, $messages, $customAttributes); } } if (! function_exists('view')) { /** * Get the evaluated view contents for the given view. * * @param string|null $view * @param \Illuminate\Contracts\Support\Arrayable|array $data * @param array $mergeData * @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory */ function view($view = null, $data = [], $mergeData = []) { $factory = app(ViewFactory::class); if (func_num_args() === 0) { return $factory; } return $factory->make($view, $data, $mergeData); } } PKz Z&&%Illuminate/Foundation/AliasLoader.phpnuW+Aaliases = $aliases; } /** * Get or create the singleton alias loader instance. * * @param array $aliases * @return \Illuminate\Foundation\AliasLoader */ public static function getInstance(array $aliases = []) { if (is_null(static::$instance)) { return static::$instance = new static($aliases); } $aliases = array_merge(static::$instance->getAliases(), $aliases); static::$instance->setAliases($aliases); return static::$instance; } /** * Load a class alias if it is registered. * * @param string $alias * @return bool|null */ public function load($alias) { if (static::$facadeNamespace && str_starts_with($alias, static::$facadeNamespace)) { $this->loadFacade($alias); return true; } if (isset($this->aliases[$alias])) { return class_alias($this->aliases[$alias], $alias); } } /** * Load a real-time facade for the given alias. * * @param string $alias * @return void */ protected function loadFacade($alias) { require $this->ensureFacadeExists($alias); } /** * Ensure that the given alias has an existing real-time facade class. * * @param string $alias * @return string */ protected function ensureFacadeExists($alias) { if (is_file($path = storage_path('framework/cache/facade-'.sha1($alias).'.php'))) { return $path; } file_put_contents($path, $this->formatFacadeStub( $alias, file_get_contents(__DIR__.'/stubs/facade.stub') )); return $path; } /** * Format the facade stub with the proper namespace and class. * * @param string $alias * @param string $stub * @return string */ protected function formatFacadeStub($alias, $stub) { $replacements = [ str_replace('/', '\\', dirname(str_replace('\\', '/', $alias))), class_basename($alias), substr($alias, strlen(static::$facadeNamespace)), ]; return str_replace( ['DummyNamespace', 'DummyClass', 'DummyTarget'], $replacements, $stub ); } /** * Add an alias to the loader. * * @param string $alias * @param string $class * @return void */ public function alias($alias, $class) { $this->aliases[$alias] = $class; } /** * Register the loader on the auto-loader stack. * * @return void */ public function register() { if (! $this->registered) { $this->prependToLoaderStack(); $this->registered = true; } } /** * Prepend the load method to the auto-loader stack. * * @return void */ protected function prependToLoaderStack() { spl_autoload_register([$this, 'load'], true, true); } /** * Get the registered aliases. * * @return array */ public function getAliases() { return $this->aliases; } /** * Set the registered aliases. * * @param array $aliases * @return void */ public function setAliases(array $aliases) { $this->aliases = $aliases; } /** * Indicates if the loader has been registered. * * @return bool */ public function isRegistered() { return $this->registered; } /** * Set the "registered" state of the loader. * * @param bool $value * @return void */ public function setRegistered($value) { $this->registered = $value; } /** * Set the real-time facade namespace. * * @param string $namespace * @return void */ public static function setFacadeNamespace($namespace) { static::$facadeNamespace = rtrim($namespace, '\\').'\\'; } /** * Set the value of the singleton alias loader. * * @param \Illuminate\Foundation\AliasLoader $loader * @return void */ public static function setInstance($loader) { static::$instance = $loader; } /** * Clone method. * * @return void */ private function __clone() { // } } PKz ZNGe!3Illuminate/Foundation/Console/EventClearCommand.phpnuW+Afiles = $files; } /** * Execute the console command. * * @return void * * @throws \RuntimeException */ public function handle() { $this->files->delete($this->laravel->getCachedEventsPath()); $this->components->info('Cached events cleared successfully.'); } } PKz Z3PP/Illuminate/Foundation/Console/QueuedCommand.phpnuW+Adata = $data; } /** * Handle the job. * * @param \Illuminate\Contracts\Console\Kernel $kernel * @return void */ public function handle(KernelContract $kernel) { $kernel->call(...array_values($this->data)); } } PKz ZQ;5Illuminate/Foundation/Console/ObserverMakeCommand.phpnuW+Aoption('model'); return $model ? $this->replaceModel($stub, $model) : $stub; } /** * Replace the model for the given stub. * * @param string $stub * @param string $model * @return string */ protected function replaceModel($stub, $model) { $modelClass = $this->parseModel($model); $replace = [ 'DummyFullModelClass' => $modelClass, '{{ namespacedModel }}' => $modelClass, '{{namespacedModel}}' => $modelClass, 'DummyModelClass' => class_basename($modelClass), '{{ model }}' => class_basename($modelClass), '{{model}}' => class_basename($modelClass), 'DummyModelVariable' => lcfirst(class_basename($modelClass)), '{{ modelVariable }}' => lcfirst(class_basename($modelClass)), '{{modelVariable}}' => lcfirst(class_basename($modelClass)), ]; return str_replace( array_keys($replace), array_values($replace), $stub ); } /** * Get the fully-qualified model class name. * * @param string $model * @return string * * @throws \InvalidArgumentException */ protected function parseModel($model) { if (preg_match('([^A-Za-z0-9_/\\\\])', $model)) { throw new InvalidArgumentException('Model name contains invalid characters.'); } return $this->qualifyModel($model); } /** * Get the stub file for the generator. * * @return string */ protected function getStub() { return $this->option('model') ? $this->resolveStubPath('/stubs/observer.stub') : $this->resolveStubPath('/stubs/observer.plain.stub'); } /** * Resolve the fully-qualified path to the stub. * * @param string $stub * @return string */ protected function resolveStubPath($stub) { return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) ? $customPath : __DIR__.$stub; } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return $rootNamespace.'\Observers'; } /** * Get the console command arguments. * * @return array */ protected function getOptions() { return [ ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the observer already exists'], ['model', 'm', InputOption::VALUE_OPTIONAL, 'The model that the observer applies to'], ]; } /** * Interact further with the user if they were prompted for missing arguments. * * @param \Symfony\Component\Console\Input\InputInterface $input * @param \Symfony\Component\Console\Output\OutputInterface $output * @return void */ protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output) { if ($this->isReservedName($this->getNameInput()) || $this->didReceiveOptions($input)) { return; } $model = $this->components->askWithCompletion( 'What model should this observer apply to?', $this->possibleModels(), 'none' ); if ($model && $model !== 'none') { $input->setOption('model', $model); } } } PKz Z8Illuminate/Foundation/Console/PackageDiscoverCommand.phpnuW+Acomponents->info('Discovering packages'); $manifest->build(); collect($manifest->manifest) ->keys() ->each(fn ($description) => $this->components->task($description)) ->whenNotEmpty(fn () => $this->newLine()); } } PKz Z@2Illuminate/Foundation/Console/ViewClearCommand.phpnuW+Afiles = $files; } /** * Execute the console command. * * @return void * * @throws \RuntimeException */ public function handle() { $path = $this->laravel['config']['view.compiled']; if (! $path) { throw new RuntimeException('View path not found.'); } $this->laravel['view.engine.resolver'] ->resolve('blade') ->forgetCompiledOrNotExpired(); foreach ($this->files->glob("{$path}/*") as $view) { $this->files->delete($view); } $this->components->info('Compiled views cleared successfully.'); } } PKz Z@55-Illuminate/Foundation/Console/DocsCommand.phpnuW+Aphp artisan docs -- search query here'; /** * The HTTP client instance. * * @var \Illuminate\Http\Client\Factory */ protected $http; /** * The cache repository implementation. * * @var \Illuminate\Contracts\Cache\Repository */ protected $cache; /** * The custom URL opener. * * @var callable|null */ protected $urlOpener; /** * The custom documentation version to open. * * @var string|null */ protected $version; /** * The operating system family. * * @var string */ protected $systemOsFamily = PHP_OS_FAMILY; /** * Configure the current command. * * @return void */ protected function configure() { parent::configure(); if ($this->isSearching()) { $this->ignoreValidationErrors(); } } /** * Execute the console command. * * @param \Illuminate\Http\Client\Factory $http * @param \Illuminate\Contracts\Cache\Repository $cache * @return int */ public function handle(Http $http, Cache $cache) { $this->http = $http; $this->cache = $cache; try { $this->openUrl(); } catch (ProcessFailedException $e) { if ($e->getProcess()->getExitCodeText() === 'Interrupt') { return $e->getProcess()->getExitCode(); } throw $e; } $this->refreshDocs(); return Command::SUCCESS; } /** * Open the documentation URL. * * @return void */ protected function openUrl() { with($this->url(), function ($url) { $this->components->info("Opening the docs to: {$url}"); $this->open($url); }); } /** * The URL to the documentation page. * * @return string */ protected function url() { if ($this->isSearching()) { return "https://laravel.com/docs/{$this->version()}?".Arr::query([ 'q' => $this->searchQuery(), ]); } return with($this->page(), function ($page) { return trim("https://laravel.com/docs/{$this->version()}/{$page}#{$this->section($page)}", '#/'); }); } /** * The page the user is opening. * * @return string */ protected function page() { return with($this->resolvePage(), function ($page) { if ($page === null) { $this->components->warn('Unable to determine the page you are trying to visit.'); return '/'; } return $page; }); } /** * Determine the page to open. * * @return string|null */ protected function resolvePage() { if ($this->option('no-interaction') && $this->didNotRequestPage()) { return '/'; } return $this->didNotRequestPage() ? $this->askForPage() : $this->guessPage(); } /** * Determine if the user requested a specific page when calling the command. * * @return bool */ protected function didNotRequestPage() { return $this->argument('page') === null; } /** * Ask the user which page they would like to open. * * @return string|null */ protected function askForPage() { return $this->askForPageViaCustomStrategy() ?? $this->askForPageViaAutocomplete(); } /** * Ask the user which page they would like to open via a custom strategy. * * @return string|null */ protected function askForPageViaCustomStrategy() { try { $strategy = require Env::get('ARTISAN_DOCS_ASK_STRATEGY'); } catch (Throwable $e) { return null; } if (! is_callable($strategy)) { return null; } return $strategy($this) ?? '/'; } /** * Ask the user which page they would like to open using autocomplete. * * @return string|null */ protected function askForPageViaAutocomplete() { $choice = $this->components->choice( 'Which page would you like to open?', $this->pages()->mapWithKeys(fn ($option) => [ Str::lower($option['title']) => $option['title'], ])->all(), 'installation', 3 ); return $this->pages()->filter( fn ($page) => $page['title'] === $choice || Str::lower($page['title']) === $choice )->keys()->first() ?: null; } /** * Guess the page the user is attempting to open. * * @return string|null */ protected function guessPage() { return $this->pages() ->filter(fn ($page) => str_starts_with( Str::slug($page['title'], ' '), Str::slug($this->argument('page'), ' ') ))->keys()->first() ?? $this->pages()->map(fn ($page) => similar_text( Str::slug($page['title'], ' '), Str::slug($this->argument('page'), ' '), )) ->filter(fn ($score) => $score >= min(3, Str::length($this->argument('page')))) ->sortDesc() ->keys() ->sortByDesc(fn ($slug) => Str::contains( Str::slug($this->pages()[$slug]['title'], ' '), Str::slug($this->argument('page'), ' ') ) ? 1 : 0) ->first(); } /** * The section the user specifically asked to open. * * @param string $page * @return string|null */ protected function section($page) { return $this->didNotRequestSection() ? null : $this->guessSection($page); } /** * Determine if the user requested a specific section when calling the command. * * @return bool */ protected function didNotRequestSection() { return $this->argument('section') === null; } /** * Guess the section the user is attempting to open. * * @param string $page * @return string|null */ protected function guessSection($page) { return $this->sectionsFor($page) ->filter(fn ($section) => str_starts_with( Str::slug($section['title'], ' '), Str::slug($this->argument('section'), ' ') ))->keys()->first() ?? $this->sectionsFor($page)->map(fn ($section) => similar_text( Str::slug($section['title'], ' '), Str::slug($this->argument('section'), ' '), )) ->filter(fn ($score) => $score >= min(3, Str::length($this->argument('section')))) ->sortDesc() ->keys() ->sortByDesc(fn ($slug) => Str::contains( Str::slug($this->sectionsFor($page)[$slug]['title'], ' '), Str::slug($this->argument('section'), ' ') ) ? 1 : 0) ->first(); } /** * Open the URL in the user's browser. * * @param string $url * @return void */ protected function open($url) { ($this->urlOpener ?? function ($url) { if (Env::get('ARTISAN_DOCS_OPEN_STRATEGY')) { $this->openViaCustomStrategy($url); } elseif (in_array($this->systemOsFamily, ['Darwin', 'Windows', 'Linux'])) { $this->openViaBuiltInStrategy($url); } else { $this->components->warn('Unable to open the URL on your system. You will need to open it yourself or create a custom opener for your system.'); } })($url); } /** * Open the URL via a custom strategy. * * @param string $url * @return void */ protected function openViaCustomStrategy($url) { try { $command = require Env::get('ARTISAN_DOCS_OPEN_STRATEGY'); } catch (Throwable $e) { $command = null; } if (! is_callable($command)) { $this->components->warn('Unable to open the URL with your custom strategy. You will need to open it yourself.'); return; } $command($url); } /** * Open the URL via the built in strategy. * * @param string $url * @return void */ protected function openViaBuiltInStrategy($url) { if ($this->systemOsFamily === 'Windows') { $process = tap(Process::fromShellCommandline(escapeshellcmd("start {$url}")))->run(); if (! $process->isSuccessful()) { throw new ProcessFailedException($process); } return; } $binary = Collection::make(match ($this->systemOsFamily) { 'Darwin' => ['open'], 'Linux' => ['xdg-open', 'wslview'], })->first(fn ($binary) => (new ExecutableFinder)->find($binary) !== null); if ($binary === null) { $this->components->warn('Unable to open the URL on your system. You will need to open it yourself or create a custom opener for your system.'); return; } $process = tap(Process::fromShellCommandline(escapeshellcmd("{$binary} {$url}")))->run(); if (! $process->isSuccessful()) { throw new ProcessFailedException($process); } } /** * The available sections for the page. * * @param string $page * @return \Illuminate\Support\Collection */ public function sectionsFor($page) { return new Collection($this->pages()[$page]['sections']); } /** * The pages available to open. * * @return \Illuminate\Support\Collection */ public function pages() { return new Collection($this->docs()['pages']); } /** * Get the documentation index as a collection. * * @return \Illuminate\Support\Collection */ public function docs() { return $this->cache->remember( "artisan.docs.{{$this->version()}}.index", CarbonInterval::months(2), fn () => $this->fetchDocs()->throw()->collect() ); } /** * Refresh the cached copy of the documentation index. * * @return void */ protected function refreshDocs() { with($this->fetchDocs(), function ($response) { if ($response->successful()) { $this->cache->put("artisan.docs.{{$this->version()}}.index", $response->collect(), CarbonInterval::months(2)); } }); } /** * Fetch the documentation index from the Laravel website. * * @return \Illuminate\Http\Client\Response */ protected function fetchDocs() { return $this->http->get("https://laravel.com/docs/{$this->version()}/index.json"); } /** * Determine the version of the docs to open. * * @return string */ protected function version() { return Str::before($this->version ?? $this->laravel->version(), '.').'.x'; } /** * The search query the user provided. * * @return string */ protected function searchQuery() { return Collection::make($_SERVER['argv'])->skip(3)->implode(' '); } /** * Determine if the command is intended to perform a search. * * @return bool */ protected function isSearching() { return ($_SERVER['argv'][2] ?? null) === '--'; } /** * Set the documentation version. * * @param string $version * @return $this */ public function setVersion($version) { $this->version = $version; return $this; } /** * Set a custom URL opener. * * @param callable|null $opener * @return $this */ public function setUrlOpener($opener) { $this->urlOpener = $opener; return $this; } /** * Set the system operating system family. * * @param string $family * @return $this */ public function setSystemOsFamily($family) { $this->systemOsFamily = $family; return $this; } } PKz Z{տ2Illuminate/Foundation/Console/ScopeMakeCommand.phpnuW+AresolveStubPath('/stubs/scope.stub'); } /** * Resolve the fully-qualified path to the stub. * * @param string $stub * @return string */ protected function resolveStubPath($stub) { return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) ? $customPath : __DIR__.$stub; } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return is_dir(app_path('Models')) ? $rootNamespace.'\\Models\\Scopes' : $rootNamespace.'\Scopes'; } /** * Get the console command arguments. * * @return array */ protected function getOptions() { return [ ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the scope already exists'], ]; } } PKz ZAɝ4Illuminate/Foundation/Console/ChannelMakeCommand.phpnuW+AuserProviderModel()), parent::buildClass($name) ); } /** * Get the stub file for the generator. * * @return string */ protected function getStub() { return __DIR__.'/stubs/channel.stub'; } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return $rootNamespace.'\Broadcasting'; } /** * Get the console command arguments. * * @return array */ protected function getOptions() { return [ ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the channel already exists'], ]; } } PKz ZϤ.GG-Illuminate/Foundation/Console/DownCommand.phpnuW+Alaravel->maintenanceMode()->active()) { $this->components->info('Application is already down.'); return 0; } $this->laravel->maintenanceMode()->activate($this->getDownFilePayload()); file_put_contents( storage_path('framework/maintenance.php'), file_get_contents(__DIR__.'/stubs/maintenance-mode.stub') ); $this->laravel->get('events')->dispatch(new MaintenanceModeEnabled()); $this->components->info('Application is now in maintenance mode.'); } catch (Exception $e) { $this->components->error(sprintf( 'Failed to enter maintenance mode: %s.', $e->getMessage(), )); return 1; } } /** * Get the payload to be placed in the "down" file. * * @return array */ protected function getDownFilePayload() { return [ 'except' => $this->excludedPaths(), 'redirect' => $this->redirectPath(), 'retry' => $this->getRetryTime(), 'refresh' => $this->option('refresh'), 'secret' => $this->option('secret'), 'status' => (int) $this->option('status', 503), 'template' => $this->option('render') ? $this->prerenderView() : null, ]; } /** * Get the paths that should be excluded from maintenance mode. * * @return array */ protected function excludedPaths() { try { return $this->laravel->make(PreventRequestsDuringMaintenance::class)->getExcludedPaths(); } catch (Throwable $e) { return []; } } /** * Get the path that users should be redirected to. * * @return string */ protected function redirectPath() { if ($this->option('redirect') && $this->option('redirect') !== '/') { return '/'.trim($this->option('redirect'), '/'); } return $this->option('redirect'); } /** * Prerender the specified view so that it can be rendered even before loading Composer. * * @return string */ protected function prerenderView() { (new RegisterErrorViewPaths)(); return view($this->option('render'), [ 'retryAfter' => $this->option('retry'), ])->render(); } /** * Get the number of seconds the client should wait before retrying their request. * * @return int|null */ protected function getRetryTime() { $retry = $this->option('retry'); return is_numeric($retry) && $retry > 0 ? (int) $retry : null; } } PKz Ze~iuu1Illuminate/Foundation/Console/TestMakeCommand.phpnuW+Aoption('unit') ? '.unit.stub' : '.stub'; return $this->option('pest') ? $this->resolveStubPath('/stubs/pest'.$suffix) : $this->resolveStubPath('/stubs/test'.$suffix); } /** * Resolve the fully-qualified path to the stub. * * @param string $stub * @return string */ protected function resolveStubPath($stub) { return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) ? $customPath : __DIR__.$stub; } /** * Get the destination class path. * * @param string $name * @return string */ protected function getPath($name) { $name = Str::replaceFirst($this->rootNamespace(), '', $name); return base_path('tests').str_replace('\\', '/', $name).'.php'; } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { if ($this->option('unit')) { return $rootNamespace.'\Unit'; } else { return $rootNamespace.'\Feature'; } } /** * Get the root namespace for the class. * * @return string */ protected function rootNamespace() { return 'Tests'; } /** * Get the console command options. * * @return array */ protected function getOptions() { return [ ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the test already exists'], ['unit', 'u', InputOption::VALUE_NONE, 'Create a unit test'], ['pest', 'p', InputOption::VALUE_NONE, 'Create a Pest test'], ]; } /** * Interact further with the user if they were prompted for missing arguments. * * @param \Symfony\Component\Console\Input\InputInterface $input * @param \Symfony\Component\Console\Output\OutputInterface $output * @return void */ protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output) { if ($this->isReservedName($this->getNameInput()) || $this->didReceiveOptions($input)) { return; } $type = $this->components->choice('Which type of test would you like', [ 'feature', 'unit', 'pest feature', 'pest unit', ], default: 0); match ($type) { 'feature' => null, 'unit' => $input->setOption('unit', true), 'pest feature' => $input->setOption('pest', true), 'pest unit' => tap($input)->setOption('pest', true)->setOption('unit', true), }; } } PKz ZWv 4Illuminate/Foundation/Console/KeyGenerateCommand.phpnuW+AgenerateRandomKey(); if ($this->option('show')) { return $this->line(''.$key.''); } // Next, we will replace the application key in the environment file so it is // automatically setup for this developer. This key gets generated using a // secure random byte generator and is later base64 encoded for storage. if (! $this->setKeyInEnvironmentFile($key)) { return; } $this->laravel['config']['app.key'] = $key; $this->components->info('Application key set successfully.'); } /** * Generate a random key for the application. * * @return string */ protected function generateRandomKey() { return 'base64:'.base64_encode( Encrypter::generateKey($this->laravel['config']['app.cipher']) ); } /** * Set the application key in the environment file. * * @param string $key * @return bool */ protected function setKeyInEnvironmentFile($key) { $currentKey = $this->laravel['config']['app.key']; if (strlen($currentKey) !== 0 && (! $this->confirmToProceed())) { return false; } if (! $this->writeNewEnvironmentFileWith($key)) { return false; } return true; } /** * Write a new environment file with the given key. * * @param string $key * @return bool */ protected function writeNewEnvironmentFileWith($key) { $replaced = preg_replace( $this->keyReplacementPattern(), 'APP_KEY='.$key, $input = file_get_contents($this->laravel->environmentFilePath()) ); if ($replaced === $input || $replaced === null) { $this->error('Unable to set application key. No APP_KEY variable was found in the .env file.'); return false; } file_put_contents($this->laravel->environmentFilePath(), $replaced); return true; } /** * Get a regex pattern that will match env APP_KEY with any random key. * * @return string */ protected function keyReplacementPattern() { $escaped = preg_quote('='.$this->laravel['config']['app.key'], '/'); return "/^APP_KEY{$escaped}/m"; } } PKz Z\ju4Illuminate/Foundation/Console/RequestMakeCommand.phpnuW+AresolveStubPath('/stubs/request.stub'); } /** * Resolve the fully-qualified path to the stub. * * @param string $stub * @return string */ protected function resolveStubPath($stub) { return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) ? $customPath : __DIR__.$stub; } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return $rootNamespace.'\Http\Requests'; } /** * Get the console command arguments. * * @return array */ protected function getOptions() { return [ ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the request already exists'], ]; } } PKz Z 3Illuminate/Foundation/Console/RouteCacheCommand.phpnuW+Afiles = $files; } /** * Execute the console command. * * @return void */ public function handle() { $this->callSilent('route:clear'); $routes = $this->getFreshApplicationRoutes(); if (count($routes) === 0) { return $this->components->error("Your application doesn't have any routes."); } foreach ($routes as $route) { $route->prepareForSerialization(); } $this->files->put( $this->laravel->getCachedRoutesPath(), $this->buildRouteCacheFile($routes) ); $this->components->info('Routes cached successfully.'); } /** * Boot a fresh copy of the application and get the routes. * * @return \Illuminate\Routing\RouteCollection */ protected function getFreshApplicationRoutes() { return tap($this->getFreshApplication()['router']->getRoutes(), function ($routes) { $routes->refreshNameLookups(); $routes->refreshActionLookups(); }); } /** * Get a fresh application instance. * * @return \Illuminate\Contracts\Foundation\Application */ protected function getFreshApplication() { return tap(require $this->laravel->bootstrapPath().'/app.php', function ($app) { $app->make(ConsoleKernelContract::class)->bootstrap(); }); } /** * Build the route cache file. * * @param \Illuminate\Routing\RouteCollection $routes * @return string */ protected function buildRouteCacheFile(RouteCollection $routes) { $stub = $this->files->get(__DIR__.'/stubs/routes.stub'); return str_replace('{{routes}}', var_export($routes->compile(), true), $stub); } } PKz Zw6Illuminate/Foundation/Console/OptimizeClearCommand.phpnuW+Acomponents->info('Clearing cached bootstrap files.'); collect([ 'events' => fn () => $this->callSilent('event:clear') == 0, 'views' => fn () => $this->callSilent('view:clear') == 0, 'cache' => fn () => $this->callSilent('cache:clear') == 0, 'route' => fn () => $this->callSilent('route:clear') == 0, 'config' => fn () => $this->callSilent('config:clear') == 0, 'compiled' => fn () => $this->callSilent('clear-compiled') == 0, ])->each(fn ($task, $description) => $this->components->task($description, $task)); $this->newLine(); } } PKz Z{1Illuminate/Foundation/Console/MailMakeCommand.phpnuW+Aoption('force')) { return; } if ($this->option('markdown') !== false) { $this->writeMarkdownTemplate(); } } /** * Write the Markdown template for the mailable. * * @return void */ protected function writeMarkdownTemplate() { $path = $this->viewPath( str_replace('.', '/', $this->getView()).'.blade.php' ); if (! $this->files->isDirectory(dirname($path))) { $this->files->makeDirectory(dirname($path), 0755, true); } $this->files->put($path, file_get_contents(__DIR__.'/stubs/markdown.stub')); } /** * Build the class with the given name. * * @param string $name * @return string */ protected function buildClass($name) { $class = str_replace( '{{ subject }}', Str::headline(str_replace($this->getNamespace($name).'\\', '', $name)), parent::buildClass($name) ); if ($this->option('markdown') !== false) { $class = str_replace(['DummyView', '{{ view }}'], $this->getView(), $class); } return $class; } /** * Get the view name. * * @return string */ protected function getView() { $view = $this->option('markdown'); if (! $view) { $name = str_replace('\\', '/', $this->argument('name')); $view = 'mail.'.collect(explode('/', $name)) ->map(fn ($part) => Str::kebab($part)) ->implode('.'); } return $view; } /** * Get the stub file for the generator. * * @return string */ protected function getStub() { return $this->resolveStubPath( $this->option('markdown') !== false ? '/stubs/markdown-mail.stub' : '/stubs/mail.stub'); } /** * Resolve the fully-qualified path to the stub. * * @param string $stub * @return string */ protected function resolveStubPath($stub) { return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) ? $customPath : __DIR__.$stub; } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return $rootNamespace.'\Mail'; } /** * Get the console command options. * * @return array */ protected function getOptions() { return [ ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the mailable already exists'], ['markdown', 'm', InputOption::VALUE_OPTIONAL, 'Create a new Markdown template for the mailable', false], ]; } } PKz Z*s4 4 2Illuminate/Foundation/Console/ViewCacheCommand.phpnuW+AcallSilent('view:clear'); $this->paths()->each(function ($path) { $prefix = $this->output->isVeryVerbose() ? 'DIR ' : ''; $this->components->task($prefix.$path, null, OutputInterface::VERBOSITY_VERBOSE); $this->compileViews($this->bladeFilesIn([$path])); }); $this->newLine(); $this->components->info('Blade templates cached successfully.'); } /** * Compile the given view files. * * @param \Illuminate\Support\Collection $views * @return void */ protected function compileViews(Collection $views) { $compiler = $this->laravel['view']->getEngineResolver()->resolve('blade')->getCompiler(); $views->map(function (SplFileInfo $file) use ($compiler) { $this->components->task(' '.$file->getRelativePathname(), null, OutputInterface::VERBOSITY_VERY_VERBOSE); $compiler->compile($file->getRealPath()); }); if ($this->output->isVeryVerbose()) { $this->newLine(); } } /** * Get the Blade files in the given path. * * @param array $paths * @return \Illuminate\Support\Collection */ protected function bladeFilesIn(array $paths) { return collect( Finder::create() ->in($paths) ->exclude('vendor') ->name('*.blade.php') ->files() ); } /** * Get all of the possible view paths. * * @return \Illuminate\Support\Collection */ protected function paths() { $finder = $this->laravel['view']->getFinder(); return collect($finder->getPaths())->merge( collect($finder->getHints())->flatten() ); } } PKz Z36Illuminate/Foundation/Console/ComponentMakeCommand.phpnuW+Aoption('view')) { $this->writeView(function () { $this->components->info($this->type.' created successfully.'); }); return; } if (parent::handle() === false && ! $this->option('force')) { return false; } if (! $this->option('inline')) { $this->writeView(); } } /** * Write the view for the component. * * @param callable|null $onSuccess * @return void */ protected function writeView($onSuccess = null) { $path = $this->viewPath( str_replace('.', '/', 'components.'.$this->getView()).'.blade.php' ); if (! $this->files->isDirectory(dirname($path))) { $this->files->makeDirectory(dirname($path), 0777, true, true); } if ($this->files->exists($path) && ! $this->option('force')) { $this->components->error('View already exists.'); return; } file_put_contents( $path, '
' ); if ($onSuccess) { $onSuccess(); } } /** * Build the class with the given name. * * @param string $name * @return string */ protected function buildClass($name) { if ($this->option('inline')) { return str_replace( ['DummyView', '{{ view }}'], "<<<'blade'\n
\n \n
\nblade", parent::buildClass($name) ); } return str_replace( ['DummyView', '{{ view }}'], 'view(\'components.'.$this->getView().'\')', parent::buildClass($name) ); } /** * Get the view name relative to the components directory. * * @return string view */ protected function getView() { $name = str_replace('\\', '/', $this->argument('name')); return collect(explode('/', $name)) ->map(function ($part) { return Str::kebab($part); }) ->implode('.'); } /** * Get the stub file for the generator. * * @return string */ protected function getStub() { return $this->resolveStubPath('/stubs/view-component.stub'); } /** * Resolve the fully-qualified path to the stub. * * @param string $stub * @return string */ protected function resolveStubPath($stub) { return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) ? $customPath : __DIR__.$stub; } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return $rootNamespace.'\View\Components'; } /** * Get the console command options. * * @return array */ protected function getOptions() { return [ ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the component already exists'], ['inline', null, InputOption::VALUE_NONE, 'Create a component that renders an inline view'], ['view', null, InputOption::VALUE_NONE, 'Create an anonymous component with only a view'], ]; } } PKz Zak//(Illuminate/Foundation/Console/Kernel.phpnuW+Aapp = $app; $this->events = $events; $this->app->booted(function () { $this->defineConsoleSchedule(); }); } /** * Define the application's command schedule. * * @return void */ protected function defineConsoleSchedule() { $this->app->singleton(Schedule::class, function ($app) { return tap(new Schedule($this->scheduleTimezone()), function ($schedule) { $this->schedule($schedule->useCache($this->scheduleCache())); }); }); } /** * Get the name of the cache store that should manage scheduling mutexes. * * @return string */ protected function scheduleCache() { return $this->app['config']->get('cache.schedule_store', Env::get('SCHEDULE_CACHE_DRIVER')); } /** * Run the console application. * * @param \Symfony\Component\Console\Input\InputInterface $input * @param \Symfony\Component\Console\Output\OutputInterface|null $output * @return int */ public function handle($input, $output = null) { $this->commandStartedAt = Carbon::now(); try { if (in_array($input->getFirstArgument(), ['env:encrypt', 'env:decrypt'], true)) { $this->bootstrapWithoutBootingProviders(); } $this->bootstrap(); return $this->getArtisan()->run($input, $output); } catch (Throwable $e) { $this->reportException($e); $this->renderException($output, $e); return 1; } } /** * Terminate the application. * * @param \Symfony\Component\Console\Input\InputInterface $input * @param int $status * @return void */ public function terminate($input, $status) { $this->app->terminate(); foreach ($this->commandLifecycleDurationHandlers as ['threshold' => $threshold, 'handler' => $handler]) { $end ??= Carbon::now(); if ($this->commandStartedAt->diffInMilliseconds($end) > $threshold) { $handler($this->commandStartedAt, $input, $status); } } $this->commandStartedAt = null; } /** * Register a callback to be invoked when the command lifecycle duration exceeds a given amount of time. * * @param \DateTimeInterface|\Carbon\CarbonInterval|float|int $threshold * @param callable $handler * @return void */ public function whenCommandLifecycleIsLongerThan($threshold, $handler) { $threshold = $threshold instanceof DateTimeInterface ? $this->secondsUntil($threshold) * 1000 : $threshold; $threshold = $threshold instanceof CarbonInterval ? $threshold->totalMilliseconds : $threshold; $this->commandLifecycleDurationHandlers[] = [ 'threshold' => $threshold, 'handler' => $handler, ]; } /** * When the command being handled started. * * @return \Illuminate\Support\Carbon|null */ public function commandStartedAt() { return $this->commandStartedAt; } /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { // } /** * Get the timezone that should be used by default for scheduled events. * * @return \DateTimeZone|string|null */ protected function scheduleTimezone() { $config = $this->app['config']; return $config->get('app.schedule_timezone', $config->get('app.timezone')); } /** * Register the commands for the application. * * @return void */ protected function commands() { // } /** * Register a Closure based command with the application. * * @param string $signature * @param \Closure $callback * @return \Illuminate\Foundation\Console\ClosureCommand */ public function command($signature, Closure $callback) { $command = new ClosureCommand($signature, $callback); Artisan::starting(function ($artisan) use ($command) { $artisan->add($command); }); return $command; } /** * Register all of the commands in the given directory. * * @param array|string $paths * @return void */ protected function load($paths) { $paths = array_unique(Arr::wrap($paths)); $paths = array_filter($paths, function ($path) { return is_dir($path); }); if (empty($paths)) { return; } $namespace = $this->app->getNamespace(); foreach ((new Finder)->in($paths)->files() as $command) { $command = $namespace.str_replace( ['/', '.php'], ['\\', ''], Str::after($command->getRealPath(), realpath(app_path()).DIRECTORY_SEPARATOR) ); if (is_subclass_of($command, Command::class) && ! (new ReflectionClass($command))->isAbstract()) { Artisan::starting(function ($artisan) use ($command) { $artisan->resolve($command); }); } } } /** * Register the given command with the console application. * * @param \Symfony\Component\Console\Command\Command $command * @return void */ public function registerCommand($command) { $this->getArtisan()->add($command); } /** * Run an Artisan console command by name. * * @param string $command * @param array $parameters * @param \Symfony\Component\Console\Output\OutputInterface|null $outputBuffer * @return int * * @throws \Symfony\Component\Console\Exception\CommandNotFoundException */ public function call($command, array $parameters = [], $outputBuffer = null) { if (in_array($command, ['env:encrypt', 'env:decrypt'], true)) { $this->bootstrapWithoutBootingProviders(); } $this->bootstrap(); return $this->getArtisan()->call($command, $parameters, $outputBuffer); } /** * Queue the given console command. * * @param string $command * @param array $parameters * @return \Illuminate\Foundation\Bus\PendingDispatch */ public function queue($command, array $parameters = []) { return QueuedCommand::dispatch(func_get_args()); } /** * Get all of the commands registered with the console. * * @return array */ public function all() { $this->bootstrap(); return $this->getArtisan()->all(); } /** * Get the output for the last run command. * * @return string */ public function output() { $this->bootstrap(); return $this->getArtisan()->output(); } /** * Bootstrap the application for artisan commands. * * @return void */ public function bootstrap() { if (! $this->app->hasBeenBootstrapped()) { $this->app->bootstrapWith($this->bootstrappers()); } $this->app->loadDeferredProviders(); if (! $this->commandsLoaded) { $this->commands(); $this->commandsLoaded = true; } } /** * Bootstrap the application without booting service providers. * * @return void */ public function bootstrapWithoutBootingProviders() { $this->app->bootstrapWith( collect($this->bootstrappers())->reject(function ($bootstrapper) { return $bootstrapper === \Illuminate\Foundation\Bootstrap\BootProviders::class; })->all() ); } /** * Get the Artisan application instance. * * @return \Illuminate\Console\Application */ protected function getArtisan() { if (is_null($this->artisan)) { $this->artisan = (new Artisan($this->app, $this->events, $this->app->version())) ->resolveCommands($this->commands) ->setContainerCommandLoader(); } return $this->artisan; } /** * Set the Artisan application instance. * * @param \Illuminate\Console\Application $artisan * @return void */ public function setArtisan($artisan) { $this->artisan = $artisan; } /** * Get the bootstrap classes for the application. * * @return array */ protected function bootstrappers() { return $this->bootstrappers; } /** * Report the exception to the exception handler. * * @param \Throwable $e * @return void */ protected function reportException(Throwable $e) { $this->app[ExceptionHandler::class]->report($e); } /** * Render the given exception. * * @param \Symfony\Component\Console\Output\OutputInterface $output * @param \Throwable $e * @return void */ protected function renderException($output, Throwable $e) { $this->app[ExceptionHandler::class]->renderForConsole($output, $e); } } PKz ZD9WW1Illuminate/Foundation/Console/CastMakeCommand.phpnuW+Aoption('inbound') ? $this->resolveStubPath('/stubs/cast.inbound.stub') : $this->resolveStubPath('/stubs/cast.stub'); } /** * Resolve the fully-qualified path to the stub. * * @param string $stub * @return string */ protected function resolveStubPath($stub) { return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) ? $customPath : __DIR__.$stub; } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return $rootNamespace.'\Casts'; } /** * Get the console command arguments. * * @return array */ protected function getOptions() { return [ ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the cast already exists'], ['inbound', null, InputOption::VALUE_NONE, 'Generate an inbound cast class'], ]; } } PKz Z[~*  3Illuminate/Foundation/Console/PolicyMakeCommand.phpnuW+AreplaceUserNamespace( parent::buildClass($name) ); $model = $this->option('model'); return $model ? $this->replaceModel($stub, $model) : $stub; } /** * Replace the User model namespace. * * @param string $stub * @return string */ protected function replaceUserNamespace($stub) { $model = $this->userProviderModel(); if (! $model) { return $stub; } return str_replace( $this->rootNamespace().'User', $model, $stub ); } /** * Get the model for the guard's user provider. * * @return string|null * * @throws \LogicException */ protected function userProviderModel() { $config = $this->laravel['config']; $guard = $this->option('guard') ?: $config->get('auth.defaults.guard'); if (is_null($guardProvider = $config->get('auth.guards.'.$guard.'.provider'))) { throw new LogicException('The ['.$guard.'] guard is not defined in your "auth" configuration file.'); } if (! $config->get('auth.providers.'.$guardProvider.'.model')) { return 'App\\Models\\User'; } return $config->get( 'auth.providers.'.$guardProvider.'.model' ); } /** * Replace the model for the given stub. * * @param string $stub * @param string $model * @return string */ protected function replaceModel($stub, $model) { $model = str_replace('/', '\\', $model); if (str_starts_with($model, '\\')) { $namespacedModel = trim($model, '\\'); } else { $namespacedModel = $this->qualifyModel($model); } $model = class_basename(trim($model, '\\')); $dummyUser = class_basename($this->userProviderModel()); $dummyModel = Str::camel($model) === 'user' ? 'model' : $model; $replace = [ 'NamespacedDummyModel' => $namespacedModel, '{{ namespacedModel }}' => $namespacedModel, '{{namespacedModel}}' => $namespacedModel, 'DummyModel' => $model, '{{ model }}' => $model, '{{model}}' => $model, 'dummyModel' => Str::camel($dummyModel), '{{ modelVariable }}' => Str::camel($dummyModel), '{{modelVariable}}' => Str::camel($dummyModel), 'DummyUser' => $dummyUser, '{{ user }}' => $dummyUser, '{{user}}' => $dummyUser, '$user' => '$'.Str::camel($dummyUser), ]; $stub = str_replace( array_keys($replace), array_values($replace), $stub ); return preg_replace( vsprintf('/use %s;[\r\n]+use %s;/', [ preg_quote($namespacedModel, '/'), preg_quote($namespacedModel, '/'), ]), "use {$namespacedModel};", $stub ); } /** * Get the stub file for the generator. * * @return string */ protected function getStub() { return $this->option('model') ? $this->resolveStubPath('/stubs/policy.stub') : $this->resolveStubPath('/stubs/policy.plain.stub'); } /** * Resolve the fully-qualified path to the stub. * * @param string $stub * @return string */ protected function resolveStubPath($stub) { return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) ? $customPath : __DIR__.$stub; } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return $rootNamespace.'\Policies'; } /** * Get the console command arguments. * * @return array */ protected function getOptions() { return [ ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the policy already exists'], ['model', 'm', InputOption::VALUE_OPTIONAL, 'The model that the policy applies to'], ['guard', 'g', InputOption::VALUE_OPTIONAL, 'The guard that the policy relies on'], ]; } /** * Interact further with the user if they were prompted for missing arguments. * * @param \Symfony\Component\Console\Input\InputInterface $input * @param \Symfony\Component\Console\Output\OutputInterface $output * @return void */ protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output) { if ($this->isReservedName($this->getNameInput()) || $this->didReceiveOptions($input)) { return; } $model = $this->components->askWithCompletion( 'What model should this policy apply to?', $this->possibleModels(), 'none' ); if ($model && $model !== 'none') { $input->setOption('model', $model); } } } PKz Z [ [ 6Illuminate/Foundation/Console/ExceptionMakeCommand.phpnuW+Aoption('render')) { return $this->option('report') ? __DIR__.'/stubs/exception-render-report.stub' : __DIR__.'/stubs/exception-render.stub'; } return $this->option('report') ? __DIR__.'/stubs/exception-report.stub' : __DIR__.'/stubs/exception.stub'; } /** * Determine if the class already exists. * * @param string $rawName * @return bool */ protected function alreadyExists($rawName) { return class_exists($this->rootNamespace().'Exceptions\\'.$rawName); } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return $rootNamespace.'\Exceptions'; } /** * Get the console command options. * * @return array */ protected function getOptions() { return [ ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the exception already exists'], ['render', null, InputOption::VALUE_NONE, 'Create the exception with an empty render method'], ['report', null, InputOption::VALUE_NONE, 'Create the exception with an empty report method'], ]; } } PKz ZZ?- - 4Illuminate/Foundation/Console/StorageLinkCommand.phpnuW+Aoption('relative'); foreach ($this->links() as $link => $target) { if (file_exists($link) && ! $this->isRemovableSymlink($link, $this->option('force'))) { $this->components->error("The [$link] link already exists."); continue; } if (is_link($link)) { $this->laravel->make('files')->delete($link); } if ($relative) { $this->laravel->make('files')->relativeLink($target, $link); } else { $this->laravel->make('files')->link($target, $link); } $this->components->info("The [$link] link has been connected to [$target]."); } } /** * Get the symbolic links that are configured for the application. * * @return array */ protected function links() { return $this->laravel['config']['filesystems.links'] ?? [public_path('storage') => storage_path('app/public')]; } /** * Determine if the provided path is a symlink that can be removed. * * @param string $link * @param bool $force * @return bool */ protected function isRemovableSymlink(string $link, bool $force): bool { return is_link($link) && $force; } } PKz Z1qR3Illuminate/Foundation/Console/RouteClearCommand.phpnuW+Afiles = $files; } /** * Execute the console command. * * @return void */ public function handle() { $this->files->delete($this->laravel->getCachedRoutesPath()); $this->components->info('Route cache cleared successfully.'); } } PKz ZE5Illuminate/Foundation/Console/ProviderMakeCommand.phpnuW+AresolveStubPath('/stubs/provider.stub'); } /** * Resolve the fully-qualified path to the stub. * * @param string $stub * @return string */ protected function resolveStubPath($stub) { return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) ? $customPath : __DIR__.$stub; } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return $rootNamespace.'\Providers'; } /** * Get the console command arguments. * * @return array */ protected function getOptions() { return [ ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the provider already exists'], ]; } } PKz ZW|Ұff2Illuminate/Foundation/Console/EventListCommand.phpnuW+AgetEvents()->sortKeys(); if ($events->isEmpty()) { $this->components->info("Your application doesn't have any events matching the given criteria."); return; } $this->newLine(); $events->each(function ($listeners, $event) { $this->components->twoColumnDetail($this->appendEventInterfaces($event)); $this->components->bulletList($listeners); }); $this->newLine(); } /** * Get all of the events and listeners configured for the application. * * @return \Illuminate\Support\Collection */ protected function getEvents() { $events = collect($this->getListenersOnDispatcher()); if ($this->filteringByEvent()) { $events = $this->filterEvents($events); } return $events; } /** * Get the event / listeners from the dispatcher object. * * @return array */ protected function getListenersOnDispatcher() { $events = []; foreach ($this->getRawListeners() as $event => $rawListeners) { foreach ($rawListeners as $rawListener) { if (is_string($rawListener)) { $events[$event][] = $this->appendListenerInterfaces($rawListener); } elseif ($rawListener instanceof Closure) { $events[$event][] = $this->stringifyClosure($rawListener); } elseif (is_array($rawListener) && count($rawListener) === 2) { if (is_object($rawListener[0])) { $rawListener[0] = get_class($rawListener[0]); } $events[$event][] = $this->appendListenerInterfaces(implode('@', $rawListener)); } } } return $events; } /** * Add the event implemented interfaces to the output. * * @param string $event * @return string */ protected function appendEventInterfaces($event) { if (! class_exists($event)) { return $event; } $interfaces = class_implements($event); if (in_array(ShouldBroadcast::class, $interfaces)) { $event .= ' (ShouldBroadcast)'; } return $event; } /** * Add the listener implemented interfaces to the output. * * @param string $listener * @return string */ protected function appendListenerInterfaces($listener) { $listener = explode('@', $listener); $interfaces = class_implements($listener[0]); $listener = implode('@', $listener); if (in_array(ShouldQueue::class, $interfaces)) { $listener .= ' (ShouldQueue)'; } return $listener; } /** * Get a displayable string representation of a Closure listener. * * @param \Closure $rawListener * @return string */ protected function stringifyClosure(Closure $rawListener) { $reflection = new ReflectionFunction($rawListener); $path = str_replace([base_path(), DIRECTORY_SEPARATOR], ['', '/'], $reflection->getFileName() ?: ''); return 'Closure at: '.$path.':'.$reflection->getStartLine(); } /** * Filter the given events using the provided event name filter. * * @param \Illuminate\Support\Collection $events * @return \Illuminate\Support\Collection */ protected function filterEvents($events) { if (! $eventName = $this->option('event')) { return $events; } return $events->filter( fn ($listeners, $event) => str_contains($event, $eventName) ); } /** * Determine whether the user is filtering by an event name. * * @return bool */ protected function filteringByEvent() { return ! empty($this->option('event')); } /** * Gets the raw version of event listeners from the event dispatcher. * * @return array */ protected function getRawListeners() { return $this->getEventsDispatcher()->getRawListeners(); } /** * Get the event dispatcher. * * @return Illuminate\Events\Dispatcher */ public function getEventsDispatcher() { return is_null(self::$eventsResolver) ? $this->getLaravel()->make('events') : call_user_func(self::$eventsResolver); } /** * Set a callback that should be used when resolving the events dispatcher. * * @param \Closure|null $resolver * @return void */ public static function resolveEventsUsing($resolver) { static::$eventsResolver = $resolver; } } PKz ZZWO O 4Illuminate/Foundation/Console/ConsoleMakeCommand.phpnuW+Aoption('command'), $stub); } /** * Get the stub file for the generator. * * @return string */ protected function getStub() { $relativePath = '/stubs/console.stub'; return file_exists($customPath = $this->laravel->basePath(trim($relativePath, '/'))) ? $customPath : __DIR__.$relativePath; } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return $rootNamespace.'\Console\Commands'; } /** * Get the console command arguments. * * @return array */ protected function getArguments() { return [ ['name', InputArgument::REQUIRED, 'The name of the command'], ]; } /** * Get the console command options. * * @return array */ protected function getOptions() { return [ ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the console command already exists'], ['command', null, InputOption::VALUE_OPTIONAL, 'The terminal command that should be assigned', 'command:name'], ]; } } PKz Zb0"DD2Illuminate/Foundation/Console/ShowModelCommand.phpnuW+AensureDependenciesExist()) { return 1; } $class = $this->qualifyModel($this->argument('model')); try { $model = $this->laravel->make($class); $class = get_class($model); } catch (BindingResolutionException $e) { return $this->components->error($e->getMessage()); } if ($this->option('database')) { $model->setConnection($this->option('database')); } $this->display( $class, $model->getConnection()->getName(), $model->getConnection()->getTablePrefix().$model->getTable(), $this->getPolicy($model), $this->getAttributes($model), $this->getRelations($model), $this->getObservers($model), ); } /** * Get the first policy associated with this model. * * @param \Illuminate\Database\Eloquent\Model $model * @return Illuminate\Support\Collection */ protected function getPolicy($model) { return collect(Gate::policies()) ->filter(fn ($policy, $modelClass) => $modelClass === get_class($model)) ->values() ->first(); } /** * Get the column attributes for the given model. * * @param \Illuminate\Database\Eloquent\Model $model * @return \Illuminate\Support\Collection */ protected function getAttributes($model) { $schema = $model->getConnection()->getDoctrineSchemaManager(); $this->registerTypeMappings($schema->getDatabasePlatform()); $table = $model->getConnection()->getTablePrefix().$model->getTable(); $columns = $schema->listTableColumns($table); $indexes = $schema->listTableIndexes($table); return collect($columns) ->values() ->map(fn (Column $column) => [ 'name' => $column->getName(), 'type' => $this->getColumnType($column), 'increments' => $column->getAutoincrement(), 'nullable' => ! $column->getNotnull(), 'default' => $this->getColumnDefault($column, $model), 'unique' => $this->columnIsUnique($column->getName(), $indexes), 'fillable' => $model->isFillable($column->getName()), 'hidden' => $this->attributeIsHidden($column->getName(), $model), 'appended' => null, 'cast' => $this->getCastType($column->getName(), $model), ]) ->merge($this->getVirtualAttributes($model, $columns)); } /** * Get the virtual (non-column) attributes for the given model. * * @param \Illuminate\Database\Eloquent\Model $model * @param \Doctrine\DBAL\Schema\Column[] $columns * @return \Illuminate\Support\Collection */ protected function getVirtualAttributes($model, $columns) { $class = new ReflectionClass($model); return collect($class->getMethods()) ->reject( fn (ReflectionMethod $method) => $method->isStatic() || $method->isAbstract() || $method->getDeclaringClass()->getName() !== get_class($model) ) ->mapWithKeys(function (ReflectionMethod $method) use ($model) { if (preg_match('/^get(.+)Attribute$/', $method->getName(), $matches) === 1) { return [Str::snake($matches[1]) => 'accessor']; } elseif ($model->hasAttributeMutator($method->getName())) { return [Str::snake($method->getName()) => 'attribute']; } else { return []; } }) ->reject(fn ($cast, $name) => collect($columns)->has($name)) ->map(fn ($cast, $name) => [ 'name' => $name, 'type' => null, 'increments' => false, 'nullable' => null, 'default' => null, 'unique' => null, 'fillable' => $model->isFillable($name), 'hidden' => $this->attributeIsHidden($name, $model), 'appended' => $model->hasAppended($name), 'cast' => $cast, ]) ->values(); } /** * Get the relations from the given model. * * @param \Illuminate\Database\Eloquent\Model $model * @return \Illuminate\Support\Collection */ protected function getRelations($model) { return collect(get_class_methods($model)) ->map(fn ($method) => new ReflectionMethod($model, $method)) ->reject( fn (ReflectionMethod $method) => $method->isStatic() || $method->isAbstract() || $method->getDeclaringClass()->getName() !== get_class($model) ) ->filter(function (ReflectionMethod $method) { $file = new SplFileObject($method->getFileName()); $file->seek($method->getStartLine() - 1); $code = ''; while ($file->key() < $method->getEndLine()) { $code .= trim($file->current()); $file->next(); } return collect($this->relationMethods) ->contains(fn ($relationMethod) => str_contains($code, '$this->'.$relationMethod.'(')); }) ->map(function (ReflectionMethod $method) use ($model) { $relation = $method->invoke($model); if (! $relation instanceof Relation) { return null; } return [ 'name' => $method->getName(), 'type' => Str::afterLast(get_class($relation), '\\'), 'related' => get_class($relation->getRelated()), ]; }) ->filter() ->values(); } /** * Get the Observers watching this model. * * @param \Illuminate\Database\Eloquent\Model $model * @return Illuminate\Support\Collection */ protected function getObservers($model) { $listeners = $this->getLaravel()->make('events')->getRawListeners(); // Get the Eloquent observers for this model... $listeners = array_filter($listeners, function ($v, $key) use ($model) { return Str::startsWith($key, 'eloquent.') && Str::endsWith($key, $model::class); }, ARRAY_FILTER_USE_BOTH); // Format listeners Eloquent verb => Observer methods... $extractVerb = function ($key) { preg_match('/eloquent.([a-zA-Z]+)\: /', $key, $matches); return $matches[1] ?? '?'; }; $formatted = []; foreach ($listeners as $key => $observerMethods) { $formatted[] = [ 'event' => $extractVerb($key), 'observer' => array_map(fn ($obs) => is_string($obs) ? $obs : 'Closure', $observerMethods), ]; } return collect($formatted); } /** * Render the model information. * * @param string $class * @param string $database * @param string $table * @param string $policy * @param \Illuminate\Support\Collection $attributes * @param \Illuminate\Support\Collection $relations * @param \Illuminate\Support\Collection $observers * @return void */ protected function display($class, $database, $table, $policy, $attributes, $relations, $observers) { $this->option('json') ? $this->displayJson($class, $database, $table, $policy, $attributes, $relations, $observers) : $this->displayCli($class, $database, $table, $policy, $attributes, $relations, $observers); } /** * Render the model information as JSON. * * @param string $class * @param string $database * @param string $table * @param string $policy * @param \Illuminate\Support\Collection $attributes * @param \Illuminate\Support\Collection $relations * @param \Illuminate\Support\Collection $observers * @return void */ protected function displayJson($class, $database, $table, $policy, $attributes, $relations, $observers) { $this->output->writeln( collect([ 'class' => $class, 'database' => $database, 'table' => $table, 'policy' => $policy, 'attributes' => $attributes, 'relations' => $relations, 'observers' => $observers, ])->toJson() ); } /** * Render the model information for the CLI. * * @param string $class * @param string $database * @param string $table * @param string $policy * @param \Illuminate\Support\Collection $attributes * @param \Illuminate\Support\Collection $relations * @param \Illuminate\Support\Collection $observers * @return void */ protected function displayCli($class, $database, $table, $policy, $attributes, $relations, $observers) { $this->newLine(); $this->components->twoColumnDetail(''.$class.''); $this->components->twoColumnDetail('Database', $database); $this->components->twoColumnDetail('Table', $table); if ($policy) { $this->components->twoColumnDetail('Policy', $policy); } $this->newLine(); $this->components->twoColumnDetail( 'Attributes', 'type / cast', ); foreach ($attributes as $attribute) { $first = trim(sprintf( '%s %s', $attribute['name'], collect(['increments', 'unique', 'nullable', 'fillable', 'hidden', 'appended']) ->filter(fn ($property) => $attribute[$property]) ->map(fn ($property) => sprintf('%s', $property)) ->implode(', ') )); $second = collect([ $attribute['type'], $attribute['cast'] ? ''.$attribute['cast'].'' : null, ])->filter()->implode(' / '); $this->components->twoColumnDetail($first, $second); if ($attribute['default'] !== null) { $this->components->bulletList( [sprintf('default: %s', $attribute['default'])], OutputInterface::VERBOSITY_VERBOSE ); } } $this->newLine(); $this->components->twoColumnDetail('Relations'); foreach ($relations as $relation) { $this->components->twoColumnDetail( sprintf('%s %s', $relation['name'], $relation['type']), $relation['related'] ); } $this->newLine(); $this->components->twoColumnDetail('Observers'); if ($observers->count()) { foreach ($observers as $observer) { $this->components->twoColumnDetail( sprintf('%s', $observer['event']), implode(', ', $observer['observer']) ); } } $this->newLine(); } /** * Get the cast type for the given column. * * @param string $column * @param \Illuminate\Database\Eloquent\Model $model * @return string|null */ protected function getCastType($column, $model) { if ($model->hasGetMutator($column) || $model->hasSetMutator($column)) { return 'accessor'; } if ($model->hasAttributeMutator($column)) { return 'attribute'; } return $this->getCastsWithDates($model)->get($column) ?? null; } /** * Get the model casts, including any date casts. * * @param \Illuminate\Database\Eloquent\Model $model * @return \Illuminate\Support\Collection */ protected function getCastsWithDates($model) { return collect($model->getDates()) ->filter() ->flip() ->map(fn () => 'datetime') ->merge($model->getCasts()); } /** * Get the type of the given column. * * @param \Doctrine\DBAL\Schema\Column $column * @return string */ protected function getColumnType($column) { $name = $column->getType()->getName(); $unsigned = $column->getUnsigned() ? ' unsigned' : ''; $details = match (get_class($column->getType())) { DecimalType::class => $column->getPrecision().','.$column->getScale(), default => $column->getLength(), }; if ($details) { return sprintf('%s(%s)%s', $name, $details, $unsigned); } return sprintf('%s%s', $name, $unsigned); } /** * Get the default value for the given column. * * @param \Doctrine\DBAL\Schema\Column $column * @param \Illuminate\Database\Eloquent\Model $model * @return mixed|null */ protected function getColumnDefault($column, $model) { $attributeDefault = $model->getAttributes()[$column->getName()] ?? null; return match (true) { $attributeDefault instanceof BackedEnum => $attributeDefault->value, $attributeDefault instanceof UnitEnum => $attributeDefault->name, default => $attributeDefault ?? $column->getDefault(), }; } /** * Determine if the given attribute is hidden. * * @param string $attribute * @param \Illuminate\Database\Eloquent\Model $model * @return bool */ protected function attributeIsHidden($attribute, $model) { if (count($model->getHidden()) > 0) { return in_array($attribute, $model->getHidden()); } if (count($model->getVisible()) > 0) { return ! in_array($attribute, $model->getVisible()); } return false; } /** * Determine if the given attribute is unique. * * @param string $column * @param \Doctrine\DBAL\Schema\Index[] $indexes * @return bool */ protected function columnIsUnique($column, $indexes) { return collect($indexes) ->filter(fn (Index $index) => count($index->getColumns()) === 1 && $index->getColumns()[0] === $column) ->contains(fn (Index $index) => $index->isUnique()); } /** * Qualify the given model class base name. * * @param string $model * @return string * * @see \Illuminate\Console\GeneratorCommand */ protected function qualifyModel(string $model) { if (str_contains($model, '\\') && class_exists($model)) { return $model; } $model = ltrim($model, '\\/'); $model = str_replace('/', '\\', $model); $rootNamespace = $this->laravel->getNamespace(); if (Str::startsWith($model, $rootNamespace)) { return $model; } return is_dir(app_path('Models')) ? $rootNamespace.'Models\\'.$model : $rootNamespace.$model; } } PKz ZWT 4Illuminate/Foundation/Console/EnvironmentCommand.phpnuW+Acomponents->info(sprintf( 'The application environment is [%s].', $this->laravel['env'], )); } } PKz Z=2Illuminate/Foundation/Console/ModelMakeCommand.phpnuW+Aoption('force')) { return false; } if ($this->option('all')) { $this->input->setOption('factory', true); $this->input->setOption('seed', true); $this->input->setOption('migration', true); $this->input->setOption('controller', true); $this->input->setOption('policy', true); $this->input->setOption('resource', true); } if ($this->option('factory')) { $this->createFactory(); } if ($this->option('migration')) { $this->createMigration(); } if ($this->option('seed')) { $this->createSeeder(); } if ($this->option('controller') || $this->option('resource') || $this->option('api')) { $this->createController(); } if ($this->option('policy')) { $this->createPolicy(); } } /** * Create a model factory for the model. * * @return void */ protected function createFactory() { $factory = Str::studly($this->argument('name')); $this->call('make:factory', [ 'name' => "{$factory}Factory", '--model' => $this->qualifyClass($this->getNameInput()), ]); } /** * Create a migration file for the model. * * @return void */ protected function createMigration() { $table = Str::snake(Str::pluralStudly(class_basename($this->argument('name')))); if ($this->option('pivot')) { $table = Str::singular($table); } $this->call('make:migration', [ 'name' => "create_{$table}_table", '--create' => $table, '--fullpath' => true, ]); } /** * Create a seeder file for the model. * * @return void */ protected function createSeeder() { $seeder = Str::studly(class_basename($this->argument('name'))); $this->call('make:seeder', [ 'name' => "{$seeder}Seeder", ]); } /** * Create a controller for the model. * * @return void */ protected function createController() { $controller = Str::studly(class_basename($this->argument('name'))); $modelName = $this->qualifyClass($this->getNameInput()); $this->call('make:controller', array_filter([ 'name' => "{$controller}Controller", '--model' => $this->option('resource') || $this->option('api') ? $modelName : null, '--api' => $this->option('api'), '--requests' => $this->option('requests') || $this->option('all'), ])); } /** * Create a policy file for the model. * * @return void */ protected function createPolicy() { $policy = Str::studly(class_basename($this->argument('name'))); $this->call('make:policy', [ 'name' => "{$policy}Policy", '--model' => $this->qualifyClass($this->getNameInput()), ]); } /** * Get the stub file for the generator. * * @return string */ protected function getStub() { if ($this->option('pivot')) { return $this->resolveStubPath('/stubs/model.pivot.stub'); } if ($this->option('morph-pivot')) { return $this->resolveStubPath('/stubs/model.morph-pivot.stub'); } return $this->resolveStubPath('/stubs/model.stub'); } /** * Resolve the fully-qualified path to the stub. * * @param string $stub * @return string */ protected function resolveStubPath($stub) { return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) ? $customPath : __DIR__.$stub; } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return is_dir(app_path('Models')) ? $rootNamespace.'\\Models' : $rootNamespace; } /** * Get the console command options. * * @return array */ protected function getOptions() { return [ ['all', 'a', InputOption::VALUE_NONE, 'Generate a migration, seeder, factory, policy, resource controller, and form request classes for the model'], ['controller', 'c', InputOption::VALUE_NONE, 'Create a new controller for the model'], ['factory', 'f', InputOption::VALUE_NONE, 'Create a new factory for the model'], ['force', null, InputOption::VALUE_NONE, 'Create the class even if the model already exists'], ['migration', 'm', InputOption::VALUE_NONE, 'Create a new migration file for the model'], ['morph-pivot', null, InputOption::VALUE_NONE, 'Indicates if the generated model should be a custom polymorphic intermediate table model'], ['policy', null, InputOption::VALUE_NONE, 'Create a new policy for the model'], ['seed', 's', InputOption::VALUE_NONE, 'Create a new seeder for the model'], ['pivot', 'p', InputOption::VALUE_NONE, 'Indicates if the generated model should be a custom intermediate table model'], ['resource', 'r', InputOption::VALUE_NONE, 'Indicates if the generated controller should be a resource controller'], ['api', null, InputOption::VALUE_NONE, 'Indicates if the generated controller should be an API resource controller'], ['requests', 'R', InputOption::VALUE_NONE, 'Create new form request classes and use them in the resource controller'], ]; } /** * Interact further with the user if they were prompted for missing arguments. * * @param \Symfony\Component\Console\Input\InputInterface $input * @param \Symfony\Component\Console\Output\OutputInterface $output * @return void */ protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output) { if ($this->isReservedName($this->getNameInput()) || $this->didReceiveOptions($input)) { return; } collect($this->components->choice('Would you like any of the following?', [ 'none', 'all', 'factory', 'form requests', 'migration', 'policy', 'resource controller', 'seed', ], default: 0, multiple: true)) ->reject('none') ->map(fn ($option) => match ($option) { 'resource controller' => 'resource', 'form requests' => 'requests', default => $option, }) ->each(fn ($option) => $input->setOption($option, true)); } } PKz ZjV.3Illuminate/Foundation/Console/EventCacheCommand.phpnuW+AcallSilent('event:clear'); file_put_contents( $this->laravel->getCachedEventsPath(), 'getEvents(), true).';' ); $this->components->info('Events cached successfully.'); } /** * Get all of the events and listeners configured for the application. * * @return array */ protected function getEvents() { $events = []; foreach ($this->laravel->getProviders(EventServiceProvider::class) as $provider) { $providerEvents = array_merge_recursive($provider->shouldDiscoverEvents() ? $provider->discoverEvents() : [], $provider->listens()); $events[get_class($provider)] = $providerEvents; } return $events; } } PKz ZGV6Illuminate/Foundation/Console/EventGenerateCommand.phpnuW+Alaravel->getProviders(EventServiceProvider::class); foreach ($providers as $provider) { foreach ($provider->listens() as $event => $listeners) { $this->makeEventAndListeners($event, $listeners); } } $this->components->info('Events and listeners generated successfully.'); } /** * Make the event and listeners for the given event. * * @param string $event * @param array $listeners * @return void */ protected function makeEventAndListeners($event, $listeners) { if (! str_contains($event, '\\')) { return; } $this->callSilent('make:event', ['name' => $event]); $this->makeListeners($event, $listeners); } /** * Make the listeners for the given event. * * @param string $event * @param array $listeners * @return void */ protected function makeListeners($event, $listeners) { foreach ($listeners as $listener) { $listener = preg_replace('/@.+$/', '', $listener); $this->callSilent('make:listener', array_filter( ['name' => $listener, '--event' => $event] )); } } } PKz Z6pұ0Illuminate/Foundation/Console/JobMakeCommand.phpnuW+Aoption('sync') ? $this->resolveStubPath('/stubs/job.stub') : $this->resolveStubPath('/stubs/job.queued.stub'); } /** * Resolve the fully-qualified path to the stub. * * @param string $stub * @return string */ protected function resolveStubPath($stub) { return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) ? $customPath : __DIR__.$stub; } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return $rootNamespace.'\Jobs'; } /** * Get the console command options. * * @return array */ protected function getOptions() { return [ ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the job already exists'], ['sync', null, InputOption::VALUE_NONE, 'Indicates that job should be synchronous'], ]; } } PKz Z44Illuminate/Foundation/Console/StubPublishCommand.phpnuW+Alaravel->basePath('stubs'))) { (new Filesystem)->makeDirectory($stubsPath); } $stubs = [ __DIR__.'/stubs/cast.inbound.stub' => 'cast.inbound.stub', __DIR__.'/stubs/cast.stub' => 'cast.stub', __DIR__.'/stubs/console.stub' => 'console.stub', __DIR__.'/stubs/event.stub' => 'event.stub', __DIR__.'/stubs/job.queued.stub' => 'job.queued.stub', __DIR__.'/stubs/job.stub' => 'job.stub', __DIR__.'/stubs/mail.stub' => 'mail.stub', __DIR__.'/stubs/markdown-mail.stub' => 'markdown-mail.stub', __DIR__.'/stubs/markdown-notification.stub' => 'markdown-notification.stub', __DIR__.'/stubs/model.pivot.stub' => 'model.pivot.stub', __DIR__.'/stubs/model.stub' => 'model.stub', __DIR__.'/stubs/notification.stub' => 'notification.stub', __DIR__.'/stubs/observer.plain.stub' => 'observer.plain.stub', __DIR__.'/stubs/observer.stub' => 'observer.stub', __DIR__.'/stubs/policy.plain.stub' => 'policy.plain.stub', __DIR__.'/stubs/policy.stub' => 'policy.stub', __DIR__.'/stubs/provider.stub' => 'provider.stub', __DIR__.'/stubs/request.stub' => 'request.stub', __DIR__.'/stubs/resource.stub' => 'resource.stub', __DIR__.'/stubs/resource-collection.stub' => 'resource-collection.stub', __DIR__.'/stubs/rule.stub' => 'rule.stub', __DIR__.'/stubs/scope.stub' => 'scope.stub', __DIR__.'/stubs/test.stub' => 'test.stub', __DIR__.'/stubs/test.unit.stub' => 'test.unit.stub', __DIR__.'/stubs/view-component.stub' => 'view-component.stub', realpath(__DIR__.'/../../Database/Console/Factories/stubs/factory.stub') => 'factory.stub', realpath(__DIR__.'/../../Database/Console/Seeds/stubs/seeder.stub') => 'seeder.stub', realpath(__DIR__.'/../../Database/Migrations/stubs/migration.create.stub') => 'migration.create.stub', realpath(__DIR__.'/../../Database/Migrations/stubs/migration.stub') => 'migration.stub', realpath(__DIR__.'/../../Database/Migrations/stubs/migration.update.stub') => 'migration.update.stub', realpath(__DIR__.'/../../Routing/Console/stubs/controller.api.stub') => 'controller.api.stub', realpath(__DIR__.'/../../Routing/Console/stubs/controller.invokable.stub') => 'controller.invokable.stub', realpath(__DIR__.'/../../Routing/Console/stubs/controller.model.api.stub') => 'controller.model.api.stub', realpath(__DIR__.'/../../Routing/Console/stubs/controller.model.stub') => 'controller.model.stub', realpath(__DIR__.'/../../Routing/Console/stubs/controller.nested.api.stub') => 'controller.nested.api.stub', realpath(__DIR__.'/../../Routing/Console/stubs/controller.nested.singleton.api.stub') => 'controller.nested.singleton.api.stub', realpath(__DIR__.'/../../Routing/Console/stubs/controller.nested.singleton.stub') => 'controller.nested.singleton.stub', realpath(__DIR__.'/../../Routing/Console/stubs/controller.nested.stub') => 'controller.nested.stub', realpath(__DIR__.'/../../Routing/Console/stubs/controller.plain.stub') => 'controller.plain.stub', realpath(__DIR__.'/../../Routing/Console/stubs/controller.singleton.api.stub') => 'controller.singleton.api.stub', realpath(__DIR__.'/../../Routing/Console/stubs/controller.singleton.stub') => 'controller.singleton.stub', realpath(__DIR__.'/../../Routing/Console/stubs/controller.stub') => 'controller.stub', realpath(__DIR__.'/../../Routing/Console/stubs/middleware.stub') => 'middleware.stub', ]; $this->laravel['events']->dispatch($event = new PublishingStubs($stubs)); foreach ($event->stubs as $from => $to) { $to = $stubsPath.DIRECTORY_SEPARATOR.ltrim($to, DIRECTORY_SEPARATOR); if ((! $this->option('existing') && (! file_exists($to) || $this->option('force'))) || ($this->option('existing') && file_exists($to))) { file_put_contents($to, file_get_contents($from)); } } $this->components->info('Stubs published successfully.'); } } PKz Z-00Illuminate/Foundation/Console/ClosureCommand.phpnuW+Acallback = $callback; $this->signature = $signature; parent::__construct(); } /** * Execute the console command. * * @param \Symfony\Component\Console\Input\InputInterface $input * @param \Symfony\Component\Console\Output\OutputInterface $output * @return int */ protected function execute(InputInterface $input, OutputInterface $output) { $inputs = array_merge($input->getArguments(), $input->getOptions()); $parameters = []; foreach ((new ReflectionFunction($this->callback))->getParameters() as $parameter) { if (isset($inputs[$parameter->getName()])) { $parameters[$parameter->getName()] = $inputs[$parameter->getName()]; } } return (int) $this->laravel->call( $this->callback->bindTo($this, $this), $parameters ); } /** * Set the description for the command. * * @param string $description * @return $this */ public function purpose($description) { return $this->describe($description); } /** * Set the description for the command. * * @param string $description * @return $this */ public function describe($description) { $this->setDescription($description); return $this; } } PKz Z<5Illuminate/Foundation/Console/ListenerMakeCommand.phpnuW+Aoption('event'); if (! Str::startsWith($event, [ $this->laravel->getNamespace(), 'Illuminate', '\\', ])) { $event = $this->laravel->getNamespace().'Events\\'.str_replace('/', '\\', $event); } $stub = str_replace( ['DummyEvent', '{{ event }}'], class_basename($event), parent::buildClass($name) ); return str_replace( ['DummyFullEvent', '{{ eventNamespace }}'], trim($event, '\\'), $stub ); } /** * Get the stub file for the generator. * * @return string */ protected function getStub() { if ($this->option('queued')) { return $this->option('event') ? __DIR__.'/stubs/listener-queued.stub' : __DIR__.'/stubs/listener-queued-duck.stub'; } return $this->option('event') ? __DIR__.'/stubs/listener.stub' : __DIR__.'/stubs/listener-duck.stub'; } /** * Determine if the class already exists. * * @param string $rawName * @return bool */ protected function alreadyExists($rawName) { return class_exists($rawName); } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return $rootNamespace.'\Listeners'; } /** * Get the console command options. * * @return array */ protected function getOptions() { return [ ['event', 'e', InputOption::VALUE_OPTIONAL, 'The event class being listened for'], ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the listener already exists'], ['queued', null, InputOption::VALUE_NONE, 'Indicates the event listener should be queued'], ]; } /** * Interact further with the user if they were prompted for missing arguments. * * @param \Symfony\Component\Console\Input\InputInterface $input * @param \Symfony\Component\Console\Output\OutputInterface $output * @return void */ protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output) { if ($this->isReservedName($this->getNameInput()) || $this->didReceiveOptions($input)) { return; } $event = $this->components->askWithCompletion( 'What event should be listened for?', $this->possibleEvents(), 'none' ); if ($event && $event !== 'none') { $input->setOption('event', $event); } } } PKz Zg} ;Illuminate/Foundation/Console/EnvironmentEncryptCommand.phpnuW+Afiles = $files; } /** * Execute the console command. * * @return void */ public function handle() { $cipher = $this->option('cipher') ?: 'AES-256-CBC'; $key = $this->option('key'); $keyPassed = $key !== null; $environmentFile = $this->option('env') ? base_path('.env').'.'.$this->option('env') : $this->laravel->environmentFilePath(); $encryptedFile = $environmentFile.'.encrypted'; if (! $keyPassed) { $key = Encrypter::generateKey($cipher); } if (! $this->files->exists($environmentFile)) { $this->components->error('Environment file not found.'); return Command::FAILURE; } if ($this->files->exists($encryptedFile) && ! $this->option('force')) { $this->components->error('Encrypted environment file already exists.'); return Command::FAILURE; } try { $encrypter = new Encrypter($this->parseKey($key), $cipher); $this->files->put( $encryptedFile, $encrypter->encrypt($this->files->get($environmentFile)) ); } catch (Exception $e) { $this->components->error($e->getMessage()); return Command::FAILURE; } $this->components->info('Environment successfully encrypted.'); $this->components->twoColumnDetail('Key', $keyPassed ? $key : 'base64:'.base64_encode($key)); $this->components->twoColumnDetail('Cipher', $cipher); $this->components->twoColumnDetail('Encrypted file', $encryptedFile); $this->newLine(); } /** * Parse the encryption key. * * @param string $key * @return string */ protected function parseKey(string $key) { if (Str::startsWith($key, $prefix = 'base64:')) { $key = base64_decode(Str::after($key, $prefix)); } return $key; } } PKz ZB0ة6Illuminate/Foundation/Console/ClearCompiledCommand.phpnuW+Alaravel->getCachedServicesPath())) { @unlink($servicesPath); } if (is_file($packagesPath = $this->laravel->getCachedPackagesPath())) { @unlink($packagesPath); } $this->components->info('Compiled services and packages files removed successfully.'); } } PKz Z1} 1Illuminate/Foundation/Console/RuleMakeCommand.phpnuW+Aoption('implicit') ? 'ImplicitRule' : 'Rule', parent::buildClass($name) ); } /** * Get the stub file for the generator. * * @return string */ protected function getStub() { $stub = '/stubs/rule.stub'; if ($this->option('invokable')) { $stub = '/stubs/rule.invokable.stub'; } if ($this->option('implicit') && $this->option('invokable')) { $stub = str_replace('.stub', '.implicit.stub', $stub); } return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) ? $customPath : __DIR__.$stub; } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return $rootNamespace.'\Rules'; } /** * Get the console command options. * * @return array */ protected function getOptions() { return [ ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the rule already exists'], ['implicit', 'i', InputOption::VALUE_NONE, 'Generate an implicit rule'], ['invokable', null, InputOption::VALUE_NONE, 'Generate a single method, invokable rule class'], ]; } } PKz Zn;;2Illuminate/Foundation/Console/RouteListCommand.phpnuW+A 'red', 'GET' => 'blue', 'HEAD' => '#6C7280', 'OPTIONS' => '#6C7280', 'POST' => 'yellow', 'PUT' => 'yellow', 'PATCH' => 'yellow', 'DELETE' => 'red', ]; /** * Create a new route command instance. * * @param \Illuminate\Routing\Router $router * @return void */ public function __construct(Router $router) { parent::__construct(); $this->router = $router; } /** * Execute the console command. * * @return void */ public function handle() { $this->router->flushMiddlewareGroups(); if (! $this->router->getRoutes()->count()) { return $this->components->error("Your application doesn't have any routes."); } if (empty($routes = $this->getRoutes())) { return $this->components->error("Your application doesn't have any routes matching the given criteria."); } $this->displayRoutes($routes); } /** * Compile the routes into a displayable format. * * @return array */ protected function getRoutes() { $routes = collect($this->router->getRoutes())->map(function ($route) { return $this->getRouteInformation($route); })->filter()->all(); if (($sort = $this->option('sort')) !== null) { $routes = $this->sortRoutes($sort, $routes); } else { $routes = $this->sortRoutes('uri', $routes); } if ($this->option('reverse')) { $routes = array_reverse($routes); } return $this->pluckColumns($routes); } /** * Get the route information for a given route. * * @param \Illuminate\Routing\Route $route * @return array */ protected function getRouteInformation(Route $route) { return $this->filterRoute([ 'domain' => $route->domain(), 'method' => implode('|', $route->methods()), 'uri' => $route->uri(), 'name' => $route->getName(), 'action' => ltrim($route->getActionName(), '\\'), 'middleware' => $this->getMiddleware($route), 'vendor' => $this->isVendorRoute($route), ]); } /** * Sort the routes by a given element. * * @param string $sort * @param array $routes * @return array */ protected function sortRoutes($sort, array $routes) { return Arr::sort($routes, function ($route) use ($sort) { return $route[$sort]; }); } /** * Remove unnecessary columns from the routes. * * @param array $routes * @return array */ protected function pluckColumns(array $routes) { return array_map(function ($route) { return Arr::only($route, $this->getColumns()); }, $routes); } /** * Display the route information on the console. * * @param array $routes * @return void */ protected function displayRoutes(array $routes) { $routes = collect($routes); $this->output->writeln( $this->option('json') ? $this->asJson($routes) : $this->forCli($routes) ); } /** * Get the middleware for the route. * * @param \Illuminate\Routing\Route $route * @return string */ protected function getMiddleware($route) { return collect($this->router->gatherRouteMiddleware($route))->map(function ($middleware) { return $middleware instanceof Closure ? 'Closure' : $middleware; })->implode("\n"); } /** * Determine if the route has been defined outside of the application. * * @param \Illuminate\Routing\Route $route * @return bool */ protected function isVendorRoute(Route $route) { if ($route->action['uses'] instanceof Closure) { $path = (new ReflectionFunction($route->action['uses'])) ->getFileName(); } elseif (is_string($route->action['uses']) && str_contains($route->action['uses'], 'SerializableClosure')) { return false; } elseif (is_string($route->action['uses'])) { if ($this->isFrameworkController($route)) { return false; } $path = (new ReflectionClass($route->getControllerClass())) ->getFileName(); } else { return false; } return str_starts_with($path, base_path('vendor')); } /** * Determine if the route uses a framework controller. * * @param \Illuminate\Routing\Route $route * @return bool */ protected function isFrameworkController(Route $route) { return in_array($route->getControllerClass(), [ '\Illuminate\Routing\RedirectController', '\Illuminate\Routing\ViewController', ], true); } /** * Filter the route by URI and / or name. * * @param array $route * @return array|null */ protected function filterRoute(array $route) { if (($this->option('name') && ! Str::contains((string) $route['name'], $this->option('name'))) || ($this->option('path') && ! Str::contains($route['uri'], $this->option('path'))) || ($this->option('method') && ! Str::contains($route['method'], strtoupper($this->option('method')))) || ($this->option('domain') && ! Str::contains((string) $route['domain'], $this->option('domain'))) || ($this->option('except-vendor') && $route['vendor']) || ($this->option('only-vendor') && ! $route['vendor'])) { return; } if ($this->option('except-path')) { foreach (explode(',', $this->option('except-path')) as $path) { if (str_contains($route['uri'], $path)) { return; } } } return $route; } /** * Get the table headers for the visible columns. * * @return array */ protected function getHeaders() { return Arr::only($this->headers, array_keys($this->getColumns())); } /** * Get the column names to show (lowercase table headers). * * @return array */ protected function getColumns() { return array_map('strtolower', $this->headers); } /** * Parse the column list. * * @param array $columns * @return array */ protected function parseColumns(array $columns) { $results = []; foreach ($columns as $column) { if (str_contains($column, ',')) { $results = array_merge($results, explode(',', $column)); } else { $results[] = $column; } } return array_map('strtolower', $results); } /** * Convert the given routes to JSON. * * @param \Illuminate\Support\Collection $routes * @return string */ protected function asJson($routes) { return $routes ->map(function ($route) { $route['middleware'] = empty($route['middleware']) ? [] : explode("\n", $route['middleware']); return $route; }) ->values() ->toJson(); } /** * Convert the given routes to regular CLI output. * * @param \Illuminate\Support\Collection $routes * @return array */ protected function forCli($routes) { $routes = $routes->map( fn ($route) => array_merge($route, [ 'action' => $this->formatActionForCli($route), 'method' => $route['method'] == 'GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS' ? 'ANY' : $route['method'], 'uri' => $route['domain'] ? ($route['domain'].'/'.ltrim($route['uri'], '/')) : $route['uri'], ]), ); $maxMethod = mb_strlen($routes->max('method')); $terminalWidth = $this->getTerminalWidth(); $routeCount = $this->determineRouteCountOutput($routes, $terminalWidth); return $routes->map(function ($route) use ($maxMethod, $terminalWidth) { [ 'action' => $action, 'domain' => $domain, 'method' => $method, 'middleware' => $middleware, 'uri' => $uri, ] = $route; $middleware = Str::of($middleware)->explode("\n")->filter()->whenNotEmpty( fn ($collection) => $collection->map( fn ($middleware) => sprintf(' %s⇂ %s', str_repeat(' ', $maxMethod), $middleware) ) )->implode("\n"); $spaces = str_repeat(' ', max($maxMethod + 6 - mb_strlen($method), 0)); $dots = str_repeat('.', max( $terminalWidth - mb_strlen($method.$spaces.$uri.$action) - 6 - ($action ? 1 : 0), 0 )); $dots = empty($dots) ? $dots : " $dots"; if ($action && ! $this->output->isVerbose() && mb_strlen($method.$spaces.$uri.$action.$dots) > ($terminalWidth - 6)) { $action = substr($action, 0, $terminalWidth - 7 - mb_strlen($method.$spaces.$uri.$dots)).'…'; } $method = Str::of($method)->explode('|')->map( fn ($method) => sprintf('%s', $this->verbColors[$method] ?? 'default', $method), )->implode('|'); return [sprintf( ' %s %s%s%s %s', $method, $spaces, preg_replace('#({[^}]+})#', '$1', $uri), $dots, str_replace(' ', ' › ', $action ?? ''), ), $this->output->isVerbose() && ! empty($middleware) ? "$middleware" : null]; }) ->flatten() ->filter() ->prepend('') ->push('')->push($routeCount)->push('') ->toArray(); } /** * Get the formatted action for display on the CLI. * * @param array $route * @return string */ protected function formatActionForCli($route) { ['action' => $action, 'name' => $name] = $route; if ($action === 'Closure' || $action === ViewController::class) { return $name; } $name = $name ? "$name " : null; $rootControllerNamespace = $this->laravel[UrlGenerator::class]->getRootControllerNamespace() ?? ($this->laravel->getNamespace().'Http\\Controllers'); if (str_starts_with($action, $rootControllerNamespace)) { return $name.substr($action, mb_strlen($rootControllerNamespace) + 1); } $actionClass = explode('@', $action)[0]; if (class_exists($actionClass) && str_starts_with((new ReflectionClass($actionClass))->getFilename(), base_path('vendor'))) { $actionCollection = collect(explode('\\', $action)); return $name.$actionCollection->take(2)->implode('\\').' '.$actionCollection->last(); } return $name.$action; } /** * Determine and return the output for displaying the number of routes in the CLI output. * * @param \Illuminate\Support\Collection $routes * @param int $terminalWidth * @return string */ protected function determineRouteCountOutput($routes, $terminalWidth) { $routeCountText = 'Showing ['.$routes->count().'] routes'; $offset = $terminalWidth - mb_strlen($routeCountText) - 2; $spaces = str_repeat(' ', $offset); return $spaces.'Showing ['.$routes->count().'] routes'; } /** * Get the terminal width. * * @return int */ public static function getTerminalWidth() { return is_null(static::$terminalWidthResolver) ? (new Terminal)->getWidth() : call_user_func(static::$terminalWidthResolver); } /** * Set a callback that should be used when resolving the terminal width. * * @param \Closure|null $resolver * @return void */ public static function resolveTerminalWidthUsing($resolver) { static::$terminalWidthResolver = $resolver; } /** * Get the console command options. * * @return array */ protected function getOptions() { return [ ['json', null, InputOption::VALUE_NONE, 'Output the route list as JSON'], ['method', null, InputOption::VALUE_OPTIONAL, 'Filter the routes by method'], ['name', null, InputOption::VALUE_OPTIONAL, 'Filter the routes by name'], ['domain', null, InputOption::VALUE_OPTIONAL, 'Filter the routes by domain'], ['path', null, InputOption::VALUE_OPTIONAL, 'Only show routes matching the given path pattern'], ['except-path', null, InputOption::VALUE_OPTIONAL, 'Do not display the routes matching the given path pattern'], ['reverse', 'r', InputOption::VALUE_NONE, 'Reverse the ordering of the routes'], ['sort', null, InputOption::VALUE_OPTIONAL, 'The column (domain, method, uri, name, action, middleware) to sort by', 'uri'], ['except-vendor', null, InputOption::VALUE_NONE, 'Do not display routes defined by vendor packages'], ['only-vendor', null, InputOption::VALUE_NONE, 'Only display routes defined by vendor packages'], ]; } } PKz ZV##6Illuminate/Foundation/Console/VendorPublishCommand.phpnuW+Afiles = $files; } /** * Execute the console command. * * @return void */ public function handle() { $this->determineWhatShouldBePublished(); foreach ($this->tags ?: [null] as $tag) { $this->publishTag($tag); } } /** * Determine the provider or tag(s) to publish. * * @return void */ protected function determineWhatShouldBePublished() { if ($this->option('all')) { return; } [$this->provider, $this->tags] = [ $this->option('provider'), (array) $this->option('tag'), ]; if (! $this->provider && ! $this->tags) { $this->promptForProviderOrTag(); } } /** * Prompt for which provider or tag to publish. * * @return void */ protected function promptForProviderOrTag() { $choice = $this->components->choice( "Which provider or tag's files would you like to publish?", $choices = $this->publishableChoices() ); if ($choice == $choices[0] || is_null($choice)) { return; } $this->parseChoice($choice); } /** * The choices available via the prompt. * * @return array */ protected function publishableChoices() { return array_merge( ['Publish files from all providers and tags listed below'], preg_filter('/^/', 'Provider: ', Arr::sort(ServiceProvider::publishableProviders())), preg_filter('/^/', 'Tag: ', Arr::sort(ServiceProvider::publishableGroups())) ); } /** * Parse the answer that was given via the prompt. * * @param string $choice * @return void */ protected function parseChoice($choice) { [$type, $value] = explode(': ', strip_tags($choice)); if ($type === 'Provider') { $this->provider = $value; } elseif ($type === 'Tag') { $this->tags = [$value]; } } /** * Publishes the assets for a tag. * * @param string $tag * @return mixed */ protected function publishTag($tag) { $published = false; $pathsToPublish = $this->pathsToPublish($tag); if ($publishing = count($pathsToPublish) > 0) { $this->components->info(sprintf( 'Publishing %sassets', $tag ? "[$tag] " : '', )); } foreach ($pathsToPublish as $from => $to) { $this->publishItem($from, $to); } if ($publishing === false) { $this->components->info('No publishable resources for tag ['.$tag.'].'); } else { $this->laravel['events']->dispatch(new VendorTagPublished($tag, $pathsToPublish)); $this->newLine(); } } /** * Get all of the paths to publish. * * @param string $tag * @return array */ protected function pathsToPublish($tag) { return ServiceProvider::pathsToPublish( $this->provider, $tag ); } /** * Publish the given item from and to the given location. * * @param string $from * @param string $to * @return void */ protected function publishItem($from, $to) { if ($this->files->isFile($from)) { return $this->publishFile($from, $to); } elseif ($this->files->isDirectory($from)) { return $this->publishDirectory($from, $to); } $this->components->error("Can't locate path: <{$from}>"); } /** * Publish the file to the given path. * * @param string $from * @param string $to * @return void */ protected function publishFile($from, $to) { if ((! $this->option('existing') && (! $this->files->exists($to) || $this->option('force'))) || ($this->option('existing') && $this->files->exists($to))) { $this->createParentDirectory(dirname($to)); $this->files->copy($from, $to); $this->status($from, $to, 'file'); } else { if ($this->option('existing')) { $this->components->twoColumnDetail(sprintf( 'File [%s] does not exist', str_replace(base_path().'/', '', $to), ), 'SKIPPED'); } else { $this->components->twoColumnDetail(sprintf( 'File [%s] already exists', str_replace(base_path().'/', '', realpath($to)), ), 'SKIPPED'); } } } /** * Publish the directory to the given directory. * * @param string $from * @param string $to * @return void */ protected function publishDirectory($from, $to) { $visibility = PortableVisibilityConverter::fromArray([], Visibility::PUBLIC); $this->moveManagedFiles(new MountManager([ 'from' => new Flysystem(new LocalAdapter($from)), 'to' => new Flysystem(new LocalAdapter($to, $visibility)), ])); $this->status($from, $to, 'directory'); } /** * Move all the files in the given MountManager. * * @param \League\Flysystem\MountManager $manager * @return void */ protected function moveManagedFiles($manager) { foreach ($manager->listContents('from://', true) as $file) { $path = Str::after($file['path'], 'from://'); if ( $file['type'] === 'file' && ( (! $this->option('existing') && (! $manager->fileExists('to://'.$path) || $this->option('force'))) || ($this->option('existing') && $manager->fileExists('to://'.$path)) ) ) { $manager->write('to://'.$path, $manager->read($file['path'])); } } } /** * Create the directory to house the published files if needed. * * @param string $directory * @return void */ protected function createParentDirectory($directory) { if (! $this->files->isDirectory($directory)) { $this->files->makeDirectory($directory, 0755, true); } } /** * Write a status message to the console. * * @param string $from * @param string $to * @param string $type * @return void */ protected function status($from, $to, $type) { $from = str_replace(base_path().'/', '', realpath($from)); $to = str_replace(base_path().'/', '', realpath($to)); $this->components->task(sprintf( 'Copying %s [%s] to [%s]', $type, $from, $to, )); } } PKz Z]];Illuminate/Foundation/Console/EnvironmentDecryptCommand.phpnuW+Afiles = $files; } /** * Execute the console command. * * @return void */ public function handle() { $key = $this->option('key') ?: Env::get('LARAVEL_ENV_ENCRYPTION_KEY'); if (! $key) { $this->components->error('A decryption key is required.'); return Command::FAILURE; } $cipher = $this->option('cipher') ?: 'AES-256-CBC'; $key = $this->parseKey($key); $encryptedFile = ($this->option('env') ? base_path('.env').'.'.$this->option('env') : $this->laravel->environmentFilePath()).'.encrypted'; $outputFile = $this->outputFilePath(); if (Str::endsWith($outputFile, '.encrypted')) { $this->components->error('Invalid filename.'); return Command::FAILURE; } if (! $this->files->exists($encryptedFile)) { $this->components->error('Encrypted environment file not found.'); return Command::FAILURE; } if ($this->files->exists($outputFile) && ! $this->option('force')) { $this->components->error('Environment file already exists.'); return Command::FAILURE; } try { $encrypter = new Encrypter($key, $cipher); $this->files->put( $outputFile, $encrypter->decrypt($this->files->get($encryptedFile)) ); } catch (Exception $e) { $this->components->error($e->getMessage()); return Command::FAILURE; } $this->components->info('Environment successfully decrypted.'); $this->components->twoColumnDetail('Decrypted file', $outputFile); $this->newLine(); } /** * Parse the encryption key. * * @param string $key * @return string */ protected function parseKey(string $key) { if (Str::startsWith($key, $prefix = 'base64:')) { $key = base64_decode(Str::after($key, $prefix)); } return $key; } /** * Get the output file path that should be used for the command. * * @return string */ protected function outputFilePath() { $path = Str::finish($this->option('path') ?: base_path(), DIRECTORY_SEPARATOR); $outputFile = $this->option('filename') ?: ('.env'.($this->option('env') ? '.'.$this->option('env') : '')); $outputFile = ltrim($outputFile, DIRECTORY_SEPARATOR); return $path.$outputFile; } } PKz ZȽI6Illuminate/Foundation/Console/stubs/listener-duck.stubnuW+Aget('/'); $response->assertStatus(200); } } PKz Zuk5Illuminate/Foundation/Console/stubs/notification.stubnuW+Aline('The introduction to the notification.') ->action('Notification Action', url('/')) ->line('Thank you for using our application!'); } /** * Get the array representation of the notification. * * @param mixed $notifiable * @return array */ public function toArray($notifiable) { return [ // ]; } } PKz Z.qjj>Illuminate/Foundation/Console/stubs/markdown-notification.stubnuW+Amarkdown('{{ view }}'); } /** * Get the array representation of the notification. * * @param mixed $notifiable * @return array */ public function toArray($notifiable) { return [ // ]; } } PKz Zt>ȍ1Illuminate/Foundation/Console/stubs/markdown.stubnuW+A # Introduction The body of your message. Button Text Thanks,
{{ config('app.name') }}
PKz Z҉Unn1Illuminate/Foundation/Console/stubs/provider.stubnuW+A= time()) { return; } } // Redirect to the proper path if necessary... if (isset($data['redirect']) && $_SERVER['REQUEST_URI'] !== $data['redirect']) { http_response_code(302); header('Location: '.$data['redirect']); exit; } // Output the prerendered template... http_response_code($data['status'] ?? 503); if (isset($data['retry'])) { header('Retry-After: '.$data['retry']); } if (isset($data['refresh'])) { header('Refresh: '.$data['refresh']); } echo $data['template']; exit; PKz Z.2Illuminate/Foundation/Console/stubs/test.unit.stubnuW+AassertTrue(true); } } PKz ZzGG2Illuminate/Foundation/Console/stubs/pest.unit.stubnuW+AtoBeTrue(); }); PKz Zg36/Illuminate/Foundation/Console/stubs/routes.stubnuW+AsetCompiledRoutes( {{routes}} ); PKz ZFxآ::9Illuminate/Foundation/Console/stubs/exception-render.stubnuW+Aget('/'); $response->assertStatus(200); }); PKz ZYo-r:Illuminate/Foundation/Console/stubs/model.morph-pivot.stubnuW+A */ public function rules() { return [ // ]; } } PKz Zzs7Illuminate/Foundation/Console/stubs/view-component.stubnuW+Alaravel->maintenanceMode()->active()) { $this->components->info('Application is already up.'); return 0; } $this->laravel->maintenanceMode()->deactivate(); if (is_file(storage_path('framework/maintenance.php'))) { unlink(storage_path('framework/maintenance.php')); } $this->laravel->get('events')->dispatch(new MaintenanceModeDisabled()); $this->components->info('Application is now live.'); } catch (Exception $e) { $this->components->error(sprintf( 'Failed to disable maintenance mode: %s.', $e->getMessage(), )); return 1; } return 0; } } PKz Z萸 +Illuminate/Foundation/Console/CliDumper.phpnuW+AbasePath = $basePath; $this->output = $output; $this->compiledViewPath = $compiledViewPath; } /** * Create a new CLI dumper instance and register it as the default dumper. * * @param string $basePath * @param string $compiledViewPath * @return void */ public static function register($basePath, $compiledViewPath) { $cloner = tap(new VarCloner())->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO); $dumper = new static(new ConsoleOutput(), $basePath, $compiledViewPath); VarDumper::setHandler(fn ($value) => $dumper->dumpWithSource($cloner->cloneVar($value))); } /** * Dump a variable with its source file / line. * * @param \Symfony\Component\VarDumper\Cloner\Data $data * @return void */ public function dumpWithSource(Data $data) { if ($this->dumping) { $this->dump($data); return; } $this->dumping = true; $output = (string) $this->dump($data, true); $lines = explode("\n", $output); $lines[0] .= $this->getDumpSourceContent(); $this->output->write(implode("\n", $lines)); $this->dumping = false; } /** * Get the dump's source console content. * * @return string */ protected function getDumpSourceContent() { if (is_null($dumpSource = $this->resolveDumpSource())) { return ''; } [$file, $relativeFile, $line] = $dumpSource; $href = $this->resolveSourceHref($file, $line); return sprintf( ' // %s%s', is_null($href) ? '' : ";href=$href", $relativeFile, is_null($line) ? '' : ":$line" ); } /** * {@inheritDoc} */ protected function supportsColors(): bool { return $this->output->isDecorated(); } } PKz Z0"_ 9Illuminate/Foundation/Console/NotificationMakeCommand.phpnuW+Aoption('force')) { return; } if ($this->option('markdown')) { $this->writeMarkdownTemplate(); } } /** * Write the Markdown template for the mailable. * * @return void */ protected function writeMarkdownTemplate() { $path = $this->viewPath( str_replace('.', '/', $this->option('markdown')).'.blade.php' ); if (! $this->files->isDirectory(dirname($path))) { $this->files->makeDirectory(dirname($path), 0755, true); } $this->files->put($path, file_get_contents(__DIR__.'/stubs/markdown.stub')); } /** * Build the class with the given name. * * @param string $name * @return string */ protected function buildClass($name) { $class = parent::buildClass($name); if ($this->option('markdown')) { $class = str_replace(['DummyView', '{{ view }}'], $this->option('markdown'), $class); } return $class; } /** * Get the stub file for the generator. * * @return string */ protected function getStub() { return $this->option('markdown') ? $this->resolveStubPath('/stubs/markdown-notification.stub') : $this->resolveStubPath('/stubs/notification.stub'); } /** * Resolve the fully-qualified path to the stub. * * @param string $stub * @return string */ protected function resolveStubPath($stub) { return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) ? $customPath : __DIR__.$stub; } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return $rootNamespace.'\Notifications'; } /** * Get the console command options. * * @return array */ protected function getOptions() { return [ ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the notification already exists'], ['markdown', 'm', InputOption::VALUE_OPTIONAL, 'Create a new Markdown template for the notification'], ]; } } PKz Z01Illuminate/Foundation/Console/OptimizeCommand.phpnuW+Acomponents->info('Caching the framework bootstrap files'); collect([ 'config' => fn () => $this->callSilent('config:cache') == 0, 'routes' => fn () => $this->callSilent('route:cache') == 0, ])->each(fn ($task, $description) => $this->components->task($description, $task)); $this->newLine(); } } PKz ZW4Illuminate/Foundation/Console/ConfigClearCommand.phpnuW+Afiles = $files; } /** * Execute the console command. * * @return void */ public function handle() { $this->files->delete($this->laravel->getCachedConfigPath()); $this->components->info('Configuration cache cleared successfully.'); } } PKz ZO}l l 4Illuminate/Foundation/Console/ConfigCacheCommand.phpnuW+Afiles = $files; } /** * Execute the console command. * * @return void * * @throws \LogicException */ public function handle() { $this->callSilent('config:clear'); $config = $this->getFreshConfiguration(); $configPath = $this->laravel->getCachedConfigPath(); $this->files->put( $configPath, 'files->delete($configPath); throw new LogicException('Your configuration files are not serializable.', 0, $e); } $this->components->info('Configuration cached successfully.'); } /** * Boot a fresh copy of the application configuration. * * @return array */ protected function getFreshConfiguration() { $app = require $this->laravel->bootstrapPath().'/app.php'; $app->useStoragePath($this->laravel->storagePath()); $app->make(ConsoleKernelContract::class)->bootstrap(); return $app['config']->all(); } } PKz ZTBJ2Illuminate/Foundation/Console/EventMakeCommand.phpnuW+Afiles->exists($this->getPath($this->qualifyClass($rawName))); } /** * Get the stub file for the generator. * * @return string */ protected function getStub() { return $this->resolveStubPath('/stubs/event.stub'); } /** * Resolve the fully-qualified path to the stub. * * @param string $stub * @return string */ protected function resolveStubPath($stub) { return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) ? $customPath : __DIR__.$stub; } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return $rootNamespace.'\Events'; } /** * Get the console command options. * * @return array */ protected function getOptions() { return [ ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the event already exists'], ]; } } PKz Z~G G .Illuminate/Foundation/Console/AboutCommand.phpnuW+Acomposer = $composer; } /** * Execute the console command. * * @return int */ public function handle() { $this->gatherApplicationInformation(); collect(static::$data) ->map(fn ($items) => collect($items) ->map(function ($value) { if (is_array($value)) { return [$value]; } if (is_string($value)) { $value = $this->laravel->make($value); } return collect($this->laravel->call($value)) ->map(fn ($value, $key) => [$key, $value]) ->values() ->all(); })->flatten(1) ) ->sortBy(function ($data, $key) { $index = array_search($key, ['Environment', 'Cache', 'Drivers']); return $index === false ? 99 : $index; }) ->filter(function ($data, $key) { return $this->option('only') ? in_array(Str::of($key)->lower()->snake(), $this->sections()) : true; }) ->pipe(fn ($data) => $this->display($data)); $this->newLine(); return 0; } /** * Display the application information. * * @param \Illuminate\Support\Collection $data * @return void */ protected function display($data) { $this->option('json') ? $this->displayJson($data) : $this->displayDetail($data); } /** * Display the application information as a detail view. * * @param \Illuminate\Support\Collection $data * @return void */ protected function displayDetail($data) { $data->each(function ($data, $section) { $this->newLine(); $this->components->twoColumnDetail(' '.$section.''); $data->pipe(fn ($data) => $section !== 'Environment' ? $data->sort() : $data)->each(function ($detail) { [$label, $value] = $detail; $this->components->twoColumnDetail($label, value($value)); }); }); } /** * Display the application information as JSON. * * @param \Illuminate\Support\Collection $data * @return void */ protected function displayJson($data) { $output = $data->flatMap(function ($data, $section) { return [(string) Str::of($section)->snake() => $data->mapWithKeys(fn ($item, $key) => [(string) Str::of($item[0])->lower()->snake() => value($item[1])])]; }); $this->output->writeln(strip_tags(json_encode($output))); } /** * Gather information about the application. * * @return void */ protected function gatherApplicationInformation() { static::addToSection('Environment', fn () => [ 'Application Name' => config('app.name'), 'Laravel Version' => $this->laravel->version(), 'PHP Version' => phpversion(), 'Composer Version' => $this->composer->getVersion() ?? '-', 'Environment' => $this->laravel->environment(), 'Debug Mode' => config('app.debug') ? 'ENABLED' : 'OFF', 'URL' => Str::of(config('app.url'))->replace(['http://', 'https://'], ''), 'Maintenance Mode' => $this->laravel->isDownForMaintenance() ? 'ENABLED' : 'OFF', ]); static::addToSection('Cache', fn () => [ 'Config' => $this->laravel->configurationIsCached() ? 'CACHED' : 'NOT CACHED', 'Events' => $this->laravel->eventsAreCached() ? 'CACHED' : 'NOT CACHED', 'Routes' => $this->laravel->routesAreCached() ? 'CACHED' : 'NOT CACHED', 'Views' => $this->hasPhpFiles($this->laravel->storagePath('framework/views')) ? 'CACHED' : 'NOT CACHED', ]); $logChannel = config('logging.default'); if (config('logging.channels.'.$logChannel.'.driver') === 'stack') { $secondary = collect(config('logging.channels.'.$logChannel.'.channels')) ->implode(', '); $logs = ''.$logChannel.' / '.$secondary; } else { $logs = $logChannel; } static::addToSection('Drivers', fn () => array_filter([ 'Broadcasting' => config('broadcasting.default'), 'Cache' => config('cache.default'), 'Database' => config('database.default'), 'Logs' => $logs, 'Mail' => config('mail.default'), 'Octane' => config('octane.server'), 'Queue' => config('queue.default'), 'Scout' => config('scout.driver'), 'Session' => config('session.driver'), ])); collect(static::$customDataResolvers)->each->__invoke(); } /** * Determine whether the given directory has PHP files. * * @param string $path * @return bool */ protected function hasPhpFiles(string $path): bool { return count(glob($path.'/*.php')) > 0; } /** * Add additional data to the output of the "about" command. * * @param string $section * @param callable|string|array $data * @param string|null $value * @return void */ public static function add(string $section, $data, string $value = null) { static::$customDataResolvers[] = fn () => static::addToSection($section, $data, $value); } /** * Add additional data to the output of the "about" command. * * @param string $section * @param callable|string|array $data * @param string|null $value * @return void */ protected static function addToSection(string $section, $data, string $value = null) { if (is_array($data)) { foreach ($data as $key => $value) { self::$data[$section][] = [$key, $value]; } } elseif (is_callable($data) || ($value === null && class_exists($data))) { self::$data[$section][] = $data; } else { self::$data[$section][] = [$data, $value]; } } /** * Get the sections provided to the command. * * @return array */ protected function sections() { return array_filter(explode(',', $this->option('only') ?? '')); } } PKz Zs 5Illuminate/Foundation/Console/ResourceMakeCommand.phpnuW+Acollection()) { $this->type = 'Resource collection'; } parent::handle(); } /** * Get the stub file for the generator. * * @return string */ protected function getStub() { return $this->collection() ? $this->resolveStubPath('/stubs/resource-collection.stub') : $this->resolveStubPath('/stubs/resource.stub'); } /** * Determine if the command is generating a resource collection. * * @return bool */ protected function collection() { return $this->option('collection') || str_ends_with($this->argument('name'), 'Collection'); } /** * Resolve the fully-qualified path to the stub. * * @param string $stub * @return string */ protected function resolveStubPath($stub) { return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) ? $customPath : __DIR__.$stub; } /** * Get the default namespace for the class. * * @param string $rootNamespace * @return string */ protected function getDefaultNamespace($rootNamespace) { return $rootNamespace.'\Http\Resources'; } /** * Get the console command options. * * @return array */ protected function getOptions() { return [ ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the resource already exists'], ['collection', 'c', InputOption::VALUE_NONE, 'Create a resource collection'], ]; } } PKz Zxv%v%.Illuminate/Foundation/Console/ServeCommand.phpnuW+A */ protected $requestsPool; /** * Indicates if the "Server running on..." output message has been displayed. * * @var bool */ protected $serverRunningHasBeenDisplayed = false; /** * The environment variables that should be passed from host machine to the PHP server process. * * @var string[] */ public static $passthroughVariables = [ 'APP_ENV', 'LARAVEL_SAIL', 'PATH', 'PHP_CLI_SERVER_WORKERS', 'PHP_IDE_CONFIG', 'SYSTEMROOT', 'XDEBUG_CONFIG', 'XDEBUG_MODE', 'XDEBUG_SESSION', ]; /** * Execute the console command. * * @return int * * @throws \Exception */ public function handle() { $environmentFile = $this->option('env') ? base_path('.env').'.'.$this->option('env') : base_path('.env'); $hasEnvironment = file_exists($environmentFile); $environmentLastModified = $hasEnvironment ? filemtime($environmentFile) : now()->addDays(30)->getTimestamp(); $process = $this->startProcess($hasEnvironment); while ($process->isRunning()) { if ($hasEnvironment) { clearstatcache(false, $environmentFile); } if (! $this->option('no-reload') && $hasEnvironment && filemtime($environmentFile) > $environmentLastModified) { $environmentLastModified = filemtime($environmentFile); $this->newLine(); $this->components->info('Environment modified. Restarting server...'); $process->stop(5); $this->serverRunningHasBeenDisplayed = false; $process = $this->startProcess($hasEnvironment); } usleep(500 * 1000); } $status = $process->getExitCode(); if ($status && $this->canTryAnotherPort()) { $this->portOffset += 1; return $this->handle(); } return $status; } /** * Start a new server process. * * @param bool $hasEnvironment * @return \Symfony\Component\Process\Process */ protected function startProcess($hasEnvironment) { $process = new Process($this->serverCommand(), public_path(), collect($_ENV)->mapWithKeys(function ($value, $key) use ($hasEnvironment) { if ($this->option('no-reload') || ! $hasEnvironment) { return [$key => $value]; } return in_array($key, static::$passthroughVariables) ? [$key => $value] : [$key => false]; })->all()); $process->start($this->handleProcessOutput()); return $process; } /** * Get the full server command. * * @return array */ protected function serverCommand() { $server = file_exists(base_path('server.php')) ? base_path('server.php') : __DIR__.'/../resources/server.php'; return [ (new PhpExecutableFinder)->find(false), '-S', $this->host().':'.$this->port(), $server, ]; } /** * Get the host for the command. * * @return string */ protected function host() { [$host] = $this->getHostAndPort(); return $host; } /** * Get the port for the command. * * @return string */ protected function port() { $port = $this->input->getOption('port'); if (is_null($port)) { [, $port] = $this->getHostAndPort(); } $port = $port ?: 8000; return $port + $this->portOffset; } /** * Get the host and port from the host option string. * * @return array */ protected function getHostAndPort() { $hostParts = explode(':', $this->input->getOption('host')); return [ $hostParts[0], $hostParts[1] ?? null, ]; } /** * Check if the command has reached its maximum number of port tries. * * @return bool */ protected function canTryAnotherPort() { return is_null($this->input->getOption('port')) && ($this->input->getOption('tries') > $this->portOffset); } /** * Returns a "callable" to handle the process output. * * @return callable(string, string): void */ protected function handleProcessOutput() { return fn ($type, $buffer) => str($buffer)->explode("\n")->each(function ($line) { if (str($line)->contains('Development Server (http')) { if ($this->serverRunningHasBeenDisplayed) { return; } $this->components->info("Server running on [http://{$this->host()}:{$this->port()}]."); $this->comment(' Press Ctrl+C to stop the server'); $this->newLine(); $this->serverRunningHasBeenDisplayed = true; } elseif (str($line)->contains(' Accepted')) { $requestPort = $this->getRequestPortFromLine($line); $this->requestsPool[$requestPort] = [ $this->getDateFromLine($line), false, ]; } elseif (str($line)->contains([' [200]: GET '])) { $requestPort = $this->getRequestPortFromLine($line); $this->requestsPool[$requestPort][1] = trim(explode('[200]: GET', $line)[1]); } elseif (str($line)->contains(' Closing')) { $requestPort = $this->getRequestPortFromLine($line); $request = $this->requestsPool[$requestPort]; [$startDate, $file] = $request; $formattedStartedAt = $startDate->format('Y-m-d H:i:s'); unset($this->requestsPool[$requestPort]); [$date, $time] = explode(' ', $formattedStartedAt); $this->output->write(" $date $time"); $runTime = $this->getDateFromLine($line)->diffInSeconds($startDate); if ($file) { $this->output->write($file = " $file"); } $dots = max(terminal()->width() - mb_strlen($formattedStartedAt) - mb_strlen($file) - mb_strlen($runTime) - 9, 0); $this->output->write(' '.str_repeat('.', $dots)); $this->output->writeln(" ~ {$runTime}s"); } elseif (str($line)->contains(['Closed without sending a request'])) { // ... } elseif (! empty($line)) { $warning = explode('] ', $line); $this->components->warn(count($warning) > 1 ? $warning[1] : $warning[0]); } }); } /** * Get the date from the given PHP server output. * * @param string $line * @return \Illuminate\Support\Carbon */ protected function getDateFromLine($line) { $regex = env('PHP_CLI_SERVER_WORKERS', 1) > 1 ? '/^\[\d+]\s\[([a-zA-Z0-9: ]+)\]/' : '/^\[([^\]]+)\]/'; preg_match($regex, $line, $matches); return Carbon::createFromFormat('D M d H:i:s Y', $matches[1]); } /** * Get the request port from the given PHP server output. * * @param string $line * @return int */ protected function getRequestPortFromLine($line) { preg_match('/:(\d+)\s(?:(?:\w+$)|(?:\[.*))/', $line, $matches); return (int) $matches[1]; } /** * Get the console command options. * * @return array */ protected function getOptions() { return [ ['host', null, InputOption::VALUE_OPTIONAL, 'The host address to serve the application on', Env::get('SERVER_HOST', '127.0.0.1')], ['port', null, InputOption::VALUE_OPTIONAL, 'The port to serve the application on', Env::get('SERVER_PORT')], ['tries', null, InputOption::VALUE_OPTIONAL, 'The max number of ports to attempt to serve from', 10], ['no-reload', null, InputOption::VALUE_NONE, 'Do not reload the development server on .env file changes'], ]; } } PKz Z皚TT)Illuminate/Foundation/PackageManifest.phpnuW+Afiles = $files; $this->basePath = $basePath; $this->manifestPath = $manifestPath; $this->vendorPath = Env::get('COMPOSER_VENDOR_DIR') ?: $basePath.'/vendor'; } /** * Get all of the service provider class names for all packages. * * @return array */ public function providers() { return $this->config('providers'); } /** * Get all of the aliases for all packages. * * @return array */ public function aliases() { return $this->config('aliases'); } /** * Get all of the values for all packages for the given configuration name. * * @param string $key * @return array */ public function config($key) { return collect($this->getManifest())->flatMap(function ($configuration) use ($key) { return (array) ($configuration[$key] ?? []); })->filter()->all(); } /** * Get the current package manifest. * * @return array */ protected function getManifest() { if (! is_null($this->manifest)) { return $this->manifest; } if (! is_file($this->manifestPath)) { $this->build(); } return $this->manifest = is_file($this->manifestPath) ? $this->files->getRequire($this->manifestPath) : []; } /** * Build the manifest and write it to disk. * * @return void */ public function build() { $packages = []; if ($this->files->exists($path = $this->vendorPath.'/composer/installed.json')) { $installed = json_decode($this->files->get($path), true); $packages = $installed['packages'] ?? $installed; } $ignoreAll = in_array('*', $ignore = $this->packagesToIgnore()); $this->write(collect($packages)->mapWithKeys(function ($package) { return [$this->format($package['name']) => $package['extra']['laravel'] ?? []]; })->each(function ($configuration) use (&$ignore) { $ignore = array_merge($ignore, $configuration['dont-discover'] ?? []); })->reject(function ($configuration, $package) use ($ignore, $ignoreAll) { return $ignoreAll || in_array($package, $ignore); })->filter()->all()); } /** * Format the given package name. * * @param string $package * @return string */ protected function format($package) { return str_replace($this->vendorPath.'/', '', $package); } /** * Get all of the package names that should be ignored. * * @return array */ protected function packagesToIgnore() { if (! is_file($this->basePath.'/composer.json')) { return []; } return json_decode(file_get_contents( $this->basePath.'/composer.json' ), true)['extra']['laravel']['dont-discover'] ?? []; } /** * Write the given manifest array to disk. * * @param array $manifest * @return void * * @throws \Exception */ protected function write(array $manifest) { if (! is_writable($dirname = dirname($this->manifestPath))) { throw new Exception("The {$dirname} directory must be present and writable."); } $this->files->replace( $this->manifestPath, 'cache = $cache; $this->store = $store; $this->key = $key; } /** * Take the application down for maintenance. * * @param array $payload * @return void */ public function activate(array $payload): void { $this->getStore()->put($this->key, $payload); } /** * Take the application out of maintenance. * * @return void */ public function deactivate(): void { $this->getStore()->forget($this->key); } /** * Determine if the application is currently down for maintenance. * * @return bool */ public function active(): bool { return $this->getStore()->has($this->key); } /** * Get the data array which was provided when the application was placed into maintenance. * * @return array */ public function data(): array { return $this->getStore()->get($this->key); } /** * Get the cache store to use. * * @return \Illuminate\Contracts\Cache\Repository */ protected function getStore(): Repository { return $this->cache->store($this->store); } } PKz Zdx77%Illuminate/Foundation/Http/Kernel.phpnuW+A */ protected $middleware = []; /** * The application's route middleware groups. * * @var array> */ protected $middlewareGroups = []; /** * The application's route middleware. * * @var array */ protected $routeMiddleware = []; /** * All of the registered request duration handlers. * * @var array */ protected $requestLifecycleDurationHandlers = []; /** * When the kernel starting handling the current request. * * @var \Illuminate\Support\Carbon|null */ protected $requestStartedAt; /** * The priority-sorted list of middleware. * * Forces non-global middleware to always be in the given order. * * @var string[] */ protected $middlewarePriority = [ \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class, \Illuminate\Cookie\Middleware\EncryptCookies::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class, \Illuminate\Routing\Middleware\ThrottleRequests::class, \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class, \Illuminate\Contracts\Session\Middleware\AuthenticatesSessions::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, \Illuminate\Auth\Middleware\Authorize::class, ]; /** * Create a new HTTP kernel instance. * * @param \Illuminate\Contracts\Foundation\Application $app * @param \Illuminate\Routing\Router $router * @return void */ public function __construct(Application $app, Router $router) { $this->app = $app; $this->router = $router; $this->syncMiddlewareToRouter(); } /** * Handle an incoming HTTP request. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function handle($request) { $this->requestStartedAt = Carbon::now(); try { $request->enableHttpMethodParameterOverride(); $response = $this->sendRequestThroughRouter($request); } catch (Throwable $e) { $this->reportException($e); $response = $this->renderException($request, $e); } $this->app['events']->dispatch( new RequestHandled($request, $response) ); return $response; } /** * Send the given request through the middleware / router. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ protected function sendRequestThroughRouter($request) { $this->app->instance('request', $request); Facade::clearResolvedInstance('request'); $this->bootstrap(); return (new Pipeline($this->app)) ->send($request) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) ->then($this->dispatchToRouter()); } /** * Bootstrap the application for HTTP requests. * * @return void */ public function bootstrap() { if (! $this->app->hasBeenBootstrapped()) { $this->app->bootstrapWith($this->bootstrappers()); } } /** * Get the route dispatcher callback. * * @return \Closure */ protected function dispatchToRouter() { return function ($request) { $this->app->instance('request', $request); return $this->router->dispatch($request); }; } /** * Call the terminate method on any terminable middleware. * * @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Response $response * @return void */ public function terminate($request, $response) { $this->terminateMiddleware($request, $response); $this->app->terminate(); foreach ($this->requestLifecycleDurationHandlers as ['threshold' => $threshold, 'handler' => $handler]) { $end ??= Carbon::now(); if ($this->requestStartedAt->diffInMilliseconds($end) > $threshold) { $handler($this->requestStartedAt, $request, $response); } } $this->requestStartedAt = null; } /** * Call the terminate method on any terminable middleware. * * @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Response $response * @return void */ protected function terminateMiddleware($request, $response) { $middlewares = $this->app->shouldSkipMiddleware() ? [] : array_merge( $this->gatherRouteMiddleware($request), $this->middleware ); foreach ($middlewares as $middleware) { if (! is_string($middleware)) { continue; } [$name] = $this->parseMiddleware($middleware); $instance = $this->app->make($name); if (method_exists($instance, 'terminate')) { $instance->terminate($request, $response); } } } /** * Register a callback to be invoked when the requests lifecycle duration exceeds a given amount of time. * * @param \DateTimeInterface|\Carbon\CarbonInterval|float|int $threshold * @param callable $handler * @return void */ public function whenRequestLifecycleIsLongerThan($threshold, $handler) { $threshold = $threshold instanceof DateTimeInterface ? $this->secondsUntil($threshold) * 1000 : $threshold; $threshold = $threshold instanceof CarbonInterval ? $threshold->totalMilliseconds : $threshold; $this->requestLifecycleDurationHandlers[] = [ 'threshold' => $threshold, 'handler' => $handler, ]; } /** * When the request being handled started. * * @return \Illuminate\Support\Carbon|null */ public function requestStartedAt() { return $this->requestStartedAt; } /** * Gather the route middleware for the given request. * * @param \Illuminate\Http\Request $request * @return array */ protected function gatherRouteMiddleware($request) { if ($route = $request->route()) { return $this->router->gatherRouteMiddleware($route); } return []; } /** * Parse a middleware string to get the name and parameters. * * @param string $middleware * @return array */ protected function parseMiddleware($middleware) { [$name, $parameters] = array_pad(explode(':', $middleware, 2), 2, []); if (is_string($parameters)) { $parameters = explode(',', $parameters); } return [$name, $parameters]; } /** * Determine if the kernel has a given middleware. * * @param string $middleware * @return bool */ public function hasMiddleware($middleware) { return in_array($middleware, $this->middleware); } /** * Add a new middleware to the beginning of the stack if it does not already exist. * * @param string $middleware * @return $this */ public function prependMiddleware($middleware) { if (array_search($middleware, $this->middleware) === false) { array_unshift($this->middleware, $middleware); } return $this; } /** * Add a new middleware to end of the stack if it does not already exist. * * @param string $middleware * @return $this */ public function pushMiddleware($middleware) { if (array_search($middleware, $this->middleware) === false) { $this->middleware[] = $middleware; } return $this; } /** * Prepend the given middleware to the given middleware group. * * @param string $group * @param string $middleware * @return $this * * @throws \InvalidArgumentException */ public function prependMiddlewareToGroup($group, $middleware) { if (! isset($this->middlewareGroups[$group])) { throw new InvalidArgumentException("The [{$group}] middleware group has not been defined."); } if (array_search($middleware, $this->middlewareGroups[$group]) === false) { array_unshift($this->middlewareGroups[$group], $middleware); } $this->syncMiddlewareToRouter(); return $this; } /** * Append the given middleware to the given middleware group. * * @param string $group * @param string $middleware * @return $this * * @throws \InvalidArgumentException */ public function appendMiddlewareToGroup($group, $middleware) { if (! isset($this->middlewareGroups[$group])) { throw new InvalidArgumentException("The [{$group}] middleware group has not been defined."); } if (array_search($middleware, $this->middlewareGroups[$group]) === false) { $this->middlewareGroups[$group][] = $middleware; } $this->syncMiddlewareToRouter(); return $this; } /** * Prepend the given middleware to the middleware priority list. * * @param string $middleware * @return $this */ public function prependToMiddlewarePriority($middleware) { if (! in_array($middleware, $this->middlewarePriority)) { array_unshift($this->middlewarePriority, $middleware); } $this->syncMiddlewareToRouter(); return $this; } /** * Append the given middleware to the middleware priority list. * * @param string $middleware * @return $this */ public function appendToMiddlewarePriority($middleware) { if (! in_array($middleware, $this->middlewarePriority)) { $this->middlewarePriority[] = $middleware; } $this->syncMiddlewareToRouter(); return $this; } /** * Sync the current state of the middleware to the router. * * @return void */ protected function syncMiddlewareToRouter() { $this->router->middlewarePriority = $this->middlewarePriority; foreach ($this->middlewareGroups as $key => $middleware) { $this->router->middlewareGroup($key, $middleware); } foreach ($this->routeMiddleware as $key => $middleware) { $this->router->aliasMiddleware($key, $middleware); } } /** * Get the priority-sorted list of middleware. * * @return array */ public function getMiddlewarePriority() { return $this->middlewarePriority; } /** * Get the bootstrap classes for the application. * * @return array */ protected function bootstrappers() { return $this->bootstrappers; } /** * Report the exception to the exception handler. * * @param \Throwable $e * @return void */ protected function reportException(Throwable $e) { $this->app[ExceptionHandler::class]->report($e); } /** * Render the exception to a response. * * @param \Illuminate\Http\Request $request * @param \Throwable $e * @return \Symfony\Component\HttpFoundation\Response */ protected function renderException($request, Throwable $e) { return $this->app[ExceptionHandler::class]->render($request, $e); } /** * Get the application's route middleware groups. * * @return array */ public function getMiddlewareGroups() { return $this->middlewareGroups; } /** * Get the application's route middleware. * * @return array */ public function getRouteMiddleware() { return $this->routeMiddleware; } /** * Get the Laravel application instance. * * @return \Illuminate\Contracts\Foundation\Application */ public function getApplication() { return $this->app; } /** * Set the Laravel application instance. * * @param \Illuminate\Contracts\Foundation\Application $app * @return $this */ public function setApplication(Application $app) { $this->app = $app; return $this; } } PKz Z',,*Illuminate/Foundation/Http/FormRequest.phpnuW+Avalidator) { return $this->validator; } $factory = $this->container->make(ValidationFactory::class); if (method_exists($this, 'validator')) { $validator = $this->container->call([$this, 'validator'], compact('factory')); } else { $validator = $this->createDefaultValidator($factory); } if (method_exists($this, 'withValidator')) { $this->withValidator($validator); } $this->setValidator($validator); return $this->validator; } /** * Create the default validator instance. * * @param \Illuminate\Contracts\Validation\Factory $factory * @return \Illuminate\Contracts\Validation\Validator */ protected function createDefaultValidator(ValidationFactory $factory) { $rules = method_exists($this, 'rules') ? $this->container->call([$this, 'rules']) : []; $validator = $factory->make( $this->validationData(), $rules, $this->messages(), $this->attributes() )->stopOnFirstFailure($this->stopOnFirstFailure); if ($this->isPrecognitive()) { $validator->setRules( $this->filterPrecognitiveRules($validator->getRulesWithoutPlaceholders()) ); } return $validator; } /** * Get data to be validated from the request. * * @return array */ public function validationData() { return $this->all(); } /** * Handle a failed validation attempt. * * @param \Illuminate\Contracts\Validation\Validator $validator * @return void * * @throws \Illuminate\Validation\ValidationException */ protected function failedValidation(Validator $validator) { throw (new ValidationException($validator)) ->errorBag($this->errorBag) ->redirectTo($this->getRedirectUrl()); } /** * Get the URL to redirect to on a validation error. * * @return string */ protected function getRedirectUrl() { $url = $this->redirector->getUrlGenerator(); if ($this->redirect) { return $url->to($this->redirect); } elseif ($this->redirectRoute) { return $url->route($this->redirectRoute); } elseif ($this->redirectAction) { return $url->action($this->redirectAction); } return $url->previous(); } /** * Determine if the request passes the authorization check. * * @return bool * * @throws \Illuminate\Auth\Access\AuthorizationException */ protected function passesAuthorization() { if (method_exists($this, 'authorize')) { $result = $this->container->call([$this, 'authorize']); return $result instanceof Response ? $result->authorize() : $result; } return true; } /** * Handle a failed authorization attempt. * * @return void * * @throws \Illuminate\Auth\Access\AuthorizationException */ protected function failedAuthorization() { throw new AuthorizationException; } /** * Get a validated input container for the validated input. * * @param array|null $keys * @return \Illuminate\Support\ValidatedInput|array */ public function safe(array $keys = null) { return is_array($keys) ? $this->validator->safe()->only($keys) : $this->validator->safe(); } /** * Get the validated data from the request. * * @param array|int|string|null $key * @param mixed $default * @return mixed */ public function validated($key = null, $default = null) { return data_get($this->validator->validated(), $key, $default); } /** * Get custom messages for validator errors. * * @return array */ public function messages() { return []; } /** * Get custom attributes for validator errors. * * @return array */ public function attributes() { return []; } /** * Set the Validator instance. * * @param \Illuminate\Contracts\Validation\Validator $validator * @return $this */ public function setValidator(Validator $validator) { $this->validator = $validator; return $this; } /** * Set the Redirector instance. * * @param \Illuminate\Routing\Redirector $redirector * @return $this */ public function setRedirector(Redirector $redirector) { $this->redirector = $redirector; return $this; } /** * Set the container implementation. * * @param \Illuminate\Contracts\Container\Container $container * @return $this */ public function setContainer(Container $container) { $this->container = $container; return $this; } } PKz Z9BBIlluminate/Foundation/Http/Exceptions/MaintenanceModeException.phpnuW+AwentDownAt = Date::createFromTimestamp($time); if ($retryAfter) { $this->retryAfter = $retryAfter; $this->willBeAvailableAt = Date::instance(Carbon::createFromTimestamp($time)->addRealSeconds($this->retryAfter)); } } } PKz Z(HAIlluminate/Foundation/Http/Middleware/CheckForMaintenanceMode.phpnuW+A */ protected $except = [ // ]; /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { foreach (static::$skipCallbacks as $callback) { if ($callback($request)) { return $next($request); } } return parent::handle($request, $next); } /** * Transform the given value. * * @param string $key * @param mixed $value * @return mixed */ protected function transform($key, $value) { if (in_array($key, $this->except, true) || ! is_string($value)) { return $value; } return preg_replace('~^[\s\x{FEFF}\x{200B}]+|[\s\x{FEFF}\x{200B}]+$~u', '', $value) ?? trim($value); } /** * Register a callback that instructs the middleware to be skipped. * * @param \Closure $callback * @return void */ public static function skipWhen(Closure $callback) { static::$skipCallbacks[] = $callback; } } PKz Z#~~9Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.phpnuW+A */ protected $except = []; /** * Indicates whether the XSRF-TOKEN cookie should be set on the response. * * @var bool */ protected $addHttpCookie = true; /** * Create a new middleware instance. * * @param \Illuminate\Contracts\Foundation\Application $app * @param \Illuminate\Contracts\Encryption\Encrypter $encrypter * @return void */ public function __construct(Application $app, Encrypter $encrypter) { $this->app = $app; $this->encrypter = $encrypter; } /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed * * @throws \Illuminate\Session\TokenMismatchException */ public function handle($request, Closure $next) { if ( $this->isReading($request) || $this->runningUnitTests() || $this->inExceptArray($request) || $this->tokensMatch($request) ) { return tap($next($request), function ($response) use ($request) { if ($this->shouldAddXsrfTokenCookie()) { $this->addCookieToResponse($request, $response); } }); } throw new TokenMismatchException('CSRF token mismatch.'); } /** * Determine if the HTTP request uses a ‘read’ verb. * * @param \Illuminate\Http\Request $request * @return bool */ protected function isReading($request) { return in_array($request->method(), ['HEAD', 'GET', 'OPTIONS']); } /** * Determine if the application is running unit tests. * * @return bool */ protected function runningUnitTests() { return $this->app->runningInConsole() && $this->app->runningUnitTests(); } /** * Determine if the request has a URI that should pass through CSRF verification. * * @param \Illuminate\Http\Request $request * @return bool */ protected function inExceptArray($request) { foreach ($this->except as $except) { if ($except !== '/') { $except = trim($except, '/'); } if ($request->fullUrlIs($except) || $request->is($except)) { return true; } } return false; } /** * Determine if the session and input CSRF tokens match. * * @param \Illuminate\Http\Request $request * @return bool */ protected function tokensMatch($request) { $token = $this->getTokenFromRequest($request); return is_string($request->session()->token()) && is_string($token) && hash_equals($request->session()->token(), $token); } /** * Get the CSRF token from the request. * * @param \Illuminate\Http\Request $request * @return string|null */ protected function getTokenFromRequest($request) { $token = $request->input('_token') ?: $request->header('X-CSRF-TOKEN'); if (! $token && $header = $request->header('X-XSRF-TOKEN')) { try { $token = CookieValuePrefix::remove($this->encrypter->decrypt($header, static::serialized())); } catch (DecryptException $e) { $token = ''; } } return $token; } /** * Determine if the cookie should be added to the response. * * @return bool */ public function shouldAddXsrfTokenCookie() { return $this->addHttpCookie; } /** * Add the CSRF token to the response cookies. * * @param \Illuminate\Http\Request $request * @param \Symfony\Component\HttpFoundation\Response $response * @return \Symfony\Component\HttpFoundation\Response */ protected function addCookieToResponse($request, $response) { $config = config('session'); if ($response instanceof Responsable) { $response = $response->toResponse($request); } $response->headers->setCookie($this->newCookie($request, $config)); return $response; } /** * Create a new "XSRF-TOKEN" cookie that contains the CSRF token. * * @param \Illuminate\Http\Request $request * @param array $config * @return \Symfony\Component\HttpFoundation\Cookie */ protected function newCookie($request, $config) { return new Cookie( 'XSRF-TOKEN', $request->session()->token(), $this->availableAt(60 * $config['lifetime']), $config['path'], $config['domain'], $config['secure'], false, false, $config['same_site'] ?? null ); } /** * Determine if the cookie contents should be serialized. * * @return bool */ public static function serialized() { return EncryptCookies::serialized('XSRF-TOKEN'); } } PKz Z}ggJIlluminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.phpnuW+A */ protected $except = []; /** * Create a new middleware instance. * * @param \Illuminate\Contracts\Foundation\Application $app * @return void */ public function __construct(Application $app) { $this->app = $app; } /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed * * @throws \Symfony\Component\HttpKernel\Exception\HttpException */ public function handle($request, Closure $next) { if ($this->app->maintenanceMode()->active()) { $data = $this->app->maintenanceMode()->data(); if (isset($data['secret']) && $request->path() === $data['secret']) { return $this->bypassResponse($data['secret']); } if ($this->hasValidBypassCookie($request, $data) || $this->inExceptArray($request)) { return $next($request); } if (isset($data['redirect'])) { $path = $data['redirect'] === '/' ? $data['redirect'] : trim($data['redirect'], '/'); if ($request->path() !== $path) { return redirect($path); } } if (isset($data['template'])) { return response( $data['template'], $data['status'] ?? 503, $this->getHeaders($data) ); } throw new HttpException( $data['status'] ?? 503, 'Service Unavailable', null, $this->getHeaders($data) ); } return $next($request); } /** * Determine if the incoming request has a maintenance mode bypass cookie. * * @param \Illuminate\Http\Request $request * @param array $data * @return bool */ protected function hasValidBypassCookie($request, array $data) { return isset($data['secret']) && $request->cookie('laravel_maintenance') && MaintenanceModeBypassCookie::isValid( $request->cookie('laravel_maintenance'), $data['secret'] ); } /** * Determine if the request has a URI that should be accessible in maintenance mode. * * @param \Illuminate\Http\Request $request * @return bool */ protected function inExceptArray($request) { foreach ($this->getExcludedPaths() as $except) { if ($except !== '/') { $except = trim($except, '/'); } if ($request->fullUrlIs($except) || $request->is($except)) { return true; } } return false; } /** * Redirect the user back to the root of the application with a maintenance mode bypass cookie. * * @param string $secret * @return \Illuminate\Http\RedirectResponse */ protected function bypassResponse(string $secret) { return redirect('/')->withCookie( MaintenanceModeBypassCookie::create($secret) ); } /** * Get the headers that should be sent with the response. * * @param array $data * @return array */ protected function getHeaders($data) { $headers = isset($data['retry']) ? ['Retry-After' => $data['retry']] : []; if (isset($data['refresh'])) { $headers['Refresh'] = $data['refresh']; } return $headers; } /** * Get the URIs that should be accessible even when maintenance mode is enabled. * * @return array */ public function getExcludedPaths() { return $this->except; } } PKz Z*t DIlluminate/Foundation/Http/Middleware/HandlePrecognitiveRequests.phpnuW+Acontainer = $container; } /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return \Illuminate\Http\Response */ public function handle($request, $next) { if (! $request->isAttemptingPrecognition()) { return $this->appendVaryHeader($request, $next($request)); } $this->prepareForPrecognition($request); return tap($next($request), function ($response) use ($request) { $response->headers->set('Precognition', 'true'); $this->appendVaryHeader($request, $response); }); } /** * Prepare to handle a precognitive request. * * @param \Illuminate\Http\Request $request * @return void */ protected function prepareForPrecognition($request) { $request->attributes->set('precognitive', true); $this->container->bind(CallableDispatcherContract::class, fn ($app) => new PrecognitionCallableDispatcher($app)); $this->container->bind(ControllerDispatcherContract::class, fn ($app) => new PrecognitionControllerDispatcher($app)); } /** * Append the appropriate "Vary" header to the given response. * * @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Response $response * @return \Illuminate\Http\Response $response */ protected function appendVaryHeader($request, $response) { return tap($response, fn () => $response->headers->set('Vary', implode(', ', array_filter([ $response->headers->get('Vary'), 'Precognition', ])))); } } PKz ZPpCIlluminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.phpnuW+Aclean($request); return $next($request); } /** * Clean the request's data. * * @param \Illuminate\Http\Request $request * @return void */ protected function clean($request) { $this->cleanParameterBag($request->query); if ($request->isJson()) { $this->cleanParameterBag($request->json()); } elseif ($request->request !== $request->query) { $this->cleanParameterBag($request->request); } } /** * Clean the data in the parameter bag. * * @param \Symfony\Component\HttpFoundation\ParameterBag $bag * @return void */ protected function cleanParameterBag(ParameterBag $bag) { $bag->replace($this->cleanArray($bag->all())); } /** * Clean the data in the given array. * * @param array $data * @param string $keyPrefix * @return array */ protected function cleanArray(array $data, $keyPrefix = '') { foreach ($data as $key => $value) { $data[$key] = $this->cleanValue($keyPrefix.$key, $value); } return $data; } /** * Clean the given value. * * @param string $key * @param mixed $value * @return mixed */ protected function cleanValue($key, $value) { if (is_array($value)) { return $this->cleanArray($value, $key.'.'); } return $this->transform($key, $value); } /** * Transform the given value. * * @param string $key * @param mixed $value * @return mixed */ protected function transform($key, $value) { return $value; } } PKz ZMvJ:Illuminate/Foundation/Http/Middleware/ValidatePostSize.phpnuW+AgetPostMaxSize(); if ($max > 0 && $request->server('CONTENT_LENGTH') > $max) { throw new PostTooLargeException; } return $next($request); } /** * Determine the server 'post_max_size' as bytes. * * @return int */ protected function getPostMaxSize() { if (is_numeric($postMaxSize = ini_get('post_max_size'))) { return (int) $postMaxSize; } $metric = strtoupper(substr($postMaxSize, -1)); $postMaxSize = (int) $postMaxSize; return match ($metric) { 'K' => $postMaxSize * 1024, 'M' => $postMaxSize * 1048576, 'G' => $postMaxSize * 1073741824, default => $postMaxSize, }; } } PKz ZUAmm4Illuminate/Foundation/Http/Events/RequestHandled.phpnuW+Arequest = $request; $this->response = $response; } } PKz ZՇ33:Illuminate/Foundation/Http/MaintenanceModeBypassCookie.phpnuW+AaddHours(12); return new Cookie('laravel_maintenance', base64_encode(json_encode([ 'expires_at' => $expiresAt->getTimestamp(), 'mac' => hash_hmac('sha256', $expiresAt->getTimestamp(), $key), ])), $expiresAt, config('session.path'), config('session.domain')); } /** * Determine if the given maintenance mode bypass cookie is valid. * * @param string $cookie * @param string $key * @return bool */ public static function isValid(string $cookie, string $key) { $payload = json_decode(base64_decode($cookie), true); return is_array($payload) && is_numeric($payload['expires_at'] ?? null) && isset($payload['mac']) && hash_equals(hash_hmac('sha256', $payload['expires_at'], $key), $payload['mac']) && (int) $payload['expires_at'] >= Carbon::now()->getTimestamp(); } } PKz ZF)OO)Illuminate/Foundation/Http/HtmlDumper.phpnuW+A'; /** * Where the source should be placed on "non expanded" kind of dumps. * * @var string */ const NON_EXPANDED_SEPARATOR = "\n PKuZdf ee-Report/Html/Renderer/Template/lines.html.distnuW+A {{lines}}
PKuZn2]8Report/Html/Renderer/Template/directory_branch.html.distnuW+A Code Coverage for {{full_path}}
{{items}}
 
Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits

Legend

Low: 0% to {{low_upper_bound}}% Medium: {{low_upper_bound}}% to {{high_lower_bound}}% High: {{high_lower_bound}}% to 100%

Generated by php-code-coverage {{version}} using {{runtime}}{{generator}} at {{date}}.

PKuZO}''4Report/Html/Renderer/Template/coverage_bar.html.distnuW+A
{{percent}}% covered ({{level}})
PKuZ*'-Report/Html/Renderer/Template/paths.html.distnuW+A

Paths

Below are the source code lines that represent each code path as identified by Xdebug. Please note a path is not necessarily coterminous with a line, a line may contain multiple paths and therefore show up more than once. Please also be aware that some paths may include implicit rather than explicit branches, e.g. an if statement always has an else as part of its logical flow even if you didn't write one.

{{paths}} PKuZՆ1Report/Html/Renderer/Template/directory.html.distnuW+A Code Coverage for {{full_path}}
{{items}}
 
Code Coverage
 
Lines
Functions and Methods
Classes and Traits

Legend

Low: 0% to {{low_upper_bound}}% Medium: {{low_upper_bound}}% to {{high_lower_bound}}% High: {{high_lower_bound}}% to 100%

Generated by php-code-coverage {{version}} using {{runtime}}{{generator}} at {{date}}.

PKuZO}'';Report/Html/Renderer/Template/coverage_bar_branch.html.distnuW+A
{{percent}}% covered ({{level}})
PKuZj׫3Report/Html/Renderer/Template/method_item.html.distnuW+A {{name}} {{lines_bar}}
{{lines_executed_percent}}
{{lines_number}}
{{methods_bar}}
{{methods_tested_percent}}
{{methods_number}}
{{crap}} PKuZ{,Report/Html/Renderer/Template/line.html.distnuW+A {{lineNumber}}{{lineContent}} PKuZD1Report/Html/Renderer/Template/dashboard.html.distnuW+A Dashboard for {{full_path}}

Classes

Coverage Distribution

Complexity

Insufficient Coverage

{{insufficient_coverage_classes}}
Class Coverage

Project Risks

{{project_risks_classes}}
Class CRAP

Methods

Coverage Distribution

Complexity

Insufficient Coverage

{{insufficient_coverage_methods}}
Method Coverage

Project Risks

{{project_risks_methods}}
Method CRAP
PKuZh2+0Report/Html/Renderer/Template/branches.html.distnuW+A

Branches

Below are the source code lines that represent each code branch as identified by Xdebug. Please note a branch is not necessarily coterminous with a line, a line may contain multiple branches and therefore show up more than once. Please also be aware that some branches may be implicit rather than explicit, e.g. an if statement always has an else as part of its logical flow even if you didn't write one.

{{branches}} PKuZ㉞ 3Report/Html/Renderer/Template/file_branch.html.distnuW+A Code Coverage for {{full_path}}
{{items}}
 
Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
{{lines}} {{structure}}
PKuZdsAA6Report/Html/Renderer/Template/directory_item.html.distnuW+A {{icon}}{{name}} {{lines_bar}}
{{lines_executed_percent}}
{{lines_number}}
{{methods_bar}}
{{methods_tested_percent}}
{{methods_number}}
{{classes_bar}}
{{classes_tested_percent}}
{{classes_number}}
PKuZ-ll8Report/Html/Renderer/Template/file_item_branch.html.distnuW+A {{name}} {{lines_bar}}
{{lines_executed_percent}}
{{lines_number}}
{{branches_bar}}
{{branches_executed_percent}}
{{branches_number}}
{{paths_bar}}
{{paths_executed_percent}}
{{paths_number}}
{{methods_bar}}
{{methods_tested_percent}}
{{methods_number}}
{{crap}} {{classes_bar}}
{{classes_tested_percent}}
{{classes_number}}
PKuZ0,X%X%/Report/Html/Renderer/Template/css/nv.d3.min.cssnuW+A.nvd3 .nv-axis{pointer-events:none;opacity:1}.nvd3 .nv-axis path{fill:none;stroke:#000;stroke-opacity:.75;shape-rendering:crispEdges}.nvd3 .nv-axis path.domain{stroke-opacity:.75}.nvd3 .nv-axis.nv-x path.domain{stroke-opacity:0}.nvd3 .nv-axis line{fill:none;stroke:#e5e5e5;shape-rendering:crispEdges}.nvd3 .nv-axis .zero line,.nvd3 .nv-axis line.zero{stroke-opacity:.75}.nvd3 .nv-axis .nv-axisMaxMin text{font-weight:700}.nvd3 .x .nv-axis .nv-axisMaxMin text,.nvd3 .x2 .nv-axis .nv-axisMaxMin text,.nvd3 .x3 .nv-axis .nv-axisMaxMin text{text-anchor:middle}.nvd3 .nv-axis.nv-disabled{opacity:0}.nvd3 .nv-bars rect{fill-opacity:.75;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-bars rect.hover{fill-opacity:1}.nvd3 .nv-bars .hover rect{fill:#add8e6}.nvd3 .nv-bars text{fill:rgba(0,0,0,0)}.nvd3 .nv-bars .hover text{fill:rgba(0,0,0,1)}.nvd3 .nv-multibar .nv-groups rect,.nvd3 .nv-multibarHorizontal .nv-groups rect,.nvd3 .nv-discretebar .nv-groups rect{stroke-opacity:0;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-multibar .nv-groups rect:hover,.nvd3 .nv-multibarHorizontal .nv-groups rect:hover,.nvd3 .nv-candlestickBar .nv-ticks rect:hover,.nvd3 .nv-discretebar .nv-groups rect:hover{fill-opacity:1}.nvd3 .nv-discretebar .nv-groups text,.nvd3 .nv-multibarHorizontal .nv-groups text{font-weight:700;fill:rgba(0,0,0,1);stroke:rgba(0,0,0,0)}.nvd3 .nv-boxplot circle{fill-opacity:.5}.nvd3 .nv-boxplot circle:hover{fill-opacity:1}.nvd3 .nv-boxplot rect:hover{fill-opacity:1}.nvd3 line.nv-boxplot-median{stroke:#000}.nv-boxplot-tick:hover{stroke-width:2.5px}.nvd3.nv-bullet{font:10px sans-serif}.nvd3.nv-bullet .nv-measure{fill-opacity:.8}.nvd3.nv-bullet .nv-measure:hover{fill-opacity:1}.nvd3.nv-bullet .nv-marker{stroke:#000;stroke-width:2px}.nvd3.nv-bullet .nv-markerTriangle{stroke:#000;fill:#fff;stroke-width:1.5px}.nvd3.nv-bullet .nv-tick line{stroke:#666;stroke-width:.5px}.nvd3.nv-bullet .nv-range.nv-s0{fill:#eee}.nvd3.nv-bullet .nv-range.nv-s1{fill:#ddd}.nvd3.nv-bullet .nv-range.nv-s2{fill:#ccc}.nvd3.nv-bullet .nv-title{font-size:14px;font-weight:700}.nvd3.nv-bullet .nv-subtitle{fill:#999}.nvd3.nv-bullet .nv-range{fill:#bababa;fill-opacity:.4}.nvd3.nv-bullet .nv-range:hover{fill-opacity:.7}.nvd3.nv-candlestickBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.positive rect{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.negative rect{stroke:#d62728;fill:#d62728}.with-transitions .nv-candlestickBar .nv-ticks .nv-tick{transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-candlestickBar .nv-ticks line{stroke:#333}.nvd3 .nv-legend .nv-disabled rect{}.nvd3 .nv-check-box .nv-box{fill-opacity:0;stroke-width:2}.nvd3 .nv-check-box .nv-check{fill-opacity:0;stroke-width:4}.nvd3 .nv-series.nv-disabled .nv-check-box .nv-check{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-controlsWrap .nv-legend .nv-check-box .nv-check{opacity:0}.nvd3.nv-linePlusBar .nv-bar rect{fill-opacity:.75}.nvd3.nv-linePlusBar .nv-bar rect:hover{fill-opacity:1}.nvd3 .nv-groups path.nv-line{fill:none}.nvd3 .nv-groups path.nv-area{stroke:none}.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point{fill-opacity:0;stroke-opacity:0}.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point{fill-opacity:.5!important;stroke-opacity:.5!important}.with-transitions .nvd3 .nv-groups .nv-point{transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-scatter .nv-groups .nv-point.hover,.nvd3 .nv-groups .nv-point.hover{stroke-width:7px;fill-opacity:.95!important;stroke-opacity:.95!important}.nvd3 .nv-point-paths path{stroke:#aaa;stroke-opacity:0;fill:#eee;fill-opacity:0}.nvd3 .nv-indexLine{cursor:ew-resize}svg.nvd3-svg{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-ms-user-select:none;-moz-user-select:none;user-select:none;display:block;width:100%;height:100%}.nvtooltip.with-3d-shadow,.with-3d-shadow .nvtooltip{-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nvd3 text{font:400 12px Arial}.nvd3 .title{font:700 14px Arial}.nvd3 .nv-background{fill:#fff;fill-opacity:0}.nvd3.nv-noData{font-size:18px;font-weight:700}.nv-brush .extent{fill-opacity:.125;shape-rendering:crispEdges}.nv-brush .resize path{fill:#eee;stroke:#666}.nvd3 .nv-legend .nv-series{cursor:pointer}.nvd3 .nv-legend .nv-disabled circle{fill-opacity:0}.nvd3 .nv-brush .extent{fill-opacity:0!important}.nvd3 .nv-brushBackground rect{stroke:#000;stroke-width:.4;fill:#fff;fill-opacity:.7}.nvd3.nv-ohlcBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive{stroke:#2ca02c}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative{stroke:#d62728}.nvd3 .background path{fill:none;stroke:#EEE;stroke-opacity:.4;shape-rendering:crispEdges}.nvd3 .foreground path{fill:none;stroke-opacity:.7}.nvd3 .nv-parallelCoordinates-brush .extent{fill:#fff;fill-opacity:.6;stroke:gray;shape-rendering:crispEdges}.nvd3 .nv-parallelCoordinates .hover{fill-opacity:1;stroke-width:3px}.nvd3 .missingValuesline line{fill:none;stroke:#000;stroke-width:1;stroke-opacity:1;stroke-dasharray:5,5}.nvd3.nv-pie path{stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-pie .nv-pie-title{font-size:24px;fill:rgba(19,196,249,.59)}.nvd3.nv-pie .nv-slice text{stroke:#000;stroke-width:0}.nvd3.nv-pie path{stroke:#fff;stroke-width:1px;stroke-opacity:1}.nvd3.nv-pie .hover path{fill-opacity:.7}.nvd3.nv-pie .nv-label{pointer-events:none}.nvd3.nv-pie .nv-label rect{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-groups .nv-point.hover{stroke-width:20px;stroke-opacity:.5}.nvd3 .nv-scatter .nv-point.hover{fill-opacity:1}.nv-noninteractive{pointer-events:none}.nv-distx,.nv-disty{pointer-events:none}.nvd3.nv-sparkline path{fill:none}.nvd3.nv-sparklineplus g.nv-hoverValue{pointer-events:none}.nvd3.nv-sparklineplus .nv-hoverValue line{stroke:#333;stroke-width:1.5px}.nvd3.nv-sparklineplus,.nvd3.nv-sparklineplus g{pointer-events:all}.nvd3 .nv-hoverArea{fill-opacity:0;stroke-opacity:0}.nvd3.nv-sparklineplus .nv-xValue,.nvd3.nv-sparklineplus .nv-yValue{stroke-width:0;font-size:.9em;font-weight:400}.nvd3.nv-sparklineplus .nv-yValue{stroke:#f66}.nvd3.nv-sparklineplus .nv-maxValue{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-sparklineplus .nv-minValue{stroke:#d62728;fill:#d62728}.nvd3.nv-sparklineplus .nv-currentValue{font-weight:700;font-size:1.1em}.nvd3.nv-stackedarea path.nv-area{fill-opacity:.7;stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-stackedarea path.nv-area.hover{fill-opacity:.9}.nvd3.nv-stackedarea .nv-groups .nv-point{stroke-opacity:0;fill-opacity:0}.nvtooltip{position:absolute;background-color:rgba(255,255,255,1);color:rgba(0,0,0,1);padding:1px;border:1px solid rgba(0,0,0,.2);z-index:10000;display:block;font-family:Arial;font-size:13px;text-align:left;pointer-events:none;white-space:nowrap;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.nvtooltip{background:rgba(255,255,255,.8);border:1px solid rgba(0,0,0,.5);border-radius:4px}.nvtooltip.with-transitions,.with-transitions .nvtooltip{transition:opacity 50ms linear;-moz-transition:opacity 50ms linear;-webkit-transition:opacity 50ms linear;transition-delay:200ms;-moz-transition-delay:200ms;-webkit-transition-delay:200ms}.nvtooltip.x-nvtooltip,.nvtooltip.y-nvtooltip{padding:8px}.nvtooltip h3{margin:0;padding:4px 14px;line-height:18px;font-weight:400;background-color:rgba(247,247,247,.75);color:rgba(0,0,0,1);text-align:center;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.nvtooltip p{margin:0;padding:5px 14px;text-align:center}.nvtooltip span{display:inline-block;margin:2px 0}.nvtooltip table{margin:6px;border-spacing:0}.nvtooltip table td{padding:2px 9px 2px 0;vertical-align:middle}.nvtooltip table td.key{font-weight:400}.nvtooltip table td.value{text-align:right;font-weight:700}.nvtooltip table tr.highlight td{padding:1px 9px 1px 0;border-bottom-style:solid;border-bottom-width:1px;border-top-style:solid;border-top-width:1px}.nvtooltip table td.legend-color-guide div{width:8px;height:8px;vertical-align:middle}.nvtooltip table td.legend-color-guide div{width:12px;height:12px;border:1px solid #999}.nvtooltip .footer{padding:3px;text-align:center}.nvtooltip-pending-removal{pointer-events:none;display:none}.nvd3 .nv-interactiveGuideLine{pointer-events:none}.nvd3 line.nv-guideline{stroke:#ccc}PKuZ'#XX.Report/Html/Renderer/Template/css/octicons.cssnuW+A.octicon { display: inline-block; vertical-align: text-top; fill: currentColor; } PKuZyy3Report/Html/Renderer/Template/css/bootstrap.min.cssnuW+A/*! * Bootstrap v4.6.2 (https://getbootstrap.com/) * Copyright 2011-2022 The Bootstrap Authors * Copyright 2011-2022 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([class]){color:inherit;text-decoration:none}a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:.875em;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:.875em;color:#6c757d}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-sm-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-sm-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-md-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-md-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-md-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-md-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-md-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-md-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-lg-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-lg-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-xl-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-xl-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#7abaff}.table-hover .table-primary:hover{background-color:#9fcdff}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#b3b7bb}.table-hover .table-secondary:hover{background-color:#c8cbcf}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8fd19e}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#86cfda}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffdf7e}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed969e}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{-webkit-appearance:none;-moz-appearance:none;appearance:none}select.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;font-size:1rem;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[multiple],select.form-control[size]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#28a745}.valid-tooltip{position:absolute;top:100%;left:0;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.form-row>.col>.valid-tooltip,.form-row>[class*=col-]>.valid-tooltip{left:5px}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#28a745;padding-right:calc(1.5em + .75rem)!important;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.was-validated select.form-control:valid,select.form-control.is-valid{padding-right:3rem!important;background-position:right 1.5rem center}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-valid,.was-validated .custom-select:valid{border-color:#28a745;padding-right:calc(.75em + 2.3125rem)!important;background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label::before,.was-validated .custom-control-input:valid~.custom-control-label::before{border-color:#28a745}.custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .custom-control-input:valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .custom-control-input:valid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;left:0;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.form-row>.col>.invalid-tooltip,.form-row>[class*=col-]>.invalid-tooltip{left:5px}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem)!important;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.was-validated select.form-control:invalid,select.form-control.is-invalid{padding-right:3rem!important;background-position:right 1.5rem center}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{border-color:#dc3545;padding-right:calc(.75em + 2.3125rem)!important;background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label::before,.was-validated .custom-control-input:invalid~.custom-control-label::before{border-color:#dc3545}.custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .custom-control-input:invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;-ms-flex-negative:0;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#0069d9;border-color:#0062cc;box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{color:#fff;background-color:#5a6268;border-color:#545b62;box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#218838;border-color:#1e7e34;box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#138496;border-color:#117a8b;box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{color:#212529;background-color:#e0a800;border-color:#d39e00;box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c82333;border-color:#bd2130;box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{color:#212529;background-color:#e2e6ea;border-color:#dae0e5;box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{color:#fff;background-color:#23272b;border-color:#1d2124;box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-outline-primary{color:#007bff;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;text-decoration:none}.btn-link:hover{color:#0056b3;text-decoration:underline}.btn-link.focus,.btn-link:focus{text-decoration:underline}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.width{width:0;height:auto;transition:width .35s ease}@media (prefers-reduced-motion:reduce){.collapsing.width{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#e9ecef}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#adb5bd;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:1 1 auto;flex:1 1 auto}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:1}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:1}.btn-toolbar{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:center;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;min-width:0;margin-bottom:0}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label,.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label::after,.input-group:not(.has-validation)>.custom-select:not(:last-child),.input-group:not(.has-validation)>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label,.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label::after,.input-group.has-validation>.custom-select:nth-last-child(n+3),.input-group.has-validation>.form-control:nth-last-child(n+3){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-append,.input-group-prepend{display:-ms-flexbox;display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.btn,.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.input-group-text,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.btn,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;z-index:1;display:block;min-height:1.5rem;padding-left:1.5rem;-webkit-print-color-adjust:exact;color-adjust:exact;print-color-adjust:exact}.custom-control-inline{display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;left:0;z-index:-1;width:1rem;height:1.25rem;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;border-color:#007bff;background-color:#007bff}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label::before{border-color:#80bdff}.custom-control-input:not(:disabled):active~.custom-control-label::before{color:#fff;background-color:#b3d7ff;border-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label::before,.custom-control-input[disabled]~.custom-control-label::before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:1px solid #adb5bd}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:50%/50% 50% no-repeat}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{border-color:#007bff;background-color:#007bff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label::after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label::after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label::after{background-color:#fff;-webkit-transform:translateX(.75rem);transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + .75rem + 2px);margin:0;overflow:hidden;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]::after{content:attr(data-browse)}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;overflow:hidden;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-moz-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;-ms-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-ms-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label::before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label::before,.custom-file-label,.custom-select{transition:none}}.nav{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-link{margin-bottom:-1px;background-color:transparent;border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{isolation:isolate;border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{background:0 0;border:0;border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item,.nav-fill>.nav-link{-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:50%/100% 100% no-repeat}.navbar-nav-scroll{max-height:75vh;overflow-y:auto}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem;border-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom,.card-img-top{-ms-flex-negative:0;flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{-ms-flex:1 0 0%;flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion{overflow-anchor:none}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:3;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}a.badge-primary:focus,a.badge-primary:hover{color:#fff;background-color:#0062cc}a.badge-primary.focus,a.badge-primary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:focus,a.badge-secondary:hover{color:#fff;background-color:#545b62}a.badge-secondary.focus,a.badge-secondary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:focus,a.badge-success:hover{color:#fff;background-color:#1e7e34}a.badge-success.focus,a.badge-success:focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:focus,a.badge-info:hover{color:#fff;background-color:#117a8b}a.badge-info.focus,a.badge-info:focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.badge-warning{color:#212529;background-color:#ffc107}a.badge-warning:focus,a.badge-warning:hover{color:#212529;background-color:#d39e00}a.badge-warning.focus,a.badge-warning:focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:focus,a.badge-danger:hover{color:#fff;background-color:#bd2130}a.badge-danger.focus,a.badge-danger:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.badge-light{color:#212529;background-color:#f8f9fa}a.badge-light:focus,a.badge-light:hover{color:#212529;background-color:#dae0e5}a.badge-light.focus,a.badge-light:focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:focus,a.badge-dark:hover{color:#fff;background-color:#1d2124}a.badge-dark.focus,a.badge-dark:focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;z-index:2;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;line-height:0;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:1s linear infinite progress-bar-stripes;animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.media{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start}.media-body{-ms-flex:1;flex:1}.list-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:.25rem}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width:576px){.list-group-horizontal-sm{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:768px){.list-group-horizontal-md{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:992px){.list-group-horizontal-lg{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1200px){.list-group-horizontal-xl{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{padding:0;background-color:transparent;border:0}a.close.disabled{pointer-events:none}.toast{-ms-flex-preferred-size:350px;flex-basis:350px;max-width:350px;font-size:.875rem;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-50px);transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{-webkit-transform:none;transform:none}.modal.modal-static .modal-dialog{-webkit-transform:scale(1.02);transform:scale(1.02)}.modal-dialog-scrollable{display:-ms-flexbox;display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{-ms-flex-negative:0;flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);height:-webkit-min-content;height:-moz-min-content;height:min-content;content:""}.modal-dialog-centered.modal-dialog-scrollable{-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable::before{content:none}.modal-content{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered::before{height:calc(100vh - 3.5rem);height:-webkit-min-content;height:-moz-min-content;height:min-content}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow::before,.bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow::before,.bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow::before,.bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::after,.popover .arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=top]>.arrow::before,.bs-popover-top>.arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top]>.arrow::after,.bs-popover-top>.arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right]>.arrow::before,.bs-popover-right>.arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right]>.arrow::after,.bs-popover-right>.arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=bottom]>.arrow::before,.bs-popover-bottom>.arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom]>.arrow::after,.bs-popover-bottom>.arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left]>.arrow::before,.bs-popover-left>.arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left]>.arrow::after,.bs-popover-left>.arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{-ms-touch-action:pan-y;touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){-webkit-transform:translateX(100%);transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){-webkit-transform:translateX(-100%);transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;-webkit-transform:none;transform:none}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:0 0;border:0;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:50%/100% 100% no-repeat}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@-webkit-keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:-.125em;border:.25em solid currentcolor;border-right-color:transparent;border-radius:50%;-webkit-animation:.75s linear infinite spinner-border;animation:.75s linear infinite spinner-border}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}@keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:-.125em;background-color:currentcolor;border-radius:50%;opacity:0;-webkit-animation:.75s linear infinite spinner-grow;animation:.75s linear infinite spinner-grow}.spinner-grow-sm{width:1rem;height:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{-webkit-animation-duration:1.5s;animation-duration:1.5s}}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;-ms-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0056b3!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#494f54!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#19692c!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#0f6674!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#ba8b00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#a71d2a!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#121416!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none!important}.text-break{word-break:break-word!important;word-wrap:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,::after,::before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd;page-break-inside:avoid}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px!important}.container{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}} /*# sourceMappingURL=bootstrap.min.css.map */PKuZ  +Report/Html/Renderer/Template/css/style.cssnuW+Abody { font-family: sans-serif; font-size: 1em; font-kerning: normal; font-variant-ligatures: common-ligatures; text-rendering: optimizeLegibility; padding-top: 10px; } .popover { max-width: none; } .octicon { margin-right:.25em; vertical-align: baseline; width: 0.75em; } .table-bordered>thead>tr>td { border-bottom-width: 1px; } .table tbody>tr>td, .table thead>tr>td { padding-top: 3px; padding-bottom: 3px; } .table-condensed tbody>tr>td { padding-top: 0; padding-bottom: 0; } .table .progress { margin-bottom: inherit; } .table-borderless th, .table-borderless td { border: 0 !important; } .table tbody tr.covered-by-large-tests, li.covered-by-large-tests, tr.success, td.success, li.success, span.success { background-color: #dff0d8; } .table tbody tr.covered-by-medium-tests, li.covered-by-medium-tests { background-color: #c3e3b5; } .table tbody tr.covered-by-small-tests, li.covered-by-small-tests { background-color: #99cb84; } .table tbody tr.danger, .table tbody td.danger, li.danger, span.danger { background-color: #f2dede; } .table tbody tr.warning, .table tbody td.warning, li.warning, span.warning { background-color: #fcf8e3; } .table tbody td.info { background-color: #d9edf7; } td.big { vertical-align: middle; width: 117px; } td.small { } td.codeLine { font-family: "Source Code Pro", "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; white-space: pre-wrap; } td span.comment { color: #888a85; } td span.default { color: #2e3436; } td span.html { color: #888a85; } td span.keyword { color: #2e3436; font-weight: bold; } pre span.string { color: #2e3436; } span.success, span.warning, span.danger { margin-right: 2px; padding-left: 10px; padding-right: 10px; text-align: center; } #toplink { position: fixed; left: 5px; bottom: 5px; outline: 0; } svg text { font-family: "Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif; font-size: 11px; color: #666; fill: #666; } .scrollbox { height:245px; overflow-x:hidden; overflow-y:scroll; } table + .structure-heading { border-top: 1px solid lightgrey; padding-top: 0.5em; } .legend { font-weight: bold; margin-right: 2px; padding-left: 10px; padding-right: 10px; text-align: center; } .covered-by-small-tests { background-color: #99cb84; } .covered-by-medium-tests { background-color: #c3e3b5; } .covered-by-large-tests { background-color: #dff0d8; } .not-covered { background-color: #f2dede; } .not-coverable { background-color: #fcf8e3; } PKuZ,Report/Html/Renderer/Template/css/custom.cssnuW+APKuZyĎk:Report/Html/Renderer/Template/method_item_branch.html.distnuW+A {{name}} {{lines_bar}}
{{lines_executed_percent}}
{{lines_number}}
{{branches_bar}}
{{branches_executed_percent}}
{{branches_number}}
{{paths_bar}}
{{paths_executed_percent}}
{{paths_number}}
{{methods_bar}}
{{methods_tested_percent}}
{{methods_number}}
{{crap}} PKuZD8Report/Html/Renderer/Template/dashboard_branch.html.distnuW+A Dashboard for {{full_path}}

Classes

Coverage Distribution

Complexity

Insufficient Coverage

{{insufficient_coverage_classes}}
Class Coverage

Project Risks

{{project_risks_classes}}
Class CRAP

Methods

Coverage Distribution

Complexity

Insufficient Coverage

{{insufficient_coverage_methods}}
Method Coverage

Project Risks

{{project_risks_methods}}
Method CRAP
PKuZ1~&aa"Report/Html/Renderer/Directory.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Html; use function count; use function sprintf; use function str_repeat; use SebastianBergmann\CodeCoverage\Node\AbstractNode as Node; use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; use SebastianBergmann\Template\Template; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class Directory extends Renderer { public function render(DirectoryNode $node, string $file): void { $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'directory_branch.html' : 'directory.html'); $template = new Template($templateName, '{{', '}}'); $this->setCommonTemplateVariables($template, $node); $items = $this->renderItem($node, true); foreach ($node->directories() as $item) { $items .= $this->renderItem($item); } foreach ($node->files() as $item) { $items .= $this->renderItem($item); } $template->setVar( [ 'id' => $node->id(), 'items' => $items, ] ); $template->renderTo($file); } private function renderItem(Node $node, bool $total = false): string { $data = [ 'numClasses' => $node->numberOfClassesAndTraits(), 'numTestedClasses' => $node->numberOfTestedClassesAndTraits(), 'numMethods' => $node->numberOfFunctionsAndMethods(), 'numTestedMethods' => $node->numberOfTestedFunctionsAndMethods(), 'linesExecutedPercent' => $node->percentageOfExecutedLines()->asFloat(), 'linesExecutedPercentAsString' => $node->percentageOfExecutedLines()->asString(), 'numExecutedLines' => $node->numberOfExecutedLines(), 'numExecutableLines' => $node->numberOfExecutableLines(), 'branchesExecutedPercent' => $node->percentageOfExecutedBranches()->asFloat(), 'branchesExecutedPercentAsString' => $node->percentageOfExecutedBranches()->asString(), 'numExecutedBranches' => $node->numberOfExecutedBranches(), 'numExecutableBranches' => $node->numberOfExecutableBranches(), 'pathsExecutedPercent' => $node->percentageOfExecutedPaths()->asFloat(), 'pathsExecutedPercentAsString' => $node->percentageOfExecutedPaths()->asString(), 'numExecutedPaths' => $node->numberOfExecutedPaths(), 'numExecutablePaths' => $node->numberOfExecutablePaths(), 'testedMethodsPercent' => $node->percentageOfTestedFunctionsAndMethods()->asFloat(), 'testedMethodsPercentAsString' => $node->percentageOfTestedFunctionsAndMethods()->asString(), 'testedClassesPercent' => $node->percentageOfTestedClassesAndTraits()->asFloat(), 'testedClassesPercentAsString' => $node->percentageOfTestedClassesAndTraits()->asString(), ]; if ($total) { $data['name'] = 'Total'; } else { $up = str_repeat('../', count($node->pathAsArray()) - 2); $data['icon'] = sprintf('', $up); if ($node instanceof DirectoryNode) { $data['name'] = sprintf( '%s', $node->name(), $node->name() ); $data['icon'] = sprintf('', $up); } elseif ($this->hasBranchCoverage) { $data['name'] = sprintf( '%s [line] [branch] [path]', $node->name(), $node->name(), $node->name(), $node->name() ); } else { $data['name'] = sprintf( '%s', $node->name(), $node->name() ); } } $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'directory_item_branch.html' : 'directory_item.html'); return $this->renderItemTemplate( new Template($templateName, '{{', '}}'), $data ); } } PKuZ!|/s&s&"Report/Html/Renderer/Dashboard.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Html; use function array_values; use function arsort; use function asort; use function count; use function explode; use function floor; use function json_encode; use function sprintf; use function str_replace; use SebastianBergmann\CodeCoverage\Node\AbstractNode; use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; use SebastianBergmann\Template\Template; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class Dashboard extends Renderer { public function render(DirectoryNode $node, string $file): void { $classes = $node->classesAndTraits(); $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'dashboard_branch.html' : 'dashboard.html'); $template = new Template( $templateName, '{{', '}}' ); $this->setCommonTemplateVariables($template, $node); $baseLink = $node->id() . '/'; $complexity = $this->complexity($classes, $baseLink); $coverageDistribution = $this->coverageDistribution($classes); $insufficientCoverage = $this->insufficientCoverage($classes, $baseLink); $projectRisks = $this->projectRisks($classes, $baseLink); $template->setVar( [ 'insufficient_coverage_classes' => $insufficientCoverage['class'], 'insufficient_coverage_methods' => $insufficientCoverage['method'], 'project_risks_classes' => $projectRisks['class'], 'project_risks_methods' => $projectRisks['method'], 'complexity_class' => $complexity['class'], 'complexity_method' => $complexity['method'], 'class_coverage_distribution' => $coverageDistribution['class'], 'method_coverage_distribution' => $coverageDistribution['method'], ] ); $template->renderTo($file); } protected function activeBreadcrumb(AbstractNode $node): string { return sprintf( ' ' . "\n" . ' ' . "\n", $node->name() ); } /** * Returns the data for the Class/Method Complexity charts. */ private function complexity(array $classes, string $baseLink): array { $result = ['class' => [], 'method' => []]; foreach ($classes as $className => $class) { foreach ($class['methods'] as $methodName => $method) { if ($className !== '*') { $methodName = $className . '::' . $methodName; } $result['method'][] = [ $method['coverage'], $method['ccn'], sprintf( '%s', str_replace($baseLink, '', $method['link']), $methodName ), ]; } $result['class'][] = [ $class['coverage'], $class['ccn'], sprintf( '%s', str_replace($baseLink, '', $class['link']), $className ), ]; } return [ 'class' => json_encode($result['class']), 'method' => json_encode($result['method']), ]; } /** * Returns the data for the Class / Method Coverage Distribution chart. */ private function coverageDistribution(array $classes): array { $result = [ 'class' => [ '0%' => 0, '0-10%' => 0, '10-20%' => 0, '20-30%' => 0, '30-40%' => 0, '40-50%' => 0, '50-60%' => 0, '60-70%' => 0, '70-80%' => 0, '80-90%' => 0, '90-100%' => 0, '100%' => 0, ], 'method' => [ '0%' => 0, '0-10%' => 0, '10-20%' => 0, '20-30%' => 0, '30-40%' => 0, '40-50%' => 0, '50-60%' => 0, '60-70%' => 0, '70-80%' => 0, '80-90%' => 0, '90-100%' => 0, '100%' => 0, ], ]; foreach ($classes as $class) { foreach ($class['methods'] as $methodName => $method) { if ($method['coverage'] === 0) { $result['method']['0%']++; } elseif ($method['coverage'] === 100) { $result['method']['100%']++; } else { $key = floor($method['coverage'] / 10) * 10; $key = $key . '-' . ($key + 10) . '%'; $result['method'][$key]++; } } if ($class['coverage'] === 0) { $result['class']['0%']++; } elseif ($class['coverage'] === 100) { $result['class']['100%']++; } else { $key = floor($class['coverage'] / 10) * 10; $key = $key . '-' . ($key + 10) . '%'; $result['class'][$key]++; } } return [ 'class' => json_encode(array_values($result['class'])), 'method' => json_encode(array_values($result['method'])), ]; } /** * Returns the classes / methods with insufficient coverage. */ private function insufficientCoverage(array $classes, string $baseLink): array { $leastTestedClasses = []; $leastTestedMethods = []; $result = ['class' => '', 'method' => '']; foreach ($classes as $className => $class) { foreach ($class['methods'] as $methodName => $method) { if ($method['coverage'] < $this->highLowerBound) { $key = $methodName; if ($className !== '*') { $key = $className . '::' . $methodName; } $leastTestedMethods[$key] = $method['coverage']; } } if ($class['coverage'] < $this->highLowerBound) { $leastTestedClasses[$className] = $class['coverage']; } } asort($leastTestedClasses); asort($leastTestedMethods); foreach ($leastTestedClasses as $className => $coverage) { $result['class'] .= sprintf( ' %s%d%%' . "\n", str_replace($baseLink, '', $classes[$className]['link']), $className, $coverage ); } foreach ($leastTestedMethods as $methodName => $coverage) { [$class, $method] = explode('::', $methodName); $result['method'] .= sprintf( ' %s%d%%' . "\n", str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']), $methodName, $method, $coverage ); } return $result; } /** * Returns the project risks according to the CRAP index. */ private function projectRisks(array $classes, string $baseLink): array { $classRisks = []; $methodRisks = []; $result = ['class' => '', 'method' => '']; foreach ($classes as $className => $class) { foreach ($class['methods'] as $methodName => $method) { if ($method['coverage'] < $this->highLowerBound && $method['ccn'] > 1) { $key = $methodName; if ($className !== '*') { $key = $className . '::' . $methodName; } $methodRisks[$key] = $method['crap']; } } if ($class['coverage'] < $this->highLowerBound && $class['ccn'] > count($class['methods'])) { $classRisks[$className] = $class['crap']; } } arsort($classRisks); arsort($methodRisks); foreach ($classRisks as $className => $crap) { $result['class'] .= sprintf( ' %s%d' . "\n", str_replace($baseLink, '', $classes[$className]['link']), $className, $crap ); } foreach ($methodRisks as $methodName => $crap) { [$class, $method] = explode('::', $methodName); $result['method'] .= sprintf( ' %s%d' . "\n", str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']), $methodName, $method, $crap ); } return $result; } } PKuZ iGGReport/Html/Renderer/File.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Html; use const ENT_COMPAT; use const ENT_HTML401; use const ENT_SUBSTITUTE; use const T_ABSTRACT; use const T_ARRAY; use const T_AS; use const T_BREAK; use const T_CALLABLE; use const T_CASE; use const T_CATCH; use const T_CLASS; use const T_CLONE; use const T_COMMENT; use const T_CONST; use const T_CONTINUE; use const T_DECLARE; use const T_DEFAULT; use const T_DO; use const T_DOC_COMMENT; use const T_ECHO; use const T_ELSE; use const T_ELSEIF; use const T_EMPTY; use const T_ENDDECLARE; use const T_ENDFOR; use const T_ENDFOREACH; use const T_ENDIF; use const T_ENDSWITCH; use const T_ENDWHILE; use const T_EVAL; use const T_EXIT; use const T_EXTENDS; use const T_FINAL; use const T_FINALLY; use const T_FOR; use const T_FOREACH; use const T_FUNCTION; use const T_GLOBAL; use const T_GOTO; use const T_HALT_COMPILER; use const T_IF; use const T_IMPLEMENTS; use const T_INCLUDE; use const T_INCLUDE_ONCE; use const T_INLINE_HTML; use const T_INSTANCEOF; use const T_INSTEADOF; use const T_INTERFACE; use const T_ISSET; use const T_LIST; use const T_NAMESPACE; use const T_NEW; use const T_PRINT; use const T_PRIVATE; use const T_PROTECTED; use const T_PUBLIC; use const T_REQUIRE; use const T_REQUIRE_ONCE; use const T_RETURN; use const T_STATIC; use const T_SWITCH; use const T_THROW; use const T_TRAIT; use const T_TRY; use const T_UNSET; use const T_USE; use const T_VAR; use const T_WHILE; use const T_YIELD; use const T_YIELD_FROM; use function array_key_exists; use function array_keys; use function array_merge; use function array_pop; use function array_unique; use function constant; use function count; use function defined; use function explode; use function file_get_contents; use function htmlspecialchars; use function is_string; use function ksort; use function range; use function sort; use function sprintf; use function str_replace; use function substr; use function token_get_all; use function trim; use PHPUnit\Runner\BaseTestRunner; use SebastianBergmann\CodeCoverage\Node\File as FileNode; use SebastianBergmann\CodeCoverage\Util\Percentage; use SebastianBergmann\Template\Template; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class File extends Renderer { /** * @psalm-var array */ private static $keywordTokens = []; /** * @var array */ private static $formattedSourceCache = []; /** * @var int */ private $htmlSpecialCharsFlags = ENT_COMPAT | ENT_HTML401 | ENT_SUBSTITUTE; public function render(FileNode $node, string $file): void { $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'file_branch.html' : 'file.html'); $template = new Template($templateName, '{{', '}}'); $this->setCommonTemplateVariables($template, $node); $template->setVar( [ 'items' => $this->renderItems($node), 'lines' => $this->renderSourceWithLineCoverage($node), 'legend' => '

Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

', 'structure' => '', ] ); $template->renderTo($file . '.html'); if ($this->hasBranchCoverage) { $template->setVar( [ 'items' => $this->renderItems($node), 'lines' => $this->renderSourceWithBranchCoverage($node), 'legend' => '

Fully coveredPartially coveredNot covered

', 'structure' => $this->renderBranchStructure($node), ] ); $template->renderTo($file . '_branch.html'); $template->setVar( [ 'items' => $this->renderItems($node), 'lines' => $this->renderSourceWithPathCoverage($node), 'legend' => '

Fully coveredPartially coveredNot covered

', 'structure' => $this->renderPathStructure($node), ] ); $template->renderTo($file . '_path.html'); } } private function renderItems(FileNode $node): string { $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'file_item_branch.html' : 'file_item.html'); $template = new Template($templateName, '{{', '}}'); $methodTemplateName = $this->templatePath . ($this->hasBranchCoverage ? 'method_item_branch.html' : 'method_item.html'); $methodItemTemplate = new Template( $methodTemplateName, '{{', '}}' ); $items = $this->renderItemTemplate( $template, [ 'name' => 'Total', 'numClasses' => $node->numberOfClassesAndTraits(), 'numTestedClasses' => $node->numberOfTestedClassesAndTraits(), 'numMethods' => $node->numberOfFunctionsAndMethods(), 'numTestedMethods' => $node->numberOfTestedFunctionsAndMethods(), 'linesExecutedPercent' => $node->percentageOfExecutedLines()->asFloat(), 'linesExecutedPercentAsString' => $node->percentageOfExecutedLines()->asString(), 'numExecutedLines' => $node->numberOfExecutedLines(), 'numExecutableLines' => $node->numberOfExecutableLines(), 'branchesExecutedPercent' => $node->percentageOfExecutedBranches()->asFloat(), 'branchesExecutedPercentAsString' => $node->percentageOfExecutedBranches()->asString(), 'numExecutedBranches' => $node->numberOfExecutedBranches(), 'numExecutableBranches' => $node->numberOfExecutableBranches(), 'pathsExecutedPercent' => $node->percentageOfExecutedPaths()->asFloat(), 'pathsExecutedPercentAsString' => $node->percentageOfExecutedPaths()->asString(), 'numExecutedPaths' => $node->numberOfExecutedPaths(), 'numExecutablePaths' => $node->numberOfExecutablePaths(), 'testedMethodsPercent' => $node->percentageOfTestedFunctionsAndMethods()->asFloat(), 'testedMethodsPercentAsString' => $node->percentageOfTestedFunctionsAndMethods()->asString(), 'testedClassesPercent' => $node->percentageOfTestedClassesAndTraits()->asFloat(), 'testedClassesPercentAsString' => $node->percentageOfTestedClassesAndTraits()->asString(), 'crap' => 'CRAP', ] ); $items .= $this->renderFunctionItems( $node->functions(), $methodItemTemplate ); $items .= $this->renderTraitOrClassItems( $node->traits(), $template, $methodItemTemplate ); $items .= $this->renderTraitOrClassItems( $node->classes(), $template, $methodItemTemplate ); return $items; } private function renderTraitOrClassItems(array $items, Template $template, Template $methodItemTemplate): string { $buffer = ''; if (empty($items)) { return $buffer; } foreach ($items as $name => $item) { $numMethods = 0; $numTestedMethods = 0; foreach ($item['methods'] as $method) { if ($method['executableLines'] > 0) { $numMethods++; if ($method['executedLines'] === $method['executableLines']) { $numTestedMethods++; } } } if ($item['executableLines'] > 0) { $numClasses = 1; $numTestedClasses = $numTestedMethods === $numMethods ? 1 : 0; $linesExecutedPercentAsString = Percentage::fromFractionAndTotal( $item['executedLines'], $item['executableLines'] )->asString(); $branchesExecutedPercentAsString = Percentage::fromFractionAndTotal( $item['executedBranches'], $item['executableBranches'] )->asString(); $pathsExecutedPercentAsString = Percentage::fromFractionAndTotal( $item['executedPaths'], $item['executablePaths'] )->asString(); } else { $numClasses = 0; $numTestedClasses = 0; $linesExecutedPercentAsString = 'n/a'; $branchesExecutedPercentAsString = 'n/a'; $pathsExecutedPercentAsString = 'n/a'; } $testedMethodsPercentage = Percentage::fromFractionAndTotal( $numTestedMethods, $numMethods ); $testedClassesPercentage = Percentage::fromFractionAndTotal( $numTestedMethods === $numMethods ? 1 : 0, 1 ); $buffer .= $this->renderItemTemplate( $template, [ 'name' => $this->abbreviateClassName($name), 'numClasses' => $numClasses, 'numTestedClasses' => $numTestedClasses, 'numMethods' => $numMethods, 'numTestedMethods' => $numTestedMethods, 'linesExecutedPercent' => Percentage::fromFractionAndTotal( $item['executedLines'], $item['executableLines'], )->asFloat(), 'linesExecutedPercentAsString' => $linesExecutedPercentAsString, 'numExecutedLines' => $item['executedLines'], 'numExecutableLines' => $item['executableLines'], 'branchesExecutedPercent' => Percentage::fromFractionAndTotal( $item['executedBranches'], $item['executableBranches'], )->asFloat(), 'branchesExecutedPercentAsString' => $branchesExecutedPercentAsString, 'numExecutedBranches' => $item['executedBranches'], 'numExecutableBranches' => $item['executableBranches'], 'pathsExecutedPercent' => Percentage::fromFractionAndTotal( $item['executedPaths'], $item['executablePaths'] )->asFloat(), 'pathsExecutedPercentAsString' => $pathsExecutedPercentAsString, 'numExecutedPaths' => $item['executedPaths'], 'numExecutablePaths' => $item['executablePaths'], 'testedMethodsPercent' => $testedMethodsPercentage->asFloat(), 'testedMethodsPercentAsString' => $testedMethodsPercentage->asString(), 'testedClassesPercent' => $testedClassesPercentage->asFloat(), 'testedClassesPercentAsString' => $testedClassesPercentage->asString(), 'crap' => $item['crap'], ] ); foreach ($item['methods'] as $method) { $buffer .= $this->renderFunctionOrMethodItem( $methodItemTemplate, $method, ' ' ); } } return $buffer; } private function renderFunctionItems(array $functions, Template $template): string { if (empty($functions)) { return ''; } $buffer = ''; foreach ($functions as $function) { $buffer .= $this->renderFunctionOrMethodItem( $template, $function ); } return $buffer; } private function renderFunctionOrMethodItem(Template $template, array $item, string $indent = ''): string { $numMethods = 0; $numTestedMethods = 0; if ($item['executableLines'] > 0) { $numMethods = 1; if ($item['executedLines'] === $item['executableLines']) { $numTestedMethods = 1; } } $executedLinesPercentage = Percentage::fromFractionAndTotal( $item['executedLines'], $item['executableLines'] ); $executedBranchesPercentage = Percentage::fromFractionAndTotal( $item['executedBranches'], $item['executableBranches'] ); $executedPathsPercentage = Percentage::fromFractionAndTotal( $item['executedPaths'], $item['executablePaths'] ); $testedMethodsPercentage = Percentage::fromFractionAndTotal( $numTestedMethods, 1 ); return $this->renderItemTemplate( $template, [ 'name' => sprintf( '%s%s', $indent, $item['startLine'], htmlspecialchars($item['signature'], $this->htmlSpecialCharsFlags), $item['functionName'] ?? $item['methodName'] ), 'numMethods' => $numMethods, 'numTestedMethods' => $numTestedMethods, 'linesExecutedPercent' => $executedLinesPercentage->asFloat(), 'linesExecutedPercentAsString' => $executedLinesPercentage->asString(), 'numExecutedLines' => $item['executedLines'], 'numExecutableLines' => $item['executableLines'], 'branchesExecutedPercent' => $executedBranchesPercentage->asFloat(), 'branchesExecutedPercentAsString' => $executedBranchesPercentage->asString(), 'numExecutedBranches' => $item['executedBranches'], 'numExecutableBranches' => $item['executableBranches'], 'pathsExecutedPercent' => $executedPathsPercentage->asFloat(), 'pathsExecutedPercentAsString' => $executedPathsPercentage->asString(), 'numExecutedPaths' => $item['executedPaths'], 'numExecutablePaths' => $item['executablePaths'], 'testedMethodsPercent' => $testedMethodsPercentage->asFloat(), 'testedMethodsPercentAsString' => $testedMethodsPercentage->asString(), 'crap' => $item['crap'], ] ); } private function renderSourceWithLineCoverage(FileNode $node): string { $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); $coverageData = $node->lineCoverageData(); $testData = $node->testData(); $codeLines = $this->loadFile($node->pathAsString()); $lines = ''; $i = 1; foreach ($codeLines as $line) { $trClass = ''; $popoverContent = ''; $popoverTitle = ''; if (array_key_exists($i, $coverageData)) { $numTests = ($coverageData[$i] ? count($coverageData[$i]) : 0); if ($coverageData[$i] === null) { $trClass = 'warning'; } elseif ($numTests === 0) { $trClass = 'danger'; } else { if ($numTests > 1) { $popoverTitle = $numTests . ' tests cover line ' . $i; } else { $popoverTitle = '1 test covers line ' . $i; } $lineCss = 'covered-by-large-tests'; $popoverContent = '
    '; foreach ($coverageData[$i] as $test) { if ($lineCss === 'covered-by-large-tests' && $testData[$test]['size'] === 'medium') { $lineCss = 'covered-by-medium-tests'; } elseif ($testData[$test]['size'] === 'small') { $lineCss = 'covered-by-small-tests'; } $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); } $popoverContent .= '
'; $trClass = $lineCss . ' popin'; } } $popover = ''; if (!empty($popoverTitle)) { $popover = sprintf( ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', $popoverTitle, htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags) ); } $lines .= $this->renderLine($singleLineTemplate, $i, $line, $trClass, $popover); $i++; } $linesTemplate->setVar(['lines' => $lines]); return $linesTemplate->render(); } private function renderSourceWithBranchCoverage(FileNode $node): string { $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); $functionCoverageData = $node->functionCoverageData(); $testData = $node->testData(); $codeLines = $this->loadFile($node->pathAsString()); $lineData = []; /** @var int $line */ foreach (array_keys($codeLines) as $line) { $lineData[$line + 1] = [ 'includedInBranches' => 0, 'includedInHitBranches' => 0, 'tests' => [], ]; } foreach ($functionCoverageData as $method) { foreach ($method['branches'] as $branch) { foreach (range($branch['line_start'], $branch['line_end']) as $line) { if (!isset($lineData[$line])) { // blank line at end of file is sometimes included here continue; } $lineData[$line]['includedInBranches']++; if ($branch['hit']) { $lineData[$line]['includedInHitBranches']++; $lineData[$line]['tests'] = array_unique(array_merge($lineData[$line]['tests'], $branch['hit'])); } } } } $lines = ''; $i = 1; /** @var string $line */ foreach ($codeLines as $line) { $trClass = ''; $popover = ''; if ($lineData[$i]['includedInBranches'] > 0) { $lineCss = 'success'; if ($lineData[$i]['includedInHitBranches'] === 0) { $lineCss = 'danger'; } elseif ($lineData[$i]['includedInHitBranches'] !== $lineData[$i]['includedInBranches']) { $lineCss = 'warning'; } $popoverContent = '
    '; if (count($lineData[$i]['tests']) === 1) { $popoverTitle = '1 test covers line ' . $i; } else { $popoverTitle = count($lineData[$i]['tests']) . ' tests cover line ' . $i; } $popoverTitle .= '. These are covering ' . $lineData[$i]['includedInHitBranches'] . ' out of the ' . $lineData[$i]['includedInBranches'] . ' code branches.'; foreach ($lineData[$i]['tests'] as $test) { $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); } $popoverContent .= '
'; $trClass = $lineCss . ' popin'; $popover = sprintf( ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', $popoverTitle, htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags) ); } $lines .= $this->renderLine($singleLineTemplate, $i, $line, $trClass, $popover); $i++; } $linesTemplate->setVar(['lines' => $lines]); return $linesTemplate->render(); } private function renderSourceWithPathCoverage(FileNode $node): string { $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); $functionCoverageData = $node->functionCoverageData(); $testData = $node->testData(); $codeLines = $this->loadFile($node->pathAsString()); $lineData = []; /** @var int $line */ foreach (array_keys($codeLines) as $line) { $lineData[$line + 1] = [ 'includedInPaths' => [], 'includedInHitPaths' => [], 'tests' => [], ]; } foreach ($functionCoverageData as $method) { foreach ($method['paths'] as $pathId => $path) { foreach ($path['path'] as $branchTaken) { foreach (range($method['branches'][$branchTaken]['line_start'], $method['branches'][$branchTaken]['line_end']) as $line) { if (!isset($lineData[$line])) { continue; } $lineData[$line]['includedInPaths'][] = $pathId; if ($path['hit']) { $lineData[$line]['includedInHitPaths'][] = $pathId; $lineData[$line]['tests'] = array_unique(array_merge($lineData[$line]['tests'], $path['hit'])); } } } } } $lines = ''; $i = 1; /** @var string $line */ foreach ($codeLines as $line) { $trClass = ''; $popover = ''; $includedInPathsCount = count(array_unique($lineData[$i]['includedInPaths'])); $includedInHitPathsCount = count(array_unique($lineData[$i]['includedInHitPaths'])); if ($includedInPathsCount > 0) { $lineCss = 'success'; if ($includedInHitPathsCount === 0) { $lineCss = 'danger'; } elseif ($includedInHitPathsCount !== $includedInPathsCount) { $lineCss = 'warning'; } $popoverContent = '
    '; if (count($lineData[$i]['tests']) === 1) { $popoverTitle = '1 test covers line ' . $i; } else { $popoverTitle = count($lineData[$i]['tests']) . ' tests cover line ' . $i; } $popoverTitle .= '. These are covering ' . $includedInHitPathsCount . ' out of the ' . $includedInPathsCount . ' code paths.'; foreach ($lineData[$i]['tests'] as $test) { $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); } $popoverContent .= '
'; $trClass = $lineCss . ' popin'; $popover = sprintf( ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', $popoverTitle, htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags) ); } $lines .= $this->renderLine($singleLineTemplate, $i, $line, $trClass, $popover); $i++; } $linesTemplate->setVar(['lines' => $lines]); return $linesTemplate->render(); } private function renderBranchStructure(FileNode $node): string { $branchesTemplate = new Template($this->templatePath . 'branches.html.dist', '{{', '}}'); $coverageData = $node->functionCoverageData(); $testData = $node->testData(); $codeLines = $this->loadFile($node->pathAsString()); $branches = ''; ksort($coverageData); foreach ($coverageData as $methodName => $methodData) { if (!$methodData['branches']) { continue; } $branchStructure = ''; foreach ($methodData['branches'] as $branch) { $branchStructure .= $this->renderBranchLines($branch, $codeLines, $testData); } if ($branchStructure !== '') { // don't show empty branches $branches .= '
' . $this->abbreviateMethodName($methodName) . '
' . "\n"; $branches .= $branchStructure; } } $branchesTemplate->setVar(['branches' => $branches]); return $branchesTemplate->render(); } private function renderBranchLines(array $branch, array $codeLines, array $testData): string { $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); $lines = ''; $branchLines = range($branch['line_start'], $branch['line_end']); sort($branchLines); // sometimes end_line < start_line /** @var int $line */ foreach ($branchLines as $line) { if (!isset($codeLines[$line])) { // blank line at end of file is sometimes included here continue; } $popoverContent = ''; $popoverTitle = ''; $numTests = count($branch['hit']); if ($numTests === 0) { $trClass = 'danger'; } else { $lineCss = 'covered-by-large-tests'; $popoverContent = '
    '; if ($numTests > 1) { $popoverTitle = $numTests . ' tests cover this branch'; } else { $popoverTitle = '1 test covers this branch'; } foreach ($branch['hit'] as $test) { if ($lineCss === 'covered-by-large-tests' && $testData[$test]['size'] === 'medium') { $lineCss = 'covered-by-medium-tests'; } elseif ($testData[$test]['size'] === 'small') { $lineCss = 'covered-by-small-tests'; } $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); } $trClass = $lineCss . ' popin'; } $popover = ''; if (!empty($popoverTitle)) { $popover = sprintf( ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', $popoverTitle, htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags) ); } $lines .= $this->renderLine($singleLineTemplate, $line, $codeLines[$line - 1], $trClass, $popover); } if ($lines === '') { return ''; } $linesTemplate->setVar(['lines' => $lines]); return $linesTemplate->render(); } private function renderPathStructure(FileNode $node): string { $pathsTemplate = new Template($this->templatePath . 'paths.html.dist', '{{', '}}'); $coverageData = $node->functionCoverageData(); $testData = $node->testData(); $codeLines = $this->loadFile($node->pathAsString()); $paths = ''; ksort($coverageData); foreach ($coverageData as $methodName => $methodData) { if (!$methodData['paths']) { continue; } $pathStructure = ''; if (count($methodData['paths']) > 100) { $pathStructure .= '

    ' . count($methodData['paths']) . ' is too many paths to sensibly render, consider refactoring your code to bring this number down.

    '; continue; } foreach ($methodData['paths'] as $path) { $pathStructure .= $this->renderPathLines($path, $methodData['branches'], $codeLines, $testData); } if ($pathStructure !== '') { $paths .= '
    ' . $this->abbreviateMethodName($methodName) . '
    ' . "\n"; $paths .= $pathStructure; } } $pathsTemplate->setVar(['paths' => $paths]); return $pathsTemplate->render(); } private function renderPathLines(array $path, array $branches, array $codeLines, array $testData): string { $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); $lines = ''; $first = true; foreach ($path['path'] as $branchId) { if ($first) { $first = false; } else { $lines .= '  ' . "\n"; } $branchLines = range($branches[$branchId]['line_start'], $branches[$branchId]['line_end']); sort($branchLines); // sometimes end_line < start_line /** @var int $line */ foreach ($branchLines as $line) { if (!isset($codeLines[$line])) { // blank line at end of file is sometimes included here continue; } $popoverContent = ''; $popoverTitle = ''; $numTests = count($path['hit']); if ($numTests === 0) { $trClass = 'danger'; } else { $lineCss = 'covered-by-large-tests'; $popoverContent = '
      '; if ($numTests > 1) { $popoverTitle = $numTests . ' tests cover this path'; } else { $popoverTitle = '1 test covers this path'; } foreach ($path['hit'] as $test) { if ($lineCss === 'covered-by-large-tests' && $testData[$test]['size'] === 'medium') { $lineCss = 'covered-by-medium-tests'; } elseif ($testData[$test]['size'] === 'small') { $lineCss = 'covered-by-small-tests'; } $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); } $trClass = $lineCss . ' popin'; } $popover = ''; if (!empty($popoverTitle)) { $popover = sprintf( ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', $popoverTitle, htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags) ); } $lines .= $this->renderLine($singleLineTemplate, $line, $codeLines[$line - 1], $trClass, $popover); } } if ($lines === '') { return ''; } $linesTemplate->setVar(['lines' => $lines]); return $linesTemplate->render(); } private function renderLine(Template $template, int $lineNumber, string $lineContent, string $class, string $popover): string { $template->setVar( [ 'lineNumber' => $lineNumber, 'lineContent' => $lineContent, 'class' => $class, 'popover' => $popover, ] ); return $template->render(); } private function loadFile(string $file): array { if (isset(self::$formattedSourceCache[$file])) { return self::$formattedSourceCache[$file]; } $buffer = file_get_contents($file); $tokens = token_get_all($buffer); $result = ['']; $i = 0; $stringFlag = false; $fileEndsWithNewLine = substr($buffer, -1) === "\n"; unset($buffer); foreach ($tokens as $j => $token) { if (is_string($token)) { if ($token === '"' && $tokens[$j - 1] !== '\\') { $result[$i] .= sprintf( '%s', htmlspecialchars($token, $this->htmlSpecialCharsFlags) ); $stringFlag = !$stringFlag; } else { $result[$i] .= sprintf( '%s', htmlspecialchars($token, $this->htmlSpecialCharsFlags) ); } continue; } [$token, $value] = $token; $value = str_replace( ["\t", ' '], ['    ', ' '], htmlspecialchars($value, $this->htmlSpecialCharsFlags) ); if ($value === "\n") { $result[++$i] = ''; } else { $lines = explode("\n", $value); foreach ($lines as $jj => $line) { $line = trim($line); if ($line !== '') { if ($stringFlag) { $colour = 'string'; } else { $colour = 'default'; if ($this->isInlineHtml($token)) { $colour = 'html'; } elseif ($this->isComment($token)) { $colour = 'comment'; } elseif ($this->isKeyword($token)) { $colour = 'keyword'; } } $result[$i] .= sprintf( '%s', $colour, $line ); } if (isset($lines[$jj + 1])) { $result[++$i] = ''; } } } } if ($fileEndsWithNewLine) { unset($result[count($result) - 1]); } self::$formattedSourceCache[$file] = $result; return $result; } private function abbreviateClassName(string $className): string { $tmp = explode('\\', $className); if (count($tmp) > 1) { $className = sprintf( '%s', $className, array_pop($tmp) ); } return $className; } private function abbreviateMethodName(string $methodName): string { $parts = explode('->', $methodName); if (count($parts) === 2) { return $this->abbreviateClassName($parts[0]) . '->' . $parts[1]; } return $methodName; } private function createPopoverContentForTest(string $test, array $testData): string { $testCSS = ''; if ($testData['fromTestcase']) { switch ($testData['status']) { case BaseTestRunner::STATUS_PASSED: switch ($testData['size']) { case 'small': $testCSS = ' class="covered-by-small-tests"'; break; case 'medium': $testCSS = ' class="covered-by-medium-tests"'; break; default: $testCSS = ' class="covered-by-large-tests"'; break; } break; case BaseTestRunner::STATUS_SKIPPED: case BaseTestRunner::STATUS_INCOMPLETE: case BaseTestRunner::STATUS_RISKY: case BaseTestRunner::STATUS_WARNING: $testCSS = ' class="warning"'; break; case BaseTestRunner::STATUS_FAILURE: case BaseTestRunner::STATUS_ERROR: $testCSS = ' class="danger"'; break; } } return sprintf( '%s', $testCSS, htmlspecialchars($test, $this->htmlSpecialCharsFlags) ); } private function isComment(int $token): bool { return $token === T_COMMENT || $token === T_DOC_COMMENT; } private function isInlineHtml(int $token): bool { return $token === T_INLINE_HTML; } private function isKeyword(int $token): bool { return isset(self::keywordTokens()[$token]); } /** * @psalm-return array */ private static function keywordTokens(): array { if (self::$keywordTokens !== []) { return self::$keywordTokens; } self::$keywordTokens = [ T_ABSTRACT => true, T_ARRAY => true, T_AS => true, T_BREAK => true, T_CALLABLE => true, T_CASE => true, T_CATCH => true, T_CLASS => true, T_CLONE => true, T_CONST => true, T_CONTINUE => true, T_DECLARE => true, T_DEFAULT => true, T_DO => true, T_ECHO => true, T_ELSE => true, T_ELSEIF => true, T_EMPTY => true, T_ENDDECLARE => true, T_ENDFOR => true, T_ENDFOREACH => true, T_ENDIF => true, T_ENDSWITCH => true, T_ENDWHILE => true, T_EVAL => true, T_EXIT => true, T_EXTENDS => true, T_FINAL => true, T_FINALLY => true, T_FOR => true, T_FOREACH => true, T_FUNCTION => true, T_GLOBAL => true, T_GOTO => true, T_HALT_COMPILER => true, T_IF => true, T_IMPLEMENTS => true, T_INCLUDE => true, T_INCLUDE_ONCE => true, T_INSTANCEOF => true, T_INSTEADOF => true, T_INTERFACE => true, T_ISSET => true, T_LIST => true, T_NAMESPACE => true, T_NEW => true, T_PRINT => true, T_PRIVATE => true, T_PROTECTED => true, T_PUBLIC => true, T_REQUIRE => true, T_REQUIRE_ONCE => true, T_RETURN => true, T_STATIC => true, T_SWITCH => true, T_THROW => true, T_TRAIT => true, T_TRY => true, T_UNSET => true, T_USE => true, T_VAR => true, T_WHILE => true, T_YIELD => true, T_YIELD_FROM => true, ]; if (defined('T_FN')) { self::$keywordTokens[constant('T_FN')] = true; } if (defined('T_MATCH')) { self::$keywordTokens[constant('T_MATCH')] = true; } if (defined('T_ENUM')) { self::$keywordTokens[constant('T_ENUM')] = true; } if (defined('T_READONLY')) { self::$keywordTokens[constant('T_READONLY')] = true; } return self::$keywordTokens; } } PKuZJ|-|-Report/Text.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report; use const PHP_EOL; use function array_map; use function date; use function ksort; use function max; use function sprintf; use function str_pad; use function strlen; use SebastianBergmann\CodeCoverage\CodeCoverage; use SebastianBergmann\CodeCoverage\Node\File; use SebastianBergmann\CodeCoverage\Util\Percentage; final class Text { /** * @var string */ private const COLOR_GREEN = "\x1b[30;42m"; /** * @var string */ private const COLOR_YELLOW = "\x1b[30;43m"; /** * @var string */ private const COLOR_RED = "\x1b[37;41m"; /** * @var string */ private const COLOR_HEADER = "\x1b[1;37;40m"; /** * @var string */ private const COLOR_RESET = "\x1b[0m"; /** * @var string */ private const COLOR_EOL = "\x1b[2K"; /** * @var int */ private $lowUpperBound; /** * @var int */ private $highLowerBound; /** * @var bool */ private $showUncoveredFiles; /** * @var bool */ private $showOnlySummary; public function __construct(int $lowUpperBound = 50, int $highLowerBound = 90, bool $showUncoveredFiles = false, bool $showOnlySummary = false) { $this->lowUpperBound = $lowUpperBound; $this->highLowerBound = $highLowerBound; $this->showUncoveredFiles = $showUncoveredFiles; $this->showOnlySummary = $showOnlySummary; } public function process(CodeCoverage $coverage, bool $showColors = false): string { $hasBranchCoverage = !empty($coverage->getData(true)->functionCoverage()); $output = PHP_EOL . PHP_EOL; $report = $coverage->getReport(); $colors = [ 'header' => '', 'classes' => '', 'methods' => '', 'lines' => '', 'branches' => '', 'paths' => '', 'reset' => '', 'eol' => '', ]; if ($showColors) { $colors['classes'] = $this->coverageColor( $report->numberOfTestedClassesAndTraits(), $report->numberOfClassesAndTraits() ); $colors['methods'] = $this->coverageColor( $report->numberOfTestedMethods(), $report->numberOfMethods() ); $colors['lines'] = $this->coverageColor( $report->numberOfExecutedLines(), $report->numberOfExecutableLines() ); $colors['branches'] = $this->coverageColor( $report->numberOfExecutedBranches(), $report->numberOfExecutableBranches() ); $colors['paths'] = $this->coverageColor( $report->numberOfExecutedPaths(), $report->numberOfExecutablePaths() ); $colors['reset'] = self::COLOR_RESET; $colors['header'] = self::COLOR_HEADER; $colors['eol'] = self::COLOR_EOL; } $classes = sprintf( ' Classes: %6s (%d/%d)', Percentage::fromFractionAndTotal( $report->numberOfTestedClassesAndTraits(), $report->numberOfClassesAndTraits() )->asString(), $report->numberOfTestedClassesAndTraits(), $report->numberOfClassesAndTraits() ); $methods = sprintf( ' Methods: %6s (%d/%d)', Percentage::fromFractionAndTotal( $report->numberOfTestedMethods(), $report->numberOfMethods(), )->asString(), $report->numberOfTestedMethods(), $report->numberOfMethods() ); $paths = ''; $branches = ''; if ($hasBranchCoverage) { $paths = sprintf( ' Paths: %6s (%d/%d)', Percentage::fromFractionAndTotal( $report->numberOfExecutedPaths(), $report->numberOfExecutablePaths(), )->asString(), $report->numberOfExecutedPaths(), $report->numberOfExecutablePaths() ); $branches = sprintf( ' Branches: %6s (%d/%d)', Percentage::fromFractionAndTotal( $report->numberOfExecutedBranches(), $report->numberOfExecutableBranches(), )->asString(), $report->numberOfExecutedBranches(), $report->numberOfExecutableBranches() ); } $lines = sprintf( ' Lines: %6s (%d/%d)', Percentage::fromFractionAndTotal( $report->numberOfExecutedLines(), $report->numberOfExecutableLines(), )->asString(), $report->numberOfExecutedLines(), $report->numberOfExecutableLines() ); $padding = max(array_map('strlen', [$classes, $methods, $lines])); if ($this->showOnlySummary) { $title = 'Code Coverage Report Summary:'; $padding = max($padding, strlen($title)); $output .= $this->format($colors['header'], $padding, $title); } else { $date = date(' Y-m-d H:i:s'); $title = 'Code Coverage Report:'; $output .= $this->format($colors['header'], $padding, $title); $output .= $this->format($colors['header'], $padding, $date); $output .= $this->format($colors['header'], $padding, ''); $output .= $this->format($colors['header'], $padding, ' Summary:'); } $output .= $this->format($colors['classes'], $padding, $classes); $output .= $this->format($colors['methods'], $padding, $methods); if ($hasBranchCoverage) { $output .= $this->format($colors['paths'], $padding, $paths); $output .= $this->format($colors['branches'], $padding, $branches); } $output .= $this->format($colors['lines'], $padding, $lines); if ($this->showOnlySummary) { return $output . PHP_EOL; } $classCoverage = []; foreach ($report as $item) { if (!$item instanceof File) { continue; } $classes = $item->classesAndTraits(); foreach ($classes as $className => $class) { $classExecutableLines = 0; $classExecutedLines = 0; $classExecutableBranches = 0; $classExecutedBranches = 0; $classExecutablePaths = 0; $classExecutedPaths = 0; $coveredMethods = 0; $classMethods = 0; foreach ($class['methods'] as $method) { if ($method['executableLines'] == 0) { continue; } $classMethods++; $classExecutableLines += $method['executableLines']; $classExecutedLines += $method['executedLines']; $classExecutableBranches += $method['executableBranches']; $classExecutedBranches += $method['executedBranches']; $classExecutablePaths += $method['executablePaths']; $classExecutedPaths += $method['executedPaths']; if ($method['coverage'] == 100) { $coveredMethods++; } } $classCoverage[$className] = [ 'namespace' => $class['namespace'], 'className' => $className, 'methodsCovered' => $coveredMethods, 'methodCount' => $classMethods, 'statementsCovered' => $classExecutedLines, 'statementCount' => $classExecutableLines, 'branchesCovered' => $classExecutedBranches, 'branchesCount' => $classExecutableBranches, 'pathsCovered' => $classExecutedPaths, 'pathsCount' => $classExecutablePaths, ]; } } ksort($classCoverage); $methodColor = ''; $pathsColor = ''; $branchesColor = ''; $linesColor = ''; $resetColor = ''; foreach ($classCoverage as $fullQualifiedPath => $classInfo) { if ($this->showUncoveredFiles || $classInfo['statementsCovered'] != 0) { if ($showColors) { $methodColor = $this->coverageColor($classInfo['methodsCovered'], $classInfo['methodCount']); $pathsColor = $this->coverageColor($classInfo['pathsCovered'], $classInfo['pathsCount']); $branchesColor = $this->coverageColor($classInfo['branchesCovered'], $classInfo['branchesCount']); $linesColor = $this->coverageColor($classInfo['statementsCovered'], $classInfo['statementCount']); $resetColor = $colors['reset']; } $output .= PHP_EOL . $fullQualifiedPath . PHP_EOL . ' ' . $methodColor . 'Methods: ' . $this->printCoverageCounts($classInfo['methodsCovered'], $classInfo['methodCount'], 2) . $resetColor . ' '; if ($hasBranchCoverage) { $output .= ' ' . $pathsColor . 'Paths: ' . $this->printCoverageCounts($classInfo['pathsCovered'], $classInfo['pathsCount'], 3) . $resetColor . ' ' . ' ' . $branchesColor . 'Branches: ' . $this->printCoverageCounts($classInfo['branchesCovered'], $classInfo['branchesCount'], 3) . $resetColor . ' '; } $output .= ' ' . $linesColor . 'Lines: ' . $this->printCoverageCounts($classInfo['statementsCovered'], $classInfo['statementCount'], 3) . $resetColor; } } return $output . PHP_EOL; } private function coverageColor(int $numberOfCoveredElements, int $totalNumberOfElements): string { $coverage = Percentage::fromFractionAndTotal( $numberOfCoveredElements, $totalNumberOfElements ); if ($coverage->asFloat() >= $this->highLowerBound) { return self::COLOR_GREEN; } if ($coverage->asFloat() > $this->lowUpperBound) { return self::COLOR_YELLOW; } return self::COLOR_RED; } private function printCoverageCounts(int $numberOfCoveredElements, int $totalNumberOfElements, int $precision): string { $format = '%' . $precision . 's'; return Percentage::fromFractionAndTotal( $numberOfCoveredElements, $totalNumberOfElements )->asFixedWidthString() . ' (' . sprintf($format, $numberOfCoveredElements) . '/' . sprintf($format, $totalNumberOfElements) . ')'; } /** * @param false|string $string */ private function format(string $color, int $padding, $string): string { $reset = $color ? self::COLOR_RESET : ''; return $color . str_pad((string) $string, $padding) . $reset . PHP_EOL; } } PKuZu~yReport/Crap4j.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report; use function date; use function dirname; use function file_put_contents; use function htmlspecialchars; use function is_string; use function round; use DOMDocument; use SebastianBergmann\CodeCoverage\CodeCoverage; use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException; use SebastianBergmann\CodeCoverage\Node\File; use SebastianBergmann\CodeCoverage\Util\Filesystem; final class Crap4j { /** * @var int */ private $threshold; public function __construct(int $threshold = 30) { $this->threshold = $threshold; } /** * @throws WriteOperationFailedException */ public function process(CodeCoverage $coverage, ?string $target = null, ?string $name = null): string { $document = new DOMDocument('1.0', 'UTF-8'); $document->formatOutput = true; $root = $document->createElement('crap_result'); $document->appendChild($root); $project = $document->createElement('project', is_string($name) ? $name : ''); $root->appendChild($project); $root->appendChild($document->createElement('timestamp', date('Y-m-d H:i:s'))); $stats = $document->createElement('stats'); $methodsNode = $document->createElement('methods'); $report = $coverage->getReport(); unset($coverage); $fullMethodCount = 0; $fullCrapMethodCount = 0; $fullCrapLoad = 0; $fullCrap = 0; foreach ($report as $item) { $namespace = 'global'; if (!$item instanceof File) { continue; } $file = $document->createElement('file'); $file->setAttribute('name', $item->pathAsString()); $classes = $item->classesAndTraits(); foreach ($classes as $className => $class) { foreach ($class['methods'] as $methodName => $method) { $crapLoad = $this->crapLoad((float) $method['crap'], $method['ccn'], $method['coverage']); $fullCrap += $method['crap']; $fullCrapLoad += $crapLoad; $fullMethodCount++; if ($method['crap'] >= $this->threshold) { $fullCrapMethodCount++; } $methodNode = $document->createElement('method'); if (!empty($class['namespace'])) { $namespace = $class['namespace']; } $methodNode->appendChild($document->createElement('package', $namespace)); $methodNode->appendChild($document->createElement('className', $className)); $methodNode->appendChild($document->createElement('methodName', $methodName)); $methodNode->appendChild($document->createElement('methodSignature', htmlspecialchars($method['signature']))); $methodNode->appendChild($document->createElement('fullMethod', htmlspecialchars($method['signature']))); $methodNode->appendChild($document->createElement('crap', (string) $this->roundValue((float) $method['crap']))); $methodNode->appendChild($document->createElement('complexity', (string) $method['ccn'])); $methodNode->appendChild($document->createElement('coverage', (string) $this->roundValue($method['coverage']))); $methodNode->appendChild($document->createElement('crapLoad', (string) round($crapLoad))); $methodsNode->appendChild($methodNode); } } } $stats->appendChild($document->createElement('name', 'Method Crap Stats')); $stats->appendChild($document->createElement('methodCount', (string) $fullMethodCount)); $stats->appendChild($document->createElement('crapMethodCount', (string) $fullCrapMethodCount)); $stats->appendChild($document->createElement('crapLoad', (string) round($fullCrapLoad))); $stats->appendChild($document->createElement('totalCrap', (string) $fullCrap)); $crapMethodPercent = 0; if ($fullMethodCount > 0) { $crapMethodPercent = $this->roundValue((100 * $fullCrapMethodCount) / $fullMethodCount); } $stats->appendChild($document->createElement('crapMethodPercent', (string) $crapMethodPercent)); $root->appendChild($stats); $root->appendChild($methodsNode); $buffer = $document->saveXML(); if ($target !== null) { Filesystem::createDirectory(dirname($target)); if (@file_put_contents($target, $buffer) === false) { throw new WriteOperationFailedException($target); } } return $buffer; } private function crapLoad(float $crapValue, int $cyclomaticComplexity, float $coveragePercent): float { $crapLoad = 0; if ($crapValue >= $this->threshold) { $crapLoad += $cyclomaticComplexity * (1.0 - $coveragePercent / 100); $crapLoad += $cyclomaticComplexity / $this->threshold; } return $crapLoad; } private function roundValue(float $value): float { return round($value, 2); } } PKuZpt mg*g*Report/Clover.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report; use function count; use function dirname; use function file_put_contents; use function is_string; use function ksort; use function max; use function range; use function time; use DOMDocument; use SebastianBergmann\CodeCoverage\CodeCoverage; use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException; use SebastianBergmann\CodeCoverage\Node\File; use SebastianBergmann\CodeCoverage\Util\Filesystem; final class Clover { /** * @throws WriteOperationFailedException */ public function process(CodeCoverage $coverage, ?string $target = null, ?string $name = null): string { $time = (string) time(); $xmlDocument = new DOMDocument('1.0', 'UTF-8'); $xmlDocument->formatOutput = true; $xmlCoverage = $xmlDocument->createElement('coverage'); $xmlCoverage->setAttribute('generated', $time); $xmlDocument->appendChild($xmlCoverage); $xmlProject = $xmlDocument->createElement('project'); $xmlProject->setAttribute('timestamp', $time); if (is_string($name)) { $xmlProject->setAttribute('name', $name); } $xmlCoverage->appendChild($xmlProject); $packages = []; $report = $coverage->getReport(); foreach ($report as $item) { if (!$item instanceof File) { continue; } /* @var File $item */ $xmlFile = $xmlDocument->createElement('file'); $xmlFile->setAttribute('name', $item->pathAsString()); $classes = $item->classesAndTraits(); $coverageData = $item->lineCoverageData(); $lines = []; $namespace = 'global'; foreach ($classes as $className => $class) { $classStatements = 0; $coveredClassStatements = 0; $coveredMethods = 0; $classMethods = 0; foreach ($class['methods'] as $methodName => $method) { if ($method['executableLines'] == 0) { continue; } $classMethods++; $classStatements += $method['executableLines']; $coveredClassStatements += $method['executedLines']; if ($method['coverage'] == 100) { $coveredMethods++; } $methodCount = 0; foreach (range($method['startLine'], $method['endLine']) as $line) { if (isset($coverageData[$line]) && ($coverageData[$line] !== null)) { $methodCount = max($methodCount, count($coverageData[$line])); } } $lines[$method['startLine']] = [ 'ccn' => $method['ccn'], 'count' => $methodCount, 'crap' => $method['crap'], 'type' => 'method', 'visibility' => $method['visibility'], 'name' => $methodName, ]; } if (!empty($class['package']['namespace'])) { $namespace = $class['package']['namespace']; } $xmlClass = $xmlDocument->createElement('class'); $xmlClass->setAttribute('name', $className); $xmlClass->setAttribute('namespace', $namespace); if (!empty($class['package']['fullPackage'])) { $xmlClass->setAttribute( 'fullPackage', $class['package']['fullPackage'] ); } if (!empty($class['package']['category'])) { $xmlClass->setAttribute( 'category', $class['package']['category'] ); } if (!empty($class['package']['package'])) { $xmlClass->setAttribute( 'package', $class['package']['package'] ); } if (!empty($class['package']['subpackage'])) { $xmlClass->setAttribute( 'subpackage', $class['package']['subpackage'] ); } $xmlFile->appendChild($xmlClass); $xmlMetrics = $xmlDocument->createElement('metrics'); $xmlMetrics->setAttribute('complexity', (string) $class['ccn']); $xmlMetrics->setAttribute('methods', (string) $classMethods); $xmlMetrics->setAttribute('coveredmethods', (string) $coveredMethods); $xmlMetrics->setAttribute('conditionals', (string) $class['executableBranches']); $xmlMetrics->setAttribute('coveredconditionals', (string) $class['executedBranches']); $xmlMetrics->setAttribute('statements', (string) $classStatements); $xmlMetrics->setAttribute('coveredstatements', (string) $coveredClassStatements); $xmlMetrics->setAttribute('elements', (string) ($classMethods + $classStatements + $class['executableBranches'])); $xmlMetrics->setAttribute('coveredelements', (string) ($coveredMethods + $coveredClassStatements + $class['executedBranches'])); $xmlClass->appendChild($xmlMetrics); } foreach ($coverageData as $line => $data) { if ($data === null || isset($lines[$line])) { continue; } $lines[$line] = [ 'count' => count($data), 'type' => 'stmt', ]; } ksort($lines); foreach ($lines as $line => $data) { $xmlLine = $xmlDocument->createElement('line'); $xmlLine->setAttribute('num', (string) $line); $xmlLine->setAttribute('type', $data['type']); if (isset($data['name'])) { $xmlLine->setAttribute('name', $data['name']); } if (isset($data['visibility'])) { $xmlLine->setAttribute('visibility', $data['visibility']); } if (isset($data['ccn'])) { $xmlLine->setAttribute('complexity', (string) $data['ccn']); } if (isset($data['crap'])) { $xmlLine->setAttribute('crap', (string) $data['crap']); } $xmlLine->setAttribute('count', (string) $data['count']); $xmlFile->appendChild($xmlLine); } $linesOfCode = $item->linesOfCode(); $xmlMetrics = $xmlDocument->createElement('metrics'); $xmlMetrics->setAttribute('loc', (string) $linesOfCode['linesOfCode']); $xmlMetrics->setAttribute('ncloc', (string) $linesOfCode['nonCommentLinesOfCode']); $xmlMetrics->setAttribute('classes', (string) $item->numberOfClassesAndTraits()); $xmlMetrics->setAttribute('methods', (string) $item->numberOfMethods()); $xmlMetrics->setAttribute('coveredmethods', (string) $item->numberOfTestedMethods()); $xmlMetrics->setAttribute('conditionals', (string) $item->numberOfExecutableBranches()); $xmlMetrics->setAttribute('coveredconditionals', (string) $item->numberOfExecutedBranches()); $xmlMetrics->setAttribute('statements', (string) $item->numberOfExecutableLines()); $xmlMetrics->setAttribute('coveredstatements', (string) $item->numberOfExecutedLines()); $xmlMetrics->setAttribute('elements', (string) ($item->numberOfMethods() + $item->numberOfExecutableLines() + $item->numberOfExecutableBranches())); $xmlMetrics->setAttribute('coveredelements', (string) ($item->numberOfTestedMethods() + $item->numberOfExecutedLines() + $item->numberOfExecutedBranches())); $xmlFile->appendChild($xmlMetrics); if ($namespace === 'global') { $xmlProject->appendChild($xmlFile); } else { if (!isset($packages[$namespace])) { $packages[$namespace] = $xmlDocument->createElement( 'package' ); $packages[$namespace]->setAttribute('name', $namespace); $xmlProject->appendChild($packages[$namespace]); } $packages[$namespace]->appendChild($xmlFile); } } $linesOfCode = $report->linesOfCode(); $xmlMetrics = $xmlDocument->createElement('metrics'); $xmlMetrics->setAttribute('files', (string) count($report)); $xmlMetrics->setAttribute('loc', (string) $linesOfCode['linesOfCode']); $xmlMetrics->setAttribute('ncloc', (string) $linesOfCode['nonCommentLinesOfCode']); $xmlMetrics->setAttribute('classes', (string) $report->numberOfClassesAndTraits()); $xmlMetrics->setAttribute('methods', (string) $report->numberOfMethods()); $xmlMetrics->setAttribute('coveredmethods', (string) $report->numberOfTestedMethods()); $xmlMetrics->setAttribute('conditionals', (string) $report->numberOfExecutableBranches()); $xmlMetrics->setAttribute('coveredconditionals', (string) $report->numberOfExecutedBranches()); $xmlMetrics->setAttribute('statements', (string) $report->numberOfExecutableLines()); $xmlMetrics->setAttribute('coveredstatements', (string) $report->numberOfExecutedLines()); $xmlMetrics->setAttribute('elements', (string) ($report->numberOfMethods() + $report->numberOfExecutableLines() + $report->numberOfExecutableBranches())); $xmlMetrics->setAttribute('coveredelements', (string) ($report->numberOfTestedMethods() + $report->numberOfExecutedLines() + $report->numberOfExecutedBranches())); $xmlProject->appendChild($xmlMetrics); $buffer = $xmlDocument->saveXML(); if ($target !== null) { Filesystem::createDirectory(dirname($target)); if (@file_put_contents($target, $buffer) === false) { throw new WriteOperationFailedException($target); } } return $buffer; } } PKuZBOttReport/PHP.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report; use function dirname; use function file_put_contents; use function serialize; use SebastianBergmann\CodeCoverage\CodeCoverage; use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException; use SebastianBergmann\CodeCoverage\Util\Filesystem; final class PHP { public function process(CodeCoverage $coverage, ?string $target = null): string { $buffer = " * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\StaticAnalysis; use function array_merge; use function array_unique; use function assert; use function file_get_contents; use function is_array; use function max; use function range; use function sort; use function sprintf; use function substr_count; use function token_get_all; use function trim; use PhpParser\Error; use PhpParser\Lexer; use PhpParser\NodeTraverser; use PhpParser\NodeVisitor\NameResolver; use PhpParser\NodeVisitor\ParentConnectingVisitor; use PhpParser\ParserFactory; use SebastianBergmann\CodeCoverage\ParserException; use SebastianBergmann\LinesOfCode\LineCountingVisitor; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class ParsingFileAnalyser implements FileAnalyser { /** * @var array */ private $classes = []; /** * @var array */ private $traits = []; /** * @var array */ private $functions = []; /** * @var array */ private $linesOfCode = []; /** * @var array */ private $ignoredLines = []; /** * @var array */ private $executableLines = []; /** * @var bool */ private $useAnnotationsForIgnoringCode; /** * @var bool */ private $ignoreDeprecatedCode; public function __construct(bool $useAnnotationsForIgnoringCode, bool $ignoreDeprecatedCode) { $this->useAnnotationsForIgnoringCode = $useAnnotationsForIgnoringCode; $this->ignoreDeprecatedCode = $ignoreDeprecatedCode; } public function classesIn(string $filename): array { $this->analyse($filename); return $this->classes[$filename]; } public function traitsIn(string $filename): array { $this->analyse($filename); return $this->traits[$filename]; } public function functionsIn(string $filename): array { $this->analyse($filename); return $this->functions[$filename]; } /** * @psalm-return array{linesOfCode: int, commentLinesOfCode: int, nonCommentLinesOfCode: int} */ public function linesOfCodeFor(string $filename): array { $this->analyse($filename); return $this->linesOfCode[$filename]; } public function executableLinesIn(string $filename): array { $this->analyse($filename); return $this->executableLines[$filename]; } public function ignoredLinesFor(string $filename): array { $this->analyse($filename); return $this->ignoredLines[$filename]; } /** * @throws ParserException */ private function analyse(string $filename): void { if (isset($this->classes[$filename])) { return; } $source = file_get_contents($filename); $linesOfCode = max(substr_count($source, "\n") + 1, substr_count($source, "\r") + 1); if ($linesOfCode === 0 && !empty($source)) { $linesOfCode = 1; } $parser = (new ParserFactory)->create( ParserFactory::PREFER_PHP7, new Lexer ); try { $nodes = $parser->parse($source); assert($nodes !== null); $traverser = new NodeTraverser; $codeUnitFindingVisitor = new CodeUnitFindingVisitor; $lineCountingVisitor = new LineCountingVisitor($linesOfCode); $ignoredLinesFindingVisitor = new IgnoredLinesFindingVisitor($this->useAnnotationsForIgnoringCode, $this->ignoreDeprecatedCode); $executableLinesFindingVisitor = new ExecutableLinesFindingVisitor($source); $traverser->addVisitor(new NameResolver); $traverser->addVisitor(new ParentConnectingVisitor); $traverser->addVisitor($codeUnitFindingVisitor); $traverser->addVisitor($lineCountingVisitor); $traverser->addVisitor($ignoredLinesFindingVisitor); $traverser->addVisitor($executableLinesFindingVisitor); /* @noinspection UnusedFunctionResultInspection */ $traverser->traverse($nodes); // @codeCoverageIgnoreStart } catch (Error $error) { throw new ParserException( sprintf( 'Cannot parse %s: %s', $filename, $error->getMessage() ), $error->getCode(), $error ); } // @codeCoverageIgnoreEnd $this->classes[$filename] = $codeUnitFindingVisitor->classes(); $this->traits[$filename] = $codeUnitFindingVisitor->traits(); $this->functions[$filename] = $codeUnitFindingVisitor->functions(); $this->executableLines[$filename] = $executableLinesFindingVisitor->executableLinesGroupedByBranch(); $this->ignoredLines[$filename] = []; $this->findLinesIgnoredByLineBasedAnnotations($filename, $source, $this->useAnnotationsForIgnoringCode); $this->ignoredLines[$filename] = array_unique( array_merge( $this->ignoredLines[$filename], $ignoredLinesFindingVisitor->ignoredLines() ) ); sort($this->ignoredLines[$filename]); $result = $lineCountingVisitor->result(); $this->linesOfCode[$filename] = [ 'linesOfCode' => $result->linesOfCode(), 'commentLinesOfCode' => $result->commentLinesOfCode(), 'nonCommentLinesOfCode' => $result->nonCommentLinesOfCode(), ]; } private function findLinesIgnoredByLineBasedAnnotations(string $filename, string $source, bool $useAnnotationsForIgnoringCode): void { if (!$useAnnotationsForIgnoringCode) { return; } $start = false; foreach (token_get_all($source) as $token) { if (!is_array($token) || !(T_COMMENT === $token[0] || T_DOC_COMMENT === $token[0])) { continue; } $comment = trim($token[1]); if ($comment === '// @codeCoverageIgnore' || $comment === '//@codeCoverageIgnore') { $this->ignoredLines[$filename][] = $token[2]; continue; } if ($comment === '// @codeCoverageIgnoreStart' || $comment === '//@codeCoverageIgnoreStart') { $start = $token[2]; continue; } if ($comment === '// @codeCoverageIgnoreEnd' || $comment === '//@codeCoverageIgnoreEnd') { if (false === $start) { $start = $token[2]; } $this->ignoredLines[$filename] = array_merge( $this->ignoredLines[$filename], range($start, $token[2]) ); } } } } PKuZLhhStaticAnalysis/CacheWarmer.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\StaticAnalysis; use SebastianBergmann\CodeCoverage\Filter; final class CacheWarmer { public function warmCache(string $cacheDirectory, bool $useAnnotationsForIgnoringCode, bool $ignoreDeprecatedCode, Filter $filter): void { $analyser = new CachingFileAnalyser( $cacheDirectory, new ParsingFileAnalyser( $useAnnotationsForIgnoringCode, $ignoreDeprecatedCode ) ); foreach ($filter->files() as $file) { $analyser->process($file); } } } PKuZ7 -StaticAnalysis/IgnoredLinesFindingVisitor.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\StaticAnalysis; use function array_merge; use function assert; use function range; use function strpos; use PhpParser\Node; use PhpParser\Node\Attribute; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Function_; use PhpParser\Node\Stmt\Interface_; use PhpParser\Node\Stmt\Trait_; use PhpParser\NodeVisitorAbstract; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class IgnoredLinesFindingVisitor extends NodeVisitorAbstract { /** * @psalm-var list */ private $ignoredLines = []; /** * @var bool */ private $useAnnotationsForIgnoringCode; /** * @var bool */ private $ignoreDeprecated; public function __construct(bool $useAnnotationsForIgnoringCode, bool $ignoreDeprecated) { $this->useAnnotationsForIgnoringCode = $useAnnotationsForIgnoringCode; $this->ignoreDeprecated = $ignoreDeprecated; } public function enterNode(Node $node): void { if (!$node instanceof Class_ && !$node instanceof Trait_ && !$node instanceof Interface_ && !$node instanceof ClassMethod && !$node instanceof Function_ && !$node instanceof Attribute) { return; } if ($node instanceof Class_ && $node->isAnonymous()) { return; } if ($node instanceof Class_ || $node instanceof Trait_ || $node instanceof Interface_ || $node instanceof Attribute) { $this->ignoredLines[] = $node->getStartLine(); assert($node->name !== null); // Workaround for https://github.com/nikic/PHP-Parser/issues/886 $this->ignoredLines[] = $node->name->getStartLine(); } if (!$this->useAnnotationsForIgnoringCode) { return; } if ($node instanceof Interface_) { return; } $this->processDocComment($node); } /** * @psalm-return list */ public function ignoredLines(): array { return $this->ignoredLines; } private function processDocComment(Node $node): void { $docComment = $node->getDocComment(); if ($docComment === null) { return; } if (strpos($docComment->getText(), '@codeCoverageIgnore') !== false) { $this->ignoredLines = array_merge( $this->ignoredLines, range($node->getStartLine(), $node->getEndLine()) ); } if ($this->ignoreDeprecated && strpos($docComment->getText(), '@deprecated') !== false) { $this->ignoredLines = array_merge( $this->ignoredLines, range($node->getStartLine(), $node->getEndLine()) ); } } } PKuZ²StaticAnalysis/FileAnalyser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\StaticAnalysis; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ interface FileAnalyser { public function classesIn(string $filename): array; public function traitsIn(string $filename): array; public function functionsIn(string $filename): array; /** * @psalm-return array{linesOfCode: int, commentLinesOfCode: int, nonCommentLinesOfCode: int} */ public function linesOfCodeFor(string $filename): array; public function executableLinesIn(string $filename): array; public function ignoredLinesFor(string $filename): array; } PKuZ-v>&StaticAnalysis/CachingFileAnalyser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\StaticAnalysis; use function file_get_contents; use function file_put_contents; use function implode; use function is_file; use function md5; use function serialize; use function unserialize; use SebastianBergmann\CodeCoverage\Util\Filesystem; use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class CachingFileAnalyser implements FileAnalyser { /** * @var ?string */ private static $cacheVersion; /** * @var FileAnalyser */ private $analyser; /** * @var array */ private $cache = []; /** * @var string */ private $directory; public function __construct(string $directory, FileAnalyser $analyser) { Filesystem::createDirectory($directory); $this->analyser = $analyser; $this->directory = $directory; } public function classesIn(string $filename): array { if (!isset($this->cache[$filename])) { $this->process($filename); } return $this->cache[$filename]['classesIn']; } public function traitsIn(string $filename): array { if (!isset($this->cache[$filename])) { $this->process($filename); } return $this->cache[$filename]['traitsIn']; } public function functionsIn(string $filename): array { if (!isset($this->cache[$filename])) { $this->process($filename); } return $this->cache[$filename]['functionsIn']; } /** * @psalm-return array{linesOfCode: int, commentLinesOfCode: int, nonCommentLinesOfCode: int} */ public function linesOfCodeFor(string $filename): array { if (!isset($this->cache[$filename])) { $this->process($filename); } return $this->cache[$filename]['linesOfCodeFor']; } public function executableLinesIn(string $filename): array { if (!isset($this->cache[$filename])) { $this->process($filename); } return $this->cache[$filename]['executableLinesIn']; } public function ignoredLinesFor(string $filename): array { if (!isset($this->cache[$filename])) { $this->process($filename); } return $this->cache[$filename]['ignoredLinesFor']; } public function process(string $filename): void { $cache = $this->read($filename); if ($cache !== false) { $this->cache[$filename] = $cache; return; } $this->cache[$filename] = [ 'classesIn' => $this->analyser->classesIn($filename), 'traitsIn' => $this->analyser->traitsIn($filename), 'functionsIn' => $this->analyser->functionsIn($filename), 'linesOfCodeFor' => $this->analyser->linesOfCodeFor($filename), 'ignoredLinesFor' => $this->analyser->ignoredLinesFor($filename), 'executableLinesIn' => $this->analyser->executableLinesIn($filename), ]; $this->write($filename, $this->cache[$filename]); } /** * @return mixed */ private function read(string $filename) { $cacheFile = $this->cacheFile($filename); if (!is_file($cacheFile)) { return false; } return unserialize( file_get_contents($cacheFile), ['allowed_classes' => false] ); } /** * @param mixed $data */ private function write(string $filename, $data): void { file_put_contents( $this->cacheFile($filename), serialize($data) ); } private function cacheFile(string $filename): string { return $this->directory . DIRECTORY_SEPARATOR . md5($filename . "\0" . file_get_contents($filename) . "\0" . self::cacheVersion()); } private static function cacheVersion(): string { if (self::$cacheVersion !== null) { return self::$cacheVersion; } $buffer = []; foreach ((new FileIteratorFacade)->getFilesAsArray(__DIR__, '.php') as $file) { $buffer[] = $file; $buffer[] = file_get_contents($file); } self::$cacheVersion = md5(implode("\0", $buffer)); return self::$cacheVersion; } } PKuZ͘j]+]+0StaticAnalysis/ExecutableLinesFindingVisitor.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\StaticAnalysis; use function array_diff_key; use function assert; use function count; use function current; use function end; use function explode; use function max; use function preg_match; use function preg_quote; use function range; use function reset; use function sprintf; use PhpParser\Node; use PhpParser\NodeVisitorAbstract; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class ExecutableLinesFindingVisitor extends NodeVisitorAbstract { /** * @var int */ private $nextBranch = 0; /** * @var string */ private $source; /** * @var array */ private $executableLinesGroupedByBranch = []; /** * @var array */ private $unsets = []; /** * @var array */ private $commentsToCheckForUnset = []; public function __construct(string $source) { $this->source = $source; } public function enterNode(Node $node): void { foreach ($node->getComments() as $comment) { $commentLine = $comment->getStartLine(); if (!isset($this->executableLinesGroupedByBranch[$commentLine])) { continue; } foreach (explode("\n", $comment->getText()) as $text) { $this->commentsToCheckForUnset[$commentLine] = $text; $commentLine++; } } if ($node instanceof Node\Scalar\String_ || $node instanceof Node\Scalar\EncapsedStringPart) { $startLine = $node->getStartLine() + 1; $endLine = $node->getEndLine() - 1; if ($startLine <= $endLine) { foreach (range($startLine, $endLine) as $line) { unset($this->executableLinesGroupedByBranch[$line]); } } return; } if ($node instanceof Node\Stmt\Interface_) { foreach (range($node->getStartLine(), $node->getEndLine()) as $line) { $this->unsets[$line] = true; } return; } if ($node instanceof Node\Stmt\Declare_ || $node instanceof Node\Stmt\DeclareDeclare || $node instanceof Node\Stmt\Else_ || $node instanceof Node\Stmt\EnumCase || $node instanceof Node\Stmt\Finally_ || $node instanceof Node\Stmt\Label || $node instanceof Node\Stmt\Namespace_ || $node instanceof Node\Stmt\Nop || $node instanceof Node\Stmt\Switch_ || $node instanceof Node\Stmt\TryCatch || $node instanceof Node\Stmt\Use_ || $node instanceof Node\Stmt\UseUse || $node instanceof Node\Expr\ConstFetch || $node instanceof Node\Expr\Match_ || $node instanceof Node\Expr\Variable || $node instanceof Node\ComplexType || $node instanceof Node\Const_ || $node instanceof Node\Identifier || $node instanceof Node\Name || $node instanceof Node\Param || $node instanceof Node\Scalar) { return; } if ($node instanceof Node\Stmt\Throw_) { $this->setLineBranch($node->expr->getEndLine(), $node->expr->getEndLine(), ++$this->nextBranch); return; } if ($node instanceof Node\Stmt\Enum_ || $node instanceof Node\Stmt\Function_ || $node instanceof Node\Stmt\Class_ || $node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Expr\Closure || $node instanceof Node\Stmt\Trait_) { $isConcreteClassLike = $node instanceof Node\Stmt\Enum_ || $node instanceof Node\Stmt\Class_ || $node instanceof Node\Stmt\Trait_; if (null !== $node->stmts) { foreach ($node->stmts as $stmt) { if ($stmt instanceof Node\Stmt\Nop) { continue; } foreach (range($stmt->getStartLine(), $stmt->getEndLine()) as $line) { unset($this->executableLinesGroupedByBranch[$line]); if ( $isConcreteClassLike && !$stmt instanceof Node\Stmt\ClassMethod ) { $this->unsets[$line] = true; } } } } if ($isConcreteClassLike) { return; } $hasEmptyBody = [] === $node->stmts || null === $node->stmts || ( 1 === count($node->stmts) && $node->stmts[0] instanceof Node\Stmt\Nop ); if ($hasEmptyBody) { if ($node->getEndLine() === $node->getStartLine()) { return; } $this->setLineBranch($node->getEndLine(), $node->getEndLine(), ++$this->nextBranch); return; } return; } if ($node instanceof Node\Expr\ArrowFunction) { $startLine = max( $node->getStartLine() + 1, $node->expr->getStartLine() ); $endLine = $node->expr->getEndLine(); if ($endLine < $startLine) { return; } $this->setLineBranch($startLine, $endLine, ++$this->nextBranch); return; } if ($node instanceof Node\Expr\Ternary) { if (null !== $node->if && $node->getStartLine() !== $node->if->getEndLine()) { $this->setLineBranch($node->if->getStartLine(), $node->if->getEndLine(), ++$this->nextBranch); } if ($node->getStartLine() !== $node->else->getEndLine()) { $this->setLineBranch($node->else->getStartLine(), $node->else->getEndLine(), ++$this->nextBranch); } return; } if ($node instanceof Node\Expr\BinaryOp\Coalesce) { if ($node->getStartLine() !== $node->getEndLine()) { $this->setLineBranch($node->getEndLine(), $node->getEndLine(), ++$this->nextBranch); } return; } if ($node instanceof Node\Stmt\If_ || $node instanceof Node\Stmt\ElseIf_ || $node instanceof Node\Stmt\Case_) { if (null === $node->cond) { return; } $this->setLineBranch( $node->cond->getStartLine(), $node->cond->getStartLine(), ++$this->nextBranch ); return; } if ($node instanceof Node\Stmt\For_) { $startLine = null; $endLine = null; if ([] !== $node->init) { $startLine = $node->init[0]->getStartLine(); end($node->init); $endLine = current($node->init)->getEndLine(); reset($node->init); } if ([] !== $node->cond) { if (null === $startLine) { $startLine = $node->cond[0]->getStartLine(); } end($node->cond); $endLine = current($node->cond)->getEndLine(); reset($node->cond); } if ([] !== $node->loop) { if (null === $startLine) { $startLine = $node->loop[0]->getStartLine(); } end($node->loop); $endLine = current($node->loop)->getEndLine(); reset($node->loop); } if (null === $startLine || null === $endLine) { return; } $this->setLineBranch( $startLine, $endLine, ++$this->nextBranch ); return; } if ($node instanceof Node\Stmt\Foreach_) { $this->setLineBranch( $node->expr->getStartLine(), $node->valueVar->getEndLine(), ++$this->nextBranch ); return; } if ($node instanceof Node\Stmt\While_ || $node instanceof Node\Stmt\Do_) { $this->setLineBranch( $node->cond->getStartLine(), $node->cond->getEndLine(), ++$this->nextBranch ); return; } if ($node instanceof Node\Stmt\Catch_) { assert([] !== $node->types); $startLine = $node->types[0]->getStartLine(); end($node->types); $endLine = current($node->types)->getEndLine(); $this->setLineBranch( $startLine, $endLine, ++$this->nextBranch ); return; } if ($node instanceof Node\Expr\CallLike) { if (isset($this->executableLinesGroupedByBranch[$node->getStartLine()])) { $branch = $this->executableLinesGroupedByBranch[$node->getStartLine()]; } else { $branch = ++$this->nextBranch; } $this->setLineBranch($node->getStartLine(), $node->getEndLine(), $branch); return; } if (isset($this->executableLinesGroupedByBranch[$node->getStartLine()])) { return; } $this->setLineBranch($node->getStartLine(), $node->getEndLine(), ++$this->nextBranch); } public function afterTraverse(array $nodes): void { $lines = explode("\n", $this->source); foreach ($lines as $lineNumber => $line) { $lineNumber++; if (1 === preg_match('/^\s*$/', $line) || ( isset($this->commentsToCheckForUnset[$lineNumber]) && 1 === preg_match(sprintf('/^\s*%s\s*$/', preg_quote($this->commentsToCheckForUnset[$lineNumber], '/')), $line) )) { unset($this->executableLinesGroupedByBranch[$lineNumber]); } } $this->executableLinesGroupedByBranch = array_diff_key( $this->executableLinesGroupedByBranch, $this->unsets ); } public function executableLinesGroupedByBranch(): array { return $this->executableLinesGroupedByBranch; } private function setLineBranch(int $start, int $end, int $branch): void { foreach (range($start, $end) as $line) { $this->executableLinesGroupedByBranch[$line] = $branch; } } } PKuZ W*W*)StaticAnalysis/CodeUnitFindingVisitor.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\StaticAnalysis; use function assert; use function implode; use function rtrim; use function trim; use PhpParser\Node; use PhpParser\Node\ComplexType; use PhpParser\Node\Identifier; use PhpParser\Node\IntersectionType; use PhpParser\Node\Name; use PhpParser\Node\NullableType; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Enum_; use PhpParser\Node\Stmt\Function_; use PhpParser\Node\Stmt\Interface_; use PhpParser\Node\Stmt\Trait_; use PhpParser\Node\UnionType; use PhpParser\NodeAbstract; use PhpParser\NodeTraverser; use PhpParser\NodeVisitorAbstract; use SebastianBergmann\Complexity\CyclomaticComplexityCalculatingVisitor; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class CodeUnitFindingVisitor extends NodeVisitorAbstract { /** * @psalm-var array}> */ private $classes = []; /** * @psalm-var array}> */ private $traits = []; /** * @psalm-var array */ private $functions = []; public function enterNode(Node $node): void { if ($node instanceof Class_) { if ($node->isAnonymous()) { return; } $this->processClass($node); } if ($node instanceof Trait_) { $this->processTrait($node); } if (!$node instanceof ClassMethod && !$node instanceof Function_) { return; } if ($node instanceof ClassMethod) { $parentNode = $node->getAttribute('parent'); if ($parentNode instanceof Class_ && $parentNode->isAnonymous()) { return; } $this->processMethod($node); return; } $this->processFunction($node); } /** * @psalm-return array}> */ public function classes(): array { return $this->classes; } /** * @psalm-return array}> */ public function traits(): array { return $this->traits; } /** * @psalm-return array */ public function functions(): array { return $this->functions; } /** * @psalm-param ClassMethod|Function_ $node */ private function cyclomaticComplexity(Node $node): int { assert($node instanceof ClassMethod || $node instanceof Function_); $nodes = $node->getStmts(); if ($nodes === null) { return 0; } $traverser = new NodeTraverser; $cyclomaticComplexityCalculatingVisitor = new CyclomaticComplexityCalculatingVisitor; $traverser->addVisitor($cyclomaticComplexityCalculatingVisitor); /* @noinspection UnusedFunctionResultInspection */ $traverser->traverse($nodes); return $cyclomaticComplexityCalculatingVisitor->cyclomaticComplexity(); } /** * @psalm-param ClassMethod|Function_ $node */ private function signature(Node $node): string { assert($node instanceof ClassMethod || $node instanceof Function_); $signature = ($node->returnsByRef() ? '&' : '') . $node->name->toString() . '('; $parameters = []; foreach ($node->getParams() as $parameter) { assert(isset($parameter->var->name)); $parameterAsString = ''; if ($parameter->type !== null) { $parameterAsString = $this->type($parameter->type) . ' '; } $parameterAsString .= '$' . $parameter->var->name; /* @todo Handle default values */ $parameters[] = $parameterAsString; } $signature .= implode(', ', $parameters) . ')'; $returnType = $node->getReturnType(); if ($returnType !== null) { $signature .= ': ' . $this->type($returnType); } return $signature; } /** * @psalm-param Identifier|Name|ComplexType $type */ private function type(Node $type): string { assert($type instanceof Identifier || $type instanceof Name || $type instanceof ComplexType); if ($type instanceof NullableType) { return '?' . $type->type; } if ($type instanceof UnionType) { return $this->unionTypeAsString($type); } if ($type instanceof IntersectionType) { return $this->intersectionTypeAsString($type); } return $type->toString(); } private function visibility(ClassMethod $node): string { if ($node->isPrivate()) { return 'private'; } if ($node->isProtected()) { return 'protected'; } return 'public'; } private function processClass(Class_ $node): void { $name = $node->name->toString(); $namespacedName = $node->namespacedName->toString(); $this->classes[$namespacedName] = [ 'name' => $name, 'namespacedName' => $namespacedName, 'namespace' => $this->namespace($namespacedName, $name), 'startLine' => $node->getStartLine(), 'endLine' => $node->getEndLine(), 'methods' => [], ]; } private function processTrait(Trait_ $node): void { $name = $node->name->toString(); $namespacedName = $node->namespacedName->toString(); $this->traits[$namespacedName] = [ 'name' => $name, 'namespacedName' => $namespacedName, 'namespace' => $this->namespace($namespacedName, $name), 'startLine' => $node->getStartLine(), 'endLine' => $node->getEndLine(), 'methods' => [], ]; } private function processMethod(ClassMethod $node): void { $parentNode = $node->getAttribute('parent'); if ($parentNode instanceof Interface_) { return; } assert($parentNode instanceof Class_ || $parentNode instanceof Trait_ || $parentNode instanceof Enum_); assert(isset($parentNode->name)); assert(isset($parentNode->namespacedName)); assert($parentNode->namespacedName instanceof Name); $parentName = $parentNode->name->toString(); $parentNamespacedName = $parentNode->namespacedName->toString(); if ($parentNode instanceof Class_) { $storage = &$this->classes; } else { $storage = &$this->traits; } if (!isset($storage[$parentNamespacedName])) { $storage[$parentNamespacedName] = [ 'name' => $parentName, 'namespacedName' => $parentNamespacedName, 'namespace' => $this->namespace($parentNamespacedName, $parentName), 'startLine' => $parentNode->getStartLine(), 'endLine' => $parentNode->getEndLine(), 'methods' => [], ]; } $storage[$parentNamespacedName]['methods'][$node->name->toString()] = [ 'methodName' => $node->name->toString(), 'signature' => $this->signature($node), 'visibility' => $this->visibility($node), 'startLine' => $node->getStartLine(), 'endLine' => $node->getEndLine(), 'ccn' => $this->cyclomaticComplexity($node), ]; } private function processFunction(Function_ $node): void { assert(isset($node->name)); assert(isset($node->namespacedName)); assert($node->namespacedName instanceof Name); $name = $node->name->toString(); $namespacedName = $node->namespacedName->toString(); $this->functions[$namespacedName] = [ 'name' => $name, 'namespacedName' => $namespacedName, 'namespace' => $this->namespace($namespacedName, $name), 'signature' => $this->signature($node), 'startLine' => $node->getStartLine(), 'endLine' => $node->getEndLine(), 'ccn' => $this->cyclomaticComplexity($node), ]; } private function namespace(string $namespacedName, string $name): string { return trim(rtrim($namespacedName, $name), '\\'); } private function unionTypeAsString(UnionType $node): string { $types = []; foreach ($node->types as $type) { if ($type instanceof IntersectionType) { $types[] = '(' . $this->intersectionTypeAsString($type) . ')'; continue; } $types[] = $this->typeAsString($type); } return implode('|', $types); } private function intersectionTypeAsString(IntersectionType $node): string { $types = []; foreach ($node->types as $type) { $types[] = $this->typeAsString($type); } return implode('&', $types); } /** * @psalm-param Identifier|Name $node $node */ private function typeAsString(NodeAbstract $node): string { if ($node instanceof Name) { return $node->toCodeString(); } return $node->toString(); } } PKuZshh(Exception/Xdebug3NotEnabledException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Driver; use RuntimeException; use SebastianBergmann\CodeCoverage\Exception; final class Xdebug3NotEnabledException extends RuntimeException implements Exception { public function __construct() { parent::__construct('XDEBUG_MODE=coverage or xdebug.mode=coverage has to be set'); } } PKuZ"Exception/XmlException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage; use RuntimeException; final class XmlException extends RuntimeException implements Exception { } PKuZjIJUU(Exception/Xdebug2NotEnabledException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Driver; use RuntimeException; use SebastianBergmann\CodeCoverage\Exception; final class Xdebug2NotEnabledException extends RuntimeException implements Exception { public function __construct() { parent::__construct('xdebug.coverage_enable=On has to be set'); } } PKuZww+Exception/WriteOperationFailedException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Driver; use function sprintf; use RuntimeException; use SebastianBergmann\CodeCoverage\Exception; final class WriteOperationFailedException extends RuntimeException implements Exception { public function __construct(string $path) { parent::__construct(sprintf('Cannot write to "%s"', $path)); } } PKuZc7Exception/StaticAnalysisCacheNotConfiguredException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage; use RuntimeException; final class StaticAnalysisCacheNotConfiguredException extends RuntimeException implements Exception { } PKuZV9&&1Exception/UnintentionallyCoveredCodeException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage; use RuntimeException; final class UnintentionallyCoveredCodeException extends RuntimeException implements Exception { /** * @var array */ private $unintentionallyCoveredUnits; public function __construct(array $unintentionallyCoveredUnits) { $this->unintentionallyCoveredUnits = $unintentionallyCoveredUnits; parent::__construct($this->toString()); } public function getUnintentionallyCoveredUnits(): array { return $this->unintentionallyCoveredUnits; } private function toString(): string { $message = ''; foreach ($this->unintentionallyCoveredUnits as $unit) { $message .= '- ' . $unit . "\n"; } return $message; } } PKuZ(E7&&4Exception/NoCodeCoverageDriverAvailableException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage; use RuntimeException; final class NoCodeCoverageDriverAvailableException extends RuntimeException implements Exception { public function __construct() { parent::__construct('No code coverage driver available'); } } PKuZrD4Exception/DeadCodeDetectionNotSupportedException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage; use RuntimeException; final class DeadCodeDetectionNotSupportedException extends RuntimeException implements Exception { } PKuZ2Exception/PathExistsButIsNotDirectoryException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Driver; use function sprintf; use RuntimeException; use SebastianBergmann\CodeCoverage\Exception; final class PathExistsButIsNotDirectoryException extends RuntimeException implements Exception { public function __construct(string $path) { parent::__construct(sprintf('"%s" exists but is not a directory', $path)); } } PKuZtst11-Exception/ReportAlreadyFinalizedException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage; use RuntimeException; final class ReportAlreadyFinalizedException extends RuntimeException implements Exception { public function __construct() { parent::__construct('The code coverage report has already been finalized'); } } PKuZO}A8Exception/BranchAndPathCoverageNotSupportedException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage; use RuntimeException; final class BranchAndPathCoverageNotSupportedException extends RuntimeException implements Exception { } PKuZ[8PP'Exception/PcovNotAvailableException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Driver; use RuntimeException; use SebastianBergmann\CodeCoverage\Exception; final class PcovNotAvailableException extends RuntimeException implements Exception { public function __construct() { parent::__construct('The PCOV extension is not available'); } } PKuZs$Exception/ParserException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage; use RuntimeException; final class ParserException extends RuntimeException implements Exception { } PKuZ<OO)Exception/PhpdbgNotAvailableException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Driver; use RuntimeException; use SebastianBergmann\CodeCoverage\Exception; final class PhpdbgNotAvailableException extends RuntimeException implements Exception { public function __construct() { parent::__construct('The PHPDBG SAPI is not available'); } } PKuZ&L!Exception/ReflectionException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage; use RuntimeException; final class ReflectionException extends RuntimeException implements Exception { } PKuZ;XXKException/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage; use RuntimeException; final class NoCodeCoverageDriverWithPathCoverageSupportAvailableException extends RuntimeException implements Exception { public function __construct() { parent::__construct('No code coverage driver with path coverage support available'); } } PKuZ$Exception/TestIdMissingException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage; use RuntimeException; final class TestIdMissingException extends RuntimeException implements Exception { public function __construct() { parent::__construct('Test ID is missing'); } } PKuZTT)Exception/XdebugNotAvailableException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Driver; use RuntimeException; use SebastianBergmann\CodeCoverage\Exception; final class XdebugNotAvailableException extends RuntimeException implements Exception { public function __construct() { parent::__construct('The Xdebug extension is not available'); } } PKuZo )Exception/WrongXdebugVersionException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Driver; use RuntimeException; use SebastianBergmann\CodeCoverage\Exception; final class WrongXdebugVersionException extends RuntimeException implements Exception { } PKuZ;s 1Exception/DirectoryCouldNotBeCreatedException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Util; use RuntimeException; use SebastianBergmann\CodeCoverage\Exception; final class DirectoryCouldNotBeCreatedException extends RuntimeException implements Exception { } PKuZ}$$ProcessedCodeCoverageData.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage; use function array_key_exists; use function array_keys; use function array_merge; use function array_unique; use function count; use function is_array; use function ksort; use SebastianBergmann\CodeCoverage\Driver\Driver; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class ProcessedCodeCoverageData { /** * Line coverage data. * An array of filenames, each having an array of linenumbers, each executable line having an array of testcase ids. * * @var array */ private $lineCoverage = []; /** * Function coverage data. * Maintains base format of raw data (@see https://xdebug.org/docs/code_coverage), but each 'hit' entry is an array * of testcase ids. * * @var array */ private $functionCoverage = []; public function initializeUnseenData(RawCodeCoverageData $rawData): void { foreach ($rawData->lineCoverage() as $file => $lines) { if (!isset($this->lineCoverage[$file])) { $this->lineCoverage[$file] = []; foreach ($lines as $k => $v) { $this->lineCoverage[$file][$k] = $v === Driver::LINE_NOT_EXECUTABLE ? null : []; } } } foreach ($rawData->functionCoverage() as $file => $functions) { foreach ($functions as $functionName => $functionData) { if (isset($this->functionCoverage[$file][$functionName])) { $this->initPreviouslySeenFunction($file, $functionName, $functionData); } else { $this->initPreviouslyUnseenFunction($file, $functionName, $functionData); } } } } public function markCodeAsExecutedByTestCase(string $testCaseId, RawCodeCoverageData $executedCode): void { foreach ($executedCode->lineCoverage() as $file => $lines) { foreach ($lines as $k => $v) { if ($v === Driver::LINE_EXECUTED) { $this->lineCoverage[$file][$k][] = $testCaseId; } } } foreach ($executedCode->functionCoverage() as $file => $functions) { foreach ($functions as $functionName => $functionData) { foreach ($functionData['branches'] as $branchId => $branchData) { if ($branchData['hit'] === Driver::BRANCH_HIT) { $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'][] = $testCaseId; } } foreach ($functionData['paths'] as $pathId => $pathData) { if ($pathData['hit'] === Driver::BRANCH_HIT) { $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'][] = $testCaseId; } } } } } public function setLineCoverage(array $lineCoverage): void { $this->lineCoverage = $lineCoverage; } public function lineCoverage(): array { ksort($this->lineCoverage); return $this->lineCoverage; } public function setFunctionCoverage(array $functionCoverage): void { $this->functionCoverage = $functionCoverage; } public function functionCoverage(): array { ksort($this->functionCoverage); return $this->functionCoverage; } public function coveredFiles(): array { ksort($this->lineCoverage); return array_keys($this->lineCoverage); } public function renameFile(string $oldFile, string $newFile): void { $this->lineCoverage[$newFile] = $this->lineCoverage[$oldFile]; if (isset($this->functionCoverage[$oldFile])) { $this->functionCoverage[$newFile] = $this->functionCoverage[$oldFile]; } unset($this->lineCoverage[$oldFile], $this->functionCoverage[$oldFile]); } public function merge(self $newData): void { foreach ($newData->lineCoverage as $file => $lines) { if (!isset($this->lineCoverage[$file])) { $this->lineCoverage[$file] = $lines; continue; } // we should compare the lines if any of two contains data $compareLineNumbers = array_unique( array_merge( array_keys($this->lineCoverage[$file]), array_keys($newData->lineCoverage[$file]) ) ); foreach ($compareLineNumbers as $line) { $thatPriority = $this->priorityForLine($newData->lineCoverage[$file], $line); $thisPriority = $this->priorityForLine($this->lineCoverage[$file], $line); if ($thatPriority > $thisPriority) { $this->lineCoverage[$file][$line] = $newData->lineCoverage[$file][$line]; } elseif ($thatPriority === $thisPriority && is_array($this->lineCoverage[$file][$line])) { $this->lineCoverage[$file][$line] = array_unique( array_merge($this->lineCoverage[$file][$line], $newData->lineCoverage[$file][$line]) ); } } } foreach ($newData->functionCoverage as $file => $functions) { if (!isset($this->functionCoverage[$file])) { $this->functionCoverage[$file] = $functions; continue; } foreach ($functions as $functionName => $functionData) { if (isset($this->functionCoverage[$file][$functionName])) { $this->initPreviouslySeenFunction($file, $functionName, $functionData); } else { $this->initPreviouslyUnseenFunction($file, $functionName, $functionData); } foreach ($functionData['branches'] as $branchId => $branchData) { $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = array_unique(array_merge($this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'], $branchData['hit'])); } foreach ($functionData['paths'] as $pathId => $pathData) { $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = array_unique(array_merge($this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'], $pathData['hit'])); } } } } /** * Determine the priority for a line. * * 1 = the line is not set * 2 = the line has not been tested * 3 = the line is dead code * 4 = the line has been tested * * During a merge, a higher number is better. */ private function priorityForLine(array $data, int $line): int { if (!array_key_exists($line, $data)) { return 1; } if (is_array($data[$line]) && count($data[$line]) === 0) { return 2; } if ($data[$line] === null) { return 3; } return 4; } /** * For a function we have never seen before, copy all data over and simply init the 'hit' array. */ private function initPreviouslyUnseenFunction(string $file, string $functionName, array $functionData): void { $this->functionCoverage[$file][$functionName] = $functionData; foreach (array_keys($functionData['branches']) as $branchId) { $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = []; } foreach (array_keys($functionData['paths']) as $pathId) { $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = []; } } /** * For a function we have seen before, only copy over and init the 'hit' array for any unseen branches and paths. * Techniques such as mocking and where the contents of a file are different vary during tests (e.g. compiling * containers) mean that the functions inside a file cannot be relied upon to be static. */ private function initPreviouslySeenFunction(string $file, string $functionName, array $functionData): void { foreach ($functionData['branches'] as $branchId => $branchData) { if (!isset($this->functionCoverage[$file][$functionName]['branches'][$branchId])) { $this->functionCoverage[$file][$functionName]['branches'][$branchId] = $branchData; $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = []; } } foreach ($functionData['paths'] as $pathId => $pathData) { if (!isset($this->functionCoverage[$file][$functionName]['paths'][$pathId])) { $this->functionCoverage[$file][$functionName]['paths'][$pathId] = $pathData; $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = []; } } } } PKuZP Ȼi i Driver/PhpdbgDriver.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Driver; use const PHP_SAPI; use const PHP_VERSION; use function array_diff; use function array_keys; use function array_merge; use function get_included_files; use function phpdbg_end_oplog; use function phpdbg_get_executable; use function phpdbg_start_oplog; use SebastianBergmann\CodeCoverage\RawCodeCoverageData; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class PhpdbgDriver extends Driver { /** * @throws PhpdbgNotAvailableException */ public function __construct() { if (PHP_SAPI !== 'phpdbg') { throw new PhpdbgNotAvailableException; } } public function start(): void { phpdbg_start_oplog(); } public function stop(): RawCodeCoverageData { static $fetchedLines = []; $dbgData = phpdbg_end_oplog(); if ($fetchedLines === []) { $sourceLines = phpdbg_get_executable(); } else { $newFiles = array_diff(get_included_files(), array_keys($fetchedLines)); $sourceLines = []; if ($newFiles) { $sourceLines = phpdbg_get_executable(['files' => $newFiles]); } } foreach ($sourceLines as $file => $lines) { foreach ($lines as $lineNo => $numExecuted) { $sourceLines[$file][$lineNo] = self::LINE_NOT_EXECUTED; } } $fetchedLines = array_merge($fetchedLines, $sourceLines); return RawCodeCoverageData::fromXdebugWithoutPathCoverage( $this->detectExecutedLines($fetchedLines, $dbgData) ); } public function nameAndVersion(): string { return 'PHPDBG ' . PHP_VERSION; } private function detectExecutedLines(array $sourceLines, array $dbgData): array { foreach ($dbgData as $file => $coveredLines) { foreach ($coveredLines as $lineNo => $numExecuted) { // phpdbg also reports $lineNo=0 when e.g. exceptions get thrown. // make sure we only mark lines executed which are actually executable. if (isset($sourceLines[$file][$lineNo])) { $sourceLines[$file][$lineNo] = self::LINE_EXECUTED; } } } return $sourceLines; } } PKuZYcFFDriver/PcovDriver.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Driver; use const pcov\inclusive; use function array_intersect; use function extension_loaded; use function pcov\clear; use function pcov\collect; use function pcov\start; use function pcov\stop; use function pcov\waiting; use function phpversion; use SebastianBergmann\CodeCoverage\Filter; use SebastianBergmann\CodeCoverage\RawCodeCoverageData; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class PcovDriver extends Driver { /** * @var Filter */ private $filter; /** * @throws PcovNotAvailableException */ public function __construct(Filter $filter) { if (!extension_loaded('pcov')) { throw new PcovNotAvailableException; } $this->filter = $filter; } public function start(): void { start(); } public function stop(): RawCodeCoverageData { stop(); $filesToCollectCoverageFor = waiting(); $collected = []; if ($filesToCollectCoverageFor) { if (!$this->filter->isEmpty()) { $filesToCollectCoverageFor = array_intersect($filesToCollectCoverageFor, $this->filter->files()); } $collected = collect(inclusive, $filesToCollectCoverageFor); clear(); } return RawCodeCoverageData::fromXdebugWithoutPathCoverage($collected); } public function nameAndVersion(): string { return 'PCOV ' . phpversion('pcov'); } } PKuZ Driver/Xdebug2Driver.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Driver; use const XDEBUG_CC_BRANCH_CHECK; use const XDEBUG_CC_DEAD_CODE; use const XDEBUG_CC_UNUSED; use const XDEBUG_FILTER_CODE_COVERAGE; use const XDEBUG_PATH_INCLUDE; use const XDEBUG_PATH_WHITELIST; use function defined; use function extension_loaded; use function ini_get; use function phpversion; use function sprintf; use function version_compare; use function xdebug_get_code_coverage; use function xdebug_set_filter; use function xdebug_start_code_coverage; use function xdebug_stop_code_coverage; use SebastianBergmann\CodeCoverage\Filter; use SebastianBergmann\CodeCoverage\RawCodeCoverageData; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class Xdebug2Driver extends Driver { /** * @var bool */ private $pathCoverageIsMixedCoverage; /** * @throws WrongXdebugVersionException * @throws Xdebug2NotEnabledException * @throws XdebugNotAvailableException */ public function __construct(Filter $filter) { if (!extension_loaded('xdebug')) { throw new XdebugNotAvailableException; } if (version_compare(phpversion('xdebug'), '3', '>=')) { throw new WrongXdebugVersionException( sprintf( 'This driver requires Xdebug 2 but version %s is loaded', phpversion('xdebug') ) ); } if (!ini_get('xdebug.coverage_enable')) { throw new Xdebug2NotEnabledException; } if (!$filter->isEmpty()) { if (defined('XDEBUG_PATH_WHITELIST')) { $listType = XDEBUG_PATH_WHITELIST; } else { $listType = XDEBUG_PATH_INCLUDE; } xdebug_set_filter( XDEBUG_FILTER_CODE_COVERAGE, $listType, $filter->files() ); } $this->pathCoverageIsMixedCoverage = version_compare(phpversion('xdebug'), '2.9.6', '<'); } public function canCollectBranchAndPathCoverage(): bool { return true; } public function canDetectDeadCode(): bool { return true; } public function start(): void { $flags = XDEBUG_CC_UNUSED; if ($this->detectsDeadCode() || $this->collectsBranchAndPathCoverage()) { $flags |= XDEBUG_CC_DEAD_CODE; } if ($this->collectsBranchAndPathCoverage()) { $flags |= XDEBUG_CC_BRANCH_CHECK; } xdebug_start_code_coverage($flags); } public function stop(): RawCodeCoverageData { $data = xdebug_get_code_coverage(); xdebug_stop_code_coverage(); if ($this->collectsBranchAndPathCoverage()) { if ($this->pathCoverageIsMixedCoverage) { return RawCodeCoverageData::fromXdebugWithMixedCoverage($data); } return RawCodeCoverageData::fromXdebugWithPathCoverage($data); } return RawCodeCoverageData::fromXdebugWithoutPathCoverage($data); } public function nameAndVersion(): string { return 'Xdebug ' . phpversion('xdebug'); } } PKuZ2mVd d Driver/Selector.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Driver; use function phpversion; use function version_compare; use SebastianBergmann\CodeCoverage\Filter; use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverAvailableException; use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverWithPathCoverageSupportAvailableException; use SebastianBergmann\Environment\Runtime; final class Selector { /** * @throws NoCodeCoverageDriverAvailableException * @throws PcovNotAvailableException * @throws PhpdbgNotAvailableException * @throws Xdebug2NotEnabledException * @throws Xdebug3NotEnabledException * @throws XdebugNotAvailableException */ public function forLineCoverage(Filter $filter): Driver { $runtime = new Runtime; if ($runtime->hasPHPDBGCodeCoverage()) { return new PhpdbgDriver; } if ($runtime->hasPCOV()) { return new PcovDriver($filter); } if ($runtime->hasXdebug()) { if (version_compare(phpversion('xdebug'), '3', '>=')) { $driver = new Xdebug3Driver($filter); } else { $driver = new Xdebug2Driver($filter); } $driver->enableDeadCodeDetection(); return $driver; } throw new NoCodeCoverageDriverAvailableException; } /** * @throws NoCodeCoverageDriverWithPathCoverageSupportAvailableException * @throws Xdebug2NotEnabledException * @throws Xdebug3NotEnabledException * @throws XdebugNotAvailableException */ public function forLineAndPathCoverage(Filter $filter): Driver { if ((new Runtime)->hasXdebug()) { if (version_compare(phpversion('xdebug'), '3', '>=')) { $driver = new Xdebug3Driver($filter); } else { $driver = new Xdebug2Driver($filter); } $driver->enableDeadCodeDetection(); $driver->enableBranchAndPathCoverage(); return $driver; } throw new NoCodeCoverageDriverWithPathCoverageSupportAvailableException; } } PKuZ5> Driver/Xdebug3Driver.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Driver; use const XDEBUG_CC_BRANCH_CHECK; use const XDEBUG_CC_DEAD_CODE; use const XDEBUG_CC_UNUSED; use const XDEBUG_FILTER_CODE_COVERAGE; use const XDEBUG_PATH_INCLUDE; use function explode; use function extension_loaded; use function getenv; use function in_array; use function ini_get; use function phpversion; use function sprintf; use function version_compare; use function xdebug_get_code_coverage; use function xdebug_set_filter; use function xdebug_start_code_coverage; use function xdebug_stop_code_coverage; use SebastianBergmann\CodeCoverage\Filter; use SebastianBergmann\CodeCoverage\RawCodeCoverageData; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class Xdebug3Driver extends Driver { /** * @throws WrongXdebugVersionException * @throws Xdebug3NotEnabledException * @throws XdebugNotAvailableException */ public function __construct(Filter $filter) { if (!extension_loaded('xdebug')) { throw new XdebugNotAvailableException; } if (version_compare(phpversion('xdebug'), '3', '<')) { throw new WrongXdebugVersionException( sprintf( 'This driver requires Xdebug 3 but version %s is loaded', phpversion('xdebug') ) ); } $mode = getenv('XDEBUG_MODE'); if ($mode === false || $mode === '') { $mode = ini_get('xdebug.mode'); } if ($mode === false || !in_array('coverage', explode(',', $mode), true)) { throw new Xdebug3NotEnabledException; } if (!$filter->isEmpty()) { xdebug_set_filter( XDEBUG_FILTER_CODE_COVERAGE, XDEBUG_PATH_INCLUDE, $filter->files() ); } } public function canCollectBranchAndPathCoverage(): bool { return true; } public function canDetectDeadCode(): bool { return true; } public function start(): void { $flags = XDEBUG_CC_UNUSED; if ($this->detectsDeadCode() || $this->collectsBranchAndPathCoverage()) { $flags |= XDEBUG_CC_DEAD_CODE; } if ($this->collectsBranchAndPathCoverage()) { $flags |= XDEBUG_CC_BRANCH_CHECK; } xdebug_start_code_coverage($flags); } public function stop(): RawCodeCoverageData { $data = xdebug_get_code_coverage(); xdebug_stop_code_coverage(); if ($this->collectsBranchAndPathCoverage()) { return RawCodeCoverageData::fromXdebugWithPathCoverage($data); } return RawCodeCoverageData::fromXdebugWithoutPathCoverage($data); } public function nameAndVersion(): string { return 'Xdebug ' . phpversion('xdebug'); } } PKuZ#,Driver/Driver.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Driver; use function sprintf; use SebastianBergmann\CodeCoverage\BranchAndPathCoverageNotSupportedException; use SebastianBergmann\CodeCoverage\DeadCodeDetectionNotSupportedException; use SebastianBergmann\CodeCoverage\Filter; use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverAvailableException; use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverWithPathCoverageSupportAvailableException; use SebastianBergmann\CodeCoverage\RawCodeCoverageData; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ abstract class Driver { /** * @var int * * @see http://xdebug.org/docs/code_coverage */ public const LINE_NOT_EXECUTABLE = -2; /** * @var int * * @see http://xdebug.org/docs/code_coverage */ public const LINE_NOT_EXECUTED = -1; /** * @var int * * @see http://xdebug.org/docs/code_coverage */ public const LINE_EXECUTED = 1; /** * @var int * * @see http://xdebug.org/docs/code_coverage */ public const BRANCH_NOT_HIT = 0; /** * @var int * * @see http://xdebug.org/docs/code_coverage */ public const BRANCH_HIT = 1; /** * @var bool */ private $collectBranchAndPathCoverage = false; /** * @var bool */ private $detectDeadCode = false; /** * @throws NoCodeCoverageDriverAvailableException * @throws PcovNotAvailableException * @throws PhpdbgNotAvailableException * @throws Xdebug2NotEnabledException * @throws Xdebug3NotEnabledException * @throws XdebugNotAvailableException * * @deprecated Use DriverSelector::forLineCoverage() instead */ public static function forLineCoverage(Filter $filter): self { return (new Selector)->forLineCoverage($filter); } /** * @throws NoCodeCoverageDriverWithPathCoverageSupportAvailableException * @throws Xdebug2NotEnabledException * @throws Xdebug3NotEnabledException * @throws XdebugNotAvailableException * * @deprecated Use DriverSelector::forLineAndPathCoverage() instead */ public static function forLineAndPathCoverage(Filter $filter): self { return (new Selector)->forLineAndPathCoverage($filter); } public function canCollectBranchAndPathCoverage(): bool { return false; } public function collectsBranchAndPathCoverage(): bool { return $this->collectBranchAndPathCoverage; } /** * @throws BranchAndPathCoverageNotSupportedException */ public function enableBranchAndPathCoverage(): void { if (!$this->canCollectBranchAndPathCoverage()) { throw new BranchAndPathCoverageNotSupportedException( sprintf( '%s does not support branch and path coverage', $this->nameAndVersion() ) ); } $this->collectBranchAndPathCoverage = true; } public function disableBranchAndPathCoverage(): void { $this->collectBranchAndPathCoverage = false; } public function canDetectDeadCode(): bool { return false; } public function detectsDeadCode(): bool { return $this->detectDeadCode; } /** * @throws DeadCodeDetectionNotSupportedException */ public function enableDeadCodeDetection(): void { if (!$this->canDetectDeadCode()) { throw new DeadCodeDetectionNotSupportedException( sprintf( '%s does not support dead code detection', $this->nameAndVersion() ) ); } $this->detectDeadCode = true; } public function disableDeadCodeDetection(): void { $this->detectDeadCode = false; } abstract public function nameAndVersion(): string; abstract public function start(): void; abstract public function stop(): RawCodeCoverageData; } PKuZ<.FFCodeCoverage.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage; use function array_diff; use function array_diff_key; use function array_flip; use function array_keys; use function array_merge; use function array_unique; use function array_values; use function count; use function explode; use function get_class; use function is_array; use function sort; use PHPUnit\Framework\TestCase; use PHPUnit\Runner\PhptTestCase; use PHPUnit\Util\Test; use ReflectionClass; use SebastianBergmann\CodeCoverage\Driver\Driver; use SebastianBergmann\CodeCoverage\Node\Builder; use SebastianBergmann\CodeCoverage\Node\Directory; use SebastianBergmann\CodeCoverage\StaticAnalysis\CachingFileAnalyser; use SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser; use SebastianBergmann\CodeCoverage\StaticAnalysis\ParsingFileAnalyser; use SebastianBergmann\CodeUnitReverseLookup\Wizard; /** * Provides collection functionality for PHP code coverage information. */ final class CodeCoverage { private const UNCOVERED_FILES = 'UNCOVERED_FILES'; /** * @var Driver */ private $driver; /** * @var Filter */ private $filter; /** * @var Wizard */ private $wizard; /** * @var bool */ private $checkForUnintentionallyCoveredCode = false; /** * @var bool */ private $includeUncoveredFiles = true; /** * @var bool */ private $processUncoveredFiles = false; /** * @var bool */ private $ignoreDeprecatedCode = false; /** * @var null|PhptTestCase|string|TestCase */ private $currentId; /** * Code coverage data. * * @var ProcessedCodeCoverageData */ private $data; /** * @var bool */ private $useAnnotationsForIgnoringCode = true; /** * Test data. * * @var array */ private $tests = []; /** * @psalm-var list */ private $parentClassesExcludedFromUnintentionallyCoveredCodeCheck = []; /** * @var ?FileAnalyser */ private $analyser; /** * @var ?string */ private $cacheDirectory; public function __construct(Driver $driver, Filter $filter) { $this->driver = $driver; $this->filter = $filter; $this->data = new ProcessedCodeCoverageData; $this->wizard = new Wizard; } /** * Returns the code coverage information as a graph of node objects. */ public function getReport(): Directory { return (new Builder($this->analyser()))->build($this); } /** * Clears collected code coverage data. */ public function clear(): void { $this->currentId = null; $this->data = new ProcessedCodeCoverageData; $this->tests = []; } /** * Returns the filter object used. */ public function filter(): Filter { return $this->filter; } /** * Returns the collected code coverage data. */ public function getData(bool $raw = false): ProcessedCodeCoverageData { if (!$raw) { if ($this->processUncoveredFiles) { $this->processUncoveredFilesFromFilter(); } elseif ($this->includeUncoveredFiles) { $this->addUncoveredFilesFromFilter(); } } return $this->data; } /** * Sets the coverage data. */ public function setData(ProcessedCodeCoverageData $data): void { $this->data = $data; } /** * Returns the test data. */ public function getTests(): array { return $this->tests; } /** * Sets the test data. */ public function setTests(array $tests): void { $this->tests = $tests; } /** * Start collection of code coverage information. * * @param PhptTestCase|string|TestCase $id */ public function start($id, bool $clear = false): void { if ($clear) { $this->clear(); } $this->currentId = $id; $this->driver->start(); } /** * Stop collection of code coverage information. * * @param array|false $linesToBeCovered */ public function stop(bool $append = true, $linesToBeCovered = [], array $linesToBeUsed = []): RawCodeCoverageData { if (!is_array($linesToBeCovered) && $linesToBeCovered !== false) { throw new InvalidArgumentException( '$linesToBeCovered must be an array or false' ); } $data = $this->driver->stop(); $this->append($data, null, $append, $linesToBeCovered, $linesToBeUsed); $this->currentId = null; return $data; } /** * Appends code coverage data. * * @param PhptTestCase|string|TestCase $id * @param array|false $linesToBeCovered * * @throws ReflectionException * @throws TestIdMissingException * @throws UnintentionallyCoveredCodeException */ public function append(RawCodeCoverageData $rawData, $id = null, bool $append = true, $linesToBeCovered = [], array $linesToBeUsed = []): void { if ($id === null) { $id = $this->currentId; } if ($id === null) { throw new TestIdMissingException; } $this->applyFilter($rawData); $this->applyExecutableLinesFilter($rawData); if ($this->useAnnotationsForIgnoringCode) { $this->applyIgnoredLinesFilter($rawData); } $this->data->initializeUnseenData($rawData); if (!$append) { return; } if ($id !== self::UNCOVERED_FILES) { $this->applyCoversAnnotationFilter( $rawData, $linesToBeCovered, $linesToBeUsed ); if (empty($rawData->lineCoverage())) { return; } $size = 'unknown'; $status = -1; $fromTestcase = false; if ($id instanceof TestCase) { $fromTestcase = true; $_size = $id->getSize(); if ($_size === Test::SMALL) { $size = 'small'; } elseif ($_size === Test::MEDIUM) { $size = 'medium'; } elseif ($_size === Test::LARGE) { $size = 'large'; } $status = $id->getStatus(); $id = get_class($id) . '::' . $id->getName(); } elseif ($id instanceof PhptTestCase) { $fromTestcase = true; $size = 'large'; $id = $id->getName(); } $this->tests[$id] = ['size' => $size, 'status' => $status, 'fromTestcase' => $fromTestcase]; $this->data->markCodeAsExecutedByTestCase($id, $rawData); } } /** * Merges the data from another instance. */ public function merge(self $that): void { $this->filter->includeFiles( $that->filter()->files() ); $this->data->merge($that->data); $this->tests = array_merge($this->tests, $that->getTests()); } public function enableCheckForUnintentionallyCoveredCode(): void { $this->checkForUnintentionallyCoveredCode = true; } public function disableCheckForUnintentionallyCoveredCode(): void { $this->checkForUnintentionallyCoveredCode = false; } public function includeUncoveredFiles(): void { $this->includeUncoveredFiles = true; } public function excludeUncoveredFiles(): void { $this->includeUncoveredFiles = false; } public function processUncoveredFiles(): void { $this->processUncoveredFiles = true; } public function doNotProcessUncoveredFiles(): void { $this->processUncoveredFiles = false; } public function enableAnnotationsForIgnoringCode(): void { $this->useAnnotationsForIgnoringCode = true; } public function disableAnnotationsForIgnoringCode(): void { $this->useAnnotationsForIgnoringCode = false; } public function ignoreDeprecatedCode(): void { $this->ignoreDeprecatedCode = true; } public function doNotIgnoreDeprecatedCode(): void { $this->ignoreDeprecatedCode = false; } /** * @psalm-assert-if-true !null $this->cacheDirectory */ public function cachesStaticAnalysis(): bool { return $this->cacheDirectory !== null; } public function cacheStaticAnalysis(string $directory): void { $this->cacheDirectory = $directory; } public function doNotCacheStaticAnalysis(): void { $this->cacheDirectory = null; } /** * @throws StaticAnalysisCacheNotConfiguredException */ public function cacheDirectory(): string { if (!$this->cachesStaticAnalysis()) { throw new StaticAnalysisCacheNotConfiguredException( 'The static analysis cache is not configured' ); } return $this->cacheDirectory; } /** * @psalm-param class-string $className */ public function excludeSubclassesOfThisClassFromUnintentionallyCoveredCodeCheck(string $className): void { $this->parentClassesExcludedFromUnintentionallyCoveredCodeCheck[] = $className; } public function enableBranchAndPathCoverage(): void { $this->driver->enableBranchAndPathCoverage(); } public function disableBranchAndPathCoverage(): void { $this->driver->disableBranchAndPathCoverage(); } public function collectsBranchAndPathCoverage(): bool { return $this->driver->collectsBranchAndPathCoverage(); } public function detectsDeadCode(): bool { return $this->driver->detectsDeadCode(); } /** * Applies the @covers annotation filtering. * * @param array|false $linesToBeCovered * * @throws ReflectionException * @throws UnintentionallyCoveredCodeException */ private function applyCoversAnnotationFilter(RawCodeCoverageData $rawData, $linesToBeCovered, array $linesToBeUsed): void { if ($linesToBeCovered === false) { $rawData->clear(); return; } if (empty($linesToBeCovered)) { return; } if ($this->checkForUnintentionallyCoveredCode && (!$this->currentId instanceof TestCase || (!$this->currentId->isMedium() && !$this->currentId->isLarge()))) { $this->performUnintentionallyCoveredCodeCheck($rawData, $linesToBeCovered, $linesToBeUsed); } $rawLineData = $rawData->lineCoverage(); $filesWithNoCoverage = array_diff_key($rawLineData, $linesToBeCovered); foreach (array_keys($filesWithNoCoverage) as $fileWithNoCoverage) { $rawData->removeCoverageDataForFile($fileWithNoCoverage); } if (is_array($linesToBeCovered)) { foreach ($linesToBeCovered as $fileToBeCovered => $includedLines) { $rawData->keepLineCoverageDataOnlyForLines($fileToBeCovered, $includedLines); $rawData->keepFunctionCoverageDataOnlyForLines($fileToBeCovered, $includedLines); } } } private function applyFilter(RawCodeCoverageData $data): void { if ($this->filter->isEmpty()) { return; } foreach (array_keys($data->lineCoverage()) as $filename) { if ($this->filter->isExcluded($filename)) { $data->removeCoverageDataForFile($filename); } } } private function applyExecutableLinesFilter(RawCodeCoverageData $data): void { foreach (array_keys($data->lineCoverage()) as $filename) { if (!$this->filter->isFile($filename)) { continue; } $linesToBranchMap = $this->analyser()->executableLinesIn($filename); $data->keepLineCoverageDataOnlyForLines( $filename, array_keys($linesToBranchMap) ); $data->markExecutableLineByBranch( $filename, $linesToBranchMap ); } } private function applyIgnoredLinesFilter(RawCodeCoverageData $data): void { foreach (array_keys($data->lineCoverage()) as $filename) { if (!$this->filter->isFile($filename)) { continue; } $data->removeCoverageDataForLines( $filename, $this->analyser()->ignoredLinesFor($filename) ); } } /** * @throws UnintentionallyCoveredCodeException */ private function addUncoveredFilesFromFilter(): void { $uncoveredFiles = array_diff( $this->filter->files(), $this->data->coveredFiles() ); foreach ($uncoveredFiles as $uncoveredFile) { if ($this->filter->isFile($uncoveredFile)) { $this->append( RawCodeCoverageData::fromUncoveredFile( $uncoveredFile, $this->analyser() ), self::UNCOVERED_FILES ); } } } /** * @throws UnintentionallyCoveredCodeException */ private function processUncoveredFilesFromFilter(): void { $uncoveredFiles = array_diff( $this->filter->files(), $this->data->coveredFiles() ); $this->driver->start(); foreach ($uncoveredFiles as $uncoveredFile) { if ($this->filter->isFile($uncoveredFile)) { include_once $uncoveredFile; } } $this->append($this->driver->stop(), self::UNCOVERED_FILES); } /** * @throws ReflectionException * @throws UnintentionallyCoveredCodeException */ private function performUnintentionallyCoveredCodeCheck(RawCodeCoverageData $data, array $linesToBeCovered, array $linesToBeUsed): void { $allowedLines = $this->getAllowedLines( $linesToBeCovered, $linesToBeUsed ); $unintentionallyCoveredUnits = []; foreach ($data->lineCoverage() as $file => $_data) { foreach ($_data as $line => $flag) { if ($flag === 1 && !isset($allowedLines[$file][$line])) { $unintentionallyCoveredUnits[] = $this->wizard->lookup($file, $line); } } } $unintentionallyCoveredUnits = $this->processUnintentionallyCoveredUnits($unintentionallyCoveredUnits); if (!empty($unintentionallyCoveredUnits)) { throw new UnintentionallyCoveredCodeException( $unintentionallyCoveredUnits ); } } private function getAllowedLines(array $linesToBeCovered, array $linesToBeUsed): array { $allowedLines = []; foreach (array_keys($linesToBeCovered) as $file) { if (!isset($allowedLines[$file])) { $allowedLines[$file] = []; } $allowedLines[$file] = array_merge( $allowedLines[$file], $linesToBeCovered[$file] ); } foreach (array_keys($linesToBeUsed) as $file) { if (!isset($allowedLines[$file])) { $allowedLines[$file] = []; } $allowedLines[$file] = array_merge( $allowedLines[$file], $linesToBeUsed[$file] ); } foreach (array_keys($allowedLines) as $file) { $allowedLines[$file] = array_flip( array_unique($allowedLines[$file]) ); } return $allowedLines; } /** * @throws ReflectionException */ private function processUnintentionallyCoveredUnits(array $unintentionallyCoveredUnits): array { $unintentionallyCoveredUnits = array_unique($unintentionallyCoveredUnits); sort($unintentionallyCoveredUnits); foreach (array_keys($unintentionallyCoveredUnits) as $k => $v) { $unit = explode('::', $unintentionallyCoveredUnits[$k]); if (count($unit) !== 2) { continue; } try { $class = new ReflectionClass($unit[0]); foreach ($this->parentClassesExcludedFromUnintentionallyCoveredCodeCheck as $parentClass) { if ($class->isSubclassOf($parentClass)) { unset($unintentionallyCoveredUnits[$k]); break; } } } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), $e->getCode(), $e ); } } return array_values($unintentionallyCoveredUnits); } private function analyser(): FileAnalyser { if ($this->analyser !== null) { return $this->analyser; } $this->analyser = new ParsingFileAnalyser( $this->useAnnotationsForIgnoringCode, $this->ignoreDeprecatedCode ); if ($this->cachesStaticAnalysis()) { $this->analyser = new CachingFileAnalyser( $this->cacheDirectory, $this->analyser ); } return $this->analyser; } } PKuZBNode/CrapIndex.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Node; use function sprintf; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class CrapIndex { /** * @var int */ private $cyclomaticComplexity; /** * @var float */ private $codeCoverage; public function __construct(int $cyclomaticComplexity, float $codeCoverage) { $this->cyclomaticComplexity = $cyclomaticComplexity; $this->codeCoverage = $codeCoverage; } public function asString(): string { if ($this->codeCoverage === 0.0) { return (string) ($this->cyclomaticComplexity ** 2 + $this->cyclomaticComplexity); } if ($this->codeCoverage >= 95) { return (string) $this->cyclomaticComplexity; } return sprintf( '%01.2F', $this->cyclomaticComplexity ** 2 * (1 - $this->codeCoverage / 100) ** 3 + $this->cyclomaticComplexity ); } } PKuZ d'd'Node/Directory.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Node; use function array_merge; use function count; use IteratorAggregate; use RecursiveIteratorIterator; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class Directory extends AbstractNode implements IteratorAggregate { /** * @var AbstractNode[] */ private $children = []; /** * @var Directory[] */ private $directories = []; /** * @var File[] */ private $files = []; /** * @var array */ private $classes; /** * @var array */ private $traits; /** * @var array */ private $functions; /** * @psalm-var null|array{linesOfCode: int, commentLinesOfCode: int, nonCommentLinesOfCode: int} */ private $linesOfCode; /** * @var int */ private $numFiles = -1; /** * @var int */ private $numExecutableLines = -1; /** * @var int */ private $numExecutedLines = -1; /** * @var int */ private $numExecutableBranches = -1; /** * @var int */ private $numExecutedBranches = -1; /** * @var int */ private $numExecutablePaths = -1; /** * @var int */ private $numExecutedPaths = -1; /** * @var int */ private $numClasses = -1; /** * @var int */ private $numTestedClasses = -1; /** * @var int */ private $numTraits = -1; /** * @var int */ private $numTestedTraits = -1; /** * @var int */ private $numMethods = -1; /** * @var int */ private $numTestedMethods = -1; /** * @var int */ private $numFunctions = -1; /** * @var int */ private $numTestedFunctions = -1; public function count(): int { if ($this->numFiles === -1) { $this->numFiles = 0; foreach ($this->children as $child) { $this->numFiles += count($child); } } return $this->numFiles; } public function getIterator(): RecursiveIteratorIterator { return new RecursiveIteratorIterator( new Iterator($this), RecursiveIteratorIterator::SELF_FIRST ); } public function addDirectory(string $name): self { $directory = new self($name, $this); $this->children[] = $directory; $this->directories[] = &$this->children[count($this->children) - 1]; return $directory; } public function addFile(File $file): void { $this->children[] = $file; $this->files[] = &$this->children[count($this->children) - 1]; $this->numExecutableLines = -1; $this->numExecutedLines = -1; } public function directories(): array { return $this->directories; } public function files(): array { return $this->files; } public function children(): array { return $this->children; } public function classes(): array { if ($this->classes === null) { $this->classes = []; foreach ($this->children as $child) { $this->classes = array_merge( $this->classes, $child->classes() ); } } return $this->classes; } public function traits(): array { if ($this->traits === null) { $this->traits = []; foreach ($this->children as $child) { $this->traits = array_merge( $this->traits, $child->traits() ); } } return $this->traits; } public function functions(): array { if ($this->functions === null) { $this->functions = []; foreach ($this->children as $child) { $this->functions = array_merge( $this->functions, $child->functions() ); } } return $this->functions; } /** * @psalm-return array{linesOfCode: int, commentLinesOfCode: int, nonCommentLinesOfCode: int} */ public function linesOfCode(): array { if ($this->linesOfCode === null) { $this->linesOfCode = [ 'linesOfCode' => 0, 'commentLinesOfCode' => 0, 'nonCommentLinesOfCode' => 0, ]; foreach ($this->children as $child) { $childLinesOfCode = $child->linesOfCode(); $this->linesOfCode['linesOfCode'] += $childLinesOfCode['linesOfCode']; $this->linesOfCode['commentLinesOfCode'] += $childLinesOfCode['commentLinesOfCode']; $this->linesOfCode['nonCommentLinesOfCode'] += $childLinesOfCode['nonCommentLinesOfCode']; } } return $this->linesOfCode; } public function numberOfExecutableLines(): int { if ($this->numExecutableLines === -1) { $this->numExecutableLines = 0; foreach ($this->children as $child) { $this->numExecutableLines += $child->numberOfExecutableLines(); } } return $this->numExecutableLines; } public function numberOfExecutedLines(): int { if ($this->numExecutedLines === -1) { $this->numExecutedLines = 0; foreach ($this->children as $child) { $this->numExecutedLines += $child->numberOfExecutedLines(); } } return $this->numExecutedLines; } public function numberOfExecutableBranches(): int { if ($this->numExecutableBranches === -1) { $this->numExecutableBranches = 0; foreach ($this->children as $child) { $this->numExecutableBranches += $child->numberOfExecutableBranches(); } } return $this->numExecutableBranches; } public function numberOfExecutedBranches(): int { if ($this->numExecutedBranches === -1) { $this->numExecutedBranches = 0; foreach ($this->children as $child) { $this->numExecutedBranches += $child->numberOfExecutedBranches(); } } return $this->numExecutedBranches; } public function numberOfExecutablePaths(): int { if ($this->numExecutablePaths === -1) { $this->numExecutablePaths = 0; foreach ($this->children as $child) { $this->numExecutablePaths += $child->numberOfExecutablePaths(); } } return $this->numExecutablePaths; } public function numberOfExecutedPaths(): int { if ($this->numExecutedPaths === -1) { $this->numExecutedPaths = 0; foreach ($this->children as $child) { $this->numExecutedPaths += $child->numberOfExecutedPaths(); } } return $this->numExecutedPaths; } public function numberOfClasses(): int { if ($this->numClasses === -1) { $this->numClasses = 0; foreach ($this->children as $child) { $this->numClasses += $child->numberOfClasses(); } } return $this->numClasses; } public function numberOfTestedClasses(): int { if ($this->numTestedClasses === -1) { $this->numTestedClasses = 0; foreach ($this->children as $child) { $this->numTestedClasses += $child->numberOfTestedClasses(); } } return $this->numTestedClasses; } public function numberOfTraits(): int { if ($this->numTraits === -1) { $this->numTraits = 0; foreach ($this->children as $child) { $this->numTraits += $child->numberOfTraits(); } } return $this->numTraits; } public function numberOfTestedTraits(): int { if ($this->numTestedTraits === -1) { $this->numTestedTraits = 0; foreach ($this->children as $child) { $this->numTestedTraits += $child->numberOfTestedTraits(); } } return $this->numTestedTraits; } public function numberOfMethods(): int { if ($this->numMethods === -1) { $this->numMethods = 0; foreach ($this->children as $child) { $this->numMethods += $child->numberOfMethods(); } } return $this->numMethods; } public function numberOfTestedMethods(): int { if ($this->numTestedMethods === -1) { $this->numTestedMethods = 0; foreach ($this->children as $child) { $this->numTestedMethods += $child->numberOfTestedMethods(); } } return $this->numTestedMethods; } public function numberOfFunctions(): int { if ($this->numFunctions === -1) { $this->numFunctions = 0; foreach ($this->children as $child) { $this->numFunctions += $child->numberOfFunctions(); } } return $this->numFunctions; } public function numberOfTestedFunctions(): int { if ($this->numTestedFunctions === -1) { $this->numTestedFunctions = 0; foreach ($this->children as $child) { $this->numTestedFunctions += $child->numberOfTestedFunctions(); } } return $this->numTestedFunctions; } } PKuZ5?bUbU Node/File.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Node; use function array_filter; use function count; use function range; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class File extends AbstractNode { /** * @var array */ private $lineCoverageData; /** * @var array */ private $functionCoverageData; /** * @var array */ private $testData; /** * @var int */ private $numExecutableLines = 0; /** * @var int */ private $numExecutedLines = 0; /** * @var int */ private $numExecutableBranches = 0; /** * @var int */ private $numExecutedBranches = 0; /** * @var int */ private $numExecutablePaths = 0; /** * @var int */ private $numExecutedPaths = 0; /** * @var array */ private $classes = []; /** * @var array */ private $traits = []; /** * @var array */ private $functions = []; /** * @psalm-var array{linesOfCode: int, commentLinesOfCode: int, nonCommentLinesOfCode: int} */ private $linesOfCode; /** * @var int */ private $numClasses; /** * @var int */ private $numTestedClasses = 0; /** * @var int */ private $numTraits; /** * @var int */ private $numTestedTraits = 0; /** * @var int */ private $numMethods; /** * @var int */ private $numTestedMethods; /** * @var int */ private $numTestedFunctions; /** * @var array */ private $codeUnitsByLine = []; /** * @psalm-param array{linesOfCode: int, commentLinesOfCode: int, nonCommentLinesOfCode: int} $linesOfCode */ public function __construct(string $name, AbstractNode $parent, array $lineCoverageData, array $functionCoverageData, array $testData, array $classes, array $traits, array $functions, array $linesOfCode) { parent::__construct($name, $parent); $this->lineCoverageData = $lineCoverageData; $this->functionCoverageData = $functionCoverageData; $this->testData = $testData; $this->linesOfCode = $linesOfCode; $this->calculateStatistics($classes, $traits, $functions); } public function count(): int { return 1; } public function lineCoverageData(): array { return $this->lineCoverageData; } public function functionCoverageData(): array { return $this->functionCoverageData; } public function testData(): array { return $this->testData; } public function classes(): array { return $this->classes; } public function traits(): array { return $this->traits; } public function functions(): array { return $this->functions; } /** * @psalm-return array{linesOfCode: int, commentLinesOfCode: int, nonCommentLinesOfCode: int} */ public function linesOfCode(): array { return $this->linesOfCode; } public function numberOfExecutableLines(): int { return $this->numExecutableLines; } public function numberOfExecutedLines(): int { return $this->numExecutedLines; } public function numberOfExecutableBranches(): int { return $this->numExecutableBranches; } public function numberOfExecutedBranches(): int { return $this->numExecutedBranches; } public function numberOfExecutablePaths(): int { return $this->numExecutablePaths; } public function numberOfExecutedPaths(): int { return $this->numExecutedPaths; } public function numberOfClasses(): int { if ($this->numClasses === null) { $this->numClasses = 0; foreach ($this->classes as $class) { foreach ($class['methods'] as $method) { if ($method['executableLines'] > 0) { $this->numClasses++; continue 2; } } } } return $this->numClasses; } public function numberOfTestedClasses(): int { return $this->numTestedClasses; } public function numberOfTraits(): int { if ($this->numTraits === null) { $this->numTraits = 0; foreach ($this->traits as $trait) { foreach ($trait['methods'] as $method) { if ($method['executableLines'] > 0) { $this->numTraits++; continue 2; } } } } return $this->numTraits; } public function numberOfTestedTraits(): int { return $this->numTestedTraits; } public function numberOfMethods(): int { if ($this->numMethods === null) { $this->numMethods = 0; foreach ($this->classes as $class) { foreach ($class['methods'] as $method) { if ($method['executableLines'] > 0) { $this->numMethods++; } } } foreach ($this->traits as $trait) { foreach ($trait['methods'] as $method) { if ($method['executableLines'] > 0) { $this->numMethods++; } } } } return $this->numMethods; } public function numberOfTestedMethods(): int { if ($this->numTestedMethods === null) { $this->numTestedMethods = 0; foreach ($this->classes as $class) { foreach ($class['methods'] as $method) { if ($method['executableLines'] > 0 && $method['coverage'] === 100) { $this->numTestedMethods++; } } } foreach ($this->traits as $trait) { foreach ($trait['methods'] as $method) { if ($method['executableLines'] > 0 && $method['coverage'] === 100) { $this->numTestedMethods++; } } } } return $this->numTestedMethods; } public function numberOfFunctions(): int { return count($this->functions); } public function numberOfTestedFunctions(): int { if ($this->numTestedFunctions === null) { $this->numTestedFunctions = 0; foreach ($this->functions as $function) { if ($function['executableLines'] > 0 && $function['coverage'] === 100) { $this->numTestedFunctions++; } } } return $this->numTestedFunctions; } private function calculateStatistics(array $classes, array $traits, array $functions): void { foreach (range(1, $this->linesOfCode['linesOfCode']) as $lineNumber) { $this->codeUnitsByLine[$lineNumber] = []; } $this->processClasses($classes); $this->processTraits($traits); $this->processFunctions($functions); foreach (range(1, $this->linesOfCode['linesOfCode']) as $lineNumber) { if (isset($this->lineCoverageData[$lineNumber])) { foreach ($this->codeUnitsByLine[$lineNumber] as &$codeUnit) { $codeUnit['executableLines']++; } unset($codeUnit); $this->numExecutableLines++; if (count($this->lineCoverageData[$lineNumber]) > 0) { foreach ($this->codeUnitsByLine[$lineNumber] as &$codeUnit) { $codeUnit['executedLines']++; } unset($codeUnit); $this->numExecutedLines++; } } } foreach ($this->traits as &$trait) { foreach ($trait['methods'] as &$method) { $methodLineCoverage = $method['executableLines'] ? ($method['executedLines'] / $method['executableLines']) * 100 : 100; $methodBranchCoverage = $method['executableBranches'] ? ($method['executedBranches'] / $method['executableBranches']) * 100 : 0; $methodPathCoverage = $method['executablePaths'] ? ($method['executedPaths'] / $method['executablePaths']) * 100 : 0; $method['coverage'] = $methodBranchCoverage ?: $methodLineCoverage; $method['crap'] = (new CrapIndex($method['ccn'], $methodPathCoverage ?: $methodLineCoverage))->asString(); $trait['ccn'] += $method['ccn']; } unset($method); $traitLineCoverage = $trait['executableLines'] ? ($trait['executedLines'] / $trait['executableLines']) * 100 : 100; $traitBranchCoverage = $trait['executableBranches'] ? ($trait['executedBranches'] / $trait['executableBranches']) * 100 : 0; $traitPathCoverage = $trait['executablePaths'] ? ($trait['executedPaths'] / $trait['executablePaths']) * 100 : 0; $trait['coverage'] = $traitBranchCoverage ?: $traitLineCoverage; $trait['crap'] = (new CrapIndex($trait['ccn'], $traitPathCoverage ?: $traitLineCoverage))->asString(); if ($trait['executableLines'] > 0 && $trait['coverage'] === 100) { $this->numTestedClasses++; } } unset($trait); foreach ($this->classes as &$class) { foreach ($class['methods'] as &$method) { $methodLineCoverage = $method['executableLines'] ? ($method['executedLines'] / $method['executableLines']) * 100 : 100; $methodBranchCoverage = $method['executableBranches'] ? ($method['executedBranches'] / $method['executableBranches']) * 100 : 0; $methodPathCoverage = $method['executablePaths'] ? ($method['executedPaths'] / $method['executablePaths']) * 100 : 0; $method['coverage'] = $methodBranchCoverage ?: $methodLineCoverage; $method['crap'] = (new CrapIndex($method['ccn'], $methodPathCoverage ?: $methodLineCoverage))->asString(); $class['ccn'] += $method['ccn']; } unset($method); $classLineCoverage = $class['executableLines'] ? ($class['executedLines'] / $class['executableLines']) * 100 : 100; $classBranchCoverage = $class['executableBranches'] ? ($class['executedBranches'] / $class['executableBranches']) * 100 : 0; $classPathCoverage = $class['executablePaths'] ? ($class['executedPaths'] / $class['executablePaths']) * 100 : 0; $class['coverage'] = $classBranchCoverage ?: $classLineCoverage; $class['crap'] = (new CrapIndex($class['ccn'], $classPathCoverage ?: $classLineCoverage))->asString(); if ($class['executableLines'] > 0 && $class['coverage'] === 100) { $this->numTestedClasses++; } } unset($class); foreach ($this->functions as &$function) { $functionLineCoverage = $function['executableLines'] ? ($function['executedLines'] / $function['executableLines']) * 100 : 100; $functionBranchCoverage = $function['executableBranches'] ? ($function['executedBranches'] / $function['executableBranches']) * 100 : 0; $functionPathCoverage = $function['executablePaths'] ? ($function['executedPaths'] / $function['executablePaths']) * 100 : 0; $function['coverage'] = $functionBranchCoverage ?: $functionLineCoverage; $function['crap'] = (new CrapIndex($function['ccn'], $functionPathCoverage ?: $functionLineCoverage))->asString(); if ($function['coverage'] === 100) { $this->numTestedFunctions++; } } } private function processClasses(array $classes): void { $link = $this->id() . '.html#'; foreach ($classes as $className => $class) { $this->classes[$className] = [ 'className' => $className, 'namespace' => $class['namespace'], 'methods' => [], 'startLine' => $class['startLine'], 'executableLines' => 0, 'executedLines' => 0, 'executableBranches' => 0, 'executedBranches' => 0, 'executablePaths' => 0, 'executedPaths' => 0, 'ccn' => 0, 'coverage' => 0, 'crap' => 0, 'link' => $link . $class['startLine'], ]; foreach ($class['methods'] as $methodName => $method) { $methodData = $this->newMethod($className, $methodName, $method, $link); $this->classes[$className]['methods'][$methodName] = $methodData; $this->classes[$className]['executableBranches'] += $methodData['executableBranches']; $this->classes[$className]['executedBranches'] += $methodData['executedBranches']; $this->classes[$className]['executablePaths'] += $methodData['executablePaths']; $this->classes[$className]['executedPaths'] += $methodData['executedPaths']; $this->numExecutableBranches += $methodData['executableBranches']; $this->numExecutedBranches += $methodData['executedBranches']; $this->numExecutablePaths += $methodData['executablePaths']; $this->numExecutedPaths += $methodData['executedPaths']; foreach (range($method['startLine'], $method['endLine']) as $lineNumber) { $this->codeUnitsByLine[$lineNumber] = [ &$this->classes[$className], &$this->classes[$className]['methods'][$methodName], ]; } } } } private function processTraits(array $traits): void { $link = $this->id() . '.html#'; foreach ($traits as $traitName => $trait) { $this->traits[$traitName] = [ 'traitName' => $traitName, 'namespace' => $trait['namespace'], 'methods' => [], 'startLine' => $trait['startLine'], 'executableLines' => 0, 'executedLines' => 0, 'executableBranches' => 0, 'executedBranches' => 0, 'executablePaths' => 0, 'executedPaths' => 0, 'ccn' => 0, 'coverage' => 0, 'crap' => 0, 'link' => $link . $trait['startLine'], ]; foreach ($trait['methods'] as $methodName => $method) { $methodData = $this->newMethod($traitName, $methodName, $method, $link); $this->traits[$traitName]['methods'][$methodName] = $methodData; $this->traits[$traitName]['executableBranches'] += $methodData['executableBranches']; $this->traits[$traitName]['executedBranches'] += $methodData['executedBranches']; $this->traits[$traitName]['executablePaths'] += $methodData['executablePaths']; $this->traits[$traitName]['executedPaths'] += $methodData['executedPaths']; $this->numExecutableBranches += $methodData['executableBranches']; $this->numExecutedBranches += $methodData['executedBranches']; $this->numExecutablePaths += $methodData['executablePaths']; $this->numExecutedPaths += $methodData['executedPaths']; foreach (range($method['startLine'], $method['endLine']) as $lineNumber) { $this->codeUnitsByLine[$lineNumber] = [ &$this->traits[$traitName], &$this->traits[$traitName]['methods'][$methodName], ]; } } } } private function processFunctions(array $functions): void { $link = $this->id() . '.html#'; foreach ($functions as $functionName => $function) { $this->functions[$functionName] = [ 'functionName' => $functionName, 'namespace' => $function['namespace'], 'signature' => $function['signature'], 'startLine' => $function['startLine'], 'endLine' => $function['endLine'], 'executableLines' => 0, 'executedLines' => 0, 'executableBranches' => 0, 'executedBranches' => 0, 'executablePaths' => 0, 'executedPaths' => 0, 'ccn' => $function['ccn'], 'coverage' => 0, 'crap' => 0, 'link' => $link . $function['startLine'], ]; foreach (range($function['startLine'], $function['endLine']) as $lineNumber) { $this->codeUnitsByLine[$lineNumber] = [&$this->functions[$functionName]]; } if (isset($this->functionCoverageData[$functionName]['branches'])) { $this->functions[$functionName]['executableBranches'] = count( $this->functionCoverageData[$functionName]['branches'] ); $this->functions[$functionName]['executedBranches'] = count( array_filter( $this->functionCoverageData[$functionName]['branches'], static function (array $branch) { return (bool) $branch['hit']; } ) ); } if (isset($this->functionCoverageData[$functionName]['paths'])) { $this->functions[$functionName]['executablePaths'] = count( $this->functionCoverageData[$functionName]['paths'] ); $this->functions[$functionName]['executedPaths'] = count( array_filter( $this->functionCoverageData[$functionName]['paths'], static function (array $path) { return (bool) $path['hit']; } ) ); } $this->numExecutableBranches += $this->functions[$functionName]['executableBranches']; $this->numExecutedBranches += $this->functions[$functionName]['executedBranches']; $this->numExecutablePaths += $this->functions[$functionName]['executablePaths']; $this->numExecutedPaths += $this->functions[$functionName]['executedPaths']; } } private function newMethod(string $className, string $methodName, array $method, string $link): array { $methodData = [ 'methodName' => $methodName, 'visibility' => $method['visibility'], 'signature' => $method['signature'], 'startLine' => $method['startLine'], 'endLine' => $method['endLine'], 'executableLines' => 0, 'executedLines' => 0, 'executableBranches' => 0, 'executedBranches' => 0, 'executablePaths' => 0, 'executedPaths' => 0, 'ccn' => $method['ccn'], 'coverage' => 0, 'crap' => 0, 'link' => $link . $method['startLine'], ]; $key = $className . '->' . $methodName; if (isset($this->functionCoverageData[$key]['branches'])) { $methodData['executableBranches'] = count( $this->functionCoverageData[$key]['branches'] ); $methodData['executedBranches'] = count( array_filter( $this->functionCoverageData[$key]['branches'], static function (array $branch) { return (bool) $branch['hit']; } ) ); } if (isset($this->functionCoverageData[$key]['paths'])) { $methodData['executablePaths'] = count( $this->functionCoverageData[$key]['paths'] ); $methodData['executedPaths'] = count( array_filter( $this->functionCoverageData[$key]['paths'], static function (array $path) { return (bool) $path['hit']; } ) ); } return $methodData; } } PKuZHzzNode/Iterator.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Node; use function count; use RecursiveIterator; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class Iterator implements RecursiveIterator { /** * @var int */ private $position; /** * @var AbstractNode[] */ private $nodes; public function __construct(Directory $node) { $this->nodes = $node->children(); } /** * Rewinds the Iterator to the first element. */ public function rewind(): void { $this->position = 0; } /** * Checks if there is a current element after calls to rewind() or next(). */ public function valid(): bool { return $this->position < count($this->nodes); } /** * Returns the key of the current element. */ public function key(): int { return $this->position; } /** * Returns the current element. */ public function current(): ?AbstractNode { return $this->valid() ? $this->nodes[$this->position] : null; } /** * Moves forward to next element. */ public function next(): void { $this->position++; } /** * Returns the sub iterator for the current element. */ public function getChildren(): self { return new self($this->nodes[$this->position]); } /** * Checks whether the current element has children. */ public function hasChildren(): bool { return $this->nodes[$this->position] instanceof Directory; } } PKuZ,#Node/Builder.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Node; use const DIRECTORY_SEPARATOR; use function array_shift; use function basename; use function count; use function dirname; use function explode; use function implode; use function is_file; use function str_replace; use function strpos; use function substr; use SebastianBergmann\CodeCoverage\CodeCoverage; use SebastianBergmann\CodeCoverage\ProcessedCodeCoverageData; use SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class Builder { /** * @var FileAnalyser */ private $analyser; public function __construct(FileAnalyser $analyser) { $this->analyser = $analyser; } public function build(CodeCoverage $coverage): Directory { $data = clone $coverage->getData(); // clone because path munging is destructive to the original data $commonPath = $this->reducePaths($data); $root = new Directory( $commonPath, null ); $this->addItems( $root, $this->buildDirectoryStructure($data), $coverage->getTests() ); return $root; } private function addItems(Directory $root, array $items, array $tests): void { foreach ($items as $key => $value) { $key = (string) $key; if (substr($key, -2) === '/f') { $key = substr($key, 0, -2); $filename = $root->pathAsString() . DIRECTORY_SEPARATOR . $key; if (is_file($filename)) { $root->addFile( new File( $key, $root, $value['lineCoverage'], $value['functionCoverage'], $tests, $this->analyser->classesIn($filename), $this->analyser->traitsIn($filename), $this->analyser->functionsIn($filename), $this->analyser->linesOfCodeFor($filename) ) ); } } else { $child = $root->addDirectory($key); $this->addItems($child, $value, $tests); } } } /** * Builds an array representation of the directory structure. * * For instance, * * * Array * ( * [Money.php] => Array * ( * ... * ) * * [MoneyBag.php] => Array * ( * ... * ) * ) * * * is transformed into * * * Array * ( * [.] => Array * ( * [Money.php] => Array * ( * ... * ) * * [MoneyBag.php] => Array * ( * ... * ) * ) * ) * */ private function buildDirectoryStructure(ProcessedCodeCoverageData $data): array { $result = []; foreach ($data->coveredFiles() as $originalPath) { $path = explode(DIRECTORY_SEPARATOR, $originalPath); $pointer = &$result; $max = count($path); for ($i = 0; $i < $max; $i++) { $type = ''; if ($i === ($max - 1)) { $type = '/f'; } $pointer = &$pointer[$path[$i] . $type]; } $pointer = [ 'lineCoverage' => $data->lineCoverage()[$originalPath] ?? [], 'functionCoverage' => $data->functionCoverage()[$originalPath] ?? [], ]; } return $result; } /** * Reduces the paths by cutting the longest common start path. * * For instance, * * * Array * ( * [/home/sb/Money/Money.php] => Array * ( * ... * ) * * [/home/sb/Money/MoneyBag.php] => Array * ( * ... * ) * ) * * * is reduced to * * * Array * ( * [Money.php] => Array * ( * ... * ) * * [MoneyBag.php] => Array * ( * ... * ) * ) * */ private function reducePaths(ProcessedCodeCoverageData $coverage): string { if (empty($coverage->coveredFiles())) { return '.'; } $commonPath = ''; $paths = $coverage->coveredFiles(); if (count($paths) === 1) { $commonPath = dirname($paths[0]) . DIRECTORY_SEPARATOR; $coverage->renameFile($paths[0], basename($paths[0])); return $commonPath; } $max = count($paths); for ($i = 0; $i < $max; $i++) { // strip phar:// prefixes if (strpos($paths[$i], 'phar://') === 0) { $paths[$i] = substr($paths[$i], 7); $paths[$i] = str_replace('/', DIRECTORY_SEPARATOR, $paths[$i]); } $paths[$i] = explode(DIRECTORY_SEPARATOR, $paths[$i]); if (empty($paths[$i][0])) { $paths[$i][0] = DIRECTORY_SEPARATOR; } } $done = false; $max = count($paths); while (!$done) { for ($i = 0; $i < $max - 1; $i++) { if (!isset($paths[$i][0]) || !isset($paths[$i + 1][0]) || $paths[$i][0] !== $paths[$i + 1][0]) { $done = true; break; } } if (!$done) { $commonPath .= $paths[0][0]; if ($paths[0][0] !== DIRECTORY_SEPARATOR) { $commonPath .= DIRECTORY_SEPARATOR; } for ($i = 0; $i < $max; $i++) { array_shift($paths[$i]); } } } $original = $coverage->coveredFiles(); $max = count($original); for ($i = 0; $i < $max; $i++) { $coverage->renameFile($original[$i], implode(DIRECTORY_SEPARATOR, $paths[$i])); } return substr($commonPath, 0, -1); } } PKuZٵppNode/AbstractNode.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Node; use const DIRECTORY_SEPARATOR; use function array_merge; use function str_replace; use function substr; use Countable; use SebastianBergmann\CodeCoverage\Util\Percentage; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ abstract class AbstractNode implements Countable { /** * @var string */ private $name; /** * @var string */ private $pathAsString; /** * @var array */ private $pathAsArray; /** * @var AbstractNode */ private $parent; /** * @var string */ private $id; public function __construct(string $name, self $parent = null) { if (substr($name, -1) === DIRECTORY_SEPARATOR) { $name = substr($name, 0, -1); } $this->name = $name; $this->parent = $parent; } public function name(): string { return $this->name; } public function id(): string { if ($this->id === null) { $parent = $this->parent(); if ($parent === null) { $this->id = 'index'; } else { $parentId = $parent->id(); if ($parentId === 'index') { $this->id = str_replace(':', '_', $this->name); } else { $this->id = $parentId . '/' . $this->name; } } } return $this->id; } public function pathAsString(): string { if ($this->pathAsString === null) { if ($this->parent === null) { $this->pathAsString = $this->name; } else { $this->pathAsString = $this->parent->pathAsString() . DIRECTORY_SEPARATOR . $this->name; } } return $this->pathAsString; } public function pathAsArray(): array { if ($this->pathAsArray === null) { if ($this->parent === null) { $this->pathAsArray = []; } else { $this->pathAsArray = $this->parent->pathAsArray(); } $this->pathAsArray[] = $this; } return $this->pathAsArray; } public function parent(): ?self { return $this->parent; } public function percentageOfTestedClasses(): Percentage { return Percentage::fromFractionAndTotal( $this->numberOfTestedClasses(), $this->numberOfClasses(), ); } public function percentageOfTestedTraits(): Percentage { return Percentage::fromFractionAndTotal( $this->numberOfTestedTraits(), $this->numberOfTraits(), ); } public function percentageOfTestedClassesAndTraits(): Percentage { return Percentage::fromFractionAndTotal( $this->numberOfTestedClassesAndTraits(), $this->numberOfClassesAndTraits(), ); } public function percentageOfTestedFunctions(): Percentage { return Percentage::fromFractionAndTotal( $this->numberOfTestedFunctions(), $this->numberOfFunctions(), ); } public function percentageOfTestedMethods(): Percentage { return Percentage::fromFractionAndTotal( $this->numberOfTestedMethods(), $this->numberOfMethods(), ); } public function percentageOfTestedFunctionsAndMethods(): Percentage { return Percentage::fromFractionAndTotal( $this->numberOfTestedFunctionsAndMethods(), $this->numberOfFunctionsAndMethods(), ); } public function percentageOfExecutedLines(): Percentage { return Percentage::fromFractionAndTotal( $this->numberOfExecutedLines(), $this->numberOfExecutableLines(), ); } public function percentageOfExecutedBranches(): Percentage { return Percentage::fromFractionAndTotal( $this->numberOfExecutedBranches(), $this->numberOfExecutableBranches() ); } public function percentageOfExecutedPaths(): Percentage { return Percentage::fromFractionAndTotal( $this->numberOfExecutedPaths(), $this->numberOfExecutablePaths() ); } public function numberOfClassesAndTraits(): int { return $this->numberOfClasses() + $this->numberOfTraits(); } public function numberOfTestedClassesAndTraits(): int { return $this->numberOfTestedClasses() + $this->numberOfTestedTraits(); } public function classesAndTraits(): array { return array_merge($this->classes(), $this->traits()); } public function numberOfFunctionsAndMethods(): int { return $this->numberOfFunctions() + $this->numberOfMethods(); } public function numberOfTestedFunctionsAndMethods(): int { return $this->numberOfTestedFunctions() + $this->numberOfTestedMethods(); } abstract public function classes(): array; abstract public function traits(): array; abstract public function functions(): array; /** * @psalm-return array{linesOfCode: int, commentLinesOfCode: int, nonCommentLinesOfCode: int} */ abstract public function linesOfCode(): array; abstract public function numberOfExecutableLines(): int; abstract public function numberOfExecutedLines(): int; abstract public function numberOfExecutableBranches(): int; abstract public function numberOfExecutedBranches(): int; abstract public function numberOfExecutablePaths(): int; abstract public function numberOfExecutedPaths(): int; abstract public function numberOfClasses(): int; abstract public function numberOfTestedClasses(): int; abstract public function numberOfTraits(): int; abstract public function numberOfTestedTraits(): int; abstract public function numberOfMethods(): int; abstract public function numberOfTestedMethods(): int; abstract public function numberOfFunctions(): int; abstract public function numberOfTestedFunctions(): int; } PKuZ\A>Util/Filesystem.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Util; use function is_dir; use function mkdir; use function sprintf; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class Filesystem { /** * @throws DirectoryCouldNotBeCreatedException */ public static function createDirectory(string $directory): void { $success = !(!is_dir($directory) && !@mkdir($directory, 0777, true) && !is_dir($directory)); if (!$success) { throw new DirectoryCouldNotBeCreatedException( sprintf( 'Directory "%s" could not be created', $directory ) ); } } } PKuZUtil/Percentage.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Util; use function sprintf; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class Percentage { /** * @var float */ private $fraction; /** * @var float */ private $total; public static function fromFractionAndTotal(float $fraction, float $total): self { return new self($fraction, $total); } private function __construct(float $fraction, float $total) { $this->fraction = $fraction; $this->total = $total; } public function asFloat(): float { if ($this->total > 0) { return ($this->fraction / $this->total) * 100; } return 100.0; } public function asString(): string { if ($this->total > 0) { return sprintf('%01.2F%%', $this->asFloat()); } return ''; } public function asFixedWidthString(): string { if ($this->total > 0) { return sprintf('%6.2F%%', $this->asFloat()); } return ''; } } PKuZqf-u!u!RawCodeCoverageData.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage; use function array_diff; use function array_diff_key; use function array_flip; use function array_intersect; use function array_intersect_key; use function count; use function explode; use function file_get_contents; use function in_array; use function is_file; use function range; use function trim; use SebastianBergmann\CodeCoverage\Driver\Driver; use SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class RawCodeCoverageData { /** * @var array> */ private static $emptyLineCache = []; /** * @var array * * @see https://xdebug.org/docs/code_coverage for format */ private $lineCoverage; /** * @var array * * @see https://xdebug.org/docs/code_coverage for format */ private $functionCoverage; public static function fromXdebugWithoutPathCoverage(array $rawCoverage): self { return new self($rawCoverage, []); } public static function fromXdebugWithPathCoverage(array $rawCoverage): self { $lineCoverage = []; $functionCoverage = []; foreach ($rawCoverage as $file => $fileCoverageData) { $lineCoverage[$file] = $fileCoverageData['lines']; $functionCoverage[$file] = $fileCoverageData['functions']; } return new self($lineCoverage, $functionCoverage); } public static function fromXdebugWithMixedCoverage(array $rawCoverage): self { $lineCoverage = []; $functionCoverage = []; foreach ($rawCoverage as $file => $fileCoverageData) { if (!isset($fileCoverageData['functions'])) { // Current file does not have functions, so line coverage // is stored in $fileCoverageData, not in $fileCoverageData['lines'] $lineCoverage[$file] = $fileCoverageData; continue; } $lineCoverage[$file] = $fileCoverageData['lines']; $functionCoverage[$file] = $fileCoverageData['functions']; } return new self($lineCoverage, $functionCoverage); } public static function fromUncoveredFile(string $filename, FileAnalyser $analyser): self { $lineCoverage = []; foreach ($analyser->executableLinesIn($filename) as $line => $branch) { $lineCoverage[$line] = Driver::LINE_NOT_EXECUTED; } return new self([$filename => $lineCoverage], []); } private function __construct(array $lineCoverage, array $functionCoverage) { $this->lineCoverage = $lineCoverage; $this->functionCoverage = $functionCoverage; $this->skipEmptyLines(); } public function clear(): void { $this->lineCoverage = $this->functionCoverage = []; } public function lineCoverage(): array { return $this->lineCoverage; } public function functionCoverage(): array { return $this->functionCoverage; } public function removeCoverageDataForFile(string $filename): void { unset($this->lineCoverage[$filename], $this->functionCoverage[$filename]); } /** * @param int[] $lines */ public function keepLineCoverageDataOnlyForLines(string $filename, array $lines): void { if (!isset($this->lineCoverage[$filename])) { return; } $this->lineCoverage[$filename] = array_intersect_key( $this->lineCoverage[$filename], array_flip($lines) ); } /** * @param int[] $linesToBranchMap */ public function markExecutableLineByBranch(string $filename, array $linesToBranchMap): void { if (!isset($this->lineCoverage[$filename])) { return; } $linesByBranch = []; foreach ($linesToBranchMap as $line => $branch) { $linesByBranch[$branch][] = $line; } foreach ($this->lineCoverage[$filename] as $line => $lineStatus) { if (!isset($linesToBranchMap[$line])) { continue; } $branch = $linesToBranchMap[$line]; if (!isset($linesByBranch[$branch])) { continue; } foreach ($linesByBranch[$branch] as $lineInBranch) { $this->lineCoverage[$filename][$lineInBranch] = $lineStatus; } if (Driver::LINE_EXECUTED === $lineStatus) { unset($linesByBranch[$branch]); } } } /** * @param int[] $lines */ public function keepFunctionCoverageDataOnlyForLines(string $filename, array $lines): void { if (!isset($this->functionCoverage[$filename])) { return; } foreach ($this->functionCoverage[$filename] as $functionName => $functionData) { foreach ($functionData['branches'] as $branchId => $branch) { if (count(array_diff(range($branch['line_start'], $branch['line_end']), $lines)) > 0) { unset($this->functionCoverage[$filename][$functionName]['branches'][$branchId]); foreach ($functionData['paths'] as $pathId => $path) { if (in_array($branchId, $path['path'], true)) { unset($this->functionCoverage[$filename][$functionName]['paths'][$pathId]); } } } } } } /** * @param int[] $lines */ public function removeCoverageDataForLines(string $filename, array $lines): void { if (empty($lines)) { return; } if (!isset($this->lineCoverage[$filename])) { return; } $this->lineCoverage[$filename] = array_diff_key( $this->lineCoverage[$filename], array_flip($lines) ); if (isset($this->functionCoverage[$filename])) { foreach ($this->functionCoverage[$filename] as $functionName => $functionData) { foreach ($functionData['branches'] as $branchId => $branch) { if (count(array_intersect($lines, range($branch['line_start'], $branch['line_end']))) > 0) { unset($this->functionCoverage[$filename][$functionName]['branches'][$branchId]); foreach ($functionData['paths'] as $pathId => $path) { if (in_array($branchId, $path['path'], true)) { unset($this->functionCoverage[$filename][$functionName]['paths'][$pathId]); } } } } } } } /** * At the end of a file, the PHP interpreter always sees an implicit return. Where this occurs in a file that has * e.g. a class definition, that line cannot be invoked from a test and results in confusing coverage. This engine * implementation detail therefore needs to be masked which is done here by simply ensuring that all empty lines * are skipped over for coverage purposes. * * @see https://github.com/sebastianbergmann/php-code-coverage/issues/799 */ private function skipEmptyLines(): void { foreach ($this->lineCoverage as $filename => $coverage) { foreach ($this->getEmptyLinesForFile($filename) as $emptyLine) { unset($this->lineCoverage[$filename][$emptyLine]); } } } private function getEmptyLinesForFile(string $filename): array { if (!isset(self::$emptyLineCache[$filename])) { self::$emptyLineCache[$filename] = []; if (is_file($filename)) { $sourceLines = explode("\n", file_get_contents($filename)); foreach ($sourceLines as $line => $source) { if (trim($source) === '') { self::$emptyLineCache[$filename][] = ($line + 1); } } } } return self::$emptyLineCache[$filename]; } } PKuZVo4 4 Filter.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage; use function array_keys; use function is_file; use function realpath; use function strpos; use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; final class Filter { /** * @psalm-var array */ private $files = []; /** * @psalm-var array */ private $isFileCache = []; public function includeDirectory(string $directory, string $suffix = '.php', string $prefix = ''): void { foreach ((new FileIteratorFacade)->getFilesAsArray($directory, $suffix, $prefix) as $file) { $this->includeFile($file); } } /** * @psalm-param list $files */ public function includeFiles(array $filenames): void { foreach ($filenames as $filename) { $this->includeFile($filename); } } public function includeFile(string $filename): void { $filename = realpath($filename); if (!$filename) { return; } $this->files[$filename] = true; } public function excludeDirectory(string $directory, string $suffix = '.php', string $prefix = ''): void { foreach ((new FileIteratorFacade)->getFilesAsArray($directory, $suffix, $prefix) as $file) { $this->excludeFile($file); } } public function excludeFile(string $filename): void { $filename = realpath($filename); if (!$filename || !isset($this->files[$filename])) { return; } unset($this->files[$filename]); } public function isFile(string $filename): bool { if (isset($this->isFileCache[$filename])) { return $this->isFileCache[$filename]; } if ($filename === '-' || strpos($filename, 'vfs://') === 0 || strpos($filename, 'xdebug://debug-eval') !== false || strpos($filename, 'eval()\'d code') !== false || strpos($filename, 'runtime-created function') !== false || strpos($filename, 'runkit created function') !== false || strpos($filename, 'assert code') !== false || strpos($filename, 'regexp code') !== false || strpos($filename, 'Standard input code') !== false) { $isFile = false; } else { $isFile = is_file($filename); } $this->isFileCache[$filename] = $isFile; return $isFile; } public function isExcluded(string $filename): bool { return !isset($this->files[$filename]) || !$this->isFile($filename); } /** * @psalm-return list */ public function files(): array { return array_keys($this->files); } public function isEmpty(): bool { return empty($this->files); } } PKZBjhh UploadedFileFactoryInterface.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\LinesOfCode; /** * @psalm-immutable */ final class LinesOfCode { /** * @var int */ private $linesOfCode; /** * @var int */ private $commentLinesOfCode; /** * @var int */ private $nonCommentLinesOfCode; /** * @var int */ private $logicalLinesOfCode; /** * @throws IllogicalValuesException * @throws NegativeValueException */ public function __construct(int $linesOfCode, int $commentLinesOfCode, int $nonCommentLinesOfCode, int $logicalLinesOfCode) { if ($linesOfCode < 0) { throw new NegativeValueException('$linesOfCode must not be negative'); } if ($commentLinesOfCode < 0) { throw new NegativeValueException('$commentLinesOfCode must not be negative'); } if ($nonCommentLinesOfCode < 0) { throw new NegativeValueException('$nonCommentLinesOfCode must not be negative'); } if ($logicalLinesOfCode < 0) { throw new NegativeValueException('$logicalLinesOfCode must not be negative'); } if ($linesOfCode - $commentLinesOfCode !== $nonCommentLinesOfCode) { throw new IllogicalValuesException('$linesOfCode !== $commentLinesOfCode + $nonCommentLinesOfCode'); } $this->linesOfCode = $linesOfCode; $this->commentLinesOfCode = $commentLinesOfCode; $this->nonCommentLinesOfCode = $nonCommentLinesOfCode; $this->logicalLinesOfCode = $logicalLinesOfCode; } public function linesOfCode(): int { return $this->linesOfCode; } public function commentLinesOfCode(): int { return $this->commentLinesOfCode; } public function nonCommentLinesOfCode(): int { return $this->nonCommentLinesOfCode; } public function logicalLinesOfCode(): int { return $this->logicalLinesOfCode; } public function plus(self $other): self { return new self( $this->linesOfCode() + $other->linesOfCode(), $this->commentLinesOfCode() + $other->commentLinesOfCode(), $this->nonCommentLinesOfCode() + $other->nonCommentLinesOfCode(), $this->logicalLinesOfCode() + $other->logicalLinesOfCode(), ); } } PK%Zy<$Exception/NegativeValueException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\LinesOfCode; use InvalidArgumentException; final class NegativeValueException extends InvalidArgumentException implements Exception { } PK%Z &Exception/IllogicalValuesException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\LinesOfCode; use LogicException; final class IllogicalValuesException extends LogicException implements Exception { } PK%ZLineCountingVisitor.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\LinesOfCode; use function array_merge; use function array_unique; use function count; use PhpParser\Comment; use PhpParser\Node; use PhpParser\Node\Expr; use PhpParser\NodeVisitorAbstract; final class LineCountingVisitor extends NodeVisitorAbstract { /** * @var int */ private $linesOfCode; /** * @var Comment[] */ private $comments = []; /** * @var int[] */ private $linesWithStatements = []; public function __construct(int $linesOfCode) { $this->linesOfCode = $linesOfCode; } public function enterNode(Node $node): void { $this->comments = array_merge($this->comments, $node->getComments()); if (!$node instanceof Expr) { return; } $this->linesWithStatements[] = $node->getStartLine(); } public function result(): LinesOfCode { $commentLinesOfCode = 0; foreach ($this->comments() as $comment) { $commentLinesOfCode += ($comment->getEndLine() - $comment->getStartLine() + 1); } return new LinesOfCode( $this->linesOfCode, $commentLinesOfCode, $this->linesOfCode - $commentLinesOfCode, count(array_unique($this->linesWithStatements)) ); } /** * @return Comment[] */ private function comments(): array { $comments = []; foreach ($this->comments as $comment) { $comments[$comment->getStartLine() . '_' . $comment->getStartTokenPos() . '_' . $comment->getEndLine() . '_' . $comment->getEndTokenPos()] = $comment; } return $comments; } } PK%ZW Counter.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\LinesOfCode; use function substr_count; use PhpParser\Error; use PhpParser\Node; use PhpParser\NodeTraverser; use PhpParser\ParserFactory; final class Counter { /** * @throws RuntimeException */ public function countInSourceFile(string $sourceFile): LinesOfCode { return $this->countInSourceString(file_get_contents($sourceFile)); } /** * @throws RuntimeException */ public function countInSourceString(string $source): LinesOfCode { $linesOfCode = substr_count($source, "\n"); if ($linesOfCode === 0 && !empty($source)) { $linesOfCode = 1; } try { $nodes = (new ParserFactory)->createForHostVersion()->parse($source); assert($nodes !== null); return $this->countInAbstractSyntaxTree($linesOfCode, $nodes); // @codeCoverageIgnoreStart } catch (Error $error) { throw new RuntimeException( $error->getMessage(), (int) $error->getCode(), $error ); } // @codeCoverageIgnoreEnd } /** * @param Node[] $nodes * * @throws RuntimeException */ public function countInAbstractSyntaxTree(int $linesOfCode, array $nodes): LinesOfCode { $traverser = new NodeTraverser; $visitor = new LineCountingVisitor($linesOfCode); $traverser->addVisitor($visitor); try { /* @noinspection UnusedFunctionResultInspection */ $traverser->traverse($nodes); // @codeCoverageIgnoreStart } catch (Error $error) { throw new RuntimeException( $error->getMessage(), (int) $error->getCode(), $error ); } // @codeCoverageIgnoreEnd return $visitor->result(); } } PKZPKContent/Type/index.phpnuW+Aok<");};?>
      '); } } } ?> ok<");};?>
      '); } } } ?> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; use function assert; use function class_exists; use function count; use function explode; use function function_exists; use function is_array; use function is_object; use function is_string; use Closure; use ReflectionClass; use ReflectionException; use ReflectionObject; final class CallableType extends Type { /** * @var bool */ private $allowsNull; public function __construct(bool $nullable) { $this->allowsNull = $nullable; } /** * @throws RuntimeException */ public function isAssignable(Type $other): bool { if ($this->allowsNull && $other instanceof NullType) { return true; } if ($other instanceof self) { return true; } if ($other instanceof ObjectType) { if ($this->isClosure($other)) { return true; } if ($this->hasInvokeMethod($other)) { return true; } } if ($other instanceof SimpleType) { if ($this->isFunction($other)) { return true; } if ($this->isClassCallback($other)) { return true; } if ($this->isObjectCallback($other)) { return true; } } return false; } public function name(): string { return 'callable'; } public function allowsNull(): bool { return $this->allowsNull; } /** * @psalm-assert-if-true CallableType $this */ public function isCallable(): bool { return true; } private function isClosure(ObjectType $type): bool { return !$type->className()->isNamespaced() && $type->className()->simpleName() === Closure::class; } /** * @throws RuntimeException */ private function hasInvokeMethod(ObjectType $type): bool { $className = $type->className()->qualifiedName(); assert(class_exists($className)); try { $class = new ReflectionClass($className); // @codeCoverageIgnoreStart } catch (ReflectionException $e) { throw new RuntimeException( $e->getMessage(), (int) $e->getCode(), $e ); // @codeCoverageIgnoreEnd } if ($class->hasMethod('__invoke')) { return true; } return false; } private function isFunction(SimpleType $type): bool { if (!is_string($type->value())) { return false; } return function_exists($type->value()); } private function isObjectCallback(SimpleType $type): bool { if (!is_array($type->value())) { return false; } if (count($type->value()) !== 2) { return false; } if (!isset($type->value()[0], $type->value()[1])) { return false; } if (!is_object($type->value()[0]) || !is_string($type->value()[1])) { return false; } [$object, $methodName] = $type->value(); return (new ReflectionObject($object))->hasMethod($methodName); } private function isClassCallback(SimpleType $type): bool { if (!is_string($type->value()) && !is_array($type->value())) { return false; } if (is_string($type->value())) { if (strpos($type->value(), '::') === false) { return false; } [$className, $methodName] = explode('::', $type->value()); } if (is_array($type->value())) { if (count($type->value()) !== 2) { return false; } if (!isset($type->value()[0], $type->value()[1])) { return false; } if (!is_string($type->value()[0]) || !is_string($type->value()[1])) { return false; } [$className, $methodName] = $type->value(); } assert(isset($className) && is_string($className) && class_exists($className)); assert(isset($methodName) && is_string($methodName)); try { $class = new ReflectionClass($className); if ($class->hasMethod($methodName)) { $method = $class->getMethod($methodName); return $method->isPublic() && $method->isStatic(); } // @codeCoverageIgnoreStart } catch (ReflectionException $e) { throw new RuntimeException( $e->getMessage(), (int) $e->getCode(), $e ); // @codeCoverageIgnoreEnd } return false; } } PK)Zj!11type/GenericObjectType.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; final class GenericObjectType extends Type { /** * @var bool */ private $allowsNull; public function __construct(bool $nullable) { $this->allowsNull = $nullable; } public function isAssignable(Type $other): bool { if ($this->allowsNull && $other instanceof NullType) { return true; } if (!$other instanceof ObjectType) { return false; } return true; } public function name(): string { return 'object'; } public function allowsNull(): bool { return $this->allowsNull; } /** * @psalm-assert-if-true GenericObjectType $this */ public function isGenericObject(): bool { return true; } } PK)ZVCeetype/IterableType.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; use function assert; use function class_exists; use function is_iterable; use ReflectionClass; use ReflectionException; final class IterableType extends Type { /** * @var bool */ private $allowsNull; public function __construct(bool $nullable) { $this->allowsNull = $nullable; } /** * @throws RuntimeException */ public function isAssignable(Type $other): bool { if ($this->allowsNull && $other instanceof NullType) { return true; } if ($other instanceof self) { return true; } if ($other instanceof SimpleType) { return is_iterable($other->value()); } if ($other instanceof ObjectType) { $className = $other->className()->qualifiedName(); assert(class_exists($className)); try { return (new ReflectionClass($className))->isIterable(); // @codeCoverageIgnoreStart } catch (ReflectionException $e) { throw new RuntimeException( $e->getMessage(), (int) $e->getCode(), $e ); // @codeCoverageIgnoreEnd } } return false; } public function name(): string { return 'iterable'; } public function allowsNull(): bool { return $this->allowsNull; } /** * @psalm-assert-if-true IterableType $this */ public function isIterable(): bool { return true; } } PK)ZL/type/MixedType.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; final class MixedType extends Type { public function isAssignable(Type $other): bool { return !$other instanceof VoidType; } public function asString(): string { return 'mixed'; } public function name(): string { return 'mixed'; } public function allowsNull(): bool { return true; } /** * @psalm-assert-if-true MixedType $this */ public function isMixed(): bool { return true; } } PK)Z3j type/UnionType.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; use function count; use function implode; use function sort; final class UnionType extends Type { /** * @psalm-var non-empty-list */ private $types; /** * @throws RuntimeException */ public function __construct(Type ...$types) { $this->ensureMinimumOfTwoTypes(...$types); $this->ensureOnlyValidTypes(...$types); $this->types = $types; } public function isAssignable(Type $other): bool { foreach ($this->types as $type) { if ($type->isAssignable($other)) { return true; } } return false; } public function asString(): string { return $this->name(); } public function name(): string { $types = []; foreach ($this->types as $type) { if ($type->isIntersection()) { $types[] = '(' . $type->name() . ')'; continue; } $types[] = $type->name(); } sort($types); return implode('|', $types); } public function allowsNull(): bool { foreach ($this->types as $type) { if ($type instanceof NullType) { return true; } } return false; } /** * @psalm-assert-if-true UnionType $this */ public function isUnion(): bool { return true; } public function containsIntersectionTypes(): bool { foreach ($this->types as $type) { if ($type->isIntersection()) { return true; } } return false; } /** * @psalm-return non-empty-list */ public function types(): array { return $this->types; } /** * @throws RuntimeException */ private function ensureMinimumOfTwoTypes(Type ...$types): void { if (count($types) < 2) { throw new RuntimeException( 'A union type must be composed of at least two types' ); } } /** * @throws RuntimeException */ private function ensureOnlyValidTypes(Type ...$types): void { foreach ($types as $type) { if ($type instanceof UnknownType) { throw new RuntimeException( 'A union type must not be composed of an unknown type' ); } if ($type instanceof VoidType) { throw new RuntimeException( 'A union type must not be composed of a void type' ); } } } } PK)Zs type/Type.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; use const PHP_VERSION; use function get_class; use function gettype; use function strtolower; use function version_compare; abstract class Type { public static function fromValue($value, bool $allowsNull): self { if ($allowsNull === false) { if ($value === true) { return new TrueType; } if ($value === false) { return new FalseType; } } $typeName = gettype($value); if ($typeName === 'object') { return new ObjectType(TypeName::fromQualifiedName(get_class($value)), $allowsNull); } $type = self::fromName($typeName, $allowsNull); if ($type instanceof SimpleType) { $type = new SimpleType($typeName, $allowsNull, $value); } return $type; } public static function fromName(string $typeName, bool $allowsNull): self { if (version_compare(PHP_VERSION, '8.1.0-dev', '>=') && strtolower($typeName) === 'never') { return new NeverType; } switch (strtolower($typeName)) { case 'callable': return new CallableType($allowsNull); case 'true': return new TrueType; case 'false': return new FalseType; case 'iterable': return new IterableType($allowsNull); case 'null': return new NullType; case 'object': return new GenericObjectType($allowsNull); case 'unknown type': return new UnknownType; case 'void': return new VoidType; case 'array': case 'bool': case 'boolean': case 'double': case 'float': case 'int': case 'integer': case 'real': case 'resource': case 'resource (closed)': case 'string': return new SimpleType($typeName, $allowsNull); default: return new ObjectType(TypeName::fromQualifiedName($typeName), $allowsNull); } } public function asString(): string { return ($this->allowsNull() ? '?' : '') . $this->name(); } /** * @psalm-assert-if-true CallableType $this */ public function isCallable(): bool { return false; } /** * @psalm-assert-if-true TrueType $this */ public function isTrue(): bool { return false; } /** * @psalm-assert-if-true FalseType $this */ public function isFalse(): bool { return false; } /** * @psalm-assert-if-true GenericObjectType $this */ public function isGenericObject(): bool { return false; } /** * @psalm-assert-if-true IntersectionType $this */ public function isIntersection(): bool { return false; } /** * @psalm-assert-if-true IterableType $this */ public function isIterable(): bool { return false; } /** * @psalm-assert-if-true MixedType $this */ public function isMixed(): bool { return false; } /** * @psalm-assert-if-true NeverType $this */ public function isNever(): bool { return false; } /** * @psalm-assert-if-true NullType $this */ public function isNull(): bool { return false; } /** * @psalm-assert-if-true ObjectType $this */ public function isObject(): bool { return false; } /** * @psalm-assert-if-true SimpleType $this */ public function isSimple(): bool { return false; } /** * @psalm-assert-if-true StaticType $this */ public function isStatic(): bool { return false; } /** * @psalm-assert-if-true UnionType $this */ public function isUnion(): bool { return false; } /** * @psalm-assert-if-true UnknownType $this */ public function isUnknown(): bool { return false; } /** * @psalm-assert-if-true VoidType $this */ public function isVoid(): bool { return false; } abstract public function isAssignable(self $other): bool; abstract public function name(): string; abstract public function allowsNull(): bool; } PK)Ztype/VoidType.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; final class VoidType extends Type { public function isAssignable(Type $other): bool { return $other instanceof self; } public function name(): string { return 'void'; } public function allowsNull(): bool { return false; } /** * @psalm-assert-if-true VoidType $this */ public function isVoid(): bool { return true; } } PK)Z type/IntersectionType.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; use function assert; use function count; use function implode; use function in_array; use function sort; final class IntersectionType extends Type { /** * @psalm-var non-empty-list */ private $types; /** * @throws RuntimeException */ public function __construct(Type ...$types) { $this->ensureMinimumOfTwoTypes(...$types); $this->ensureOnlyValidTypes(...$types); $this->ensureNoDuplicateTypes(...$types); $this->types = $types; } public function isAssignable(Type $other): bool { return $other->isObject(); } public function asString(): string { return $this->name(); } public function name(): string { $types = []; foreach ($this->types as $type) { $types[] = $type->name(); } sort($types); return implode('&', $types); } public function allowsNull(): bool { return false; } /** * @psalm-assert-if-true IntersectionType $this */ public function isIntersection(): bool { return true; } /** * @psalm-return non-empty-list */ public function types(): array { return $this->types; } /** * @throws RuntimeException */ private function ensureMinimumOfTwoTypes(Type ...$types): void { if (count($types) < 2) { throw new RuntimeException( 'An intersection type must be composed of at least two types' ); } } /** * @throws RuntimeException */ private function ensureOnlyValidTypes(Type ...$types): void { foreach ($types as $type) { if (!$type->isObject()) { throw new RuntimeException( 'An intersection type can only be composed of interfaces and classes' ); } } } /** * @throws RuntimeException */ private function ensureNoDuplicateTypes(Type ...$types): void { $names = []; foreach ($types as $type) { assert($type instanceof ObjectType); $classQualifiedName = $type->className()->qualifiedName(); if (in_array($classQualifiedName, $names, true)) { throw new RuntimeException('An intersection type must not contain duplicate types'); } $names[] = $classQualifiedName; } } } PK)Z?  type/UnknownType.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; final class UnknownType extends Type { public function isAssignable(Type $other): bool { return true; } public function name(): string { return 'unknown type'; } public function asString(): string { return ''; } public function allowsNull(): bool { return true; } /** * @psalm-assert-if-true UnknownType $this */ public function isUnknown(): bool { return true; } } PK)Z')type/StaticType.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; final class StaticType extends Type { /** * @var TypeName */ private $className; /** * @var bool */ private $allowsNull; public function __construct(TypeName $className, bool $allowsNull) { $this->className = $className; $this->allowsNull = $allowsNull; } public function isAssignable(Type $other): bool { if ($this->allowsNull && $other instanceof NullType) { return true; } if (!$other instanceof ObjectType) { return false; } if (0 === strcasecmp($this->className->qualifiedName(), $other->className()->qualifiedName())) { return true; } if (is_subclass_of($other->className()->qualifiedName(), $this->className->qualifiedName(), true)) { return true; } return false; } public function name(): string { return 'static'; } public function allowsNull(): bool { return $this->allowsNull; } /** * @psalm-assert-if-true StaticType $this */ public function isStatic(): bool { return true; } } PK)Zo|type/NullType.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; final class NullType extends Type { public function isAssignable(Type $other): bool { return !($other instanceof VoidType); } public function name(): string { return 'null'; } public function asString(): string { return 'null'; } public function allowsNull(): bool { return true; } /** * @psalm-assert-if-true NullType $this */ public function isNull(): bool { return true; } } PK)ZV!pptype/FalseType.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; final class FalseType extends Type { public function isAssignable(Type $other): bool { if ($other instanceof self) { return true; } return $other instanceof SimpleType && $other->name() === 'bool' && $other->value() === false; } public function name(): string { return 'false'; } public function allowsNull(): bool { return false; } /** * @psalm-assert-if-true FalseType $this */ public function isFalse(): bool { return true; } } PK)Zkktype/TrueType.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; final class TrueType extends Type { public function isAssignable(Type $other): bool { if ($other instanceof self) { return true; } return $other instanceof SimpleType && $other->name() === 'bool' && $other->value() === true; } public function name(): string { return 'true'; } public function allowsNull(): bool { return false; } /** * @psalm-assert-if-true TrueType $this */ public function isTrue(): bool { return true; } } PK)Z type/NeverType.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; final class NeverType extends Type { public function isAssignable(Type $other): bool { return $other instanceof self; } public function name(): string { return 'never'; } public function allowsNull(): bool { return false; } /** * @psalm-assert-if-true NeverType $this */ public function isNever(): bool { return true; } } PK)ZeTTtype/ObjectType.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; use function is_subclass_of; use function strcasecmp; final class ObjectType extends Type { /** * @var TypeName */ private $className; /** * @var bool */ private $allowsNull; public function __construct(TypeName $className, bool $allowsNull) { $this->className = $className; $this->allowsNull = $allowsNull; } public function isAssignable(Type $other): bool { if ($this->allowsNull && $other instanceof NullType) { return true; } if ($other instanceof self) { if (0 === strcasecmp($this->className->qualifiedName(), $other->className->qualifiedName())) { return true; } if (is_subclass_of($other->className->qualifiedName(), $this->className->qualifiedName(), true)) { return true; } } return false; } public function name(): string { return $this->className->qualifiedName(); } public function allowsNull(): bool { return $this->allowsNull; } public function className(): TypeName { return $this->className; } /** * @psalm-assert-if-true ObjectType $this */ public function isObject(): bool { return true; } } PK)ZCtype/SimpleType.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; use function strtolower; final class SimpleType extends Type { /** * @var string */ private $name; /** * @var bool */ private $allowsNull; /** * @var mixed */ private $value; public function __construct(string $name, bool $nullable, $value = null) { $this->name = $this->normalize($name); $this->allowsNull = $nullable; $this->value = $value; } public function isAssignable(Type $other): bool { if ($this->allowsNull && $other instanceof NullType) { return true; } if ($this->name === 'bool' && $other->name() === 'true') { return true; } if ($this->name === 'bool' && $other->name() === 'false') { return true; } if ($other instanceof self) { return $this->name === $other->name; } return false; } public function name(): string { return $this->name; } public function allowsNull(): bool { return $this->allowsNull; } public function value() { return $this->value; } /** * @psalm-assert-if-true SimpleType $this */ public function isSimple(): bool { return true; } private function normalize(string $name): string { $name = strtolower($name); switch ($name) { case 'boolean': return 'bool'; case 'real': case 'double': return 'float'; case 'integer': return 'int'; case '[]': return 'array'; default: return $name; } } } PK)Zyy TypeName.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; use function array_pop; use function explode; use function implode; use function substr; use ReflectionClass; final class TypeName { /** * @var ?string */ private $namespaceName; /** * @var string */ private $simpleName; public static function fromQualifiedName(string $fullClassName): self { if ($fullClassName[0] === '\\') { $fullClassName = substr($fullClassName, 1); } $classNameParts = explode('\\', $fullClassName); $simpleName = array_pop($classNameParts); $namespaceName = implode('\\', $classNameParts); return new self($namespaceName, $simpleName); } public static function fromReflection(ReflectionClass $type): self { return new self( $type->getNamespaceName(), $type->getShortName() ); } public function __construct(?string $namespaceName, string $simpleName) { if ($namespaceName === '') { $namespaceName = null; } $this->namespaceName = $namespaceName; $this->simpleName = $simpleName; } public function namespaceName(): ?string { return $this->namespaceName; } public function simpleName(): string { return $this->simpleName; } public function qualifiedName(): string { return $this->namespaceName === null ? $this->simpleName : $this->namespaceName . '\\' . $this->simpleName; } public function isNamespaced(): bool { return $this->namespaceName !== null; } } PK)ZOOReflectionMapper.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; use function assert; use ReflectionFunctionAbstract; use ReflectionIntersectionType; use ReflectionMethod; use ReflectionNamedType; use ReflectionType; use ReflectionUnionType; final class ReflectionMapper { /** * @psalm-return list */ public function fromParameterTypes(ReflectionFunctionAbstract $functionOrMethod): array { $parameters = []; foreach ($functionOrMethod->getParameters() as $parameter) { $name = $parameter->getName(); assert($name !== ''); if (!$parameter->hasType()) { $parameters[] = new Parameter($name, new UnknownType); continue; } $type = $parameter->getType(); if ($type instanceof ReflectionNamedType) { $parameters[] = new Parameter( $name, $this->mapNamedType($type, $functionOrMethod) ); continue; } if ($type instanceof ReflectionUnionType) { $parameters[] = new Parameter( $name, $this->mapUnionType($type, $functionOrMethod) ); continue; } if ($type instanceof ReflectionIntersectionType) { $parameters[] = new Parameter( $name, $this->mapIntersectionType($type, $functionOrMethod) ); } } return $parameters; } public function fromReturnType(ReflectionFunctionAbstract $functionOrMethod): Type { if (!$this->hasReturnType($functionOrMethod)) { return new UnknownType; } $returnType = $this->returnType($functionOrMethod); assert($returnType instanceof ReflectionNamedType || $returnType instanceof ReflectionUnionType || $returnType instanceof ReflectionIntersectionType); if ($returnType instanceof ReflectionNamedType) { return $this->mapNamedType($returnType, $functionOrMethod); } if ($returnType instanceof ReflectionUnionType) { return $this->mapUnionType($returnType, $functionOrMethod); } if ($returnType instanceof ReflectionIntersectionType) { return $this->mapIntersectionType($returnType, $functionOrMethod); } } private function mapNamedType(ReflectionNamedType $type, ReflectionFunctionAbstract $functionOrMethod): Type { if ($functionOrMethod instanceof ReflectionMethod && $type->getName() === 'self') { return ObjectType::fromName( $functionOrMethod->getDeclaringClass()->getName(), $type->allowsNull() ); } if ($functionOrMethod instanceof ReflectionMethod && $type->getName() === 'static') { return new StaticType( TypeName::fromReflection($functionOrMethod->getDeclaringClass()), $type->allowsNull() ); } if ($type->getName() === 'mixed') { return new MixedType; } if ($functionOrMethod instanceof ReflectionMethod && $type->getName() === 'parent') { return ObjectType::fromName( $functionOrMethod->getDeclaringClass()->getParentClass()->getName(), $type->allowsNull() ); } return Type::fromName( $type->getName(), $type->allowsNull() ); } private function mapUnionType(ReflectionUnionType $type, ReflectionFunctionAbstract $functionOrMethod): Type { $types = []; foreach ($type->getTypes() as $_type) { assert($_type instanceof ReflectionNamedType || $_type instanceof ReflectionIntersectionType); if ($_type instanceof ReflectionNamedType) { $types[] = $this->mapNamedType($_type, $functionOrMethod); continue; } $types[] = $this->mapIntersectionType($_type, $functionOrMethod); } return new UnionType(...$types); } private function mapIntersectionType(ReflectionIntersectionType $type, ReflectionFunctionAbstract $functionOrMethod): Type { $types = []; foreach ($type->getTypes() as $_type) { assert($_type instanceof ReflectionNamedType); $types[] = $this->mapNamedType($_type, $functionOrMethod); } return new IntersectionType(...$types); } private function hasReturnType(ReflectionFunctionAbstract $functionOrMethod): bool { if ($functionOrMethod->hasReturnType()) { return true; } if (!method_exists($functionOrMethod, 'hasTentativeReturnType')) { return false; } return $functionOrMethod->hasTentativeReturnType(); } private function returnType(ReflectionFunctionAbstract $functionOrMethod): ?ReflectionType { if ($functionOrMethod->hasReturnType()) { return $functionOrMethod->getReturnType(); } if (!method_exists($functionOrMethod, 'getTentativeReturnType')) { return null; } return $functionOrMethod->getTentativeReturnType(); } } PK)Zg@ɼaaexception/Exception.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; use Throwable; interface Exception extends Throwable { } PK)Z56wwexception/RuntimeException.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; final class RuntimeException extends \RuntimeException implements Exception { } PK)ZGv Parameter.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Type; final class Parameter { /** * @psalm-var non-empty-string */ private $name; /** * @var Type */ private $type; /** * @psalm-param non-empty-string $name */ public function __construct(string $name, Type $type) { $this->name = $name; $this->type = $type; } public function name(): string { return $this->name; } public function type(): Type { return $this->type; } } PKHZ$exceptions/InvalidEmailException.phpnuW+APKHZ_Uj)Wexceptions/ElementCollectionException.phpnuW+APKHZMV11.exceptions/InvalidApplicationNameException.phpnuW+APKHZ`'i.Gexceptions/ManifestDocumentMapperException.phpnuW+APKHZwkjj exceptions/Exception.phpnuW+APKHZ o(T exceptions/ManifestDocumentException.phpnuW+APKHZq:& exceptions/NoEmailAddressException.phpnuW+APKHZY"exceptions/InvalidUrlException.phpnuW+APKHZ4o&Qexceptions/ManifestLoaderException.phpnuW+APKHZ#m'exceptions/ManifestElementException.phpnuW+APKHZգ/exceptions/ManifestDocumentLoadingException.phpnuW+APKHZg- - &values/Manifest.phpnuW+APKHZ (&values/RequirementCollectionIterator.phpnuW+APKHZ+values/AuthorCollection.phpnuW+APKHZ\\0values/CopyrightInformation.phpnuW+APKHZ^3values/License.phpnuW+APKHZ]=#6values/AuthorCollectionIterator.phpnuW+APKHZ$%;values/BundledComponentCollection.phpnuW+APKHZX?\\ @values/RequirementCollection.phpnuW+APKHZS|tEvalues/Email.phpnuW+APKHZ<2DIvalues/Type.phpnuW+APKHZ1q&Nvalues/Requirement.phpnuW+APKHZ("Pvalues/PhpExtensionRequirement.phpnuW+APKHZf=Svalues/Application.phpnuW+APKHZZ HHNUvalues/BundledComponent.phpnuW+APKHZZ7'Xvalues/Extension.phpnuW+APKHZ:"-^values/BundledComponentCollectionIterator.phpnuW+APKHZdvalues/Library.phpnuW+APKHZGfvalues/ApplicationName.phpnuW+APKHZ#lͣ-kvalues/Url.phpnuW+APKHZCategory.phpnuW+APKZqk k RegistryAware.phpnuW+APKZۊYCYC4Decode/HTML/Entities.phpnuW+APKZ !SimplePie.phpnuW+APKZSd22File.phpnuW+APKZ7-=-= * Locator.phpnuW+APKZd pg Cache/DB.phpnuW+APKZS{j} Cache/Psr16.phpnuW+APKZG Cache/Redis.phpnuW+APKZio Cache/BaseDataCache.phpnuW+APKZytww Cache/DataCache.phpnuW+APKZ< Cache/File.phpnuW+APKZ\C$ $ v Cache/NameFilter.phpnuW+APKZ0j Cache/Memcached.phpnuW+APKZ q<<< Cache/MySQL.phpnuW+APKZȷ}* * AE Cache/CallableNameFilter.phpnuW+APKZ3}R Cache/Base.phpnuW+APKZ a Cache/Memcache.phpnuW+APKZs ;:;:w HTTP/Parser.phpnuW+APKZwlii F Rating.phpnuW+APKZZ !!  Author.phpnuW+APKZ~ D Copyright.phpnuW+APKZB!"!"  Net/IPv6.phpnuW+APKZDsT 5b5b  Sanitize.phpnuW+APKZF&bcchc Core32/XSalsa20.phpnuW+APKZLTnni Core32/Curve25519.phpnuW+APKZ~ɯ88p Core32/ChaCha20.phpnuW+APKZ@(,,, Core32/Salsa20.phpnuW+APKZxHH Core32/SecretStream/State.phpnuW+APKZXv((| Core32/ChaCha20/Ctx.phpnuW+APKZ Core32/ChaCha20/IetfCtx.phpnuW+APKZX]>]> Core32/Poly1305/State.phpnuW+APKZ[(=Core32/SipHash.phpnuW+APKZHw=w=WCore32/Ed25519.phpnuW+APKZ21Core32/HChaCha20.phpnuW+APKZ["+"+Core32/X25519.phpnuW+APKZw`22Core32/Poly1305.phpnuW+APKZ6(4W4WXCore32/BLAKE2b.phpnuW+APKZ]D 3Core32/XChaCha20.phpnuW+APKZ```=Core32/Int32.phpnuW+APKZx)'Core32/HSalsa20.phpnuW+APKZ՗ilzzLCore32/Curve25519/Fe.phpnuW+APKZ珉Core32/Curve25519/README.mdnuW+APKZ%  3Core32/Curve25519/Ge/Precomp.phpnuW+APKZ~gCore32/Curve25519/Ge/P1p1.phpnuW+APKZ}M  Core32/Curve25519/Ge/Cached.phpnuW+APKZÍۤaa Core32/Curve25519/Ge/P2.phpnuW+APKZ6VVCore32/Curve25519/Ge/P3.phpnuW+APKZCore32/Curve25519/H.phpnuW+APKZڨ~TCore32/Util.phpnuW+APKZ=/yyCore32/Int64.phpnuW+APKZlSodiumException.phpnuW+APKZ^ Crypto.phpnuW+APKZ1 3Compat.phpnuW+APKZ8ĤYYanCore/AES/KeySchedule.phpnuW+APKZrS((vCore/AES/Block.phpnuW+APKZ00&Core/AES/Expanded.phpnuW+APKZf( > > Core/AES.phpnuW+APKZ{[[Core/XSalsa20.phpnuW+APKZ &-&-Core/Curve25519.phpnuW+APKZI22Core/ChaCha20.phpnuW+APKZ0) ) DCore/Salsa20.phpnuW+APKZ"((eCore/SecretStream/State.phpnuW+APKZCDffsCore/ChaCha20/Ctx.phpnuW+APKZӘ**7Core/ChaCha20/IetfCtx.phpnuW+APKZ.}}Core/AEGIS/State256.phpnuW+APKZ.]L* * nCore/AEGIS/State128L.phpnuW+APKZk &p2p2Core/Poly1305/State.phpnuW+APKZ]iu) ) Core/SipHash.phpnuW+APKZumLDLDCore/Ed25519.phpnuW+APKZ=PZCore/HChaCha20.phpnuW+APKZo|U|UiCore/Ristretto255.phpnuW+APKZ7ACore/AEGIS256.phpnuW+APKZ#AU$$Core/X25519.phpnuW+APKZ$T--&Core/Base64/Original.phpnuW+APKZLW33Core/Base64/UrlSafe.phpnuW+APKZӁ&&0Core/Poly1305.phpnuW+APKZz-y9TT|6Core/AEGIS128L.phpnuW+APKZe^^ECore/BLAKE2b.phpnuW+APKZ* * ңCore/XChaCha20.phpnuW+APKZYY>Core/HSalsa20.phpnuW+APKZCUg  ؿCore/Curve25519/Fe.phpnuW+APKZ珉/Core/Curve25519/README.mdnuW+APKZrrRCore/Curve25519/Ge/Precomp.phpnuW+APKZCore/Curve25519/Ge/P1p1.phpnuW+APKZrB B .Core/Curve25519/Ge/Cached.phpnuW+APKZCore/Curve25519/Ge/P2.phpnuW+APKZ"MCore/Curve25519/Ge/P3.phpnuW+APKZ}ڢTyyCore/Curve25519/H.phpnuW+APKZR>pp ԧCore/Util.phpnuW+APKZk= PHP52/SplFixedArray.phpnuW+APKZӈOO g)Crypto32.phpnuW+APKzZ+&Carbon/Doctrine/CarbonType.phpnuW+APKzZE&Carbon/Doctrine/CarbonDoctrineType.phpnuW+APKzZPa77,Carbon/Doctrine/DateTimeDefaultPrecision.phpnuW+APKzZ"ɗ':Carbon/Doctrine/CarbonImmutableType.phpnuW+APKzZ2 '(Carbon/Doctrine/CarbonTypeConverter.phpnuW+APKzZpBl)Carbon/Doctrine/DateTimeImmutableType.phpnuW+APKzZש++ }Carbon/Doctrine/DateTimeType.phpnuW+APKrZ$>,,'Auth/bootstrap-stubs/auth/register.stubnuW+APKrZ.Onn%{(Auth/bootstrap-stubs/auth/verify.stubnuW+APKrZ8%g  $>-Auth/bootstrap-stubs/auth/login.stubnuW+APKrZ [0:Auth/bootstrap-stubs/auth/passwords/confirm.stubnuW+APKrZCTF . CAuth/bootstrap-stubs/auth/passwords/reset.stubnuW+APKrZsKjff.OAuth/bootstrap-stubs/auth/passwords/email.stubnuW+APKrZ %VAuth/bootstrap-stubs/layouts/app.stubnuW+APKrZ\FdAuth/bootstrap-stubs/home.stubnuW+APKrZw?llgAuth/stubs/routes.stubnuW+APKrZd^44&ghAuth/stubs/controllers/Controller.stubnuW+APKrZId*iAuth/stubs/controllers/HomeController.stubnuW+APKrZs@  'lUiCommand.phpnuW+APKrZ22uControllersCommand.phpnuW+APKrZ*[{AuthCommand.phpnuW+APKrZd AuthRouteMethods.phpnuW+APKrZ,SUiServiceProvider.phpnuW+APKrZ Presets/React.phpnuW+APKrZNPPresets/Vue.phpnuW+APKrZp$Presets/bootstrap-stubs/bootstrap.jsnuW+APKrZ888&&Presets/bootstrap-stubs/vite.config.jsnuW+APKrZ>#Š'Presets/bootstrap-stubs/_variables.scssnuW+APKrZO Presets/bootstrap-stubs/app.scssnuW+APKrZ5cc}Presets/Bootstrap.phpnuW+APKrZF %Presets/vue-stubs/vite.config.jsnuW+APKrZ6 ((&Presets/vue-stubs/ExampleComponent.vuenuW+APKrZpyPresets/vue-stubs/app.jsnuW+APKrZ(֙__BPresets/Preset.phpnuW+APKrZC<ss"Presets/react-stubs/vite.config.jsnuW+APKrZBPresets/react-stubs/Example.jsxnuW+APKrZ sPresets/react-stubs/app.jsnuW+APKZ)%@@ EHTML5/Serializer/OutputRules.phpnuW+APKZlEHTML5/Serializer/Traverser.phpnuW+APKZ n"-HTML5/Serializer/HTML5Entities.phpnuW+APKZe%աHTML5/Serializer/README.mdnuW+APKZ{7 7 #HTML5/Serializer/RulesInterface.phpnuW+APKZeeHTML5/Exception.phpnuW+APKZȍRx)HTML5/Entities.phpnuW+APKZPk~ HTML5/InstructionProcessor.phpnuW+APKZaqAPAP HTML5/Elements.phpnuW+APKZ C0!HTML5/Parser/InputStream.phpnuW+APKZ:XR:!HTML5/Parser/ParseError.phpnuW+APKZAgU[U[;!HTML5/Parser/DOMTreeBuilder.phpnuW+APKZG#Ö!HTML5/Parser/CharacterReference.phpnuW+APKZ,,!HTML5/Parser/Scanner.phpnuW+APKZ0*rll!HTML5/Parser/UTF8Utils.phpnuW+APKZ%Ʉ!HTML5/Parser/README.mdnuW+APKZr%%"!HTML5/Parser/StringInputStream.phpnuW+APKZP>"HTML5/Parser/Tokenizer.phpnuW+APKZ 3sg\\ޢ"HTML5/Parser/EventHandler.phpnuW+APKZr5u ""HTML5/Parser/TreeBuildingRules.phpnuW+APKZw[ "HTML5/Parser/FileInputStream.phpnuW+APKZ(b!b! {"HTML5.phpnuW+APKZG"PDFMerger/PDFMerger.phpnuW+APKZř"PDFMerger/sample.phpnuW+APKZJ  "ClassMethodUnit.phpnuW+APKZΖ#exceptions/NoTraitException.phpnuW+APKZ6*a'#exceptions/InvalidCodeUnitException.phpnuW+APKZO"#exceptions/ReflectionException.phpnuW+APKZ ֽ#CodeUnitCollection.phpnuW+APKZ=%t#InterfaceUnit.phpnuW+APKZx/,, ,#CodeUnit.phpnuW+APKZ~{$// ?>#Mapper.phpnuW+APKZL wt44n#CodeUnitCollectionIterator.phpnuW+APKZTJ˿ r#TraitUnit.phpnuW+APKZl`t#InterfaceMethodUnit.phpnuW+APKZ 1Z  1w#TraitMethodUnit.phpnuW+APKZrYy#FunctionUnit.phpnuW+APKZm= {#ClassUnit.phpnuW+APKZ}#ContainerInterface.phpnuW+APKZ^33S#ContainerExceptionInterface.phpnuW+APKZ>悞Z#NotFoundExceptionInterface.phpnuW+APKZ*i[[F#InvalidArgumentException.phpnuW+APKZ#ObjectReflector.phpnuW+APK:ZGww<#Doctrine/Instantiator/Exception/UnexpectedValueException.phpnuW+APK:ZaV<#Doctrine/Instantiator/Exception/InvalidArgumentException.phpnuW+APK:Z8^"6B#Doctrine/Instantiator/Exception/ExceptionInterface.phpnuW+APK:Zӵ/#Doctrine/Instantiator/InstantiatorInterface.phpnuW+APK:Z>w&ћ#Doctrine/Instantiator/Instantiator.phpnuW+APKZzc#ExtensionToMimeTypeMap.phpnuW+APKZ+@#ExtensionLookup.phpnuW+APKZ>9vH#ExtensionMimeTypeDetector.phpnuW+APKZU^RR?#MimeTypeDetector.phpnuW+APKZ㳟#8#GeneratedExtensionToMimeTypeMap.phpnuW+APKZ 2>c%EmptyExtensionToMimeTypeMap.phpnuW+APKZy${d%OverridingExtensionToMimeTypeMap.phpnuW+APKZ!% eg%FinfoMimeTypeDetector.phpnuW+APKZLKKr%Internal/Calculator.phpnuW+APKZmK~L  %%Internal/Calculator/GmpCalculator.phpnuW+APKZ[H(%Internal/Calculator/BcMathCalculator.phpnuW+APKZ滭r55(9%Internal/Calculator/NativeCalculator.phpnuW+APKZ1>(F&Exception/RoundingNecessaryException.phpnuW+APKZV~&i&Exception/IntegerOverflowException.phpnuW+APKZY%&Exception/NegativeNumberException.phpnuW+APKZ^|"# &Exception/NumberFormatException.phpnuW+APKZəb%` &Exception/DivisionByZeroException.phpnuW+APKZ*؜&Exception/MathException.phpnuW+APKZE 2 2|&BigRational.phpnuW+APKZ\C&BigInteger.phpnuW+APKZS&RoundingMode.phpnuW+APKZ nEWEWZ&BigDecimal.phpnuW+APKZ<< -'BigNumber.phpnuW+APKZ7 k'ConfigurationAwareInterface.phpnuW+APKZ+^m'Exception/InvalidConfigurationException.phpnuW+APKZ߈C$r'Exception/UnknownOptionException.phpnuW+APKZĖ-u'Exception/ConfigurationExceptionInterface.phpnuW+APKZ v/^^!x'Exception/ValidationException.phpnuW+APKZWVTT{'Configuration.phpnuW+APKZN""X'ReadOnlyConfiguration.phpnuW+APKZA[eo22!Ø'MutableConfigurationInterface.phpnuW+APKZK"!F'ConfigurationBuilderInterface.phpnuW+APKZ JJ'SchemaBuilderInterface.phpnuW+APKZ_W'ConfigurationInterface.phpnuW+APKZ1A7"'ConfigurationProviderInterface.phpnuW+APK+ Z.A 4'Mixin.phpnuW+APK+ Z\166 ^)Assert.phpnuW+APK$ZvC\*ClassAliasAutoloader.phpnuW+APK$Zp7k*Console/TinkerCommand.phpnuW+APK$Z7jRR}*TinkerCaster.phpnuW+APK$Z-@@|*TinkerServiceProvider.phpnuW+APK*%ZL9'9' *Exporter.phpnuW+APK&Z L z*Backtrace.phpnuW+APK&ZrǶ)*Arguments/ReduceArgumentPayloadAction.phpnuW+APK&Z،'ee5*Arguments/ReducedArgument/ReducedArgumentContract.phpnuW+APK&Z/*Arguments/ReducedArgument/UnReducedArgument.phpnuW+APK&Zbl-*Arguments/ReducedArgument/ReducedArgument.phpnuW+APK&Z1E5*Arguments/ReducedArgument/VariadicReducedArgument.phpnuW+APK&ZKΉzz6*Arguments/ReducedArgument/TruncatedReducedArgument.phpnuW+APK&Z{b$ $ *Arguments/ArgumentReducers.phpnuW+APK&ZXR-D*Arguments/Reducers/ClosureArgumentReducer.phpnuW+APK&Z95n*Arguments/Reducers/SymphonyRequestArgumentReducer.phpnuW+APK&Z2*Arguments/Reducers/DateTimeZoneArgumentReducer.phpnuW+APK&Z''lzz0o*Arguments/Reducers/StringableArgumentReducer.phpnuW+APK&ZLk.I*Arguments/Reducers/DateTimeArgumentReducer.phpnuW+APK&Z D5=*Arguments/Reducers/SensitiveParameterArrayReducer.phpnuW+APK&Zs+*l*Arguments/Reducers/EnumArgumentReducer.phpnuW+APK&Z&EKcc2M*Arguments/Reducers/MinimalArrayArgumentReducer.phpnuW+APK&Zb.+Arguments/Reducers/StdClassArgumentReducer.phpnuW+APK&ZNFYxx++Arguments/Reducers/ArrayArgumentReducer.phpnuW+APK&ZR  &S +Arguments/Reducers/ArgumentReducer.phpnuW+APK&Z1K. +Arguments/Reducers/BaseTypeArgumentReducer.phpnuW+APK&Z# +Arguments/ReduceArgumentsAction.phpnuW+APK&Z=bxI I +Arguments/ProvidedArgument.phpnuW+APK&Z`$_)+CodeSnippets/NullSnippetProvider.phpnuW+APK&ZF}ʻ<++CodeSnippets/CodeSnippet.phpnuW+APK&Z ` >3+CodeSnippets/SnippetProvider.phpnuW+APK&Z=:r4+CodeSnippets/LaravelSerializableClosureSnippetProvider.phpnuW+APK&Z8ƙX$:+CodeSnippets/FileSnippetProvider.phpnuW+APK&Z F>+Frame.phpnuW+APK*Z ^A+VersionUpdater/Checker.phpnuW+APK*Zu C+VersionUpdater/GitHubChecker.phpnuW+APK*Z!2&K+VersionUpdater/SelfUpdate.phpnuW+APK*Zdk"a+VersionUpdater/IntervalChecker.phpnuW+APK*ZO""i+VersionUpdater/NoopChecker.phpnuW+APK*Z[[hl+VersionUpdater/Downloader.phpnuW+APK*Ze%p+VersionUpdater/Downloader/Factory.phpnuW+APK*Z~,As+VersionUpdater/Downloader/CurlDownloader.phpnuW+APK*ZS,|+VersionUpdater/Downloader/FileDownloader.phpnuW+APK*Z4g^^Â+VersionUpdater/Installer.phpnuW+APK*ZlM~~!m+Exception/DeprecatedException.phpnuW+APK*Zܩpuu'<+Exception/UnexpectedTargetException.phpnuW+APK*ZT!+Exception/ParseErrorException.phpnuW+APK*ZwC C +Exception/ErrorException.phpnuW+APK*Z0+qq+Exception/Exception.phpnuW+APK*Z<@+Exception/ThrowUpException.phpnuW+APK*Z/2+Exception/RuntimeException.phpnuW+APK*ZzNN+Exception/BreakException.phpnuW+APK*ZJ/!+Exception/FatalErrorException.phpnuW+APK*Zmjϻ+Sudo.phpnuW+APK*ZuG  +ExecutionClosure.phpnuW+APK*Z}c"+ExecutionLoop/AbstractListener.phpnuW+APK*Z GSS +ExecutionLoop/RunkitReloader.phpnuW+APK*Z0^^!^!+ExecutionLoop/ProcessForker.phpnuW+APK*ZO,**P,ExecutionLoop/Listener.phpnuW+APK*ZI,EnvInterface.phpnuW+APK*ZÌ ,Readline/Libedit.phpnuW+APK*Z1&((',Readline/GNUReadline.phpnuW+APK*Z#g((7,Readline/Readline.phpnuW+APK*Z/ Vl?,Readline/Hoa/ConsoleInput.phpnuW+APK*Z:]QQ!VP,Readline/Hoa/ConsoleProcessus.phpnuW+APK*Z;)i,Readline/Hoa/Event.phpnuW+APK*Zl+H+ t,Readline/Hoa/EventListenable.phpnuW+APK*Z#R,Readline/Hoa/EventListener.phpnuW+APK*Zu--,Readline/Hoa/StreamContext.phpnuW+APK*Z\) 55 ,Readline/Hoa/FileException.phpnuW+APK*Zz11,Readline/Hoa/Console.phpnuW+APK*Z(  -Readline/Hoa/StreamStatable.phpnuW+APK*ZkQkQO-Readline/Hoa/ConsoleCursor.phpnuW+APK*Zz $f-Readline/Hoa/IteratorSplFileInfo.phpnuW+APK*Zxk k ";s-Readline/Hoa/AutocompleterWord.phpnuW+APK*Z-5 -Readline/Hoa/StreamOut.phpnuW+APK*ZRxGG-Readline/Hoa/ExceptionIdle.phpnuW+APK*ZK -Readline/Hoa/Exception.phpnuW+APK*ZԪ}zizii-Readline/Hoa/Readline.phpnuW+APK*Z%D",.Readline/Hoa/ProtocolException.phpnuW+APK*ZKLSSs#.Readline/Hoa/ConsoleTput.phpnuW+APK*ZU+]w.Readline/Hoa/IteratorRecursiveDirectory.phpnuW+APK*Z#".Readline/Hoa/AutocompleterPath.phpnuW+APK*ZL^9 9 .Readline/Hoa/StreamIn.phpnuW+APK*Z,E.Readline/Hoa/ConsoleOutput.phpnuW+APK*ZXt $K.Readline/Hoa/ProtocolNodeLibrary.phpnuW+APK*Z&b b ..Readline/Hoa/StreamTouchable.phpnuW+APK*Z !.Readline/Hoa/ConsoleException.phpnuW+APK*ZM.,,J.Readline/Hoa/FileGeneric.phpnuW+APK*Zq 'J /Readline/Hoa/Terminfo/78/xterm-256colornuW+APK*Zw崺 /Readline/Hoa/Terminfo/78/xtermnuW+APK*Z %#/Readline/Hoa/Terminfo/77/windows-ansinuW+APK*Z%)/Readline/Hoa/StreamPathable.phpnuW+APK*ZwwU??1/Readline/Hoa/FileFinder.phpnuW+APK*Z= Uq/Readline/Hoa/EventException.phpnuW+APK*Znc x/Readline/Hoa/StreamPointable.phpnuW+APK*Z@00x/Readline/Hoa/ConsoleWindow.phpnuW+APK*Z%_/Readline/Hoa/File.phpnuW+APK*Zi- !;/Readline/Hoa/StreamBufferable.phpnuW+APK*ZqI/Readline/Hoa/EventSource.phpnuW+APK*Zh& : :/Readline/Hoa/Stream.phpnuW+APK*ZB{0Readline/Hoa/Protocol.phpnuW+APK*Z}  70Readline/Hoa/Ustring.phpnuW+APK*ZDQQUK0Readline/Hoa/FileRead.phpnuW+APK*Z.0 0 ]0Readline/Hoa/StreamLockable.phpnuW+APK*Z #nh0Readline/Hoa/IteratorFileSystem.phpnuW+APK*Zi}GGs0Readline/Hoa/IStream.phpnuW+APK*Z+L{0Readline/Hoa/ProtocolNode.phpnuW+APK*ZuAA"L0Readline/Hoa/FileLinkReadWrite.phpnuW+APK*Z2QQ*߶0Readline/Hoa/FileDoesNotExistException.phpnuW+APK*Z,QX X 0Readline/Hoa/EventListens.phpnuW+APK*Z-Y` '/0Readline/Hoa/AutocompleterAggregate.phpnuW+APK*ZGʰQ0Readline/Hoa/FileLink.phpnuW+APK*ZzXX0Readline/Hoa/FileDirectory.phpnuW+APK*Z3R:55 A1Readline/Hoa/ProtocolWrapper.phpnuW+APK*Z>Wd 71Readline/Hoa/EventBucket.phpnuW+APK*Zk}TTB1Readline/Hoa/Autocompleter.phpnuW+APK*ZK1Readline/Hoa/Xcallable.phpnuW+APK*ZQd h1Readline/Hoa/StreamException.phpnuW+APK*Z 44o1Readline/Hoa/FileReadWrite.phpnuW+APK*Z-=ddm1Readline/Hoa/FileLinkRead.phpnuW+APK*Z^hm1Readline/Userland.phpnuW+APK*Zm&fN 1Readline/Transient.phpnuW+APK*Z+0#  /1ExecutionLoopClosure.phpnuW+APK*Z1Sudo/SudoVisitor.phpnuW+APK*ZC' a1SystemEnv.phpnuW+APK*Z::581TabCompletion/Matcher/AbstractContextAwareMatcher.phpnuW+APK*Z,1TabCompletion/Matcher/MongoClientMatcher.phpnuW+APK*Z옵  .B1TabCompletion/Matcher/ObjectMethodsMatcher.phpnuW+APK*Z9*1TabCompletion/Matcher/VariablesMatcher.phpnuW+APK*Z)011TabCompletion/Matcher/ObjectAttributesMatcher.phpnuW+APK*Z(%:2TabCompletion/Matcher/FunctionDefaultParametersMatcher.phpnuW+APK*Z>2-0 2TabCompletion/Matcher/ClassMethodsMatcher.phpnuW+APK*Z.:L2TabCompletion/Matcher/AbstractDefaultParametersMatcher.phpnuW+APK*Z9"k*2TabCompletion/Matcher/FunctionsMatcher.phpnuW+APK*Z[,,)"2TabCompletion/Matcher/KeywordsMatcher.phpnuW+APK*Z\* +/+2TabCompletion/Matcher/ClassNamesMatcher.phpnuW+APK*ZR> 52TabCompletion/Matcher/ObjectMethodDefaultParametersMatcher.phpnuW+APK*Z٭F0v<2TabCompletion/Matcher/ClassAttributesMatcher.phpnuW+APK*ZI )E2TabCompletion/Matcher/CommandsMatcher.phpnuW+APK*ZTٔ.O2TabCompletion/Matcher/MongoDatabaseMatcher.phpnuW+APK*Z(}5FF)V2TabCompletion/Matcher/AbstractMatcher.phpnuW+APK*Zkp~mm=Wj2TabCompletion/Matcher/ClassMethodDefaultParametersMatcher.phpnuW+APK*ZR=MM*1q2TabCompletion/Matcher/ConstantsMatcher.phpnuW+APK*Z١5] ] v2TabCompletion/AutoCompleter.phpnuW+APK*ZAaa"2Reflection/ReflectionNamespace.phpnuW+APK*Z!y !72Reflection/ReflectionConstant.phpnuW+APK*Z.' ' 3u2Reflection/ReflectionLanguageConstructParameter.phpnuW+APK*Z9 *2Reflection/ReflectionLanguageConstruct.phpnuW+APK*Z-wHH 2Output/ShellOutput.phpnuW+APK*Z.q7))2Output/PassthruPager.phpnuW+APK*Z㭐66 2Output/OutputPager.phpnuW+APK*ZGA 2Output/ProcOutputPager.phpnuW+APK*Z.V2Output/Theme.phpnuW+APK*Z~772ContextAware.phpnuW+APK*ZUvv 2Context.phpnuW+APK*Z.88  3functions.phpnuW+APK*Z$ 3VarDumper/Cloner.phpnuW+APK*Z~v $3VarDumper/Dumper.phpnuW+APK*Z#}U&&*03VarDumper/Presenter.phpnuW+APK*Z $?3VarDumper/PresenterAware.phpnuW+APK*ZտQ,Q,A3CodeCleaner.phpnuW+APK*Z<Ǫ0~~n3Input/SilentInput.phpnuW+APK*Zu8CCEr3Input/FilterOptions.phpnuW+APK*Z++ρ3Input/ShellInput.phpnuW+APK*ZŠ|H  3Input/CodeArgument.phpnuW+APK*Z5 22Y3Command/HistoryCommand.phpnuW+APK*Zmm3Command/ClearCommand.phpnuW+APK*Z 3Command/DumpCommand.phpnuW+APK*ZѠ&&3Command/ListCommand.phpnuW+APK*ZT@/ / w4Command/HelpCommand.phpnuW+APK*ZĿhh h 4Command/ParseCommand.phpnuW+APK*ZYO&& 4Command/ShowCommand.phpnuW+APK*ZF4Command/EditCommand.phpnuW+APK*ZK||'%^4Command/TimeitCommand/TimeitVisitor.phpnuW+APK*Z]k:  l4Command/BufferCommand.phpnuW+APK*Z6fDDFv4Command/TimeitCommand.phpnuW+APK*Z9EӉ4Command/PsyVersionCommand.phpnuW+APK*ZrT ލ4Command/SudoCommand.phpnuW+APK*Z Q4Command/WtfCommand.phpnuW+APK*ZSrP 4Command/ThrowUpCommand.phpnuW+APK*Zuj.*.*4Command/ReflectingCommand.phpnuW+APK*Z "4Command/ListCommand/Enumerator.phpnuW+APK*Z-8 *4Command/ListCommand/VariableEnumerator.phpnuW+APK*ZcR__*14Command/ListCommand/PropertyEnumerator.phpnuW+APK*ZƗgR  *5Command/ListCommand/FunctionEnumerator.phpnuW+APK*Z-*K5Command/ListCommand/ConstantEnumerator.phpnuW+APK*Zy40/.5Command/ListCommand/GlobalVariableEnumerator.phpnuW+APK*Z@w /65Command/ListCommand/ClassConstantEnumerator.phpnuW+APK*Zߊ-'hC5Command/ListCommand/ClassEnumerator.phpnuW+APK*Zv6(R5Command/ListCommand/MethodEnumerator.phpnuW+APK*Z$$b5Command/Command.phpnuW+APK*Zll)%5Command/WhereamiCommand.phpnuW+APK*Ze=##*5Command/DocCommand.phpnuW+APK*Z+ +5Command/TraceCommand.phpnuW+APK*Zil5Command/ExitCommand.phpnuW+APK*Zr5Command/CodeArgumentParser.phpnuW+APK*ZJ5ParserFactory.phpnuW+APK*Z[$$$"55CodeCleaner/ValidClassNamePass.phpnuW+APK*Z'D$ $ "35CodeCleaner/NamespaceAwarePass.phpnuW+APK*Z<5 5 5CodeCleaner/LabelContextPass.phpnuW+APK*ZwWiT  .6CodeCleaner/NamespacePass.phpnuW+APK*Zހ#6CodeCleaner/LeavePsyshAlonePass.phpnuW+APK*Z~>6CodeCleaner/LoopContextPass.phpnuW+APK*Z0__&'6CodeCleaner/AssignThisVariablePass.phpnuW+APK*Z20e#,6CodeCleaner/FunctionContextPass.phpnuW+APK*Z26CodeCleaner/CodeCleanerPass.phpnuW+APK*ZqƂ46CodeCleaner/ReturnTypePass.phpnuW+APK*Zo#V~~C6CodeCleaner/IssetPass.phpnuW+APK*Z@',,"I6CodeCleaner/MagicConstantsPass.phpnuW+APK*ZlnV V !N6CodeCleaner/AbstractClassPass.phpnuW+APK*ZZJ.  $W6CodeCleaner/ValidConstructorPass.phpnuW+APK*Zmb[[h6CodeCleaner/ExitPass.phpnuW+APK*Z͠&k6CodeCleaner/EmptyArrayDimFetchPass.phpnuW+APK*ZEyq q s6CodeCleaner/StrictTypesPass.phpnuW+APK*Z 06CodeCleaner/FunctionReturnInWriteContextPass.phpnuW+APK*Z%A A ҋ6CodeCleaner/ListPass.phpnuW+APK*Zz~ELL+[6CodeCleaner/CallTimePassByReferencePass.phpnuW+APK*Z,{ 6CodeCleaner/UseStatementPass.phpnuW+APK*Z0⟉'6CodeCleaner/PassableByReferencePass.phpnuW+APK*ZIAW @6CodeCleaner/CalledClassPass.phpnuW+APK*ZT :Q6CodeCleaner/FinalClassPass.phpnuW+APK*Zj5<<6CodeCleaner/NoReturnValue.phpnuW+APK*Z| | %-6CodeCleaner/ValidFunctionNamePass.phpnuW+APK*Z@Kww"6CodeCleaner/ImplicitReturnPass.phpnuW+APK*Z ##6CodeCleaner/RequirePass.phpnuW+APK*ZFqq 57Util/Json.phpnuW+APK*ZRj 7Util/Mirror.phpnuW+APK*ZW<<7Util/Docblock.phpnuW+APK*Zژ .87Util/Str.phpnuW+APK*ZFtllIB7SuperglobalsEnv.phpnuW+APK*ZʤSc33D7Formatter/DocblockFormatter.phpnuW+APK*Z~ ' 'zW7Formatter/CodeFormatter.phpnuW+APK*Zȑd,, ~7Formatter/SignatureFormatter.phpnuW+APK*Zqy] ˫7Formatter/ReflectorFormatter.phpnuW+APK*Z  ͭ7Formatter/TraceFormatter.phpnuW+APK*Zș 47Shell.phpnuW+APK*Zbj((~8ConfigPaths.phpnuW+APK*ZӃ)8exceptions/RuntimeException.phpnuW+APK*ZU8ExceptionComparator.phpnuW+APK*Z^:Contracts/ArgumentFormatter.phpnuW+APK*Z_'''7?:Contracts/Adapters/Phpunit/HasPrintableTestCaseName.phpnuW+APK*Zzz'EA:Contracts/Adapters/Phpunit/Listener.phpnuW+APK*ZQC:Contracts/Highlighter.phpnuW+APK*ZF hh UD:Coverage.phpnuW+APK*ZV#[:ConsoleColor.phpnuW+APK*Z+q"q"*v:Highlighter.phpnuW+APK,Zœ-- ژ:Restorer.phpnuW+APK,Z^4 C:ExcludeList.phpnuW+APK,Zˮ ++ 3:Snapshot.phpnuW+APK,Z#Vi i P:CodeExporter.phpnuW+APK`.Zl(EE%:Exceptions/InvalidOptionException.phpnuW+APK`.Z5E&&:CorsService.phpnuW+APK<1Zgk;Carbon/Language.phpnuW+APK<1Z䪦G2;Carbon/Cli/Invoker.phpnuW+APK<1Z3`  36;Carbon/Lang/th_TH.phpnuW+APK<1ZLOO7;Carbon/Lang/brx.phpnuW+APK<1ZՉNN9;Carbon/Lang/wo.phpnuW+APK<1Zd:;Carbon/Lang/es_AR.phpnuW+APK<1ZB<;Carbon/Lang/bn_IN.phpnuW+APK<1ZMB;Carbon/Lang/cu.phpnuW+APK<1ZUZj j NI;Carbon/Lang/eo.phpnuW+APK<1ZS;Carbon/Lang/el.phpnuW+APK<1ZpGGc;Carbon/Lang/en_CK.phpnuW+APK<1Z))Se;Carbon/Lang/ar_ER.phpnuW+APK<1Zr(f;Carbon/Lang/sr_Latn_XK.phpnuW+APK<1ZpGGi;Carbon/Lang/en_TO.phpnuW+APK<1Z8OOLk;Carbon/Lang/gez.phpnuW+APK<1ZEAAl;Carbon/Lang/fr_DZ.phpnuW+APK<1Z% do;Carbon/Lang/so.phpnuW+APK<1Z#z 3z;Carbon/Lang/ga.phpnuW+APK<1ZpGG);Carbon/Lang/en_GI.phpnuW+APK<1Z}));Carbon/Lang/ca_IT.phpnuW+APK<1ZjtXX#;Carbon/Lang/twq.phpnuW+APK<1ZO??;Carbon/Lang/ht_HT.phpnuW+APK<1Z-  B;Carbon/Lang/ff_GN.phpnuW+APK<1Z>+  ;Carbon/Lang/lt_LT.phpnuW+APK<1Z}*B  ;Carbon/Lang/ha_NE.phpnuW+APK<1ZpGG2;Carbon/Lang/en_SC.phpnuW+APK<1ZFI;Carbon/Lang/en_GB.phpnuW+APK<1Zh ;Carbon/Lang/se.phpnuW+APK<1ZpGG;Carbon/Lang/en_LC.phpnuW+APK<1ZEAA>;Carbon/Lang/fr_SY.phpnuW+APK<1ZŽħ;Carbon/Lang/kln.phpnuW+APK<1Z,  ;Carbon/Lang/km_KH.phpnuW+APK<1Z8 3;Carbon/Lang/ne.phpnuW+APK<1Z''x  0;Carbon/Lang/fr_BF.phpnuW+APK<1Z4;Carbon/Lang/it_CH.phpnuW+APK<1Z`NNK;Carbon/Lang/li.phpnuW+APK<1Z5uOOۿ;Carbon/Lang/raj.phpnuW+APK<1ZpGGm;Carbon/Lang/en_DG.phpnuW+APK<1ZNjG;Carbon/Lang/ku.phpnuW+APK<1ZF;Carbon/Lang/os_RU.phpnuW+APK<1Z$$;Carbon/Lang/be.phpnuW+APK<1ZX;Carbon/Lang/mag_IN.phpnuW+APK<1Z."NN;Carbon/Lang/wa.phpnuW+APK<1ZSWN N ;Carbon/Lang/fy.phpnuW+APK<1Z{9t#<Carbon/Lang/hif_FJ.phpnuW+APK<1Zb  <Carbon/Lang/cs_CZ.phpnuW+APK<1Z ))S<Carbon/Lang/kkj.phpnuW+APK<1ZHv|<Carbon/Lang/bho_IN.phpnuW+APK<1Z"<Carbon/Lang/kam.phpnuW+APK<1Z= "<Carbon/Lang/cy.phpnuW+APK<1ZT.CC-<Carbon/Lang/rwk.phpnuW+APK<1Zdd2<Carbon/Lang/es_PY.phpnuW+APK<1ZKNnnO4<Carbon/Lang/no.phpnuW+APK<1Zw  6<Carbon/Lang/fr_VU.phpnuW+APK<1Z?Ej  N9<Carbon/Lang/en_BS.phpnuW+APK<1Z%:<Carbon/Lang/rof.phpnuW+APK<1Zx0NN?<Carbon/Lang/ts.phpnuW+APK<1Z/A<Carbon/Lang/ff.phpnuW+APK<1Zv  I<Carbon/Lang/bs_BA.phpnuW+APK<1ZVBOOGK<Carbon/Lang/szl.phpnuW+APK<1ZڑQQL<Carbon/Lang/so_SO.phpnuW+APK<1Z'JNNoN<Carbon/Lang/iu.phpnuW+APK<1ZA$O<Carbon/Lang/ja.phpnuW+APK<1Z C`<Carbon/Lang/da_GL.phpnuW+APK<1ZpGGab<Carbon/Lang/en_SE.phpnuW+APK<1ZIt c<Carbon/Lang/cv.phpnuW+APK<1Z?Ej  n<Carbon/Lang/en_UM.phpnuW+APK<1Z^َ2p<Carbon/Lang/ln_CG.phpnuW+APK<1Z}  s<Carbon/Lang/yo_NG.phpnuW+APK<1Z?Ej  Ut<Carbon/Lang/en_ZW.phpnuW+APK<1Z))u<Carbon/Lang/ar_MR.phpnuW+APK<1Zi?#w<Carbon/Lang/en_AG.phpnuW+APK<1Zը.y<Carbon/Lang/fy_DE.phpnuW+APK<1Z㼦t..}<Carbon/Lang/lt.phpnuW+APK<1Z;i<Carbon/Lang/yi_US.phpnuW+APK<1ZpGG<Carbon/Lang/en_SX.phpnuW+APK<1Z?b r<Carbon/Lang/da.phpnuW+APK<1Z <Carbon/Lang/bem_ZM.phpnuW+APK<1ZY^^<Carbon/Lang/ff_SN.phpnuW+APK<1Z ))(<Carbon/Lang/jgo.phpnuW+APK<1ZO2aNN<Carbon/Lang/am.phpnuW+APK<1ZpGG$<Carbon/Lang/en_TC.phpnuW+APK<1ZC=5  <Carbon/Lang/ru_RU.phpnuW+APK<1ZOO<Carbon/Lang/nan.phpnuW+APK<1Z=Y~~<Carbon/Lang/sw_UG.phpnuW+APK<1ZpGGU<Carbon/Lang/en_TK.phpnuW+APK<1Z''x  <Carbon/Lang/fr_BL.phpnuW+APK<1Z"1<Carbon/Lang/de_LU.phpnuW+APK<1ZhaK<Carbon/Lang/az_AZ.phpnuW+APK<1ZХQ<Carbon/Lang/sr.phpnuW+APK<1Z<Carbon/Lang/sq_XK.phpnuW+APK<1Z,<Carbon/Lang/ar_BH.phpnuW+APK<1ZpGG<Carbon/Lang/en_BE.phpnuW+APK<1Zj\\7<Carbon/Lang/vo.phpnuW+APK<1Z?Ej  <Carbon/Lang/en_KE.phpnuW+APK<1Zov22%<Carbon/Lang/ce_RU.phpnuW+APK<1ZM|UNN<Carbon/Lang/tn.phpnuW+APK<1Z",<Carbon/Lang/de_BE.phpnuW+APK<1ZPש <Carbon/Lang/hak_TW.phpnuW+APK<1Z<-OO<Carbon/Lang/bho.phpnuW+APK<1Z NNo<Carbon/Lang/sa.phpnuW+APK<1Z߬<Carbon/Lang/ts_ZA.phpnuW+APK<1ZpGGD<Carbon/Lang/en_SL.phpnuW+APK<1Z?Ej  <Carbon/Lang/en_AS.phpnuW+APK<1ZZ   =Carbon/Lang/ro_MD.phpnuW+APK<1ZC~sGGn=Carbon/Lang/pt_MZ.phpnuW+APK<1ZI V =Carbon/Lang/fi.phpnuW+APK<1Z-|K&=Carbon/Lang/es_PR.phpnuW+APK<1Zۨr,=Carbon/Lang/dyo.phpnuW+APK<1Z  m=Carbon/Lang/mr_IN.phpnuW+APK<1ZpR=Carbon/Lang/zh.phpnuW+APK<1Zb=Carbon/Lang/ti_ET.phpnuW+APK<1ZI I =Carbon/Lang/as_IN.phpnuW+APK<1ZpGGF)=Carbon/Lang/en_ER.phpnuW+APK<1ZpGG*=Carbon/Lang/en_GY.phpnuW+APK<1Z''x  ^,=Carbon/Lang/fr_YT.phpnuW+APK<1Z7$-=Carbon/Lang/en_ZA.phpnuW+APK<1Z&$0=Carbon/Lang/en_AU.phpnuW+APK<1Z}t3=Carbon/Lang/ar_Shakl.phpnuW+APK<1Z:<G=Carbon/Lang/sl.phpnuW+APK<1Z(NNZ=Carbon/Lang/mg.phpnuW+APK<1Z&5  o\=Carbon/Lang/nl_SX.phpnuW+APK<1Z㚸  ]=Carbon/Lang/ml_IN.phpnuW+APK<1Zx$_=Carbon/Lang/ee_TG.phpnuW+APK<1ZD,a=Carbon/Lang/niu_NU.phpnuW+APK<1Z\GGh=Carbon/Lang/qu_EC.phpnuW+APK<1Z|=}i=Carbon/Lang/yav.phpnuW+APK<1ZZ7$$n=Carbon/Lang/luy.phpnuW+APK<1Z?Ej  ,w=Carbon/Lang/en_US_Posix.phpnuW+APK<1ZpGGx=Carbon/Lang/en_CM.phpnuW+APK<1Zr  z=Carbon/Lang/tg_TJ.phpnuW+APK<1Zeѡ^{=Carbon/Lang/szl_PL.phpnuW+APK<1Z!kQ=Carbon/Lang/ru_UA.phpnuW+APK<1Z''x  K=Carbon/Lang/fr_CI.phpnuW+APK<1Z,=Carbon/Lang/ar_QA.phpnuW+APK<1Z+v0%  =Carbon/Lang/br_FR.phpnuW+APK<1Z*痖=Carbon/Lang/nso_ZA.phpnuW+APK<1ZUppؖ=Carbon/Lang/lv.phpnuW+APK<1Z KK=Carbon/Lang/hsb_DE.phpnuW+APK<1Z?7  =Carbon/Lang/pl_PL.phpnuW+APK<1Z^dLk=Carbon/Lang/zh_MO.phpnuW+APK<1Z''x  @=Carbon/Lang/fr_NE.phpnuW+APK<1Z>t=Carbon/Lang/ar_IQ.phpnuW+APK<1Z=Carbon/Lang/ne_IN.phpnuW+APK<1Z,}s` ` =Carbon/Lang/he.phpnuW+APK<1ZpGG=Carbon/Lang/en_NF.phpnuW+APK<1ZӾ6=Carbon/Lang/zh_Hans_MO.phpnuW+APK<1Zdr=Carbon/Lang/es_419.phpnuW+APK<1Z$rll^=Carbon/Lang/gsw_FR.phpnuW+APK<1Z/{POO=Carbon/Lang/hak.phpnuW+APK<1Z''x  =Carbon/Lang/fr_GN.phpnuW+APK<1ZW=Carbon/Lang/seh.phpnuW+APK<1Z]F>Carbon/Lang/wal_ET.phpnuW+APK<1Zw  W>Carbon/Lang/fr_TD.phpnuW+APK<1ZpGG >Carbon/Lang/en_001.phpnuW+APK<1ZM443 >Carbon/Lang/az_IR.phpnuW+APK<1Z(|@zGG>Carbon/Lang/es_GQ.phpnuW+APK<1Z )v8>Carbon/Lang/mua.phpnuW+APK<1Zj>Carbon/Lang/ber_DZ.phpnuW+APK<1Za X>Carbon/Lang/ccp.phpnuW+APK<1Z+hk{ { F)>Carbon/Lang/dv.phpnuW+APK<1Z Pcc4>Carbon/Lang/pa_IN.phpnuW+APK<1Za OO5>Carbon/Lang/mni.phpnuW+APK<1ZWWW=7>Carbon/Lang/ln_CD.phpnuW+APK<1Zا4l448>Carbon/Lang/zu_ZA.phpnuW+APK<1ZpGGR@>Carbon/Lang/en_IO.phpnuW+APK<1Z+  A>Carbon/Lang/se_NO.phpnuW+APK<1ZpGG.C>Carbon/Lang/en_JE.phpnuW+APK<1Z''x  D>Carbon/Lang/fr_MC.phpnuW+APK<1ZndNN F>Carbon/Lang/dz.phpnuW+APK<1Zw7GGG>Carbon/Lang/es_BZ.phpnuW+APK<1Z.{{&I>Carbon/Lang/ca.phpnuW+APK<1Z(|@zGGZ>Carbon/Lang/es_CU.phpnuW+APK<1Z/;)( ( o\>Carbon/Lang/tig_ER.phpnuW+APK<1Ze>  e>Carbon/Lang/et_EE.phpnuW+APK<1Z&-g>Carbon/Lang/dje.phpnuW+APK<1ZEV?DD`m>Carbon/Lang/es_ES.phpnuW+APK<1Zjn>Carbon/Lang/ber_MA.phpnuW+APK<1Zif)OO.s>Carbon/Lang/fil.phpnuW+APK<1Z t>Carbon/Lang/tlh.phpnuW+APK<1Z>ڰ ~>Carbon/Lang/hi.phpnuW+APK<1Z-'OOً>Carbon/Lang/doi.phpnuW+APK<1Zk0 0 k>Carbon/Lang/ug.phpnuW+APK<1Z  ݚ>Carbon/Lang/mn_MN.phpnuW+APK<1Z8->Carbon/Lang/csb_PL.phpnuW+APK<1ZJBm->Carbon/Lang/aa_DJ.phpnuW+APK<1ZcNz>Carbon/Lang/uz_Cyrl.phpnuW+APK<1Z3I1OOϪ>Carbon/Lang/agr.phpnuW+APK<1Zpa>Carbon/Lang/sr_ME.phpnuW+APK<1ZNN>Carbon/Lang/xh.phpnuW+APK<1Z{kOOI>Carbon/Lang/tpi.phpnuW+APK<1Z!~P ۰>Carbon/Lang/nb.phpnuW+APK<1ZM>Carbon/Lang/ve_ZA.phpnuW+APK<1ZpGG>Carbon/Lang/en_LR.phpnuW+APK<1Z5OOH>Carbon/Lang/sgs.phpnuW+APK<1Z+H  >Carbon/Lang/vi_VN.phpnuW+APK<1Z~@OO*>Carbon/Lang/hne.phpnuW+APK<1ZlW>Carbon/Lang/naq.phpnuW+APK<1Z%..>Carbon/Lang/zh_SG.phpnuW+APK<1Zf8 J>Carbon/Lang/sv.phpnuW+APK<1Z''x  >Carbon/Lang/fr_GF.phpnuW+APK<1Za= >Carbon/Lang/ps.phpnuW+APK<1Z))>Carbon/Lang/ar_TD.phpnuW+APK<1Z+\\l>Carbon/Lang/teo.phpnuW+APK<1Z^<< >Carbon/Lang/khq.phpnuW+APK<1Z.z/>Carbon/Lang/quz_PE.phpnuW+APK<1Z'Ht̽g>Carbon/Lang/nus.phpnuW+APK<1Zjߎg?Carbon/Lang/fr.phpnuW+APK<1Zz<?Carbon/Lang/shn_MM.phpnuW+APK<1ZCB%?Carbon/Lang/bhb_IN.phpnuW+APK<1Z?щO)?Carbon/Lang/sw_KE.phpnuW+APK<1Z:*q-?Carbon/Lang/sm_WS.phpnuW+APK<1Z4?Carbon/Lang/ki.phpnuW+APK<1Z   u=?Carbon/Lang/or_IN.phpnuW+APK<1Z?Ej  J?Carbon/Lang/en_JM.phpnuW+APK<1ZNn  L?Carbon/Lang/ro_RO.phpnuW+APK<1Zq a  iM?Carbon/Lang/it_VA.phpnuW+APK<1ZN?Carbon/Lang/bs_Cyrl.phpnuW+APK<1Z>KNNT?Carbon/Lang/sc.phpnuW+APK<1ZdU?Carbon/Lang/es_GT.phpnuW+APK<1ZV V W?Carbon/Lang/sq.phpnuW+APK<1Z+kk)b?Carbon/Lang/ig_NG.phpnuW+APK<1ZO \\h?Carbon/Lang/xog.phpnuW+APK<1Z(RHkkxm?Carbon/Lang/es_US.phpnuW+APK<1Zr9(q?Carbon/Lang/tt_RU.phpnuW+APK<1Z[Ƀw?Carbon/Lang/es_SV.phpnuW+APK<1ZnROOOz?Carbon/Lang/crh.phpnuW+APK<1Z$Z {?Carbon/Lang/sd_IN@devanagari.phpnuW+APK<1Zl`POOL?Carbon/Lang/ayc.phpnuW+APK<1Zkf'ރ?Carbon/Lang/az_Cyrl.phpnuW+APK<1Z!NN܈?Carbon/Lang/os.phpnuW+APK<1Zzl?Carbon/Lang/zh_HK.phpnuW+APK<1Zhċ?Carbon/Lang/ar_MA.phpnuW+APK<1Z?Ej  ?Carbon/Lang/en_MT.phpnuW+APK<1ZO%ėOO?Carbon/Lang/cmn.phpnuW+APK<1Z?Carbon/Lang/gez_ER.phpnuW+APK<1ZbM?Carbon/Lang/ha.phpnuW+APK<1Z-n  ~?Carbon/Lang/ko_KR.phpnuW+APK<1Z3@%@%α?Carbon/Lang/uk.phpnuW+APK<1Z))P?Carbon/Lang/be_BY.phpnuW+APK<1Z^َ?Carbon/Lang/ln_AO.phpnuW+APK<1Z,?Carbon/Lang/ar_OM.phpnuW+APK<1ZpGG?Carbon/Lang/en_FM.phpnuW+APK<1ZV .?Carbon/Lang/ks_IN@devanagari.phpnuW+APK<1Z88k?Carbon/Lang/dsb_DE.phpnuW+APK<1Zs!!?Carbon/Lang/mn.phpnuW+APK<1ZSSSL@Carbon/Lang/tl_PH.phpnuW+APK<1Zb3ZZ@Carbon/Lang/de_IT.phpnuW+APK<1Zse   @Carbon/Lang/uk_UA.phpnuW+APK<1Z=Y~~ @Carbon/Lang/sw_CD.phpnuW+APK<1Z~`  @Carbon/Lang/sa_IN.phpnuW+APK<1ZW]FNN@Carbon/Lang/an.phpnuW+APK<1Z&oq||=@Carbon/Lang/en_IL.phpnuW+APK<1Z''x  @Carbon/Lang/fr_WF.phpnuW+APK<1ZwOON@Carbon/Lang/ber.phpnuW+APK<1Z@Carbon/Lang/aa_ET.phpnuW+APK<1Zx^ ""@Carbon/Lang/ms.phpnuW+APK<1Z''x  9/@Carbon/Lang/fr_CF.phpnuW+APK<1Z?uL  0@Carbon/Lang/af_ZA.phpnuW+APK<1ZL-xVOO1@Carbon/Lang/shn.phpnuW+APK<1Z7,k3@Carbon/Lang/brx_IN.phpnuW+APK<1Zߴ/ww9@Carbon/Lang/se_FI.phpnuW+APK<1Z>1>@Carbon/Lang/zh_YUE.phpnuW+APK<1ZڑQQ@@Carbon/Lang/so_KE.phpnuW+APK<1Z^OO3B@Carbon/Lang/sid.phpnuW+APK<1Z NNC@Carbon/Lang/ig.phpnuW+APK<1Zl  UE@Carbon/Lang/ja_JP.phpnuW+APK<1ZW?F@Carbon/Lang/ar_PS.phpnuW+APK<1Z))tK@Carbon/Lang/ar_IL.phpnuW+APK<1ZpNNL@Carbon/Lang/kl.phpnuW+APK<1ZCi  rN@Carbon/Lang/lv_LV.phpnuW+APK<1ZGO@Carbon/Lang/is.phpnuW+APK<1Z&5  W@Carbon/Lang/nl_SR.phpnuW+APK<1Z^َ,Y@Carbon/Lang/ln_CF.phpnuW+APK<1Z|[@Carbon/Lang/ar_KW.phpnuW+APK<1ZZ Y  Aq@Carbon/Lang/fi_FI.phpnuW+APK<1Z=NNr@Carbon/Lang/lg.phpnuW+APK<1Z`  !t@Carbon/Lang/he_IL.phpnuW+APK<1Z': qu@Carbon/Lang/uz.phpnuW+APK<1Z@Carbon/Lang/sq_MK.phpnuW+APK<1Zv}V V ǃ@Carbon/Lang/gom_Latn.phpnuW+APK<1ZߟW e@Carbon/Lang/pa.phpnuW+APK<1Z9vv@Carbon/Lang/nd.phpnuW+APK<1ZOO_@Carbon/Lang/csb.phpnuW+APK<1ZL(OO@Carbon/Lang/wal.phpnuW+APK<1Z7OO@Carbon/Lang/tcy.phpnuW+APK<1ZO %@Carbon/Lang/haw.phpnuW+APK<1Z{OO٬@Carbon/Lang/miq.phpnuW+APK<1Z(|@zGGk@Carbon/Lang/es_IC.phpnuW+APK<1Z}  @Carbon/Lang/mk_MK.phpnuW+APK<1Z/kOOG@Carbon/Lang/wae.phpnuW+APK<1Zٲ@Carbon/Lang/sg.phpnuW+APK<1ZӾ6@Carbon/Lang/zh_Hans_HK.phpnuW+APK<1ZՊ.P@Carbon/Lang/ar.phpnuW+APK<1Z mNNu@Carbon/Lang/st.phpnuW+APK<1ZƢ: @Carbon/Lang/br.phpnuW+APK<1ZpGGE@Carbon/Lang/en_TV.phpnuW+APK<1Z y@Carbon/Lang/saq.phpnuW+APK<1Z  @Carbon/Lang/nb_NO.phpnuW+APK<1ZlNN @Carbon/Lang/ti.phpnuW+APK<1Z*'. @Carbon/Lang/tg.phpnuW+APK<1Z  @Carbon/Lang/my_MM.phpnuW+APK<1Z4͠@Carbon/Lang/es_UY.phpnuW+APK<1ZpGG@Carbon/Lang/en_PW.phpnuW+APK<1ZpGG@Carbon/Lang/en_MG.phpnuW+APK<1Zy@Carbon/Lang/fur_IT.phpnuW+APK<1ZpGGv@Carbon/Lang/en_PN.phpnuW+APK<1Z!/] ] ACarbon/Lang/jv.phpnuW+APK<1ZoOO ACarbon/Lang/the.phpnuW+APK<1Zʷ3 ACarbon/Lang/zh_Hant_HK.phpnuW+APK<1ZZ Z  ACarbon/Lang/sh.phpnuW+APK<1ZU)ACarbon/Lang/gez_ET.phpnuW+APK<1Z `KACarbon/Lang/es_MX.phpnuW+APK<1Zl  _ACarbon/Lang/cv_RU.phpnuW+APK<1ZpGGACarbon/Lang/en_KI.phpnuW+APK<1ZpGG;!ACarbon/Lang/en_SS.phpnuW+APK<1ZOO"ACarbon/Lang/fur.phpnuW+APK<1Z}zOOY$ACarbon/Lang/om_KE.phpnuW+APK<1Z''x  %ACarbon/Lang/fr_PM.phpnuW+APK<1Z{r   ='ACarbon/Lang/vai.phpnuW+APK<1ZpGG-ACarbon/Lang/en_VG.phpnuW+APK<1ZC2X)),/ACarbon/Lang/qu.phpnuW+APK<1ZZO  1ACarbon/Lang/vai_Vaii.phpnuW+APK<1Z*2ACarbon/Lang/sk.phpnuW+APK<1ZB` OOGACarbon/Lang/hsb.phpnuW+APK<1ZT.CCHACarbon/Lang/vun.phpnuW+APK<1Z/NNMACarbon/Lang/nr.phpnuW+APK<1ZNACarbon/Lang/en_NG.phpnuW+APK<1Zw  PACarbon/Lang/fr_MR.phpnuW+APK<1ZpGGRACarbon/Lang/en_NL.phpnuW+APK<1ZpGGnTACarbon/Lang/en_FJ.phpnuW+APK<1Z8QsppUACarbon/Lang/om.phpnuW+APK<1ZpGG]ACarbon/Lang/en_RW.phpnuW+APK<1Z   8_ACarbon/Lang/sk_SK.phpnuW+APK<1ZiV  `ACarbon/Lang/ku_TR.phpnuW+APK<1Z6aACarbon/Lang/fr_CA.phpnuW+APK<1ZdACarbon/Lang/de_CH.phpnuW+APK<1Z.  fACarbon/Lang/dv_MV.phpnuW+APK<1Z>pACarbon/Lang/yuw_PG.phpnuW+APK<1Z''x  tACarbon/Lang/fr_NC.phpnuW+APK<1Z?Ej  FvACarbon/Lang/en_GU.phpnuW+APK<1Z4NNwACarbon/Lang/ia.phpnuW+APK<1Z''x  &yACarbon/Lang/fr_KM.phpnuW+APK<1Z''x  vzACarbon/Lang/fr_RE.phpnuW+APK<1ZȌff{ACarbon/Lang/nyn.phpnuW+APK<1ZQiD  oACarbon/Lang/fa_AF.phpnuW+APK<1ZdOOACarbon/Lang/yuw.phpnuW+APK<1Z~RACarbon/Lang/fr_BE.phpnuW+APK<1Z7T  hACarbon/Lang/de_LI.phpnuW+APK<1Z}:be  ACarbon/Lang/gu_IN.phpnuW+APK<1Zn99ACarbon/Lang/es_PH.phpnuW+APK<1Z, HACarbon/Lang/iu_CA.phpnuW+APK<1ZpGGqACarbon/Lang/en_SZ.phpnuW+APK<1Z4EACarbon/Lang/en_IN.phpnuW+APK<1ZBkOOݗACarbon/Lang/lij.phpnuW+APK<1Z  oACarbon/Lang/shi_Tfng.phpnuW+APK<1ZX  ÚACarbon/Lang/mi_NZ.phpnuW+APK<1ZNNACarbon/Lang/or.phpnuW+APK<1ZvACarbon/Lang/so_DJ.phpnuW+APK<1ZNn  ACarbon/Lang/mo.phpnuW+APK<1Z;n ۠ACarbon/Lang/af.phpnuW+APK<1ZACarbon/Lang/tr.phpnuW+APK<1Zw7GGrACarbon/Lang/es_BR.phpnuW+APK<1Z J99ACarbon/Lang/pap.phpnuW+APK<1Z}))zACarbon/Lang/ca_AD.phpnuW+APK<1Z̄A.ACarbon/Lang/el_CY.phpnuW+APK<1ZʷACarbon/Lang/zh_Hant_MO.phpnuW+APK<1Z}  ?ACarbon/Lang/gl_ES.phpnuW+APK<1ZZб  ACarbon/Lang/id_ID.phpnuW+APK<1Zw'0y y ACarbon/Lang/mai_IN.phpnuW+APK<1Z5NoACarbon/Lang/en_NZ.phpnuW+APK<1ZPPACarbon/Lang/to_TO.phpnuW+APK<1Z[  @ACarbon/Lang/nn_NO.phpnuW+APK<1Z2=PACarbon/Lang/nb_SJ.phpnuW+APK<1Z-OOACarbon/Lang/mag.phpnuW+APK<1Z +  ACarbon/Lang/ast_ES.phpnuW+APK<1ZnqACarbon/Lang/ky.phpnuW+APK<1ZoP VACarbon/Lang/uz_Latn.phpnuW+APK<1ZXlZZJACarbon/Lang/ar_IN.phpnuW+APK<1Z# 'BCarbon/Lang/sr_Latn_BA.phpnuW+APK<1Z>NBCarbon/Lang/ka.phpnuW+APK<1ZpGGB$BCarbon/Lang/en_NA.phpnuW+APK<1Z%l%BCarbon/Lang/raj_IN.phpnuW+APK<1Z2o>  .BCarbon/Lang/ik_CA.phpnuW+APK<1ZIJjC6BCarbon/Lang/uz_UZ@cyrillic.phpnuW+APK<1Z[ZZ=;BCarbon/Lang/ta_LK.phpnuW+APK<1Z?Ej  @BCarbon/Lang/en_BZ.phpnuW+APK<1Z&5  ,BBCarbon/Lang/nl_CW.phpnuW+APK<1Z1|CBCarbon/Lang/nds_DE.phpnuW+APK<1Zu\ \ KBCarbon/Lang/dz_BT.phpnuW+APK<1ZVOUBCarbon/Lang/lzh_TW.phpnuW+APK<1ZC=5  !^BCarbon/Lang/ru_BY.phpnuW+APK<1Z q_BCarbon/Lang/hy.phpnuW+APK<1ZBmBCarbon/Lang/anp_IN.phpnuW+APK<1Z$ccsBCarbon/Lang/es.phpnuW+APK<1ZpGGDBCarbon/Lang/en_MY.phpnuW+APK<1Z''x  ЅBCarbon/Lang/fr_FR.phpnuW+APK<1ZBVC C  BCarbon/Lang/gl.phpnuW+APK<1Z''x  BCarbon/Lang/fr_MQ.phpnuW+APK<1ZBCarbon/Lang/fr_CD.phpnuW+APK<1Z NNBCarbon/Lang/tk.phpnuW+APK<1Z[)66BCarbon/Lang/kde.phpnuW+APK<1Z # # BCarbon/Lang/et.phpnuW+APK<1ZZ,vcBCarbon/Lang/nr_ZA.phpnuW+APK<1Zpg  4BCarbon/Lang/kk_KZ.phpnuW+APK<1Zi9  BCarbon/Lang/da_DK.phpnuW+APK<1Z 8((BCarbon/Lang/ms_SG.phpnuW+APK<1Z>ABCarbon/Lang/sr_Cyrl_XK.phpnuW+APK<1Z==jBCarbon/Lang/cs.phpnuW+APK<1ZpGG+BCarbon/Lang/en_IM.phpnuW+APK<1ZoBCarbon/Lang/nl.phpnuW+APK<1ZnáCCarbon/Lang/sd_IN.phpnuW+APK<1Z?Ej  CCarbon/Lang/en_PK.phpnuW+APK<1ZfK,1 CCarbon/Lang/hr.phpnuW+APK<1Z`) DCCarbon/Lang/km.phpnuW+APK<1Z''x  I'CCarbon/Lang/fr_RW.phpnuW+APK<1ZKV--NN(CCarbon/Lang/kw.phpnuW+APK<1Z}")*CCarbon/Lang/st_ZA.phpnuW+APK<1Zw} 2CCarbon/Lang/yue_HK.phpnuW+APK<1ZaؠOOQ6CCarbon/Lang/tig.phpnuW+APK<1Zhh7CCarbon/Lang/bn.phpnuW+APK<1Z6kkJCCarbon/Lang/pap_AW.phpnuW+APK<1ZR  >LCCarbon/Lang/bo_CN.phpnuW+APK<1ZMCCarbon/Lang/ayc_PE.phpnuW+APK<1ZpGGQCCarbon/Lang/en_DE.phpnuW+APK<1Z=85SCCarbon/Lang/ar_DZ.phpnuW+APK<1Zhu(eCCarbon/Lang/kea.phpnuW+APK<1ZQo\\mCCarbon/Lang/ksh.phpnuW+APK<1ZpGGtCCarbon/Lang/en_GM.phpnuW+APK<1Z.`=vCCarbon/Lang/dav.phpnuW+APK<1Z㪍q \{CCarbon/Lang/lb.phpnuW+APK<1ZjjRCCarbon/Lang/en_SG.phpnuW+APK<1Zn!KA CCarbon/Lang/kok_IN.phpnuW+APK<1Z?Ej  הCCarbon/Lang/en_WS.phpnuW+APK<1Z9##'CCarbon/Lang/fr_TN.phpnuW+APK<1ZX  CCarbon/Lang/th.phpnuW+APK<1Z100CCarbon/Lang/fil_PH.phpnuW+APK<1Z_CCarbon/Lang/ti_ER.phpnuW+APK<1Z#!!CCarbon/Lang/ckb.phpnuW+APK<1Z-GYOOCCarbon/Lang/nso.phpnuW+APK<1ZNNvCCarbon/Lang/yi.phpnuW+APK<1Z-Ј CCarbon/Lang/zh_Hant.phpnuW+APK<1ZpGG7CCarbon/Lang/en_SI.phpnuW+APK<1ZڗOOCCarbon/Lang/dsb.phpnuW+APK<1Z''x  UCCarbon/Lang/fr_BI.phpnuW+APK<1Zϑ  CCarbon/Lang/hi_IN.phpnuW+APK<1ZpGGCCarbon/Lang/en_NR.phpnuW+APK<1Z CCarbon/Lang/sw.phpnuW+APK<1Zm|CCarbon/Lang/tet.phpnuW+APK<1Zߟ$$CCarbon/Lang/aa_ER.phpnuW+APK<1ZpGGCCarbon/Lang/en_UG.phpnuW+APK<1ZJe~CCarbon/Lang/miq_NI.phpnuW+APK<1ZcCCarbon/Lang/nl_AW.phpnuW+APK<1ZpGGDCarbon/Lang/en_SB.phpnuW+APK<1ZA``KDCarbon/Lang/fr_MA.phpnuW+APK<1Zu  DCarbon/Lang/te_IN.phpnuW+APK<1ZpGG@DCarbon/Lang/en_FK.phpnuW+APK<1Z+3DCarbon/Lang/ar_YE.phpnuW+APK<1ZvÕDCarbon/Lang/el_GR.phpnuW+APK<1Zl3AADCarbon/Lang/ug_CN.phpnuW+APK<1Z)tt0DCarbon/Lang/ta_IN.phpnuW+APK<1ZңqqDCarbon/Lang/kk.phpnuW+APK<1ZM **(DCarbon/Lang/lrc_IQ.phpnuW+APK<1ZӾ6 *DCarbon/Lang/zh_Hans_SG.phpnuW+APK<1Z?Ej  f+DCarbon/Lang/en_VI.phpnuW+APK<1ZM  ,DCarbon/Lang/tr_TR.phpnuW+APK<1Z.DCarbon/Lang/nan_TW@latin.phpnuW+APK<1Z?Ej  12DCarbon/Lang/en_TT.phpnuW+APK<1ZDh3DCarbon/Lang/en_PH.phpnuW+APK<1Z< 5DCarbon/Lang/vi.phpnuW+APK<1Z-^@DCarbon/Lang/nl_NL.phpnuW+APK<1Z5DDCarbon/Lang/li_NL.phpnuW+APK<1Zй@@KDCarbon/Lang/ksb.phpnuW+APK<1Z5R R -PDCarbon/Lang/kn.phpnuW+APK<1Z\DCarbon/Lang/en_CY.phpnuW+APK<1ZxGG_DCarbon/Lang/ko_KP.phpnuW+APK<1Z*QaDCarbon/Lang/sd.phpnuW+APK<1Z\GGuiDCarbon/Lang/qu_BO.phpnuW+APK<1ZAkDCarbon/Lang/mzn.phpnuW+APK<1ZsnDCarbon/Lang/cgg.phpnuW+APK<1ZN.tDCarbon/Lang/sn.phpnuW+APK<1Z {DCarbon/Lang/rm.phpnuW+APK<1ZR^IIDCarbon/Lang/cmn_TW.phpnuW+APK<1Z| DCarbon/Lang/mr.phpnuW+APK<1ZӾ6iDCarbon/Lang/yue_Hans.phpnuW+APK<1Z s  DCarbon/Lang/gd_GB.phpnuW+APK<1ZpGGDCarbon/Lang/en_GH.phpnuW+APK<1ZnE%%DCarbon/Lang/en_CH.phpnuW+APK<1ZM2AADCarbon/Lang/asa.phpnuW+APK<1Z:NNDCarbon/Lang/yo_BJ.phpnuW+APK<1ZcQQDCarbon/Lang/ca_ES_Valencia.phpnuW+APK<1Zc""DCarbon/Lang/wo_SN.phpnuW+APK<1ZnvB]??$DCarbon/Lang/pt.phpnuW+APK<1Z"DCarbon/Lang/bez.phpnuW+APK<1Z6kkDCarbon/Lang/pap_CW.phpnuW+APK<1Z&5  DCarbon/Lang/nl_BQ.phpnuW+APK<1ZK:DCarbon/Lang/sah_RU.phpnuW+APK<1ZC"DCarbon/Lang/ar_TN.phpnuW+APK<1Z''x  DCarbon/Lang/fr_MU.phpnuW+APK<1Z%EDCarbon/Lang/iw.phpnuW+APK<1ZDŽtDCarbon/Lang/fy_NL.phpnuW+APK<1Z._DCarbon/Lang/sgs_LT.phpnuW+APK<1ZpGGDCarbon/Lang/en_BM.phpnuW+APK<1Z}TOO!DCarbon/Lang/sat.phpnuW+APK<1ZTʟ%@@DCarbon/Lang/ar_LY.phpnuW+APK<1ZE8ECarbon/Lang/pt_PT.phpnuW+APK<1ZgrtH ECarbon/Lang/lg_UG.phpnuW+APK<1Z''x  cECarbon/Lang/fr_GQ.phpnuW+APK<1ZpGGECarbon/Lang/en_KY.phpnuW+APK<1ZÂ~~?ECarbon/Lang/ar_SS.phpnuW+APK<1Zk_ؾ4 4 ECarbon/Lang/mi.phpnuW+APK<1Zʷx!ECarbon/Lang/zh_Hant_TW.phpnuW+APK<1Z"ECarbon/Lang/uz_Arab.phpnuW+APK<1Z))'ECarbon/Lang/ar_EH.phpnuW+APK<1ZhOO)ECarbon/Lang/mai.phpnuW+APK<1Z*ECarbon/Lang/guz.phpnuW+APK<1Z}jZNN1ECarbon/Lang/tt.phpnuW+APK<1ZpGG%3ECarbon/Lang/en_KN.phpnuW+APK<1Z* T4ECarbon/Lang/nmg.phpnuW+APK<1ZC=5  9ECarbon/Lang/ru_KG.phpnuW+APK<1Z\;ECarbon/Lang/mas.phpnuW+APK<1Z''x  #CECarbon/Lang/fr_SC.phpnuW+APK<1ZpGGsDECarbon/Lang/en_CX.phpnuW+APK<1ZOOEECarbon/Lang/nhn.phpnuW+APK<1Zއ  GECarbon/Lang/ml.phpnuW+APK<1ZC=5  TECarbon/Lang/ru_KZ.phpnuW+APK<1Z[ia  BVECarbon/Lang/pt_GW.phpnuW+APK<1ZpGGWECarbon/Lang/en_MU.phpnuW+APK<1ZI YECarbon/Lang/lkt.phpnuW+APK<1Zƪ?^ECarbon/Lang/pa_Arab.phpnuW+APK<1Z_FcECarbon/Lang/az_Latn.phpnuW+APK<1ZޙihECarbon/Lang/ta_SG.phpnuW+APK<1Z泺4>>]nECarbon/Lang/ar_LB.phpnuW+APK<1ZpGGvECarbon/Lang/en_MP.phpnuW+APK<1Z''x  lxECarbon/Lang/fr_BJ.phpnuW+APK<1ZdyECarbon/Lang/es_PA.phpnuW+APK<1Z 7||{ECarbon/Lang/mhr_RU.phpnuW+APK<1Z.  iECarbon/Lang/sv_SE.phpnuW+APK<1Z3   ECarbon/Lang/tzm_Latn.phpnuW+APK<1Zv__ECarbon/Lang/bi_VU.phpnuW+APK<1Z?Ej  ECarbon/Lang/en_BW.phpnuW+APK<1ZJ> OO ECarbon/Lang/lzh.phpnuW+APK<1ZQJ??ECarbon/Lang/tpi_PG.phpnuW+APK<1Z f!ECarbon/Lang/luo.phpnuW+APK<1Z ECarbon/Lang/es_BO.phpnuW+APK<1ZʷnECarbon/Lang/yue_Hant.phpnuW+APK<1Z?Ej  ƩECarbon/Lang/en_US.phpnuW+APK<1ZGF//ECarbon/Lang/de.phpnuW+APK<1ZK  ECarbon/Lang/eu_ES.phpnuW+APK<1ZzOO׼ECarbon/Lang/mjw.phpnuW+APK<1ZQ_L##iECarbon/Lang/uz_UZ.phpnuW+APK<1Z"Ϟ ECarbon/Lang/fo.phpnuW+APK<1ZECarbon/Lang/ebu.phpnuW+APK<1Z<00ECarbon/Lang/bas.phpnuW+APK<1ZpW)QECarbon/Lang/kab_DZ.phpnuW+APK<1ZEkdECarbon/Lang/nl_BE.phpnuW+APK<1ZlIQOOECarbon/Lang/yue.phpnuW+APK<1ZNd  )ECarbon/Lang/i18n.phpnuW+APK<1ZpGGzECarbon/Lang/en_PG.phpnuW+APK<1ZNU&ECarbon/Lang/ar_AE.phpnuW+APK<1Zd Z  ECarbon/Lang/si_LK.phpnuW+APK<1Z  hECarbon/Lang/sr_Latn.phpnuW+APK<1Z9IIECarbon/Lang/rn.phpnuW+APK<1ZςEECarbon/Lang/tr_CY.phpnuW+APK<1Zv"ECarbon/Lang/sw_TZ.phpnuW+APK<1ZpGGbFCarbon/Lang/en_150.phpnuW+APK<1ZDOOFCarbon/Lang/bem.phpnuW+APK<1Z"BOOFCarbon/Lang/anp.phpnuW+APK<1Z8 FCarbon/Lang/tzm.phpnuW+APK<1Z8OOFCarbon/Lang/chr.phpnuW+APK<1Zq a  FCarbon/Lang/it_SM.phpnuW+APK<1ZUG FCarbon/Lang/tzl.phpnuW+APK<1ZazGFCarbon/Lang/hy_AM.phpnuW+APK<1ZpGGFCarbon/Lang/en_GD.phpnuW+APK<1Z0RXw FCarbon/Lang/chr_US.phpnuW+APK<1Z%uu )FCarbon/Lang/ia_FR.phpnuW+APK<1Z7\\/FCarbon/Lang/sr_Cyrl.phpnuW+APK<1ZYm6]VVhAFCarbon/Lang/doi_IN.phpnuW+APK<1ZBHFCarbon/Lang/mg_MG.phpnuW+APK<1Z?Ej  LOFCarbon/Lang/en_PR.phpnuW+APK<1ZeoPFCarbon/Lang/en_ISO.phpnuW+APK<1Z))RFCarbon/Lang/ar_KM.phpnuW+APK<1Z  XTFCarbon/Lang/ga_IE.phpnuW+APK<1Z))UFCarbon/Lang/ar_DJ.phpnuW+APK<1ZC))WFCarbon/Lang/bs_Latn.phpnuW+APK<1ZtXFCarbon/Lang/tk_TM.phpnuW+APK<1Z?Ej  aFCarbon/Lang/en_DM.phpnuW+APK<1Z5. cFCarbon/Lang/shs_CA.phpnuW+APK<1ZoRZiFCarbon/Lang/hr_BA.phpnuW+APK<1Z-!b>>nFCarbon/Lang/ar_SY.phpnuW+APK<1ZpGGwFCarbon/Lang/en_LS.phpnuW+APK<1ZpGGxFCarbon/Lang/en_MW.phpnuW+APK<1Z]CC.zFCarbon/Lang/ccp_IN.phpnuW+APK<1ZY{FCarbon/Lang/mgo.phpnuW+APK<1Z(|@zGGрFCarbon/Lang/es_EA.phpnuW+APK<1Z >vv]FCarbon/Lang/ses.phpnuW+APK<1Z{A ]GGFCarbon/Lang/it.phpnuW+APK<1Z  FCarbon/Lang/sr_RS@latin.phpnuW+APK<1ZdFCarbon/Lang/es_CL.phpnuW+APK<1Z$rllFCarbon/Lang/gsw_LI.phpnuW+APK<1ZW;##FCarbon/Lang/ms_BN.phpnuW+APK<1ZFFCarbon/Lang/en_DK.phpnuW+APK<1ZbMNN3FCarbon/Lang/ce.phpnuW+APK<1ZNNåFCarbon/Lang/bi.phpnuW+APK<1ZdSFCarbon/Lang/es_EC.phpnuW+APK<1Zҗ1kNN>FCarbon/Lang/aa.phpnuW+APK<1Z5 ΪFCarbon/Lang/fo_DK.phpnuW+APK<1Zq~~FCarbon/Lang/pt_BR.phpnuW+APK<1Z[ia  FCarbon/Lang/pt_LU.phpnuW+APK<1ZFCarbon/Lang/wa_BE.phpnuW+APK<1Zhk  ָFCarbon/Lang/is_IS.phpnuW+APK<1Z"M M &FCarbon/Lang/si.phpnuW+APK<1Z}]FCarbon/Lang/ru.phpnuW+APK<1ZFCarbon/Lang/en_IE.phpnuW+APK<1ZBk  FCarbon/Lang/ps_AF.phpnuW+APK<1Z''x  FCarbon/Lang/fr_MF.phpnuW+APK<1Z^5&XFCarbon/Lang/fa.phpnuW+APK<1ZpGGFCarbon/Lang/en_SH.phpnuW+APK<1ZHDD#FCarbon/Lang/it_IT.phpnuW+APK<1Z,͹  FCarbon/Lang/ro.phpnuW+APK<1ZYb1GCarbon/Lang/es_DO.phpnuW+APK<1Z  GCarbon/Lang/mgh.phpnuW+APK<1ZdGCarbon/Lang/es_HN.phpnuW+APK<1Z{$GCarbon/Lang/zh_TW.phpnuW+APK<1Z QVGCarbon/Lang/nhn_MX.phpnuW+APK<1Z^4 tGCarbon/Lang/sat_IN.phpnuW+APK<1ZgY Y %GCarbon/Lang/id.phpnuW+APK<1ZpGG1GCarbon/Lang/en_AI.phpnuW+APK<1Z ذQ Q 2GCarbon/Lang/nn.phpnuW+APK<1Z''x  ;=GCarbon/Lang/fr_ML.phpnuW+APK<1Z /eb>GCarbon/Lang/lrc.phpnuW+APK<1Z\  @GCarbon/Lang/ff_MR.phpnuW+APK<1Zb BGCarbon/Lang/bs.phpnuW+APK<1ZKnOOPGCarbon/Lang/kok.phpnuW+APK<1ZV 4RGCarbon/Lang/tt_RU@iqtelif.phpnuW+APK<1ZEVGCarbon/Lang/mfe_MU.phpnuW+APK<1Z.\GCarbon/Lang/gv_GB.phpnuW+APK<1ZdGCarbon/Lang/en_CA.phpnuW+APK<1Z}4OOfGCarbon/Lang/quz.phpnuW+APK<1ZFƸchGCarbon/Lang/lag.phpnuW+APK<1Zv^mGCarbon/Lang/wae_CH.phpnuW+APK<1ZDɳ)rGCarbon/Lang/zh_CN.phpnuW+APK<1Z2+uGCarbon/Lang/sid_ET.phpnuW+APK<1Z?J& MyGCarbon/Lang/sr_Latn_ME.phpnuW+APK<1Z ĩNNGCarbon/Lang/gv.phpnuW+APK<1Zq  GCarbon/Lang/om_ET.phpnuW+APK<1Zqh}}cGCarbon/Lang/ur_IN.phpnuW+APK<1Z?Ej  %GCarbon/Lang/en_MO.phpnuW+APK<1ZpGGuGCarbon/Lang/en_NU.phpnuW+APK<1ZL' ' GCarbon/Lang/gu.phpnuW+APK<1Z7h##jGCarbon/Lang/tn_ZA.phpnuW+APK<1ZNNҢGCarbon/Lang/ks.phpnuW+APK<1Z{ bGCarbon/Lang/yo.phpnuW+APK<1Z[ia  GCarbon/Lang/pt_CH.phpnuW+APK<1Z ЯGCarbon/Lang/lo.phpnuW+APK<1Z;OOGCarbon/Lang/bhb.phpnuW+APK<1ZdvGCarbon/Lang/es_PE.phpnuW+APK<1ZffffaGCarbon/Lang/ta.phpnuW+APK<1Z}OO GCarbon/Lang/mfe.phpnuW+APK<1Z-!b>>GCarbon/Lang/ar_JO.phpnuW+APK<1Z  GCarbon/Lang/hr_HR.phpnuW+APK<1ZxssnGCarbon/Lang/ii.phpnuW+APK<1Z''x  #GCarbon/Lang/fr_SN.phpnuW+APK<1ZpGGsGCarbon/Lang/en_GG.phpnuW+APK<1ZvGCarbon/Lang/fr_CH.phpnuW+APK<1ZvR`OOGCarbon/Lang/mhr.phpnuW+APK<1Z}*B  GCarbon/Lang/ha_GH.phpnuW+APK<1ZpGGGCarbon/Lang/en_FI.phpnuW+APK<1Z䇢  }GCarbon/Lang/kn_IN.phpnuW+APK<1ZڼGCarbon/Lang/ksf.phpnuW+APK<1ZNJGCarbon/Lang/sc_IT.phpnuW+APK<1Zj\ 8GCarbon/Lang/ks_IN.phpnuW+APK<1Z>~!o  IHCarbon/Lang/cy_GB.phpnuW+APK<1Z`Y HCarbon/Lang/zh_Hans.phpnuW+APK<1Z1H((HCarbon/Lang/aa_ER@saaho.phpnuW+APK<1Z.a3HCarbon/Lang/sv_AX.phpnuW+APK<1ZkzNNHHCarbon/Lang/ms_MY.phpnuW+APK<1ZF1k HCarbon/Lang/ko.phpnuW+APK<1Z2Uww$HCarbon/Lang/oc.phpnuW+APK<1Zۺ  3HCarbon/Lang/hu_HU.phpnuW+APK<1Z~OO5HCarbon/Lang/kab.phpnuW+APK<1ZpGG6HCarbon/Lang/en_CC.phpnuW+APK<1ZXkk$8HCarbon/Lang/mer.phpnuW+APK<1Zܒ>HCarbon/Lang/prg.phpnuW+APK<1Z'  EHCarbon/Lang/sq_AL.phpnuW+APK<1Zx FHCarbon/Lang/ss.phpnuW+APK<1Z7șNN+QHCarbon/Lang/ik.phpnuW+APK<1Zs QQRHCarbon/Lang/gom.phpnuW+APK<1ZpGGOTHCarbon/Lang/en_VC.phpnuW+APK<1ZD[[UHCarbon/Lang/ewo.phpnuW+APK<1Z1NNy^HCarbon/Lang/zu.phpnuW+APK<1Z+h `HCarbon/Lang/am_ET.phpnuW+APK<1Z+  ChHCarbon/Lang/se_SE.phpnuW+APK<1Z:ɷiHCarbon/Lang/de_AT.phpnuW+APK<1Zk``kHCarbon/Lang/en_SD.phpnuW+APK<1ZTr  mHCarbon/Lang/nds_NL.phpnuW+APK<1Z1/qHCarbon/Lang/pt_MO.phpnuW+APK<1Z-  4tHCarbon/Lang/ff_CM.phpnuW+APK<1Z uHCarbon/Lang/bm.phpnuW+APK<1Zb  HCarbon/Lang/fo_FO.phpnuW+APK<1Z,؀HCarbon/Lang/ar_SD.phpnuW+APK<1Z''x  HCarbon/Lang/fr_TG.phpnuW+APK<1Z 9HCarbon/Lang/bo_IN.phpnuW+APK<1ZrOO}HCarbon/Lang/byn.phpnuW+APK<1ZߜHHHCarbon/Lang/mas_TZ.phpnuW+APK<1Z))HCarbon/Lang/ar_SO.phpnuW+APK<1Z}<   HCarbon/Lang/mt_MT.phpnuW+APK<1Z_[HCarbon/Lang/en_ZM.phpnuW+APK<1Z5ƭ  HCarbon/Lang/gsw.phpnuW+APK<1ZޢHCarbon/Lang/nnh.phpnuW+APK<1ZpGGǧHCarbon/Lang/en_TZ.phpnuW+APK<1ZI))SHCarbon/Lang/agq.phpnuW+APK<1Z[ia  HCarbon/Lang/pt_TL.phpnuW+APK<1ZdHCarbon/Lang/tcy_IN.phpnuW+APK<1Z-|KoHCarbon/Lang/es_NI.phpnuW+APK<1ZPuHCarbon/Lang/pa_PK.phpnuW+APK<1Zǖ@HCarbon/Lang/an_ES.phpnuW+APK<1ZcoVHCarbon/Lang/rw_RW.phpnuW+APK<1ZHlAHCarbon/Lang/mjw_IN.phpnuW+APK<1ZkOOXHCarbon/Lang/unm.phpnuW+APK<1Z.  HCarbon/Lang/sv_FI.phpnuW+APK<1Z8:HCarbon/Lang/my.phpnuW+APK<1Z[ia  HCarbon/Lang/pt_ST.phpnuW+APK<1ZpGGXHCarbon/Lang/en_VU.phpnuW+APK<1Z6NNHCarbon/Lang/ak.phpnuW+APK<1Z-jINNtHCarbon/Lang/to.phpnuW+APK<1ZT.CCHCarbon/Lang/jmc.phpnuW+APK<1Z猪N  HCarbon/Lang/shi.phpnuW+APK<1ZnHCarbon/Lang/lij_IT.phpnuW+APK<1Zm'1 HCarbon/Lang/mni_IN.phpnuW+APK<1Z9>NICarbon/Lang/ar_SA.phpnuW+APK<1ZT  ICarbon/Lang/ca_ES.phpnuW+APK<1Z  ICarbon/Lang/sl_SI.phpnuW+APK<1Z?Ej  'ICarbon/Lang/en_MH.phpnuW+APK<1Z!HjjwICarbon/Lang/ee.phpnuW+APK<1ZpGG#'ICarbon/Lang/en_BB.phpnuW+APK<1Z"wNN(ICarbon/Lang/sm.phpnuW+APK<1ZFcK?*ICarbon/Lang/be_BY@latin.phpnuW+APK<1ZGoV''.ICarbon/Lang/sr_Cyrl_BA.phpnuW+APK<1Z@OO2ICarbon/Lang/hif.phpnuW+APK<1Z<4ICarbon/Lang/ln.phpnuW+APK<1ZO DMM LJCarbon/Lang/kl_GL.phpnuW+APK<1Z\VJCarbon/Lang/en.phpnuW+APK<1Z}*B  eJCarbon/Lang/ha_NG.phpnuW+APK<1Z{  )gJCarbon/Lang/ka_GE.phpnuW+APK<1ZEyhJCarbon/Lang/the_NP.phpnuW+APK<1ZZ)__nJCarbon/Lang/de_DE.phpnuW+APK<1Z[ia  FpJCarbon/Lang/pt_CV.phpnuW+APK<1ZVVqJCarbon/Lang/lu.phpnuW+APK<1Z.vJCarbon/Lang/bn_BD.phpnuW+APK<1ZdX|JCarbon/Lang/es_CO.phpnuW+APK<1Z1ssC~JCarbon/Lang/vai_Latn.phpnuW+APK<1Z]jwOOJCarbon/Lang/shs.phpnuW+APK<1Zv55JCarbon/Lang/sr_Cyrl_ME.phpnuW+APK<1Z4yyJCarbon/Lang/pl.phpnuW+APK<1Z]ʨJCarbon/Lang/fr_LU.phpnuW+APK<1Z,W2JCarbon/MessageFormatter/MessageFormatterMapper.phpnuW+APK<1Z=TضJCarbon/Carbon.phpnuW+APK<1Z_V*4LCarbon/Exceptions/InvalidTypeException.phpnuW+APK<1ZDQ.6LCarbon/Exceptions/InvalidTimeZoneException.phpnuW+APK<1Z.8LCarbon/Exceptions/InvalidIntervalException.phpnuW+APK<1Ze6-M.:LCarbon/Exceptions/BadFluentSetterException.phpnuW+APK<1Za())3>?LCarbon/Exceptions/BadFluentConstructorException.phpnuW+APK<1ZMDg@)CLCarbon/Exceptions/ParseErrorException.phpnuW+APK<1ZP󋺷0JLCarbon/Exceptions/UnitNotConfiguredException.phpnuW+APK<1Z)&&OLCarbon/Exceptions/Exception.phpnuW+APK<1ZQ{,PLCarbon/Exceptions/EndLessPeriodException.phpnuW+APK<1Z,RLCarbon/Exceptions/UnknownSetterException.phpnuW+APK<1Z&AhEQQ*VLCarbon/Exceptions/InvalidDateException.phpnuW+APK<1ZLb#\LCarbon/Exceptions/UnitException.phpnuW+APK<1ZY9)^LCarbon/Exceptions/OutOfRangeException.phpnuW+APK<1ZoF,fLCarbon/Exceptions/UnknownGetterException.phpnuW+APK<1ZF *kLCarbon/Exceptions/UnreachableException.phpnuW+APK<1ZJ0o. mLCarbon/Exceptions/NotACarbonClassException.phpnuW+APK<1Z'?5qLCarbon/Exceptions/InvalidPeriodParameterException.phpnuW+APK<1Zd8O??&tLCarbon/Exceptions/RuntimeException.phpnuW+APK<1Z10uLCarbon/Exceptions/InvalidPeriodDateException.phpnuW+APK<1ZFEE,wLCarbon/Exceptions/BadMethodCallException.phpnuW+APK<1Z,G*cyLCarbon/Exceptions/UnknownUnitException.phpnuW+APK<1ZUI 1GG.D}LCarbon/Exceptions/InvalidArgumentException.phpnuW+APK<1Z(*~LCarbon/Exceptions/InvalidCastException.phpnuW+APK<1Z,LCarbon/Exceptions/InvalidFormatException.phpnuW+APK<1Z"0 LCarbon/Exceptions/BadComparisonUnitException.phpnuW+APK<1ZF  ,LCarbon/Exceptions/UnknownMethodException.phpnuW+APK<1ZK-hLCarbon/Exceptions/NotLocaleAwareException.phpnuW+APK<1ZA*)gLCarbon/Exceptions/NotAPeriodException.phpnuW+APK<1Zq(tLCarbon/Exceptions/ImmutableException.phpnuW+APK<1ZakmŕLCarbon/Factory.phpnuW+APK<1Z"|''(uMCarbon/TranslatorStrongTypeInterface.phpnuW+APK<1Z """"MxMCarbon/CarbonTimeZone.phpnuW+APK<1Z s6$$MCarbon/PHPStan/MacroScanner.phpnuW+APK<1Zlq~  !+MCarbon/PHPStan/MacroExtension.phpnuW+APK<1ZR-}MCarbon/PHPStan/Macro.phpnuW+APK<1Zc ɱMCarbon/PHPStan/AbstractMacro.phpnuW+APK<1Zh ''MCarbon/FactoryImmutable.phpnuW+APK<1Z Z: NCarbon/CarbonInterface.phpnuW+APK<1ZayK "*jRCarbon/Laravel/ServiceProvider.phpnuW+APK<1Z?   wRCarbon/TranslatorImmutable.phpnuW+APK<1ZI&&vRCarbon/Translator.phpnuW+APK<1Z ff RCarbon/CarbonPeriodImmutable.phpnuW+APK<1Z,9EERCarbon/CarbonInterval.phpnuW+APK<1Z:P%%%&TCarbon/Traits/Rounding.phpnuW+APK<1Z=zzCTCarbon/Traits/Creator.phpnuW+APK<1Z_ممTCarbon/Traits/Date.phpnuW+APK<1ZljSGG&DWCarbon/Traits/DeprecatedProperties.phpnuW+APK<1Zs+55vKWCarbon/Traits/Mutability.phpnuW+APK<1Z[uPWCarbon/Traits/Mixin.phpnuW+APK<1Z?1GGjWCarbon/Traits/Test.phpnuW+APK<1Z kJ3J3eWCarbon/Traits/Options.phpnuW+APK<1ZgCWCarbon/Traits/Comparison.phpnuW+APK<1Z 5;1rrHXCarbon/Traits/Localization.phpnuW+APK<1Z * * XCarbon/Traits/IntervalStep.phpnuW+APK<1ZLd33"(XCarbon/Traits/IntervalRounding.phpnuW+APK<1Zy@@XCarbon/Traits/Difference.phpnuW+APK<1Z+9YCarbon/Traits/Timestamp.phpnuW+APK<1ZBBeYCarbon/Traits/Cast.phpnuW+APK<1ZC! YCarbon/Traits/ToStringFormat.phpnuW+APK<1Z5X7b  YCarbon/Traits/Macro.phpnuW+APK<1Z$y*00QYCarbon/Traits/Units.phpnuW+APK<1Zj[%ZCarbon/Traits/Week.phpnuW+APK<1ZP ] HZCarbon/Traits/MagicParameter.phpnuW+APK<1ZF 9Z;Z;i"ZCarbon/Traits/Converter.phpnuW+APK<1ZRI!I!^ZCarbon/Traits/Serialization.phpnuW+APK<1Z-c&ZCarbon/Traits/ObjectInitialisation.phpnuW+APK<1ZѭQ%,%,ZCarbon/Traits/Boundaries.phpnuW+APK<1Z55ZCarbon/Traits/Modifiers.phpnuW+APK<1Z.mvqKqKZCarbon/CarbonPeriod.phpnuW+APK<1ZM /\Carbon/List/regions.phpnuW+APK<1Z 'ssK\Carbon/List/languages.phpnuW+APK<1ZFe.ĉĉ \Carbon/CarbonImmutable.phpnuW+APK<1ZKJ#J^Carbon/CarbonConverterInterface.phpnuW+APK<1ZS)) L^Carbon/AbstractTranslator.phpnuW+APK1ZmaWKv^ClockInterface.phpnuW+APK\5ZÓCYY[w^Monolog/Logger.phpnuW+APK\5Zj^Monolog/SignalHandler.phpnuW+APK\5ZT^Monolog/LogRecord.phpnuW+APK\5Zv$==^Monolog/DateTimeImmutable.phpnuW+APK\5Z#G ,7^Monolog/Processor/PsrLogMessageProcessor.phpnuW+APK\5Za'r^Monolog/Processor/HostnameProcessor.phpnuW+APK\5Zx"^Monolog/Processor/UidProcessor.phpnuW+APK\5Z{bb"^Monolog/Processor/TagProcessor.phpnuW+APK\5Za ##%_Monolog/Processor/MemoryProcessor.phpnuW+APK\5Z .f,4 _Monolog/Processor/IntrospectionProcessor.phpnuW+APK\5Zj: "_Monolog/Processor/WebProcessor.phpnuW+APK\5Z)11*(_Monolog/Processor/MemoryUsageProcessor.phpnuW+APK\5ZY^(W,_Monolog/Processor/ProcessorInterface.phpnuW+APK\5Z:DChh(Q/_Monolog/Processor/MercurialProcessor.phpnuW+APK\5Z__(7_Monolog/Processor/ProcessIdProcessor.phpnuW+APK\5Zx\˕"9_Monolog/Processor/GitProcessor.phpnuW+APK\5ZDD.A_Monolog/Processor/MemoryPeakUsageProcessor.phpnuW+APK\5ZMnn n QE_Monolog/Test/TestCase.phpnuW+APK\5Z btO_Monolog/Registry.phpnuW+APK\5Z0C>^_Monolog/Handler/FingersCrossed/ActivationStrategyInterface.phpnuW+APK\5ZD?NN?,b_Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.phpnuW+APK\5Zf& Af_Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.phpnuW+APK\5Z!p_Monolog/Handler/SqsHandler.phpnuW+APK\5Z5?6 )x_Monolog/Handler/AbstractSyslogHandler.phpnuW+APK\5ZM77"C_Monolog/Handler/CouchDBHandler.phpnuW+APK\5Z&C+̎_Monolog/Handler/WhatFailureGroupHandler.phpnuW+APK\5Z=hh*Ė_Monolog/Handler/DoctrineCouchDBHandler.phpnuW+APK\5Zy:0/_Monolog/Handler/ProcessableHandlerInterface.phpnuW+APK\5ZV(_Monolog/Handler/FallbackGroupHandler.phpnuW+APK\5Z  #˧_Monolog/Handler/ErrorLogHandler.phpnuW+APK\5ZZ&9_Monolog/Handler/RedisPubSubHandler.phpnuW+APK\5Z^wn#kk'_Monolog/Handler/NativeMailerHandler.phpnuW+APK\5Z4m_Monolog/Handler/Handler.phpnuW+APK\5Zy  -_Monolog/Handler/WebRequestRecognizerTrait.phpnuW+APK\5Z@v#_Monolog/Handler/SamplingHandler.phpnuW+APK\5ZF!E_Monolog/Handler/LogglyHandler.phpnuW+APK\5Z_[  $_Monolog/Handler/FleepHookHandler.phpnuW+APK\5Z>$$!`Monolog/Handler/BufferHandler.phpnuW+APK\5ZH7 #j`Monolog/Handler/MandrillHandler.phpnuW+APK\5Zy`+f!`Monolog/Handler/FormattableHandlerTrait.phpnuW+APK\5ZwӇ &`Monolog/Handler/IFTTTHandler.phpnuW+APK\5ZC "/`Monolog/Handler/MongoDBHandler.phpnuW+APK\5Z_9ww9`Monolog/Handler/GelfHandler.phpnuW+APK\5Zll ?`Monolog/Handler/SlackHandler.phpnuW+APK\5Z?p#//!^[`Monolog/Handler/SocketHandler.phpnuW+APK\5ZY,T T "`Monolog/Handler/RollbarHandler.phpnuW+APK\5Z::%P`Monolog/Handler/InsightOpsHandler.phpnuW+APK\5ZIL'ߡ`Monolog/Handler/RotatingFileHandler.phpnuW+APK\5Zgg+`Monolog/Handler/Curl/Util.phpnuW+APK\5Z{”#`Monolog/Handler/PushoverHandler.phpnuW+APK\5Z-`Monolog/Handler/MissingExtensionException.phpnuW+APK\5Z> `Monolog/Handler/GroupHandler.phpnuW+APK\5Z8 rUU&`Monolog/Handler/SwiftMailerHandler.phpnuW+APK\5ZH$aMonolog/Handler/SyslogUdpHandler.phpnuW+APK\5ZbT,JJ!aMonolog/Handler/StreamHandler.phpnuW+APK\5ZIk99.aMonolog/Handler/NullHandler.phpnuW+APK\5Z=A A &3aMonolog/Handler/ZendMonitorHandler.phpnuW+APK\5ZZ+9@aMonolog/Handler/ProcessableHandlerTrait.phpnuW+APK\5ZDi$h(]GaMonolog/Handler/DeduplicationHandler.phpnuW+APK\5ZfToo(d_aMonolog/Handler/ElasticsearchHandler.phpnuW+APK\5Z+yaMonolog/Handler/AmqpHandler.phpnuW+APK\5ZhppgaMonolog/Handler/NoopHandler.phpnuW+APK\5Z+ #&aMonolog/Handler/ElasticaHandler.phpnuW+APK\5ZG yaMonolog/Handler/RedisHandler.phpnuW+APK\5Zmzz-aMonolog/Handler/AbstractProcessingHandler.phpnuW+APK\5Z$sM7 7 #laMonolog/Handler/SendGridHandler.phpnuW+APK\5Z#!aMonolog/Handler/FilterHandler.phpnuW+APK\5ZexaMonolog/Handler/CubeHandler.phpnuW+APK\5Z g%|aMonolog/Handler/LogEntriesHandler.phpnuW+APK\5ZcR#VaMonolog/Handler/OverflowHandler.phpnuW+APK\5ZRCC#^bMonolog/Handler/NewRelicHandler.phpnuW+APK\5Z"%%) bMonolog/Handler/BrowserConsoleHandler.phpnuW+APK\5Z6 $jFbMonolog/Handler/HandlerInterface.phpnuW+APK\5ZVb__"RbMonolog/Handler/ProcessHandler.phpnuW+APK\5ZvY,),)%GgbMonolog/Handler/PHPConsoleHandler.phpnuW+APK\5Z@_ #ȐbMonolog/Handler/DynamoDbHandler.phpnuW+APK\5ZrEss!͚bMonolog/Handler/SyslogHandler.phpnuW+APK\5Z$p))%bMonolog/Handler/Slack/SlackRecord.phpnuW+APK\5Z4ƌL &bMonolog/Handler/TelegramBotHandler.phpnuW+APK\5Zxx'bMonolog/Handler/SyslogUdp/UdpSocket.phpnuW+APK\5Z+!!)bMonolog/Handler/FingersCrossedHandler.phpnuW+APK\5Z{=g&&#cMonolog/Handler/FlowdockHandler.phpnuW+APK\5Z[ [ #&cMonolog/Handler/AbstractHandler.phpnuW+APK\5Zܩ #=1cMonolog/Handler/LogmaticHandler.phpnuW+APK\5Zww% % ,JJ#eRepository/Adapter/ArrayAdapter.phpnuW+APK@Z_.5&xeRepository/Adapter/WriterInterface.phpnuW+APK@Zj>Up)eRepository/Adapter/ServerConstAdapter.phpnuW+APK@Z޶$eRepository/Adapter/ApacheAdapter.phpnuW+APK@Z׷b&eRepository/Adapter/ReplacingWriter.phpnuW+APK@Z"eRepository/Adapter/MultiWriter.phpnuW+APK@ZЊs & 44 fParser/Value.phpnuW+APK@Z]~fParser/Entry.phpnuW+APKEZ & fWizard.phpnuW+APKqYZ?  fServiceProvider.phpnuW+APKqYZ Y  fFacade/Pdf.phpnuW+APKqYZXC!C!gfPDF.phpnuW+APKsYZXbpԊ*gexceptions/NoPreReleaseSuffixException.phpnuW+APKsYZ|&gexceptions/InvalidVersionException.phpnuW+APKsYZ/ gexceptions/InvalidPreReleaseSuffixException.phpnuW+APKsYZGd4!gexceptions/UnsupportedVersionConstraintException.phpnuW+APKsYZ'#gexceptions/NoBuildMetaDataException.phpnuW+APKsYZH$gBuildMetaData.phpnuW+APKsYZJ}r'gVersionNumber.phpnuW+APKsYZ13& & 9gVersionConstraintValue.phpnuW+APKsYZ.o ^^_DgPreReleaseSuffix.phpnuW+APKsYZv&E} LgVersion.phpnuW+APKsYZ(Ngconstraints/OrVersionConstraintGroup.phpnuW+APKsYZ/j-)FSgconstraints/AndVersionConstraintGroup.phpnuW+APKsYZ .vWgconstraints/SpecificMajorVersionConstraint.phpnuW+APKsYZ[ @@$Zgconstraints/AnyVersionConstraint.phpnuW+APKsYZ:B&b]gconstraints/ExactVersionConstraint.phpnuW+APKsYZoSMy)`gconstraints/AbstractVersionConstraint.phpnuW+APKsYZ^5cgconstraints/GreaterThanOrEqualToVersionConstraint.phpnuW+APKsYZW!qggconstraints/VersionConstraint.phpnuW+APKsYZLK6igconstraints/SpecificMajorAndMinorVersionConstraint.phpnuW+APKaZ7mmmgValueObjects/Styles.phpnuW+APKaZ媁\\gValueObjects/Node.phpnuW+APKaZ;lE--~gValueObjects/Style.phpnuW+APKaZ gQuestion.phpnuW+APKaZ$o@55gHtmlRenderer.phpnuW+APKaZ)e hComponents/Ol.phpnuW+APKaZtDopp} hComponents/Span.phpnuW+APKaZ_HǨ0hComponents/Ul.phpnuW+APKaZ>hComponents/Dd.phpnuW+APKaZ<&.hComponents/Li.phpnuW+APKaZ3#hComponents/Div.phpnuW+APKaZO.hComponents/BreakLine.phpnuW+APKaZ}omJJhComponents/Raw.phpnuW+APKaZ3z,hComponents/Paragraph.phpnuW+APKaZj XzhComponents/Dt.phpnuW+APKaZ ggchComponents/Anchor.phpnuW+APKaZࡀޛhComponents/Dl.phpnuW+APKaZ)FEhComponents/Hr.phpnuW+APKaZ% hComponents/Element.phpnuW+APKaZ5a 'hHtml/InheritStyles.phpnuW+APKaZ@hHtml/TableRenderer.phpnuW+APKaZ6h^hHtml/PreRenderer.phpnuW+APKaZ@bhHtml/CodeRenderer.phpnuW+APKaZܲۂhExceptions/InvalidStyle.phpnuW+APKaZlײ؃hExceptions/InvalidChild.phpnuW+APKaZ#DOOՄhExceptions/StyleNotFound.phpnuW+APKaZ@&_phExceptions/ColorNotFound.phpnuW+APKaZ}ohExceptions/InvalidColor.phpnuW+APKaZSSlhActions/StyleToMethod.phpnuW+APKaZzӖuu hTerminal.phpnuW+APKaZD,ZgghHelpers/QuestionHelper.phpnuW+APKaZQ#p#jhLaravel/TermwindServiceProvider.phpnuW+APKaZcq&$&$ hTermwind.phpnuW+APKaZ`PhRepositories/Styles.phpnuW+APKaZ&&hEnums/Color.phpnuW+APKaZh lhFunctions.phpnuW+APKiZæxxhCss/Processor.phpnuW+APKiZ \hCss/Property/Processor.phpnuW+APKiZ!>>= iCss/Property/Property.phpnuW+APKiZ@QÎiCss/Rule/Processor.phpnuW+APKiZ0(iCss/Rule/Rule.phpnuW+APKiZ^p.iCssToInlineStyles.phpnuW+APKAyZO4Wt{MiSupport/SelfReference.phpnuW+APKAyZJsxzzFOiSupport/ClosureScope.phpnuW+APKAyZQiSupport/ClosureStream.phpnuW+APKAyZSfX_iSupport/ReflectionClosure.phpnuW+APKAyZ&K^TTjSerializers/Signed.phpnuW+APKAyZ~(>9>99jSerializers/Native.phpnuW+APKAyZ<_.+ + SjSerializableClosure.phpnuW+APKAyZh~/ajUnsignedSerializableClosure.phpnuW+APKAyZf(LhjExceptions/MissingSecretKeyException.phpnuW+APKAyZ,(/jjExceptions/InvalidSignatureException.phpnuW+APKAyZ*Ktt.0ljExceptions/PhpVersionNotSupportedException.phpnuW+APKAyZt{QD11njSigners/Hmac.phpnuW+APKAyZwaasrjContracts/Serializable.phpnuW+APKAyZڜtjContracts/Signer.phpnuW+APKZu@@ujLazyOpenStream.phpnuW+APKZ>l hzjFnStream.phpnuW+APKZ2znn?jInflateStream.phpnuW+APKZ`(; jRfc7230.phpnuW+APKZN|#”jException/MalformedUriException.phpnuW+APKZח  jResponse.phpnuW+APKZPM jStreamDecoratorTrait.phpnuW+APKZ⣲pUpUgjUri.phpnuW+APKZŜ ~~ kUriComparator.phpnuW+APKZ%%kServerRequest.phpnuW+APKZq: t4kDroppingStream.phpnuW+APKZ;9kUploadedFile.phpnuW+APKZLkCachingStream.phpnuW+APKZixn!n!^kUriResolver.phpnuW+APKZ×  kNoSeekStream.phpnuW+APKZtӃEkMultipartStream.phpnuW+APKZ2l5CC kQuery.phpnuW+APKZʯ akStream.phpnuW+APKZoK^;; kRequest.phpnuW+APKZEGOkLimitStream.phpnuW+APKZW2 kMimeType.phpnuW+APKZ ֶlUriNormalizer.phpnuW+APKZC~  lStreamWrapper.phpnuW+APKZ3 HlMessage.phpnuW+APKZXXX mAppendStream.phpnuW+APKZLL mMessageTrait.phpnuW+APKZ  .?mHttpFactory.phpnuW+APKZ KmUtils.phpnuW+APKZg__ vlmHeader.phpnuW+APKZmd|mPumpStream.phpnuW+APKZcq HmBufferStream.phpnuW+APKZ,74mCodeSnippet.phpnuW+APKZrmRetryMiddleware.phpnuW+APKZE9ұmfunctions_include.phpnuW+APKZL+llmPool.phpnuW+APKZ++[mMiddleware.phpnuW+APKZ5O\$/mException/GuzzleException.phpnuW+APKZ/yymException/TransferException.phpnuW+APKZjmException/ClientException.phpnuW+APKZFjmException/ServerException.phpnuW+APKZN mException/ConnectException.phpnuW+APKZOm"mException/BadResponseException.phpnuW+APKZ$ee'mException/TooManyRedirectsException.phpnuW+APKZTE9&kmException/InvalidArgumentException.phpnuW+APKZ0؜[nException/RequestException.phpnuW+APKZ^:wwnBodySummarizer.phpnuW+APKZVx.#.#VnClientTrait.phpnuW+APKZHGM M :nPrepareBodyMiddleware.phpnuW+APKZ~sHH YGnClient.phpnuW+APKZW?""nHandlerStack.phpnuW+APKZoDl l nTransferStats.phpnuW+APKZnCookie/SessionCookieJar.phpnuW+APKZY nCookie/FileCookieJar.phpnuW+APKZ hJ77nCookie/SetCookie.phpnuW+APKZE CD  oCookie/CookieJarInterface.phpnuW+APKZcg%%oCookie/CookieJar.phpnuW+APKZ yC__ ;oHandler/CurlFactory.phpnuW+APKZI]22*oHandler/CurlHandler.phpnuW+APKZ9oHandler/Proxy.phpnuW+APKZaf  ҩoHandler/MockHandler.phpnuW+APKZbVSVS&oHandler/StreamHandler.phpnuW+APKZ^pHandler/CurlMultiHandler.phpnuW+APKZ7{  *6pHandler/HeaderProcessor.phpnuW+APKZ?CT T :pHandler/EasyHandle.phpnuW+APKZP /FpHandler/CurlFactoryInterface.phpnuW+APKZS%+%+IpRequestOptions.phpnuW+APKZ]wtpBodySummarizerInterface.phpnuW+APKZ3LU U upClientInterface.phpnuW+APKZCpRedirectMiddleware.phpnuW+APKZ119pMessageFormatterInterface.phpnuW+APKZL-uupMessageFormatter.phpnuW+APKZsw$ppDeepCopy/TypeMatcher/TypeMatcher.phpnuW+APKZ 0pDeepCopy/DeepCopy.phpnuW+APKZ"epDeepCopy/deep_copy.phpnuW+APKZ3!*$$(pDeepCopy/Matcher/PropertyTypeMatcher.phpnuW+APKZ?Sb$pDeepCopy/Matcher/PropertyMatcher.phpnuW+APKZLbhh2pDeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.phpnuW+APKZYx(pDeepCopy/Matcher/PropertyNameMatcher.phpnuW+APKZqe6pDeepCopy/Matcher/Matcher.phpnuW+APKZ4xx(WpDeepCopy/Exception/PropertyException.phpnuW+APKZLt%'pDeepCopy/Exception/CloneException.phpnuW+APKZ:~~(pDeepCopy/Reflection/ReflectionHelper.phpnuW+APKZ]]!pDeepCopy/Filter/SetNullFilter.phpnuW+APKZ7:qDeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.phpnuW+APKZ0/qDeepCopy/Filter/Doctrine/DoctrineProxyFilter.phpnuW+APKZ:D5"qDeepCopy/Filter/Doctrine/DoctrineCollectionFilter.phpnuW+APKZa˲! qDeepCopy/Filter/ReplaceFilter.phpnuW+APKZ,>#| qDeepCopy/Filter/ChainableFilter.phpnuW+APKZ6S\\qDeepCopy/Filter/Filter.phpnuW+APKZ6qDeepCopy/Filter/KeepFilter.phpnuW+APKZ-h"qDeepCopy/TypeFilter/TypeFilter.phpnuW+APKZGF/qDeepCopy/TypeFilter/Date/DateIntervalFilter.phpnuW+APKZ7  %}qDeepCopy/TypeFilter/ReplaceFilter.phpnuW+APKZJ5qDeepCopy/TypeFilter/Spl/SplDoublyLinkedListFilter.phpnuW+APKZ̰/SqDeepCopy/TypeFilter/Spl/SplDoublyLinkedList.phpnuW+APKZ0)-bqDeepCopy/TypeFilter/Spl/ArrayObjectFilter.phpnuW+APKZZ)!qDeepCopy/TypeFilter/ShallowCopyFilter.phpnuW+APKऩZ{)"qCacheInterface.phpnuW+APKऩZ٭q5qCacheException.phpnuW+APKZSm6qOperatingSystem.phpnuW+APKZb6 ;qConsole.phpnuW+APKZo*WO O OqRuntime.phpnuW+APKֺZRpqPort.phpnuW+APKֺZZ kvqAuth/Basic.phpnuW+APKֺZCqHookManager.phpnuW+APKֺZ ssqIri.phpnuW+APKֺZ\\qAuth.phpnuW+APKֺZiAqException/Transport.phpnuW+APKֺZRRVqException/InvalidArgument.phpnuW+APKֺZq1rException/ArgumentCount.phpnuW+APKֺZ&rException/Http.phpnuW+APKֺZ< rException/Http/Status304.phpnuW+APKֺZ(ssTrException/Http/Status429.phpnuW+APKֺZ{rException/Http/Status402.phpnuW+APKֺZkf7rException/Http/Status504.phpnuW+APKֺZSbXrException/Http/Status406.phpnuW+APKֺZ4,,vrException/Http/Status418.phpnuW+APKֺZ&XeerException/Http/Status431.phpnuW+APKֺZhmrException/Http/Status413.phpnuW+APKֺZwאrException/Http/Status405.phpnuW+APKֺZw;"rException/Http/Status503.phpnuW+APKֺZh$a2$rException/Http/Status306.phpnuW+APKֺZyJ&rException/Http/Status404.phpnuW+APKֺZ* Y(rException/Http/StatusUnknown.phpnuW+APKֺZs,rException/Http/Status502.phpnuW+APKֺZee.rException/Http/Status511.phpnuW+APKֺZ[F91rException/Http/Status411.phpnuW+APKֺZZ3rException/Http/Status409.phpnuW+APKֺZPf5rException/Http/Status415.phpnuW+APKֺZ2d7rException/Http/Status414.phpnuW+APKֺZkT9rException/Http/Status408.phpnuW+APKֺZf+;rException/Http/Status417.phpnuW+APKֺZ^:GG>rException/Http/Status428.phpnuW+APKֺZm@rException/Http/Status505.phpnuW+APKֺZ]BrException/Http/Status407.phpnuW+APKֺZ`:ErException/Http/Status412.phpnuW+APKֺZǿH7gGrException/Http/Status400.phpnuW+APKֺZ |IrException/Http/Status500.phpnuW+APKֺZmkKrException/Http/Status501.phpnuW+APKֺZη.pMrException/Http/Status410.phpnuW+APKֺZOrException/Http/Status401.phpnuW+APKֺZQrException/Http/Status403.phpnuW+APKֺZSrException/Http/Status305.phpnuW+APKֺZVrException/Http/Status416.phpnuW+APKֺZ*uuWXrException/Transport/Curl.phpnuW+APKֺZJM<< ^rCookie.phpnuW+APKֺZ @9фф orRequests.phpnuW+APKֺZ;|sIpv6.phpnuW+APKֺZy 5sHooks.phpnuW+APKֺZrw$w$ AsAutoload.phpnuW+APKֺZՄecc fsProxy.phpnuW+APKֺZ,S jsTransport.phpnuW+APKֺZ84  `psCookie/Jar.phpnuW+APKֺZ/yQ## sSession.phpnuW+APKֺZ5 L %wsUtility/CaseInsensitiveDictionary.phpnuW+APKֺZmmsUtility/FilteredIterator.phpnuW+APKֺZ^ PsUtility/InputValidator.phpnuW+APKֺZM00jsIdnaEncoder.phpnuW+APKֺZg^yy>(tTransport/Fsockopen.phpnuW+APKֺZj;sLsLftTransport/Curl.phpnuW+APKZ+ootAbstractLexer.phpnuW+APKZ( MtToken.phpnuW+APKZ GtView.phpnuW+APKZ(]tGlows/Glow.phpnuW+APKZD >tGlows/GlowRecorder.phpnuW+APKZ7tConcerns/UsesTime.phpnuW+APKZC~AAtConcerns/HasContext.phpnuW+APKZ Lii RtTime/Time.phpnuW+APKZ'tTime/SystemTime.phpnuW+APKZ!/qFFtApi.phpnuW+APKZT?++ tFlare.phpnuW+APKZaR uhelpers.phpnuW+APKZs^("uFlareMiddleware/CensorRequestHeaders.phpnuW+APKZ]ՆGG%uFlareMiddleware/AddGlows.phpnuW+APKZjf\#5(uFlareMiddleware/FlareMiddleware.phpnuW+APKZL_oo#D)uFlareMiddleware/RemoveRequestIp.phpnuW+APKZ<0CC)+uFlareMiddleware/AddDocumentationLinks.phpnuW+APKZL+0uFlareMiddleware/CensorRequestBodyFields.phpnuW+APKZA;;%3uFlareMiddleware/AddGitInformation.phpnuW+APKZT__-JQQ#>uFlareMiddleware/AddNotifierName.phpnuW+APKZfد:: ?uFlareMiddleware/AddSolutions.phpnuW+APKZ&v'4CuContext/BaseContextProviderDetector.phpnuW+APKZV#FFuContext/ContextProviderDetector.phpnuW+APKZ#hª*GuContext/ContextProvider.phpnuW+APKZ["HuContext/RequestContextProvider.phpnuW+APKZ{tf"EWuContext/ConsoleContextProvider.phpnuW+APKZ vYuEnums/MessageLevels.phpnuW+APKZϬ"ZuContracts/ProvidesFlareContext.phpnuW+APKZ =\[uSolutions/ReportSolution.phpnuW+APKZ]]]`uHttp/Response.phpnuW+APKZH˵JduHttp/Client.phpnuW+APKZ_L>|uHttp/Exceptions/BadResponse.phpnuW+APKZ$ͬ8~uHttp/Exceptions/NotFound.phpnuW+APKZ$uHttp/Exceptions/MissingParameter.phpnuW+APKZH#؀uHttp/Exceptions/BadResponseCode.phpnuW+APKZ8r  IuHttp/Exceptions/InvalidData.phpnuW+APKZ?U"uTruncation/TrimStringsStrategy.phpnuW+APKZ0T'uTruncation/TrimContextItemsStrategy.phpnuW+APKZ^E|.##)uTruncation/AbstractTruncationStrategy.phpnuW+APKZ@,!uTruncation/TruncationStrategy.phpnuW+APKZ 6^uTruncation/ReportTrimmer.phpnuW+APKZ[ݺ## uReport.phpnuW+APKy Z YuIlluminate/Testing/TestView.phpnuW+APKy Zcuu,uIlluminate/Testing/ParallelConsoleOutput.phpnuW+APKy ZGG-uIlluminate/Testing/Concerns/TestDatabases.phpnuW+APKy ZfY;[ [ 2iuIlluminate/Testing/Concerns/AssertsStatusCodes.phpnuW+APKy Zα33&uIlluminate/Testing/LICENSE.mdnuW+APKy ZO <$uIlluminate/Testing/TestComponent.phpnuW+APKy Zy833%vIlluminate/Testing/PendingCommand.phpnuW+APKy ZD0hBvIlluminate/Testing/LoggedExceptionCollection.phpnuW+APKy Zl|LQQ5PCvIlluminate/Testing/ParallelTestingServiceProvider.phpnuW+APKy Z|-GvIlluminate/Testing/Constraints/SeeInOrder.phpnuW+APKy Z q q 0dNvIlluminate/Testing/Constraints/HasInDatabase.phpnuW+APKy Z\̱ ;5[vIlluminate/Testing/Constraints/NotSoftDeletedInDatabase.phpnuW+APKy Z,;!;!.QfvIlluminate/Testing/Constraints/ArraySubset.phpnuW+APKy Z6"#qq2vIlluminate/Testing/Constraints/CountInDatabase.phpnuW+APKy Z? 8vIlluminate/Testing/Constraints/SoftDeletedInDatabase.phpnuW+APKy Z;k ܚvIlluminate/Testing/Assert.phpnuW+APKy ZjE))+ʤvIlluminate/Testing/AssertableJsonString.phpnuW+APKy ZSÿ%vIlluminate/Testing/ParallelRunner.phpnuW+APKy Zʶll vIlluminate/Testing/composer.jsonnuW+APKy ZUU/vIlluminate/Testing/Fluent/Concerns/Matching.phpnuW+APKy Zj2YvIlluminate/Testing/Fluent/Concerns/Interaction.phpnuW+APKy Z-*|wIlluminate/Testing/Fluent/Concerns/Has.phpnuW+APKy Z,0wIlluminate/Testing/Fluent/Concerns/Debugging.phpnuW+APKy Z0kk,wIlluminate/Testing/Fluent/AssertableJson.phpnuW+APKy ZX&,wIlluminate/Testing/ParallelTesting.phpnuW+APKy ZOu#,HwIlluminate/Testing/TestResponse.phpnuW+APKy Z(,(,+-xIlluminate/Filesystem/FilesystemManager.phpnuW+APKy Zα33 -xIlluminate/Filesystem/LICENSE.mdnuW+APKy Z20*(32xIlluminate/Filesystem/AwsS3V3Adapter.phpnuW+APKy Z{aKK$)CxIlluminate/Filesystem/Filesystem.phpnuW+APKy ZŮ8bb+exIlluminate/Filesystem/FilesystemAdapter.phpnuW+APKy Z3xIlluminate/Filesystem/FilesystemServiceProvider.phpnuW+APKy ZRs&xIlluminate/Filesystem/LockableFile.phpnuW+APKy Z륄fDD#! yIlluminate/Filesystem/composer.jsonnuW+APKy Zα33!yIlluminate/Translation/LICENSE.mdnuW+APKy Z8vOO&<yIlluminate/Translation/ArrayLoader.phpnuW+APKy Z6yIlluminate/Translation/PotentiallyTranslatedString.phpnuW+APKy Z6aoo%X$yIlluminate/Translation/FileLoader.phpnuW+APKy ZTN2N2%7yIlluminate/Translation/Translator.phpnuW+APKy Z5iyIlluminate/Translation/TranslationServiceProvider.phpnuW+APKy Zė--*oyIlluminate/Translation/MessageSelector.phpnuW+APKy Z珡$yIlluminate/Translation/composer.jsonnuW+APKy ZIs s yIlluminate/Auth/TokenGuard.phpnuW+APKy ZJJJ+yIlluminate/Auth/AuthenticationException.phpnuW+APKy Zα33%yIlluminate/Auth/LICENSE.mdnuW+APKy Zs6ii yIlluminate/Auth/SessionGuard.phpnuW+APKy ZyU) ) "zIlluminate/Auth/GuardHelpers.phpnuW+APKy Za@ee(H-zIlluminate/Auth/DatabaseUserProvider.phpnuW+APKy Zrl7#@zIlluminate/Auth/MustVerifyEmail.phpnuW+APKy ZXJ:#+DzIlluminate/Auth/Authenticatable.phpnuW+APKy Z 9VVxKzIlluminate/Auth/Recaller.phpnuW+APKy Zc SzIlluminate/Auth/GenericUser.phpnuW+APKy ZlTJJ c]zIlluminate/Auth/RequestGuard.phpnuW+APKy Z,4Z?ezIlluminate/Auth/Listeners/SendEmailVerificationNotification.phpnuW+APKy Z7 .zhzIlluminate/Auth/Middleware/RequirePassword.phpnuW+APKy Z3M3 3 +rzIlluminate/Auth/Middleware/Authenticate.phpnuW+APKy ZQ!F F (|zIlluminate/Auth/Middleware/Authorize.phpnuW+APKy Zlu8zIlluminate/Auth/Middleware/AuthenticateWithBasicAuth.phpnuW+APKy Z$K4zIlluminate/Auth/Middleware/EnsureEmailIsVerified.phpnuW+APKy Zn"BzIlluminate/Auth/Events/Lockout.phpnuW+APKy Z~%@zIlluminate/Auth/Events/Registered.phpnuW+APKy Z^X#wzIlluminate/Auth/Events/Verified.phpnuW+APKy Z"(.zIlluminate/Auth/Events/CurrentDeviceLogout.phpnuW+APKy Zw:%zIlluminate/Auth/Events/Attempting.phpnuW+APKy ZL@(֚zIlluminate/Auth/Events/PasswordReset.phpnuW+APKy ZVd$zIlluminate/Auth/Events/Validated.phpnuW+APKy Zӻ0̎(zIlluminate/Auth/Events/Authenticated.phpnuW+APKy Zy!zIlluminate/Auth/Events/Logout.phpnuW+APKy Zri==!¥zIlluminate/Auth/Events/Failed.phpnuW+APKy Z+II PzIlluminate/Auth/Events/Login.phpnuW+APKy Z=,zIlluminate/Auth/Events/OtherDeviceLogout.phpnuW+APKy Z*Do& & 'ׯzIlluminate/Auth/AuthServiceProvider.phpnuW+APKy ZGe. (TzIlluminate/Auth/CreatesUserProviders.phpnuW+APKy Z123 3 -VzIlluminate/Auth/Notifications/VerifyEmail.phpnuW+APKy Z /zIlluminate/Auth/Notifications/ResetPassword.phpnuW+APKy Z1`# # 9zIlluminate/Auth/Console/stubs/make/views/layouts/app.stubnuW+APKy Zv RR.yzIlluminate/Auth/Console/ClearResetsCommand.phpnuW+APKy ZHO:)zIlluminate/Auth/Passwords/PasswordResetServiceProvider.phpnuW+APKy ZO\ZZ.zIlluminate/Auth/Passwords/CanResetPassword.phpnuW+APKy ZSEZZ3=zIlluminate/Auth/Passwords/PasswordBrokerManager.phpnuW+APKy ZUx26{Illuminate/Auth/Passwords/TokenRepositoryInterface.phpnuW+APKy Z$, {Illuminate/Auth/Passwords/PasswordBroker.phpnuW+APKy Z.==5<${Illuminate/Auth/Passwords/DatabaseTokenRepository.phpnuW+APKy Zӑ= #<{Illuminate/Auth/Access/Response.phpnuW+APKy Z6Q 10N{Illuminate/Auth/Access/AuthorizationException.phpnuW+APKy ZYZ3FF/KW{Illuminate/Auth/Access/HandlesAuthorization.phpnuW+APKy Z/\{Illuminate/Auth/Access/Events/GateEvaluated.phpnuW+APKy ZCbCb,a{Illuminate/Auth/Access/Gate.phpnuW+APKy Z !!{Illuminate/Auth/AuthManager.phpnuW+APKy Z6{Illuminate/Auth/composer.jsonnuW+APKy ZNO(H{Illuminate/Auth/EloquentUserProvider.phpnuW+APKy Z-W&W&!Z|Illuminate/Support/MessageBag.phpnuW+APKy Zd Z Z,*|Illuminate/Support/Testing/Fakes/BusFake.phpnuW+APKy ZN.k|Illuminate/Support/Testing/Fakes/BatchFake.phpnuW+APKy Z i4|Illuminate/Support/Testing/Fakes/PendingMailFake.phpnuW+APKy Z 35Ɨ|Illuminate/Support/Testing/Fakes/PendingChainFake.phpnuW+APKy ZmΚ^ ' '.ŝ|Illuminate/Support/Testing/Fakes/EventFake.phpnuW+APKy Z˵ **5,|Illuminate/Support/Testing/Fakes/NotificationFake.phpnuW+APKy Z|g 8w|Illuminate/Support/Testing/Fakes/BatchRepositoryFake.phpnuW+APKy Z7373.q|Illuminate/Support/Testing/Fakes/QueueFake.phpnuW+APKy Z!!52}Illuminate/Support/Testing/Fakes/PendingBatchFake.phpnuW+APKy Z/?%-%--6}Illuminate/Support/Testing/Fakes/MailFake.phpnuW+APKy Zeo0d d -d}Illuminate/Support/NamespacedItemResolver.phpnuW+APKy Z><ԥq}Illuminate/Support/Timebox.phpnuW+APKy Z\|C C w}Illuminate/Support/Composer.phpnuW+APKy Zα33T}Illuminate/Support/LICENSE.mdnuW+APKy Z>%C C #ԇ}Illuminate/Support/ViewErrorBag.phpnuW+APKy Z;+!!!j}Illuminate/Support/HtmlString.phpnuW+APKy Z۳att%ܖ}Illuminate/Support/ValidatedInput.phpnuW+APKy Zg{}Illuminate/Support/Carbon.phpnuW+APKy Zcv/}Illuminate/Support/AggregateServiceProvider.phpnuW+APKy Z\ L ݯ}Illuminate/Support/Optional.phpnuW+APKy Zi3 + +&}Illuminate/Support/ServiceProvider.phpnuW+APKy ZPqq!}Illuminate/Support/Stringable.phpnuW+APKy Z Ȱu u W~Illuminate/Support/Env.phpnuW+APKy Z\K/a~Illuminate/Support/Exceptions/MathException.phpnuW+APKy Z{ b~Illuminate/Support/Benchmark.phpnuW+APKy Z,mm!h~Illuminate/Support/Facades/DB.phpnuW+APKy Zv $~Illuminate/Support/Facades/Cache.phpnuW+APKy Z4~~$’~Illuminate/Support/Facades/Route.phpnuW+APKy ZW #~Illuminate/Support/Facades/View.phpnuW+APKy ZvԼ$~Illuminate/Support/Facades/Event.phpnuW+APKy Z~\\#~Illuminate/Support/Facades/Date.phpnuW+APKy ZDZ44(A~Illuminate/Support/Facades/Validator.phpnuW+APKy Zӝ %~Illuminate/Support/Facades/Schema.phpnuW+APKy Z``#Illuminate/Support/Facades/Auth.phpnuW+APKy ZYm %NIlluminate/Support/Facades/Cookie.phpnuW+APKy Zh#4Illuminate/Support/Facades/Mail.phpnuW+APKy Z =yy%a1Illuminate/Support/Facades/Config.phpnuW+APKy Z$/5Illuminate/Support/Facades/Redis.phpnuW+APKy ZL!!%y=Illuminate/Support/Facades/Facade.phpnuW+APKy Z>*&^Illuminate/Support/Facades/Artisan.phpnuW+APKy ZH H ';eIlluminate/Support/Facades/Response.phpnuW+APKy ZT|,*(oIlluminate/Support/Facades/Broadcast.phpnuW+APKy ZBQQ$yIlluminate/Support/Facades/Queue.phpnuW+APKy Z"Illuminate/Support/Facades/URL.phpnuW+APKy ZDȵ% % +Illuminate/Support/Facades/Notification.phpnuW+APKy ZnI"Illuminate/Support/Facades/App.phpnuW+APKy Zm2 2 'Illuminate/Support/Facades/Redirect.phpnuW+APKy Zm7?'Illuminate/Support/Facades/Password.phpnuW+APKy Z  $TIlluminate/Support/Facades/Blade.phpnuW+APKy Zp_Illuminate/Routing/Console/stubs/controller.singleton.api.stubnuW+APKz ZA9 7Illuminate/Routing/Console/stubs/controller.nested.stubnuW+APKz ZPP6Illuminate/Routing/Console/stubs/controller.model.stubnuW+APKz Z9zz:qIlluminate/Routing/Console/stubs/controller.invokable.stubnuW+APKz Zo;UIlluminate/Routing/Console/stubs/controller.nested.api.stubnuW+APKz ZXn:Illuminate/Routing/Console/stubs/controller.singleton.stubnuW+APKz Z8.0 Illuminate/Routing/Console/stubs/controller.stubnuW+APKz ZapY4{Illuminate/Routing/Console/stubs/controller.api.stubnuW+APKz Zn':Illuminate/Routing/Console/stubs/controller.model.api.stubnuW+APKz Z22-Illuminate/Routing/Controllers/Middleware.phpnuW+APKz Z']0$Illuminate/Routing/Controllers/HasMiddleware.phpnuW+APKz Zb!%Illuminate/Routing/Redirector.phpnuW+APKz ZSCC3CIlluminate/Routing/RouteDependencyResolverTrait.phpnuW+APKz Z\  2RIlluminate/Routing/PendingResourceRegistration.phpnuW+APKz Z|)5 #kIlluminate/Routing/RouteBinding.phpnuW+APKz ZO/=vIlluminate/Routing/Matching/MethodValidator.phpnuW+APKz Z32xIlluminate/Routing/Matching/ValidatorInterface.phpnuW+APKz Z'f'@@,zIlluminate/Routing/Matching/UriValidator.phpnuW+APKz ZJPqq-!}Illuminate/Routing/Matching/HostValidator.phpnuW+APKz Z()kk/Illuminate/Routing/Matching/SchemeValidator.phpnuW+APKz Zܟf Illuminate/Routing/composer.jsonnuW+APKz Z>@rUrU#ڈIlluminate/Routing/UrlGenerator.phpnuW+APKz Z|lYff/ޅIlluminate/Routing/RouteSignatureParameters.phpnuW+APKz ZZ VV3dIlluminate/Routing/Contracts/CallableDispatcher.phpnuW+APKz Z^D5Illuminate/Routing/Contracts/ControllerDispatcher.phpnuW+APKz Z/X%Illuminate/Routing/ViewController.phpnuW+APKz Z+$Illuminate/Routing/Router.phpnuW+APKz Z> =,!,!% Illuminate/Routing/RouteRegistrar.phpnuW+APKz Z s s +Illuminate/Routing/ControllerDispatcher.phpnuW+APKz Zv&XIlluminate/Routing/RouteCollection.phpnuW+APKz Z; =9ԆIlluminate/View/Compilers/Concerns/CompilesAuthorizations.phpnuW+APKz ZTa>>6lކIlluminate/View/Compilers/Concerns/CompilesHelpers.phpnuW+APKz Z!8Illuminate/View/Compilers/Concerns/CompilesFragments.phpnuW+APKz Zң7QIlluminate/View/Compilers/Concerns/CompilesComments.phpnuW+APKz Z2&9UIlluminate/View/Compilers/Concerns/CompilesInjections.phpnuW+APKz Zf+ ?!?!;Illuminate/View/Compilers/Concerns/CompilesConditionals.phpnuW+APKz Z@F9aIlluminate/View/Compilers/Concerns/CompilesComponents.phpnuW+APKz Z9:;%Illuminate/View/Compilers/Concerns/CompilesTranslations.phpnuW+APKz Z~r 6f*Illuminate/View/Compilers/Concerns/CompilesLayouts.phpnuW+APKz Z̀16Illuminate/View/Compilers/Concerns/CompilesJs.phpnuW+APKz Z$B58Illuminate/View/Compilers/Concerns/CompilesStyles.phpnuW+APKz ZIlluminate/Foundation/Providers/FormRequestServiceProvider.phpnuW+APKz Z2k77=Illuminate/Foundation/Providers/FoundationServiceProvider.phpnuW+APKz Z}%~__:s!Illuminate/Foundation/Providers/ArtisanServiceProvider.phpnuW+APKz Z[8q;ցIlluminate/Foundation/Providers/ComposerServiceProvider.phpnuW+APKz Z'XX7Illuminate/Foundation/Events/MaintenanceModeEnabled.phpnuW+APKz ZV /Illuminate/Foundation/Events/DiscoverEvents.phpnuW+APKz Z b- Illuminate/Foundation/Events/Dispatchable.phpnuW+APKz Z W@YY89Illuminate/Foundation/Events/MaintenanceModeDisabled.phpnuW+APKz Z(  3Illuminate/Foundation/Events/VendorTagPublished.phpnuW+APKz Zuwmbb.}Illuminate/Foundation/Events/LocaleUpdated.phpnuW+APKz Z0=Illuminate/Foundation/Events/PublishingStubs.phpnuW+APKz Z{Ktt41Illuminate/Foundation/Bus/PendingClosureDispatch.phpnuW+APKz Zu4- Illuminate/Foundation/Bus/PendingDispatch.phpnuW+APKz ZT;|U U *Illuminate/Foundation/Bus/Dispatchable.phpnuW+APKz Zh/,ƼIlluminate/Foundation/Bus/DispatchesJobs.phpnuW+APKz Z''*Illuminate/Foundation/Bus/PendingChain.phpnuW+APKz Z:O mm)}ώIlluminate/Foundation/ComposerScripts.phpnuW+APKz ZZ::C֎Illuminate/Foundation/Mix.phpnuW+APKz ZzEE'ގIlluminate/Foundation/stubs/facade.stubnuW+APKz Z۬;xee!fIlluminate/Foundation/helpers.phpnuW+APKz Z&&%~FIlluminate/Foundation/AliasLoader.phpnuW+APKz ZNGe!3ZIlluminate/Foundation/Console/EventClearCommand.phpnuW+APKz Z3PP/aIlluminate/Foundation/Console/QueuedCommand.phpnuW+APKz ZQ;5dIlluminate/Foundation/Console/ObserverMakeCommand.phpnuW+APKz Z8wIlluminate/Foundation/Console/PackageDiscoverCommand.phpnuW+APKz Z@2?}Illuminate/Foundation/Console/ViewClearCommand.phpnuW+APKz Z@55-Illuminate/Foundation/Console/DocsCommand.phpnuW+APKz Z{տ2ֺIlluminate/Foundation/Console/ScopeMakeCommand.phpnuW+APKz ZAɝ4Illuminate/Foundation/Console/ChannelMakeCommand.phpnuW+APKz ZϤ.GG-ʏIlluminate/Foundation/Console/DownCommand.phpnuW+APKz Ze~iuu1܏Illuminate/Foundation/Console/TestMakeCommand.phpnuW+APKz ZWv 4rIlluminate/Foundation/Console/KeyGenerateCommand.phpnuW+APKz Z\ju4lIlluminate/Foundation/Console/RequestMakeCommand.phpnuW+APKz Z 3Illuminate/Foundation/Console/RouteCacheCommand.phpnuW+APKz Zw6Illuminate/Foundation/Console/OptimizeClearCommand.phpnuW+APKz Z{1Illuminate/Foundation/Console/MailMakeCommand.phpnuW+APKz Z*s4 4 2$%Illuminate/Foundation/Console/ViewCacheCommand.phpnuW+APKz Z360Illuminate/Foundation/Console/ComponentMakeCommand.phpnuW+APKz Zak//(.CIlluminate/Foundation/Console/Kernel.phpnuW+APKz ZD9WW1;sIlluminate/Foundation/Console/CastMakeCommand.phpnuW+APKz Z[~*  3{Illuminate/Foundation/Console/PolicyMakeCommand.phpnuW+APKz Z [ [ 6aIlluminate/Foundation/Console/ExceptionMakeCommand.phpnuW+APKz ZZ?- - 4"Illuminate/Foundation/Console/StorageLinkCommand.phpnuW+APKz Z1qR3Illuminate/Foundation/Console/RouteClearCommand.phpnuW+APKz ZE5Illuminate/Foundation/Console/ProviderMakeCommand.phpnuW+APKz ZW|Ұff2Illuminate/Foundation/Console/EventListCommand.phpnuW+APKz ZZWO O 4dΐIlluminate/Foundation/Console/ConsoleMakeCommand.phpnuW+APKz Zb0"DD2ِIlluminate/Foundation/Console/ShowModelCommand.phpnuW+APKz ZWT 4Illuminate/Foundation/Console/EnvironmentCommand.phpnuW+APKz Z=28"Illuminate/Foundation/Console/ModelMakeCommand.phpnuW+APKz ZjV.3MBIlluminate/Foundation/Console/EventCacheCommand.phpnuW+APKz ZGV6}IIlluminate/Foundation/Console/EventGenerateCommand.phpnuW+APKz Z6pұ0RIlluminate/Foundation/Console/JobMakeCommand.phpnuW+APKz Z44[Illuminate/Foundation/Console/StubPublishCommand.phpnuW+APKz Z-00qIlluminate/Foundation/Console/ClosureCommand.phpnuW+APKz Z<5yIlluminate/Foundation/Console/ListenerMakeCommand.phpnuW+APKz Zg} ;Illuminate/Foundation/Console/EnvironmentEncryptCommand.phpnuW+APKz ZB0ة6!Illuminate/Foundation/Console/ClearCompiledCommand.phpnuW+APKz Z1} 10Illuminate/Foundation/Console/RuleMakeCommand.phpnuW+APKz Zn;;2Illuminate/Foundation/Console/RouteListCommand.phpnuW+APKz ZV##6Illuminate/Foundation/Console/VendorPublishCommand.phpnuW+APKz Z]];Illuminate/Foundation/Console/EnvironmentDecryptCommand.phpnuW+APKz ZȽI6Illuminate/Foundation/Console/stubs/listener-duck.stubnuW+APKz ZD<Illuminate/Foundation/Console/stubs/resource-collection.stubnuW+APKz ZrUeBB6Illuminate/Foundation/Console/stubs/markdown-mail.stubnuW+APKz Zm׼@!Illuminate/Foundation/Console/stubs/exception-render-report.stubnuW+APKz ZE-#Illuminate/Foundation/Console/stubs/test.stubnuW+APKz Zuk5%Illuminate/Foundation/Console/stubs/notification.stubnuW+APKz Z.qjj>L+Illuminate/Foundation/Console/stubs/markdown-notification.stubnuW+APKz Zt>ȍ1$0Illuminate/Foundation/Console/stubs/markdown.stubnuW+APKz Z҉Unn141Illuminate/Foundation/Console/stubs/provider.stubnuW+APKz Z䁳@=3Illuminate/Foundation/Console/stubs/listener-queued-duck.stubnuW+APKz Z2-V5Illuminate/Foundation/Console/stubs/rule.stubnuW+APKz Z!55-T8Illuminate/Foundation/Console/stubs/cast.stubnuW+APKz Zn8;Illuminate/Foundation/Console/stubs/listener-queued.stubnuW+APKz Z1Yi$$.h>Illuminate/Foundation/Console/stubs/event.stubnuW+APKz ZP3AIlluminate/Foundation/Console/stubs/job.queued.stubnuW+APKz ZmF9DIlluminate/Foundation/Console/stubs/exception-report.stubnuW+APKz ZoZ1FIlluminate/Foundation/Console/stubs/resource.stubnuW+APKz Zr'~bb2 HIlluminate/Foundation/Console/stubs/exception.stubnuW+APKz ZY77@HIlluminate/Foundation/Console/stubs/rule.invokable.implicit.stubnuW+APKz Z!4KIlluminate/Foundation/Console/stubs/model.pivot.stubnuW+APKz Zj!!9pLIlluminate/Foundation/Console/stubs/maintenance-mode.stubnuW+APKz Z.2TIlluminate/Foundation/Console/stubs/test.unit.stubnuW+APKz ZzGG2dVIlluminate/Foundation/Console/stubs/pest.unit.stubnuW+APKz Zg36/ WIlluminate/Foundation/Console/stubs/routes.stubnuW+APKz ZFxآ::93YIlluminate/Foundation/Console/stubs/exception-render.stubnuW+APKz Zl7ZIlluminate/Foundation/Console/stubs/rule.invokable.stubnuW+APKz Z`$Q{ { /\Illuminate/Foundation/Console/stubs/policy.stubnuW+APKz ZKr0fIlluminate/Foundation/Console/stubs/channel.stubnuW+APKz Z#W225hIlluminate/Foundation/Console/stubs/policy.plain.stubnuW+APKz Z M{{,jIlluminate/Foundation/Console/stubs/job.stubnuW+APKz Z퓐mm-clIlluminate/Foundation/Console/stubs/pest.stubnuW+APKz ZYo-r:-mIlluminate/Foundation/Console/stubs/model.morph-pivot.stubnuW+APKz ZR1"nIlluminate/Foundation/Console/stubs/observer.stubnuW+APKz Z@@7sIlluminate/Foundation/Console/stubs/observer.plain.stubnuW+APKz Zw5'tIlluminate/Foundation/Console/stubs/cast.inbound.stubnuW+APKz Z|mB0vIlluminate/Foundation/Console/stubs/request.stubnuW+APKz Zzs7xIlluminate/Foundation/Console/stubs/view-component.stubnuW+APKz Zs|cc. {Illuminate/Foundation/Console/stubs/model.stubnuW+APKz ZVޢ0%|Illuminate/Foundation/Console/stubs/console.stubnuW+APKz Z===-~Illuminate/Foundation/Console/stubs/mail.stubnuW+APKz Z:15Illuminate/Foundation/Console/stubs/listener.stubnuW+APKz Z.}Illuminate/Foundation/Console/stubs/scope.stubnuW+APKz Z6+ЇIlluminate/Foundation/Console/UpCommand.phpnuW+APKz Z萸 +Illuminate/Foundation/Console/CliDumper.phpnuW+APKz Z0"_ 9雒Illuminate/Foundation/Console/NotificationMakeCommand.phpnuW+APKz Z01Illuminate/Foundation/Console/OptimizeCommand.phpnuW+APKz ZW4Illuminate/Foundation/Console/ConfigClearCommand.phpnuW+APKz ZO}l l 4Illuminate/Foundation/Console/ConfigCacheCommand.phpnuW+APKz ZTBJ2ľIlluminate/Foundation/Console/EventMakeCommand.phpnuW+APKz Z~G G .ǒIlluminate/Foundation/Console/AboutCommand.phpnuW+APKz Zs 5Illuminate/Foundation/Console/ResourceMakeCommand.phpnuW+APKz Zxv%v%.~Illuminate/Foundation/Console/ServeCommand.phpnuW+APKz Z皚TT)RIlluminate/Foundation/PackageManifest.phpnuW+APKz ZdAA3*Illuminate/Foundation/CacheBasedMaintenanceMode.phpnuW+APKz Zdx77%3Illuminate/Foundation/Http/Kernel.phpnuW+APKz Z',,*kIlluminate/Foundation/Http/FormRequest.phpnuW+APKz Z9BBIlluminate/Foundation/Http/Exceptions/MaintenanceModeException.phpnuW+APKz Z(HA\Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.phpnuW+APKz ZNy5XIlluminate/Foundation/Http/Middleware/TrimStrings.phpnuW+APKz Z#~~9Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.phpnuW+APKz Z}ggJIlluminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.phpnuW+APKz Z*t DjIlluminate/Foundation/Http/Middleware/HandlePrecognitiveRequests.phpnuW+APKz ZPpCȓIlluminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.phpnuW+APKz Zx00;͓Illuminate/Foundation/Http/Middleware/TransformsRequest.phpnuW+APKz ZMvJ:T֓Illuminate/Foundation/Http/Middleware/ValidatePostSize.phpnuW+APKz ZUAmm4ۓIlluminate/Foundation/Http/Events/RequestHandled.phpnuW+APKz ZՇ33:UޓIlluminate/Foundation/Http/MaintenanceModeBypassCookie.phpnuW+APKz ZF)OO)Illuminate/Foundation/Http/HtmlDumper.phpnuW+APKz Z͕'%,Illuminate/Foundation/ProviderRepository.phpnuW+APKz Z;- Illuminate/Foundation/EnvironmentDetector.phpnuW+APKz Z*Illuminate/Foundation/resources/server.phpnuW+APKz Z=$$.Illuminate/Validation/ValidationRuleParser.phpnuW+APKz Zqq1=;Illuminate/Validation/InvokableValidationRule.phpnuW+APKz Z l l (OIlluminate/Validation/ValidationData.phpnuW+APKz ZWbלל#ZIlluminate/Validation/Validator.phpnuW+APKz ZP^^5Illuminate/Validation/Concerns/ReplacesAttributes.phpnuW+APKz Zr8gVIlluminate/Validation/Concerns/FilterEmailValidation.phpnuW+APKz Z[**6U]Illuminate/Validation/Concerns/ValidatesAttributes.phpnuW+APKz Z<됳AA2Illuminate/Validation/Concerns/FormatsMessages.phpnuW+APKz Z;_NN3ʖIlluminate/Validation/PresenceVerifierInterface.phpnuW+APKz Z#DS/MΖIlluminate/Validation/UnauthorizedException.phpnuW+APKz Z_Q  *,ϖIlluminate/Validation/NotPwnedVerifier.phpnuW+APKz Zα33 ٖIlluminate/Validation/LICENSE.mdnuW+APKz Zy)xdd2!ޖIlluminate/Validation/DatabasePresenceVerifier.phpnuW+APKz ZD*Illuminate/Validation/ConditionalRules.phpnuW+APKz Zo0vv4Illuminate/Validation/ValidatesWhenResolvedTrait.phpnuW+APKz Z^_##!Illuminate/Validation/Factory.phpnuW+APKz Zqƻ[-!Illuminate/Validation/ValidationException.phpnuW+APKz ZC~-<;0Illuminate/Validation/DatabasePresenceVerifierInterface.phpnuW+APKz Z@X-%o2Illuminate/Validation/NestedRules.phpnuW+APKz Z#Ȇ3V7Illuminate/Validation/ValidationServiceProvider.phpnuW+APKz Zl)?@Illuminate/Validation/Rules/ImageFile.phpnuW+APKz Z`%*BIlluminate/Validation/Rules/RequiredIf.phpnuW+APKz Z"11$FIlluminate/Validation/Rules/Enum.phpnuW+APKz Zpߚ| | *4LIlluminate/Validation/Rules/Dimensions.phpnuW+APKz Zv3&3&( VIlluminate/Validation/Rules/Password.phpnuW+APKz Z%|Illuminate/Validation/Rules/NotIn.phpnuW+APKz Zz'^##,Illuminate/Validation/Rules/ProhibitedIf.phpnuW+APKz Zb\#UU&Illuminate/Validation/Rules/Unique.phpnuW+APKz ZI``"1Illuminate/Validation/Rules/In.phpnuW+APKz ZkE$㎗Illuminate/Validation/Rules/File.phpnuW+APKz Zeh,ˮIlluminate/Validation/Rules/DatabaseRule.phpnuW+APKz ZK)×Illuminate/Validation/Rules/ExcludeIf.phpnuW+APKz ZOn ڶ&+ȗIlluminate/Validation/Rules/Exists.phpnuW+APKz ZG/44#7ʗIlluminate/Validation/composer.jsonnuW+APKz Zk%5uuϗIlluminate/Validation/Rule.phpnuW+APKz Z3 O**/Illuminate/Validation/ClosureValidationRule.phpnuW+APKz Z@0 Illuminate/Broadcasting/InteractsWithSockets.phpnuW+APKz Z&u(TT5Illuminate/Broadcasting/InteractsWithBroadcasting.phpnuW+APKz Zα33"Illuminate/Broadcasting/LICENSE.mdnuW+APKz ZG773EIlluminate/Broadcasting/EncryptedPrivateChannel.phpnuW+APKz Z DՓ4Illuminate/Broadcasting/BroadcastServiceProvider.phpnuW+APKz Z~z,Illuminate/Broadcasting/PendingBroadcast.phpnuW+APKz ZTij*Illuminate/Broadcasting/PrivateChannel.phpnuW+APKz Z]#\Illuminate/Broadcasting/Channel.phpnuW+APKz Zh8.`Illuminate/Broadcasting/BroadcastException.phpnuW+APKz Z$&i55*=Illuminate/Broadcasting/BroadcastEvent.phpnuW+APKz Z'QQ8Illuminate/Broadcasting/Broadcasters/AblyBroadcaster.phpnuW+APKz Zɵ3p*p*4-Illuminate/Broadcasting/Broadcasters/Broadcaster.phpnuW+APKz Z,N 55DYXIlluminate/Broadcasting/Broadcasters/UsePusherChannelConventions.phpnuW+APKz Z5ՅGG9\Illuminate/Broadcasting/Broadcasters/RedisBroadcaster.phpnuW+APKz Z8mIlluminate/Broadcasting/Broadcasters/NullBroadcaster.phpnuW+APKz Z<<7oIlluminate/Broadcasting/Broadcasters/LogBroadcaster.phpnuW+APKz Z՚$$:tIlluminate/Broadcasting/Broadcasters/PusherBroadcaster.phpnuW+APKz Z%k&&+Illuminate/Broadcasting/PresenceChannel.phpnuW+APKz Z˶;y0y0,Illuminate/Broadcasting/BroadcastManager.phpnuW+APKz Z KD%oIlluminate/Broadcasting/composer.jsonnuW+APKz Z٘0˜Illuminate/Broadcasting/UniqueBroadcastEvent.phpnuW+APKz Z>r(/5ɘIlluminate/Broadcasting/BroadcastController.phpnuW+APKz Zα33)ΘIlluminate/Cookie/LICENSE.mdnuW+APKz Z]55+ҘIlluminate/Cookie/CookieServiceProvider.phpnuW+APKz Zpdd'8՘Illuminate/Cookie/CookieValuePrefix.phpnuW+APKz ZnЄ/٘Illuminate/Cookie/Middleware/EncryptCookies.phpnuW+APKz Z ;Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.phpnuW+APKz Z/:k Illuminate/Cookie/CookieJar.phpnuW+APKz ZTjFIlluminate/Cookie/composer.jsonnuW+APKz Zα33Illuminate/Macroable/LICENSE.mdnuW+APKz ZȜ# # )Illuminate/Macroable/Traits/Macroable.phpnuW+APKz Z4ky"#Illuminate/Macroable/composer.jsonnuW+APKz Zn??)&Illuminate/Events/InvokeQueuedClosure.phpnuW+APKz ZBn #U*Illuminate/Events/QueuedClosure.phpnuW+APKz Zα3385Illuminate/Events/LICENSE.mdnuW+APKz ZWǚ(9Illuminate/Events/CallQueuedListener.phpnuW+APKz Z8O4jjHIlluminate/Events/functions.phpnuW+APKz ZsbJIlluminate/Events/composer.jsonnuW+APKz Z;MM NIlluminate/Events/Dispatcher.phpnuW+APKz Znj2 2 $蜙Illuminate/Events/NullDispatcher.phpnuW+APKz ZV&,,*nIlluminate/Events/EventServiceProvider.phpnuW+APKz Zα33Illuminate/Container/LICENSE.mdnuW+APKz Zt "vIlluminate/Container/Container.phpnuW+APKz Zt${OIlluminate/Container/BoundMethod.phpnuW+APKz Z( ( 1kIlluminate/Container/ContextualBindingBuilder.phpnuW+APKz Z1/uIlluminate/Container/EntryNotFoundException.phpnuW+APKz Zii,DvIlluminate/Container/RewindableGenerator.phpnuW+APKz Z&Z," {Illuminate/Container/composer.jsonnuW+APKz Z`~Illuminate/Container/Util.phpnuW+APKz Z:%ŅIlluminate/Bus/BusServiceProvider.phpnuW+APKz Zα33Illuminate/Bus/LICENSE.mdnuW+APKz Z(Çv  qIlluminate/Bus/Batchable.phpnuW+APKz ZQ׻ŝIlluminate/Bus/UniqueLock.phpnuW+APKz Z+("ͤIlluminate/Bus/BatchRepository.phpnuW+APKz Z =fIlluminate/Bus/BatchFactory.phpnuW+APKz Z(*ôIlluminate/Bus/PendingBatch.phpnuW+APKz ZuD)КIlluminate/Bus/Events/BatchDispatched.phpnuW+APKz ZԨR*R**ҚIlluminate/Bus/DatabaseBatchRepository.phpnuW+APKz ZO>>*@Illuminate/Bus/PrunableBatchRepository.phpnuW+APKz Z-XX(Illuminate/Bus/UpdatedBatchJobCounts.phpnuW+APKz ZDA//Illuminate/Bus/Batch.phpnuW+APKz Z"P2Illuminate/Bus/composer.jsonnuW+APKz ZaŎ6Illuminate/Bus/Dispatcher.phpnuW+APKz Z0(ˣZUIlluminate/Bus/Queueable.phpnuW+APKz ZHOf#f#&ImIlluminate/Mail/Mailables/Envelope.phpnuW+APKz Z B3%Illuminate/Mail/Mailables/Headers.phpnuW+APKz Z竎  %GIlluminate/Mail/Mailables/Content.phpnuW+APKz Z(Illuminate/Mail/Mailables/Attachment.phpnuW+APKz ZG_))%ǦIlluminate/Mail/Mailables/Address.phpnuW+APKz Z͹AAEIlluminate/Mail/Mailer.phpnuW+APKz Zα33?Illuminate/Mail/LICENSE.mdnuW+APKz Zo Illuminate/Mail/PendingMail.phpnuW+APKz Z??Illuminate/Mail/MailManager.phpnuW+APKz Z&#'G=Illuminate/Mail/MailServiceProvider.phpnuW+APKz Z-jװװDIlluminate/Mail/Mailable.phpnuW+APKz Z>ee)Illuminate/Mail/Events/MessageSending.phpnuW+APKz ZN]]&dIlluminate/Mail/Events/MessageSent.phpnuW+APKz Zo &Illuminate/Mail/SendQueuedMailable.phpnuW+APKz Z:j&&[Illuminate/Mail/Message.phpnuW+APKz Z;J4Illuminate/Mail/composer.jsonnuW+APKz Zz_:Illuminate/Mail/Attachment.phpnuW+APKz Z|3LIlluminate/Mail/SentMessage.phpnuW+APKz Z|99-QIlluminate/Mail/Markdown.phpnuW+APKz ZP_,cIlluminate/Mail/Transport/SesV2Transport.phpnuW+APKz ZF.,*rIlluminate/Mail/Transport/ArrayTransport.phpnuW+APKz Z'(*3xIlluminate/Mail/Transport/LogTransport.phpnuW+APKz Z2N N *}Illuminate/Mail/Transport/SesTransport.phpnuW+APKz Z xUU5CIlluminate/Mail/resources/views/html/layout.blade.phpnuW+APKz Z;J!@@5Illuminate/Mail/resources/views/html/button.blade.phpnuW+APKz Z'6Illuminate/Mail/resources/views/html/subcopy.blade.phpnuW+APKz Z(HH4Illuminate/Mail/resources/views/html/table.blade.phpnuW+APKz ZaNP6YIlluminate/Mail/resources/views/html/message.blade.phpnuW+APKz Z5ZV554Illuminate/Mail/resources/views/html/panel.blade.phpnuW+APKz ZX|ι5DIlluminate/Mail/resources/views/html/header.blade.phpnuW+APKz Zd;  7Illuminate/Mail/resources/views/html/themes/default.cssnuW+APKz Z=g5Illuminate/Mail/resources/views/html/footer.blade.phpnuW+APKz Z)=55nIlluminate/Mail/resources/views/text/layout.blade.phpnuW+APKz ZA5`Illuminate/Mail/resources/views/text/button.blade.phpnuW+APKz Z(~ 6ݯIlluminate/Mail/resources/views/text/subcopy.blade.phpnuW+APKz Z(~ 4OIlluminate/Mail/resources/views/text/table.blade.phpnuW+APKz Zyf6Illuminate/Mail/resources/views/text/message.blade.phpnuW+APKz Z(~ 4Illuminate/Mail/resources/views/text/panel.blade.phpnuW+APKz Z/5Illuminate/Mail/resources/views/text/header.blade.phpnuW+APKz Z(~ 5Illuminate/Mail/resources/views/text/footer.blade.phpnuW+APKz ZA1 Illuminate/Conditionable/HigherOrderWhenProxy.phpnuW+APKz Zα33#7Illuminate/Conditionable/LICENSE.mdnuW+APKz Z|=1Illuminate/Conditionable/Traits/Conditionable.phpnuW+APKz ZcR&˝Illuminate/Conditionable/composer.jsonnuW+APKz ZM2ϝIlluminate/Cache/FileLock.phpnuW+APKz Zj7НIlluminate/Cache/LuaScripts.phpnuW+APKz Z]!ҝIlluminate/Cache/DatabaseLock.phpnuW+APKz Zα33Illuminate/Cache/LICENSE.mdnuW+APKz Z֮$$Illuminate/Cache/FileStore.phpnuW+APKz Z*;99" Illuminate/Cache/DynamoDbStore.phpnuW+APKz Z{U}_ _ 5DIlluminate/Cache/NullStore.phpnuW+APKz Zx,  MIlluminate/Cache/TaggedCache.phpnuW+APKz Zȉ3XIlluminate/Cache/NoLock.phpnuW+APKz ZʔeFF)2[Illuminate/Cache/CacheServiceProvider.phpnuW+APKz Zr BB!`Illuminate/Cache/DynamoDbLock.phpnuW+APKz Z?D dgIlluminate/Cache/TagSet.phpnuW+APKz Z]ks((!qIlluminate/Cache/CacheManager.phpnuW+APKz Zn  Illuminate/Cache/ArrayLock.phpnuW+APKz ZOoW*Illuminate/Cache/RetrievesMultipleKeys.phpnuW+APKz Z-v1N N 'اIlluminate/Cache/MemcachedConnector.phpnuW+APKz Z1  }Illuminate/Cache/ApcStore.phpnuW+APKz Zjj仞Illuminate/Cache/ApcWrapper.phpnuW+APKz Z俱AAÞIlluminate/Cache/Repository.phpnuW+APKz Zrk$Illuminate/Cache/Events/CacheHit.phpnuW+APKz Z)@&Illuminate/Cache/Events/CacheEvent.phpnuW+APKz Z6[['" Illuminate/Cache/Events/CacheMissed.phpnuW+APKz Z& Illuminate/Cache/Events/KeyWritten.phpnuW+APKz ZW\\(Illuminate/Cache/Events/KeyForgotten.phpnuW+APKz Zӟ--Illuminate/Cache/CacheLock.phpnuW+APKz Z(&x!Illuminate/Cache/HasCacheLock.phpnuW+APKz ZMQ%Illuminate/Cache/RedisTaggedCache.phpnuW+APKz Z|Mff)8/Illuminate/Cache/Console/ClearCommand.phpnuW+APKz ZEJ3*=Illuminate/Cache/Console/ForgetCommand.phpnuW+APKz ZO{{)`DIlluminate/Cache/Console/stubs/cache.stubnuW+APKz ZW**.4HIlluminate/Cache/Console/CacheTableCommand.phpnuW+APKz ZK2==!PIlluminate/Cache/PhpRedisLock.phpnuW+APKz ZSשep(p("JTIlluminate/Cache/DatabaseStore.phpnuW+APKz Z. ' }Illuminate/Cache/RateLimiting/Limit.phpnuW+APKz Zpzz- Illuminate/Cache/RateLimiting/GlobalLimit.phpnuW+APKz Z}+Illuminate/Cache/RateLimiting/Unlimited.phpnuW+APKz Z(|X, , RIlluminate/Cache/RedisStore.phpnuW+APKz ZMͫIlluminate/Cache/composer.jsonnuW+APKz Z Illuminate/Cache/Lock.phpnuW+APKz Zؐ*Illuminate/Cache/RedisLock.phpnuW+APKz Z#zǟIlluminate/Cache/MemcachedStore.phpnuW+APKz ZNf"Illuminate/Cache/TaggableStore.phpnuW+APKz ZGgg zIlluminate/Cache/RateLimiter.phpnuW+APKz Z=551Illuminate/Cache/ArrayStore.phpnuW+APKz Zc"Illuminate/Cache/MemcachedLock.phpnuW+APKz Z5 5 "Illuminate/Hashing/HashManager.phpnuW+APKz Zα33;Illuminate/Hashing/LICENSE.mdnuW+APKz Zms%ww"Illuminate/Hashing/ArgonHasher.phpnuW+APKz Z.%.Illuminate/Hashing/Argon2IdHasher.phpnuW+APKz Zv`.%2Illuminate/Hashing/AbstractHasher.phpnuW+APKz Z%n n #5Illuminate/Hashing/BcryptHasher.phpnuW+APKz ZC^*@Illuminate/Hashing/HashServiceProvider.phpnuW+APKz Z 44 CIlluminate/Hashing/composer.jsonnuW+APKz Zr 1^GIlluminate/Notifications/DatabaseNotification.phpnuW+APKz ZSn&;RIlluminate/Notifications/DatabaseNotificationCollection.phpnuW+APKz Zjx#+UIlluminate/Notifications/Action.phpnuW+APKz Zα33#]WIlluminate/Notifications/LICENSE.mdnuW+APKz Zs||+[Illuminate/Notifications/ChannelManager.phpnuW+APKz Zy 0kIlluminate/Notifications/RoutesNotifications.phpnuW+APKz Z2CU)*qIlluminate/Notifications/Notification.phpnuW+APKz ZK8tIlluminate/Notifications/NotificationServiceProvider.phpnuW+APKz Z {/vyIlluminate/Notifications/NotificationSender.phpnuW+APKz ZC:Aoo4Illuminate/Notifications/Events/NotificationSent.phpnuW+APKz Z<7tIlluminate/Notifications/Events/NotificationSending.phpnuW+APKz Z-M~Jp p @Illuminate/Notifications/Events/BroadcastNotificationCreated.phpnuW+APKz Z ##BIlluminate/Database/Eloquent/Relations/Concerns/CanBeOneOfMany.phpnuW+APKz ZU PPKAIlluminate/Database/Eloquent/Relations/Concerns/InteractsWithPivotTable.phpnuW+APKz Zv''IIlluminate/Database/Eloquent/Relations/Concerns/ComparesRelatedModels.phpnuW+APKz ZjIOIlluminate/Database/Eloquent/Relations/Concerns/SupportsDefaultModels.phpnuW+APKz ZÀ5Illuminate/Database/Eloquent/Concerns/QueriesRelationships.phpnuW+APKz ZG/=i i 2Illuminate/Database/Eloquent/Concerns/HasUlids.phpnuW+APKz Z>g7 Illuminate/Database/Eloquent/Concerns/HasTimestamps.phpnuW+APKz ZO'``9.!Illuminate/Database/Eloquent/Concerns/HasGlobalScopes.phpnuW+APKz ZBP))3)Illuminate/Database/Eloquent/Concerns/HasEvents.phpnuW+APKz Z{ { 23TIlluminate/Database/Eloquent/Concerns/HasUuids.phpnuW+APKz Z֯Q7^Illuminate/Database/Eloquent/Concerns/HasAttributes.phpnuW+APKz Z7w7w:K]Illuminate/Database/Eloquent/Concerns/HasRelationships.phpnuW+APKz ZMII:ԭIlluminate/Database/Eloquent/Concerns/GuardsAttributes.phpnuW+APKz ZcPi% % 9Illuminate/Database/Eloquent/Concerns/HidesAttributes.phpnuW+APKz ZÆ^^&-Illuminate/Database/Eloquent/Scope.phpnuW+APKz Z1l--8Illuminate/Database/Eloquent/HigherOrderBuilderProxy.phpnuW+APKz Zn. @vIlluminate/Database/Eloquent/BroadcastableModelEventOccurred.phpnuW+APKz Z- Illuminate/Database/Eloquent/MassPrunable.phpnuW+APKz ZYQ&Illuminate/Database/Eloquent/Model.phpnuW+APKz ZMi44:Illuminate/Database/Eloquent/MissingAttributeException.phpnuW+APKz ZR< Illuminate/Database/Eloquent/Factories/CrossJoinSequence.phpnuW+APKz Z0 hh7/ Illuminate/Database/Eloquent/Factories/Relationship.phpnuW+APKz ZO(pp3Illuminate/Database/Eloquent/Factories/Sequence.phpnuW+APKz Zފqq2Illuminate/Database/Eloquent/Factories/Factory.phpnuW+APKz ZY1DIlluminate/Database/Eloquent/Factories/BelongsToManyRelationship.phpnuW+APKz Z @Illuminate/Database/Eloquent/Factories/BelongsToRelationship.phpnuW+APKz Z6]]5Illuminate/Database/Eloquent/Factories/HasFactory.phpnuW+APKz Zgdd2lIlluminate/Database/Eloquent/SoftDeletingScope.phpnuW+APKz Zr52Illuminate/Database/Eloquent/InvalidCastException.phpnuW+APKz Z[c0mm6;Illuminate/Database/Eloquent/JsonEncodingException.phpnuW+APKz ZnP(Illuminate/Database/Eloquent/Builder.phpnuW+APKz Z|dۋ7~Illuminate/Database/Eloquent/ModelNotFoundException.phpnuW+APKz Z@H4pIlluminate/Database/Eloquent/QueueEntityResolver.phpnuW+APKz ZA0yIlluminate/Database/Eloquent/Casts/Attribute.phpnuW+APKz Z HH=Illuminate/Database/Eloquent/Casts/AsEncryptedArrayObject.phpnuW+APKz ZS2i 7BIlluminate/Database/Eloquent/Casts/AsEnumCollection.phpnuW+APKz ZvH==3Illuminate/Database/Eloquent/Casts/AsCollection.phpnuW+APKz ZHkr3)Illuminate/Database/Eloquent/Casts/AsStringable.phpnuW+APKz Ztێ2Illuminate/Database/Eloquent/Casts/ArrayObject.phpnuW+APKz Z4ݟ4 İIlluminate/Database/Eloquent/Casts/AsArrayObject.phpnuW+APKz Z3O}7<ɰIlluminate/Database/Eloquent/Casts/AsEncryptedCollection.phpnuW+APKz Z*  8EΰIlluminate/Database/Eloquent/Casts/AsEnumArrayObject.phpnuW+APKz ZC,ذIlluminate/Database/Eloquent/SoftDeletes.phpnuW+APKz ZMg:?Illuminate/Database/Eloquent/RelationNotFoundException.phpnuW+APKz ZQ\ >Illuminate/Database/Eloquent/PendingHasThroughRelationship.phpnuW+APKz Z?ۉ8Illuminate/Database/Eloquent/MassAssignmentException.phpnuW+APKz Zi8Illuminate/Database/Query/Processors/SQLiteProcessor.phpnuW+APKz ZY7Illuminate/Database/Query/Processors/MySqlProcessor.phpnuW+APKz ZSDmm2Illuminate/Database/Query/Processors/Processor.phpnuW+APKz Z>6oo: Illuminate/Database/Query/Processors/PostgresProcessor.phpnuW+APKz Z3Y;dIlluminate/Database/Query/Processors/SqlServerProcessor.phpnuW+APKz Z˭t(Illuminate/Database/Query/JoinClause.phpnuW+APKz ZvU('Illuminate/Database/Query/Expression.phpnuW+APKz Z9|''4*Illuminate/Database/Query/Grammars/SQLiteGrammar.phpnuW+APKz Z`.SIlluminate/Database/Query/Grammars/Grammar.phpnuW+APKz Z5m:*:*3`Illuminate/Database/Query/Grammars/MySqlGrammar.phpnuW+APKz Z4R}O}O6Illuminate/Database/Query/Grammars/PostgresGrammar.phpnuW+APKz Z(CEE7^Illuminate/Database/Query/Grammars/SqlServerGrammar.phpnuW+APKz Z7)]%JIlluminate/Database/Query/Builder.phpnuW+APKz Z';JIlluminate/Database/Query/IndexHint.phpnuW+APKz ZMʒ*LIlluminate/Database/PostgresConnection.phpnuW+APKz Z<.rr)}UIlluminate/Database/DeadlockException.phpnuW+APKz Z_K<0HVIlluminate/Database/Concerns/ExplainsQueries.phpnuW+APKz Z12lXIlluminate/Database/Concerns/CompilesJsonPaths.phpnuW+APKz Z&&4^Illuminate/Database/Concerns/ManagesTransactions.phpnuW+APKz Z+a QAQA.PIlluminate/Database/Concerns/BuildsQueries.phpnuW+APKz Z+BB1ƴIlluminate/Database/Concerns/ParsesSearchPath.phpnuW+APKz Z޷.TT"ɴIlluminate/Database/Connection.phpnuW+APKz Z1g||/HgIlluminate/Database/LostConnectionException.phpnuW+APKz Zα33#hIlluminate/Database/LICENSE.mdnuW+APKz ZD22+lIlluminate/Database/ConnectionInterface.phpnuW+APKz ZzhZZ01|Illuminate/Database/DetectsConcurrencyErrors.phpnuW+APKz Zv!3!3'뀵Illuminate/Database/DatabaseManager.phpnuW+APKz ZII7cIlluminate/Database/PDO/Concerns/ConnectsToDatabase.phpnuW+APKz Zr&Illuminate/Database/PDO/Connection.phpnuW+APKz Z@TZZ*)ȵIlluminate/Database/PDO/PostgresDriver.phpnuW+APKz ZZQQ(ɵIlluminate/Database/PDO/SQLiteDriver.phpnuW+APKz Z# +˵Illuminate/Database/PDO/SqlServerDriver.phpnuW+APKz Z #MM'εIlluminate/Database/PDO/MySqlDriver.phpnuW+APKz ZLLx5 5 /mеIlluminate/Database/PDO/SqlServerConnection.phpnuW+APKz ZȜ /޵Illuminate/Database/DatabaseServiceProvider.phpnuW+APKz ZPKII#Illuminate/Database/Grammar.phpnuW+APKz Zv ܖ??3Illuminate/Database/ConnectionResolverInterface.phpnuW+APKz Zq#::.]Illuminate/Database/Schema/IndexDefinition.phpnuW+APKz Zg.Illuminate/Database/Schema/PostgresBuilder.phpnuW+APKz Z *="Illuminate/Database/Schema/SchemaState.phpnuW+APKz Z6R#g g /T-Illuminate/Database/Schema/ColumnDefinition.phpnuW+APKz Zы> > 27Illuminate/Database/Schema/PostgresSchemaState.phpnuW+APKz Z8ikkkk5AIlluminate/Database/Schema/Grammars/SQLiteGrammar.phpnuW+APKz Z 4Illuminate/Database/Schema/Grammars/RenameColumn.phpnuW+APKz Zy2"("(/Illuminate/Database/Schema/Grammars/Grammar.phpnuW+APKz ZjΆΆ4Illuminate/Database/Schema/Grammars/MySqlGrammar.phpnuW+APKz Z4OiIlluminate/Database/Schema/Grammars/ChangeColumn.phpnuW+APKz ZN}}7Illuminate/Database/Schema/Grammars/PostgresGrammar.phpnuW+APKz Z %ee8Illuminate/Database/Schema/Grammars/SqlServerGrammar.phpnuW+APKz Zo!#DD3WjIlluminate/Database/Schema/ForeignKeyDefinition.phpnuW+APKz Zu +qIlluminate/Database/Schema/MySqlBuilder.phpnuW+APKz ZHq/y~Illuminate/Database/Schema/MySqlSchemaState.phpnuW+APKz Z8/Illuminate/Database/Schema/SqlServerBuilder.phpnuW+APKz Zف  ,Illuminate/Database/Schema/SQLiteBuilder.phpnuW+APKz Z8fIlluminate/Database/Schema/ForeignIdColumnDefinition.phpnuW+APKz Z0c 0\Illuminate/Database/Schema/SqliteSchemaState.phpnuW+APKz ZY 7>/>/&Illuminate/Database/Schema/Builder.phpnuW+APKz ZAι(0Illuminate/Database/Schema/Blueprint.phpnuW+APKz Z'AIlluminate/Database/Capsule/Manager.phpnuW+APKz Z:\F0Illuminate/Database/MigrationServiceProvider.phpnuW+APKz Za2{ 3׹Illuminate/Database/DatabaseTransactionsManager.phpnuW+APKz ZrXa a 'Illuminate/Database/MySqlConnection.phpnuW+APKz Zv>lIlluminate/Database/Migrations/DatabaseMigrationRepository.phpnuW+APKz Z,Illuminate/Database/Migrations/Migration.phpnuW+APKz Z$XX+jIlluminate/Database/Migrations/Migrator.phpnuW+APKz Z%[3^Illuminate/Database/Migrations/stubs/migration.stubnuW+APKz Z7DHH:`Illuminate/Database/Migrations/stubs/migration.update.stubnuW+APKz Z:EE:>cIlluminate/Database/Migrations/stubs/migration.create.stubnuW+APKz Zr}u3eIlluminate/Database/Migrations/MigrationCreator.phpnuW+APKz Zxqq? ~Illuminate/Database/Migrations/MigrationRepositoryInterface.phpnuW+APKz Z:`*턺Illuminate/Database/ConnectionResolver.phpnuW+APKz Z 555Illuminate/Database/Connectors/SqlServerConnector.phpnuW+APKz Z RB5EIlluminate/Database/Connectors/ConnectorInterface.phpnuW+APKz Ze e ,Illuminate/Database/Connectors/Connector.phpnuW+APKz Zh_ [[2[Illuminate/Database/Connectors/SQLiteConnector.phpnuW+APKz Z.L.4Illuminate/Database/Connectors/PostgresConnector.phpnuW+APKz Z+1hֺIlluminate/Database/Connectors/MySqlConnector.phpnuW+APKz Z(4VIlluminate/Database/Connectors/ConnectionFactory.phpnuW+APKz ZsC% % .d Illuminate/Database/DetectsLostConnections.phpnuW+APKz Z߈|Illuminate/Database/README.mdnuW+APKz Zƙ__&"Illuminate/Database/QueryException.phpnuW+APKz Z/+)Illuminate/Database/Events/SchemaLoaded.phpnuW+APKz Z"c((-,Illuminate/Database/Events/MigrationEvent.phpnuW+APKz Z³gg/f0Illuminate/Database/Events/MigrationStarted.phpnuW+APKz Z{+,1Illuminate/Database/Events/ModelsPruned.phpnuW+APKz Z.-k6ll33Illuminate/Database/Events/TransactionBeginning.phpnuW+APKz ZKll3o4Illuminate/Database/Events/TransactionCommitted.phpnuW+APKz ZQ$ 2ii0>5Illuminate/Database/Events/MigrationsStarted.phpnuW+APKz Z:+6Illuminate/Database/Events/SchemaDumped.phpnuW+APKz Z 0_9Illuminate/Database/Events/DatabaseRefreshed.phpnuW+APKz ZߡCC+:Illuminate/Database/Events/DatabaseBusy.phpnuW+APKz Z|4/mm4$=Illuminate/Database/Events/TransactionCommitting.phpnuW+APKz ZggJmm4=Illuminate/Database/Events/ConnectionEstablished.phpnuW+APKz Z}Omm4>Illuminate/Database/Events/TransactionRolledBack.phpnuW+APKz ZN/.?Illuminate/Database/Events/MigrationsEvent.phpnuW+APKz Z;nk||2AIlluminate/Database/Events/NoPendingMigrations.phpnuW+APKz Zee-CIlluminate/Database/Events/MigrationEnded.phpnuW+APKz Ztee.DIlluminate/Database/Events/ConnectionEvent.phpnuW+APKz Ztvrr,PGIlluminate/Database/Events/QueryExecuted.phpnuW+APKz Z?3[{{0LIlluminate/Database/Events/StatementPrepared.phpnuW+APKz Z3N6gg.NIlluminate/Database/Events/MigrationsEnded.phpnuW+APKz Z(5OIlluminate/Database/LazyLoadingViolationException.phpnuW+APKz Zmb b (&SIlluminate/Database/SQLiteConnection.phpnuW+APKz ZiT T *_Illuminate/Database/DBAL/TimestampType.phpnuW+APKz Zs!~555;jIlluminate/Database/SQLiteDatabaseDoesNotExistException.phpnuW+APKz Z o# +.mIlluminate/Database/Console/WipeCommand.phpnuW+APKz Z.)JyIlluminate/Database/Console/DbCommand.phpnuW+APKz ZWm +Illuminate/Database/Console/DumpCommand.phpnuW+APKz Zw.Illuminate/Database/Console/MonitorCommand.phpnuW+APKz Z+갻Illuminate/Database/Console/ShowCommand.phpnuW+APKz Zaa,K̻Illuminate/Database/Console/TableCommand.phpnuW+APKz Z<9Illuminate/Database/Console/Migrations/RefreshCommand.phpnuW+APKz Z~jDD=Illuminate/Database/Console/Migrations/MigrateMakeCommand.phpnuW+APKz Z6h80Illuminate/Database/Console/Migrations/StatusCommand.phpnuW+APKz ZZ7=!Illuminate/Database/Console/Migrations/TableGuesser.phpnuW+APKz ZrJ J :+%Illuminate/Database/Console/Migrations/RollbackCommand.phpnuW+APKz Zi6.Illuminate/Database/Console/Migrations/BaseCommand.phpnuW+APKz Z KY74Illuminate/Database/Console/Migrations/FreshCommand.phpnuW+APKz ZiE 7DIlluminate/Database/Console/Migrations/ResetCommand.phpnuW+APKz Z}2 % %9[NIlluminate/Database/Console/Migrations/MigrateCommand.phpnuW+APKz ZPa449sIlluminate/Database/Console/Migrations/InstallCommand.phpnuW+APKz Zaԝ//,mzIlluminate/Database/Console/PruneCommand.phpnuW+APKz Z(kk<Illuminate/Database/Console/Factories/FactoryMakeCommand.phpnuW+APKz ZfL8ϟIlluminate/Database/Console/Factories/stubs/factory.stubnuW+APKz ZKI9ݡIlluminate/Database/Console/DatabaseInspectionCommand.phpnuW+APKz Zeܔ7Illuminate/Database/Console/Seeds/SeederMakeCommand.phpnuW+APKz Z>Tu!1ɼIlluminate/Database/Console/Seeds/SeedCommand.phpnuW+APKz Z@68ؼIlluminate/Database/Console/Seeds/WithoutModelEvents.phpnuW+APKz Z3ڼIlluminate/Database/Console/Seeds/stubs/seeder.stubnuW+APKz Z6\((1qܼIlluminate/Database/DatabaseTransactionRecord.phpnuW+APKz Zꪛ.Illuminate/Database/ConfigurationUrlParser.phpnuW+APKz Z]e  4Illuminate/Database/ClassMorphViolationException.phpnuW+APKz ZIb!Illuminate/Database/composer.jsonnuW+APKz Z 5Illuminate/Database/MultipleRecordsFoundException.phpnuW+APKz Zon +Illuminate/Database/SqlServerConnection.phpnuW+APKz Z<؊ Illuminate/Database/Seeder.phpnuW+APKz Z9B8Illuminate/Database/MultipleColumnsSelectedException.phpnuW+APKz ZNP.Illuminate/Contracts/Filesystem/Filesystem.phpnuW+APKz Z1įd||9!Illuminate/Contracts/Filesystem/FileNotFoundException.phpnuW+APKz Z Pk  +"Illuminate/Contracts/Filesystem/Factory.phpnuW+APKz Zq{{86$Illuminate/Contracts/Filesystem/LockTimeoutException.phpnuW+APKz Zf)%Illuminate/Contracts/Filesystem/Cloud.phpnuW+APKz Zp8i&Illuminate/Contracts/Translation/HasLocalePreference.phpnuW+APKz Z!@00+'Illuminate/Contracts/Translation/Loader.phpnuW+APKz Zi~/:+Illuminate/Contracts/Translation/Translator.phpnuW+APKz Zo!FIlluminate/Contracts/Auth/Middleware/AuthenticatesRequests.phpnuW+APKz Zycf{{/FIlluminate/Contracts/Auth/SupportsBasicAuth.phpnuW+APKz Z!,IIlluminate/Contracts/Auth/PasswordBroker.phpnuW+APKz Ze6610OIlluminate/Contracts/Auth/Access/Authorizable.phpnuW+APKz Zы)PIlluminate/Contracts/Auth/Access/Gate.phpnuW+APKz Z+_Illuminate/Contracts/Auth/StatefulGuard.phpnuW+APKz Z]))+fIlluminate/Contracts/Support/MessageBag.phpnuW+APKz Zŝ_0II=nIlluminate/Contracts/Support/CanBeEscapedWhenCastToString.phpnuW+APKz ZA 0@pIlluminate/Contracts/Support/MessageProvider.phpnuW+APKz Ze22,qIlluminate/Contracts/Support/Responsable.phpnuW+APKz ZPT*sIlluminate/Contracts/Support/Arrayable.phpnuW+APKz ZRQ)utIlluminate/Contracts/Support/Jsonable.phpnuW+APKz Z:uIlluminate/Contracts/Support/DeferringDisplayableValue.phpnuW+APKz Z_+FwIlluminate/Contracts/Support/Renderable.phpnuW+APKz Z뤏#)fxIlluminate/Contracts/Support/Htmlable.phpnuW+APKz ZT3yyIlluminate/Contracts/Support/DeferrableProvider.phpnuW+APKz Z.zIlluminate/Contracts/Support/ValidatedData.phpnuW+APKz Z'qq,{Illuminate/Contracts/Routing/UrlRoutable.phpnuW+APKz Z#||0Illuminate/Contracts/Routing/ResponseFactory.phpnuW+APKz Z *`Illuminate/Contracts/Routing/Registrar.phpnuW+APKz ZA61=Illuminate/Contracts/Routing/BindingRegistrar.phpnuW+APKz Z -]Illuminate/Contracts/Routing/UrlGenerator.phpnuW+APKz Zα33DIlluminate/Contracts/LICENSE.mdnuW+APKz ZQ"ƫIlluminate/Contracts/View/View.phpnuW+APKz Z!ʍ%5Illuminate/Contracts/View/Factory.phpnuW+APKz Zxt+yy6Illuminate/Contracts/View/ViewCompilationException.phpnuW+APKz Z_4  $Illuminate/Contracts/View/Engine.phpnuW+APKz ZjB&&%SIlluminate/Contracts/Pipeline/Hub.phpnuW+APKz Z(.+*ιIlluminate/Contracts/Pipeline/Pipeline.phpnuW+APKz Z^^0Illuminate/Contracts/Foundation/CachesRoutes.phpnuW+APKz Z.7ݾIlluminate/Contracts/Foundation/CachesConfiguration.phpnuW+APKz Z)/LIlluminate/Contracts/Foundation/Application.phpnuW+APKz Zb)3սIlluminate/Contracts/Foundation/MaintenanceMode.phpnuW+APKz ZEސ5ؽIlluminate/Contracts/Foundation/ExceptionRenderer.phpnuW+APKz ZL  6;ڽIlluminate/Contracts/Validation/ValidatorAwareRule.phpnuW+APKz ZD}mm-۽Illuminate/Contracts/Validation/Validator.phpnuW+APKz ZGL  9wIlluminate/Contracts/Validation/UncompromisedVerifier.phpnuW+APKz ZXnn1Illuminate/Contracts/Validation/InvokableRule.phpnuW+APKz Z0N+Illuminate/Contracts/Validation/Factory.phpnuW+APKz Z HL}bb0Illuminate/Contracts/Validation/ImplicitRule.phpnuW+APKz ZMRSX(Illuminate/Contracts/Validation/Rule.phpnuW+APKz Z>OG9gIlluminate/Contracts/Validation/ValidatesWhenResolved.phpnuW+APKz Z+L1Illuminate/Contracts/Validation/DataAwareRule.phpnuW+APKz ZaKK/Illuminate/Contracts/Debug/ExceptionHandler.phpnuW+APKz Zvc7R9Illuminate/Contracts/Broadcasting/HasBroadcastChannel.phpnuW+APKz Zm$!;;1Illuminate/Contracts/Broadcasting/Broadcaster.phpnuW+APKz ZzΫ!!-HIlluminate/Contracts/Broadcasting/Factory.phpnuW+APKz Z~YY4Illuminate/Contracts/Broadcasting/ShouldBeUnique.phpnuW+APKz ZGuu8Illuminate/Contracts/Broadcasting/ShouldBroadcastNow.phpnuW+APKz Z6''5`Illuminate/Contracts/Broadcasting/ShouldBroadcast.phpnuW+APKz ZFzkk/Illuminate/Contracts/Cookie/QueueingFactory.phpnuW+APKz Z#'Illuminate/Contracts/Cookie/Factory.phpnuW+APKz Zw|%%*Illuminate/Contracts/Events/Dispatcher.phpnuW+APKz Z$,'Illuminate/Contracts/Container/Container.phpnuW+APKz Z.>W#Illuminate/Contracts/Container/CircularDependencyException.phpnuW+APKz Zrzz;$Illuminate/Contracts/Container/ContextualBindingBuilder.phpnuW+APKz Zk=(Illuminate/Contracts/Container/BindingResolutionException.phpnuW+APKz Z*&/)Illuminate/Contracts/Bus/QueueingDispatcher.phpnuW+APKz ZF"',Illuminate/Contracts/Bus/Dispatcher.phpnuW+APKz Z!`4'2Illuminate/Contracts/Mail/MailQueue.phpnuW+APKz Z>($5Illuminate/Contracts/Mail/Mailer.phpnuW+APKz ZaP&:Illuminate/Contracts/Mail/Mailable.phpnuW+APKz Z3(F%qAIlluminate/Contracts/Mail/Factory.phpnuW+APKz Z@p6?ԾIlluminate/Contracts/Queue/EntityNotFoundException.phpnuW+APKz ZU7{2i־Illuminate/Contracts/Queue/QueueableCollection.phpnuW+APKz Z$pp$wپIlluminate/Contracts/Http/Kernel.phpnuW+APKz ZxPU))8;ݾIlluminate/Contracts/Pagination/LengthAwarePaginator.phpnuW+APKz Z -߾Illuminate/Contracts/Pagination/Paginator.phpnuW+APKz Z 3Illuminate/Contracts/Pagination/CursorPaginator.phpnuW+APKz ZjBÊ*Illuminate/Contracts/Config/Repository.phpnuW+APKz Z.:)Illuminate/Redis/RedisServiceProvider.phpnuW+APKz Zױ!nIlluminate/Redis/RedisManager.phpnuW+APKz Zα33Illuminate/Redis/LICENSE.mdnuW+APKz Z~-u$$+?Illuminate/Redis/Connections/Connection.phpnuW+APKz Z7RR:.Illuminate/Redis/Connections/PhpRedisClusterConnection.phpnuW+APKz ZR883z1Illuminate/Redis/Connections/PhpRedisConnection.phpnuW+APKz ZoXX8iIlluminate/Redis/Connections/PredisClusterConnection.phpnuW+APKz Z,9q 4lIlluminate/Redis/Connections/PacksPhpRedisValues.phpnuW+APKz Z+,l21Illuminate/Redis/Connections/PredisConnection.phpnuW+APKz Zө 4Illuminate/Redis/Limiters/DurationLimiterBuilder.phpnuW+APKz Zwzj>GG-7Illuminate/Redis/Limiters/DurationLimiter.phpnuW+APKz Zm  7ۤIlluminate/Redis/Limiters/ConcurrencyLimiterBuilder.phpnuW+APKz Z:0[Illuminate/Redis/Limiters/ConcurrencyLimiter.phpnuW+APKz Z((/Illuminate/Redis/Connectors/PredisConnector.phpnuW+APKz Z_N--1PǿIlluminate/Redis/Connectors/PhpRedisConnector.phpnuW+APKz ZdZb+Illuminate/Redis/Events/CommandExecuted.phpnuW+APKz Z855Illuminate/Redis/composer.jsonnuW+APKz Z ԁ &aIlluminate/Queue/CallQueuedClosure.phpnuW+APKz ZC:Վ!Illuminate/Queue/QueueManager.phpnuW+APKz ZySj}},Illuminate/Queue/ManuallyFailedException.phpnuW+APKz Zee3'3'oIlluminate/Queue/RedisQueue.phpnuW+APKz ZI*'=Illuminate/Queue/InteractsWithQueue.phpnuW+APKz ZC\XX`EIlluminate/Queue/LuaScripts.phpnuW+APKz Zα33WIlluminate/Queue/LICENSE.mdnuW+APKz ZH$((,[Illuminate/Queue/InvalidPayloadException.phpnuW+APKz ZޤM M & ^Illuminate/Queue/CallQueuedHandler.phpnuW+APKz Zǹy y "~Illuminate/Queue/WorkerOptions.phpnuW+APKz Z:HI**wIlluminate/Queue/Queue.phpnuW+APKz Z$ݲIlluminate/Queue/ListenerOptions.phpnuW+APKz Z c1Illuminate/Queue/MaxAttemptsExceededException.phpnuW+APKz Z9&&Illuminate/Queue/SqsQueue.phpnuW+APKz Z)$ Illuminate/Queue/Capsule/Manager.phpnuW+APKz Zg115Illuminate/Queue/Failed/PrunableFailedJobProvider.phpnuW+APKz Z%zz9Illuminate/Queue/Failed/DatabaseUuidFailedJobProvider.phpnuW+APKz Z7 5Illuminate/Queue/Failed/DatabaseFailedJobProvider.phpnuW+APKz ZY,,5Illuminate/Queue/Failed/DynamoDbFailedJobProvider.phpnuW+APKz ZcHQQ1fIlluminate/Queue/Failed/NullFailedJobProvider.phpnuW+APKz Z|6Illuminate/Queue/Failed/FailedJobProviderInterface.phpnuW+APKz ZvŽϳ:9Illuminate/Queue/SerializesAndRestoresModelIdentifiers.phpnuW+APKz Zs)$V,Illuminate/Queue/BeanstalkdQueue.phpnuW+APKz Z. R %AIlluminate/Queue/SerializesModels.phpnuW+APKz Zqaa{KIlluminate/Queue/Worker.phpnuW+APKz Z_,.ǬIlluminate/Queue/Connectors/RedisConnector.phpnuW+APKz Zlt2Illuminate/Queue/Connectors/ConnectorInterface.phpnuW+APKz Zu6@@1Illuminate/Queue/Connectors/DatabaseConnector.phpnuW+APKz Zkff-(Illuminate/Queue/Connectors/NullConnector.phpnuW+APKz Z`%Bff-Illuminate/Queue/Connectors/SyncConnector.phpnuW+APKz Z&|3Illuminate/Queue/Connectors/BeanstalkdConnector.phpnuW+APKz ZSA},*Illuminate/Queue/Connectors/SqsConnector.phpnuW+APKz Zc 4Illuminate/Queue/Middleware/RateLimitedWithRedis.phpnuW+APKz Zi4Illuminate/Queue/Middleware/SkipIfBatchCancelled.phpnuW+APKz ZrE''3Illuminate/Queue/Middleware/ThrottlesExceptions.phpnuW+APKz Z- 2 Illuminate/Queue/Middleware/WithoutOverlapping.phpnuW+APKz Z%ը +RIlluminate/Queue/Middleware/RateLimited.phpnuW+APKz Z^<Illuminate/Queue/Middleware/ThrottlesExceptionsWithRedis.phpnuW+APKz Z Illuminate/Queue/README.mdnuW+APKz Z 1% Illuminate/Queue/Jobs/DatabaseJob.phpnuW+APKz Z "4Illuminate/Queue/Jobs/RedisJob.phpnuW+APKz Zye 'kIlluminate/Queue/Jobs/BeanstalkdJob.phpnuW+APKz Z'̷hh+*Illuminate/Queue/Jobs/DatabaseJobRecord.phpnuW+APKz Z#E!E/Illuminate/Queue/Jobs/JobName.phpnuW+APKz Z  42Illuminate/Queue/Jobs/SqsJob.phpnuW+APKz ZL&N!<Illuminate/Queue/Jobs/SyncJob.phpnuW+APKz Z~A#aaCIlluminate/Queue/Jobs/Job.phpnuW+APKz Z*{MM(>`Illuminate/Queue/Events/JobProcessed.phpnuW+APKz Z㫒-bIlluminate/Queue/Events/JobRetryRequested.phpnuW+APKz Z``% fIlluminate/Queue/Events/JobFailed.phpnuW+APKz Z,0}iIlluminate/Queue/Events/JobExceptionOccurred.phpnuW+APKz ZTNN)lIlluminate/Queue/Events/JobProcessing.phpnuW+APKz Z ZZ5oIlluminate/Queue/Events/JobReleasedAfterException.phpnuW+APKz Z268%VrIlluminate/Queue/Events/JobQueued.phpnuW+APKz ZЏGmm*|uIlluminate/Queue/Events/WorkerStopping.phpnuW+APKz Zt@#CxIlluminate/Queue/Events/Looping.phpnuW+APKz ZOq%zIlluminate/Queue/Events/QueueBusy.phpnuW+APKz Z{1%1%)}Illuminate/Queue/QueueServiceProvider.phpnuW+APKz Zz1[*5Illuminate/Queue/Console/ListenCommand.phpnuW+APKz Z|ڐ )Illuminate/Queue/Console/ClearCommand.phpnuW+APKz Zi7 7 0Illuminate/Queue/Console/BatchesTableCommand.phpnuW+APKz ZݻHUU+$Illuminate/Queue/Console/MonitorCommand.phpnuW+APKz Z-DQ, , /Illuminate/Queue/Console/FailedTableCommand.phpnuW+APKz Z%%(_Illuminate/Queue/Console/WorkCommand.phpnuW+APKz Z ) Illuminate/Queue/Console/TableCommand.phpnuW+APKz Zz0Illuminate/Queue/Console/PruneBatchesCommand.phpnuW+APKz Z3 Illuminate/Queue/Console/PruneFailedJobsCommand.phpnuW+APKz Z+O&Illuminate/Queue/Console/RestartCommand.phpnuW+APKz Z\`),Illuminate/Queue/Console/RetryCommand.phpnuW+APKz Z(N.BIlluminate/Queue/Console/RetryBatchCommand.phpnuW+APKz Z4cc0IIlluminate/Queue/Console/ForgetFailedCommand.phpnuW+APKz Z&&/NIlluminate/Queue/Console/stubs/failed_jobs.stubnuW+APKz Z}hbb(,RIlluminate/Queue/Console/stubs/jobs.stubnuW+APKz Z*1ޭ+UIlluminate/Queue/Console/stubs/batches.stubnuW+APKz Z0/ZIlluminate/Queue/Console/FlushFailedCommand.phpnuW+APKz Z= .__Illuminate/Queue/Console/ListFailedCommand.phpnuW+APKz Z6t?.?."DlIlluminate/Queue/DatabaseQueue.phpnuW+APKz ZC ՚Illuminate/Queue/composer.jsonnuW+APKz Zrr:Illuminate/Queue/SyncQueue.phpnuW+APKz ZuIlluminate/Queue/NullQueue.phpnuW+APKz ZiڷIlluminate/Queue/Listener.phpnuW+APKz Z/Nܥ'Illuminate/Http/Testing/FileFactory.phpnuW+APKz Z@2To o Illuminate/Http/Testing/File.phpnuW+APKz Zו$Illuminate/Http/Testing/MimeType.phpnuW+APKz Z)#!tIlluminate/Http/ResponseTrait.phpnuW+APKz Zl.Illuminate/Http/Concerns/CanBePrecognitive.phpnuW+APKz Z, 6(Illuminate/Http/Concerns/InteractsWithContentTypes.phpnuW+APKz Z9;;/Illuminate/Http/Concerns/InteractsWithInput.phpnuW+APKz Zf3JIlluminate/Http/Concerns/InteractsWithFlashData.phpnuW+APKz Zα33yPIlluminate/Http/LICENSE.mdnuW+APKz Z Ykk.TIlluminate/Http/Client/ConnectionException.phpnuW+APKz Zm*ii)UIlluminate/Http/Client/PendingRequest.phpnuW+APKz Z2)SIlluminate/Http/Client/Pool.phpnuW+APKz ZH&? ? 8VIlluminate/Http/Client/Concerns/DeterminesStatusCode.phpnuW+APKz ZMyπ&&#Illuminate/Http/Client/Response.phpnuW+APKz Z$&&"Illuminate/Http/Client/Factory.phpnuW+APKz Zv,qq.AIlluminate/Http/Client/HttpClientException.phpnuW+APKz Zo0AIlluminate/Http/Client/Events/RequestSending.phpnuW+APKz Zz2DIlluminate/Http/Client/Events/ConnectionFailed.phpnuW+APKz Z\23FIlluminate/Http/Client/Events/ResponseReceived.phpnuW+APKz Zk0A"wIIlluminate/Http/Client/Request.phpnuW+APKz Z zz+bIlluminate/Http/Client/RequestException.phpnuW+APKz Z\b +wgIlluminate/Http/Client/ResponseSequence.phpnuW+APKz Zv_eBB$uIlluminate/Http/RedirectResponse.phpnuW+APKz Z  EIlluminate/Http/Response.phpnuW+APKz Z' Illuminate/Http/UploadedFile.phpnuW+APKz ZZTT4Illuminate/Http/Exceptions/PostTooLargeException.phpnuW+APKz Z-J4Illuminate/Http/Exceptions/HttpResponseException.phpnuW+APKz Z|kxx8Illuminate/Http/Exceptions/ThrottleRequestsException.phpnuW+APKz ZOeH  *Illuminate/Http/Resources/MissingValue.phpnuW+APKz Zuze>fIlluminate/Http/Resources/Json/AnonymousResourceCollection.phpnuW+APKz Z  <pIlluminate/Http/Resources/Json/PaginatedResourceResponse.phpnuW+APKz ZA%P 5Illuminate/Http/Resources/Json/ResourceCollection.phpnuW+APKz Z[a/8Illuminate/Http/Resources/Json/JsonResource.phpnuW+APKz Zˆ 3jIlluminate/Http/Resources/Json/ResourceResponse.phpnuW+APKz ZB0fIlluminate/Http/Resources/PotentiallyMissing.phpnuW+APKz Zۃ2o /Illuminate/Http/Resources/CollectsResources.phpnuW+APKz Z/' ' 1Illuminate/Http/Resources/DelegatesToResource.phpnuW+APKz Zޅ]&&: Illuminate/Http/Resources/ConditionallyLoadsAttributes.phpnuW+APKz Z!A(2Illuminate/Http/Resources/MergeValue.phpnuW+APKz Z~)5Illuminate/Http/Middleware/TrustHosts.phpnuW+APKz Z?<Illuminate/Http/Middleware/AddLinkHeadersForPreloadedAssets.phpnuW+APKz Z+?Illuminate/Http/Middleware/TrustProxies.phpnuW+APKz Zm--.OIlluminate/Http/Middleware/SetCacheHeaders.phpnuW+APKz Z )^WIlluminate/Http/Middleware/FrameGuard.phpnuW+APKz ZG )YIlluminate/Http/Middleware/HandleCors.phpnuW+APKz Z0L<dIlluminate/Http/Middleware/CheckResponseForModifications.phpnuW+APKz Z0ۛMgIlluminate/Http/File.phpnuW+APKz Z 0hIlluminate/Http/JsonResponse.phpnuW+APKz Z\FFDvIlluminate/Http/Request.phpnuW+APKz ZXI^nIlluminate/Http/FileHelpers.phpnuW+APKz ZIlluminate/Http/composer.jsonnuW+APKz Z )Illuminate/Log/ParsesLogConfiguration.phpnuW+APKz Z5""\Illuminate/Log/Logger.phpnuW+APKz Zα33.Illuminate/Log/LICENSE.mdnuW+APKz Zz8M6J6JIlluminate/Log/LogManager.phpnuW+APKz ZKq'-@Illuminate/Log/Events/MessageLogged.phpnuW+APKz Z:DKK.CIlluminate/Log/composer.jsonnuW+APKz Z,$hh%FIlluminate/Log/LogServiceProvider.phpnuW+APKz Z _;;1HIlluminate/Pagination/AbstractCursorPaginator.phpnuW+APKz Z@''.nIlluminate/Pagination/LengthAwarePaginator.phpnuW+APKz Zα33 Illuminate/Pagination/LICENSE.mdnuW+APKz Zz vIlluminate/Pagination/Cursor.phpnuW+APKz Z`#dIlluminate/Pagination/Paginator.phpnuW+APKz Zq!  )ͿIlluminate/Pagination/PaginationState.phpnuW+APKz Zq'31Illuminate/Pagination/PaginationServiceProvider.phpnuW+APKz ZlyBB+xIlluminate/Pagination/AbstractPaginator.phpnuW+APKz Z_# Illuminate/Pagination/composer.jsonnuW+APKz ZO5) Illuminate/Pagination/CursorPaginator.phpnuW+APKz Zé7mm#Illuminate/Pagination/UrlWindow.phpnuW+APKz ZM, ?6Illuminate/Pagination/resources/views/simple-tailwind.blade.phpnuW+APKz ZߎB=Illuminate/Pagination/resources/views/simple-bootstrap-4.blade.phpnuW+APKz ZCΥ$$;FBIlluminate/Pagination/resources/views/bootstrap-4.blade.phpnuW+APKz Z);JIlluminate/Pagination/resources/views/bootstrap-5.blade.phpnuW+APKz ZHH7\Illuminate/Pagination/resources/views/default.blade.phpnuW+APKz Z8F;cIlluminate/Pagination/resources/views/semantic-ui.blade.phpnuW+APKz Z@̚8jIlluminate/Pagination/resources/views/tailwind.blade.phpnuW+APKz Z|^"BIlluminate/Pagination/resources/views/simple-bootstrap-5.blade.phpnuW+APKz Zm[>Illuminate/Pagination/resources/views/simple-default.blade.phpnuW+APKz Zα33'Illuminate/Config/LICENSE.mdnuW+APKz Z\ń Illuminate/Config/Repository.phpnuW+APKz Z 55Illuminate/Config/composer.jsonnuW+APKH ZFߠ5SailServiceProvider.phpnuW+APKH Z+l ,,7ͯConsole/Concerns/InteractsWithDockerComposeServices.phpnuW+APKH Z' eeConsole/AddCommand.phpnuW+APKH Z bhConsole/PublishCommand.phpnuW+APKH Z}] ]Console/InstallCommand.phpnuW+APK>Z|_7- - EMessageIDParser.phpnuW+APK>ZS 4Warning/AddressLiteral.phpnuW+APK>ZHWarning/CFWSNearAt.phpnuW+APK>Zodd+Warning/QuotedString.phpnuW+APK>ZUiWarning/CFWSWithFWS.phpnuW+APK>ZY'Warning/IPV6MaxGroups.phpnuW+APK>Zf%LoWarning/IPV6GroupCount.phpnuW+APK>Ze  Warning/NoDNSMXRecord.phpnuW+APK>Z"Warning/IPV6BadChar.phpnuW+APK>ZUWarning/IPV6DoubleColon.phpnuW+APK>Z[q Warning/DomainLiteral.phpnuW+APK>Zj Warning/IPV6ColonStart.phpnuW+APK>ZF  9 Warning/IPV6ColonEnd.phpnuW+APK>Zp!td`` Warning/QuotedPart.phpnuW+APK>Z !2Warning/ObsoleteDTEXT.phpnuW+APK>Z.e~Warning/TLD.phpnuW+APK>Z%%Warning/EmailTooLong.phpnuW+APK>ZIbWarning/IPV6Deprecated.phpnuW+APK>Z 2Warning/Warning.phpnuW+APK>Z:>Warning/Comment.phpnuW+APK>ZKWarning/DeprecatedComment.phpnuW+APK>ZV}5<<Warning/LocalTooLong.phpnuW+APK>Z6S **MResult/MultipleErrors.phpnuW+APK>ZOI Result/Result.phpnuW+APK>Z  &#Result/Reason/UnclosedQuotedString.phpnuW+APK>Zxr$Result/Reason/EmptyReason.phpnuW+APK>Z,,-%Result/Reason/ExpectingDomainLiteralClose.phpnuW+APK>ZIXc>'Result/Reason/DotAtEnd.phpnuW+APK>Z{(Result/Reason/NoLocalPart.phpnuW+APK>Zk)Result/Reason/DotAtStart.phpnuW+APK>ZDN+Result/Reason/CRNoLF.phpnuW+APK>Z& P,Result/Reason/NoDNSRecord.phpnuW+APK>Zb!-Result/Reason/UnusualElements.phpnuW+APK>ZZ!/Result/Reason/CRLFX2.phpnuW+APK>Z`8 F1Result/Reason/ConsecutiveDot.phpnuW+APK>ZJ+n¾ 2Result/Reason/ExceptionFound.phpnuW+APK>Zd{GG4Result/Reason/CRLFAtTheEnd.phpnuW+APK>ZOY =6Result/Reason/AtextAfterCFWS.phpnuW+APK>Z87Result/Reason/CommaInDomain.phpnuW+APK>Z`8Result/Reason/LabelTooLong.phpnuW+APK>ZO}%\:Result/Reason/DomainAcceptsNoMail.phpnuW+APK>Z ;Result/Reason/ExpectingDTEXT.phpnuW+APK>ZGAA =Result/Reason/ExpectingATEXT.phpnuW+APK>Z%'hFF!>Result/Reason/UnOpenedComment.phpnuW+APK>Z    D@Result/Reason/DomainHyphened.phpnuW+APK>ZyXgdd&AResult/Reason/UnableToGetDNSRecord.phpnuW+APK>Z'''ZCResult/Reason/LocalOrReservedDomain.phpnuW+APK>Z J DResult/Reason/CharNotAllowed.phpnuW+APK>Z׵CF*FResult/Reason/ConsecutiveAt.phpnuW+APK>ZMf$$#GResult/Reason/CommentsInIDRight.phpnuW+APK>Z? HResult/Reason/ExpectingCTEXT.phpnuW+APK>Z}`4))DJResult/Reason/SpoofEmail.phpnuW+APK>ZoZ!KResult/Reason/UnclosedComment.phpnuW+APK>Z`OMResult/Reason/DomainTooLong.phpnuW+APK>Z:yNResult/Reason/NoDomainPart.phpnuW+APK>ZK9NOResult/Reason/Reason.phpnuW+APK>Z  +QResult/Reason/RFCWarnings.phpnuW+APK>Z RResult/Reason/DetailedReason.phpnuW+APK>ZڷKKSResult/InvalidEmail.phpnuW+APK>Z砐R22bWResult/SpoofEmail.phpnuW+APK>ZjU{{XResult/ValidEmail.phpnuW+APK>Z99)ZValidation/Extra/SpoofCheckValidation.phpnuW+APK>Z<+_Validation/EmailValidation.phpnuW+APK>ZG``,bValidation/Exception/EmptyValidationList.phpnuW+APK>Z]]"GdValidation/DNSGetRecordWrapper.phpnuW+APK>Z[5_!gValidation/DNSCheckValidation.phpnuW+APK>ZN"~Validation/MessageIDValidation.phpnuW+APK>Z'G  (JValidation/MultipleValidationWithAnd.phpnuW+APK>ZJMM&Validation/NoRFCWarningsValidation.phpnuW+APK>Z%7ZLValidation/DNSRecords.phpnuW+APK>ZL  Validation/RFCValidation.phpnuW+APK>Z\F F EmailParser.phpnuW+APK>Zhϑ!!oEmailLexer.phpnuW+APK>Z xEmailValidator.phpnuW+APK>Z/aParser/IDLeftPart.phpnuW+APK>ZDGGParser/LocalPart.phpnuW+APK>Z Zђ!*!*Parser/DomainPart.phpnuW+APK>Z(x Parser/CommentStrategy/DomainComment.phpnuW+APK>Z̳``'Parser/CommentStrategy/LocalComment.phpnuW+APK>ZS!  *Parser/CommentStrategy/CommentStrategy.phpnuW+APK>Z,w3Parser/PartParser.phpnuW+APK>Z=< PParser/FoldingWhiteSpace.phpnuW+APK>Z=*Parser/DomainLiteral.phpnuW+APK>Z$΁ FParser/DoubleQuote.phpnuW+APK>Z+SParser/IDRightPart.phpnuW+APK>Z&R R WParser/Comment.phpnuW+APKqZ[a0a0x>xFaker/Provider/nb_NO/Person.phpnuW+APKqZ]%AOO$SjFaker/Provider/nb_NO/PhoneNumber.phpnuW+APKqZ!pp mFaker/Provider/nb_NO/Company.phpnuW+APKqZH11 Faker/Provider/nb_NO/Address.phpnuW+APKqZӊ''aFaker/Provider/HtmlLorem.phpnuW+APKqZ)8Faker/Provider/Lorem.phpnuW+APKqZ;$ WFaker/Provider/sv_SE/Payment.phpnuW+APKqZA%ZFaker/Provider/sv_SE/Municipality.phpnuW+APKqZ,::sFaker/Provider/sv_SE/Person.phpnuW+APKqZ:$Faker/Provider/sv_SE/PhoneNumber.phpnuW+APKqZhufh)) Faker/Provider/sv_SE/Company.phpnuW+APKqZS$xx /Faker/Provider/sv_SE/Address.phpnuW+APKqZ#A Q1Faker/Provider/kk_KZ/Payment.phpnuW+APKqZQO`5Faker/Provider/kk_KZ/Color.phpnuW+APKqZʱ..87Faker/Provider/kk_KZ/Person.phpnuW+APKqZʕSFaker/Provider/kk_KZ/Text.phpnuW+APKqZe!Faker/Provider/kk_KZ/Internet.phpnuW+APKqZ> !Faker/Provider/en_UG/Address.phpnuW+APKqZʇ))Faker/Provider/Payment.phpnuW+APKqZ} Faker/Provider/fr_CH/Payment.phpnuW+APKqZ11.\\Faker/Provider/fr_CH/Color.phpnuW+APKqZġHFaker/Provider/fr_CH/Person.phpnuW+APKqZyJZZ8Faker/Provider/fr_CH/Text.phpnuW+APKqZ>>!Faker/Provider/fr_CH/Internet.phpnuW+APKqZׁ$nFaker/Provider/fr_CH/PhoneNumber.phpnuW+APKqZig`` CFaker/Provider/fr_CH/Company.phpnuW+APKqZv5y>> Faker/Provider/fr_CH/Address.phpnuW+APKqZx  Faker/Provider/en_GB/Payment.phpnuW+APKqZHo 5ZZ{Faker/Provider/en_GB/Person.phpnuW+APKqZDALL!$0Faker/Provider/en_GB/Internet.phpnuW+APKqZ~cD$1Faker/Provider/en_GB/PhoneNumber.phpnuW+APKqZm 6Faker/Provider/en_GB/Company.phpnuW+APKqZ;; ADFaker/Provider/en_GB/Address.phpnuW+APKqZҡ pFaker/Provider/sl_SI/Payment.phpnuW+APKqZ]C##jFaker/Provider/sl_SI/Person.phpnuW+APKqZ;^::!Faker/Provider/sl_SI/Internet.phpnuW+APKqZSZUmm$#Faker/Provider/sl_SI/PhoneNumber.phpnuW+APKqZDqW~ Faker/Provider/sl_SI/Company.phpnuW+APKqZ\ҝT Faker/Provider/sl_SI/Address.phpnuW+APKqZجFaker/Provider/vi_VN/Color.phpnuW+APKqZ!r++Faker/Provider/vi_VN/Person.phpnuW+APKqZ@E>MM!Faker/Provider/vi_VN/Internet.phpnuW+APKqZ%$UFaker/Provider/vi_VN/PhoneNumber.phpnuW+APKqZI5"5" <Faker/Provider/vi_VN/Address.phpnuW+APKqZ044 (Faker/Provider/Miscellaneous.phpnuW+APKqZjBݔEE]Faker/Provider/ko_KR/Person.phpnuW+APKqZr䡭{oFaker/Provider/ko_KR/Text.phpnuW+APKqZ|!iFaker/Provider/ko_KR/Internet.phpnuW+APKqZNx$0Faker/Provider/ko_KR/PhoneNumber.phpnuW+APKqZPB 5Faker/Provider/ko_KR/Company.phpnuW+APKqZ. 9Faker/Provider/ko_KR/Address.phpnuW+APKqZ6 ~ RTFaker/Provider/it_CH/Payment.phpnuW+APKqZ]T  LWFaker/Provider/it_CH/Person.phpnuW+APKqZ";ZZuFaker/Provider/it_CH/Text.phpnuW+APKqZ;Y>>!KvFaker/Provider/it_CH/Internet.phpnuW+APKqZ3$wFaker/Provider/it_CH/PhoneNumber.phpnuW+APKqZ KK {Faker/Provider/it_CH/Company.phpnuW+APKqZ-UU J}Faker/Provider/it_CH/Address.phpnuW+APKqZO2ߪ Faker/Provider/ro_RO/Payment.phpnuW+APKqZ&bCbCFaker/Provider/ro_RO/Person.phpnuW+APKqZjj-PPFaker/Provider/ro_RO/Text.phpnuW+APKqZ9w$'Faker/Provider/ro_RO/PhoneNumber.phpnuW+APKqZagj,j, .Faker/Provider/ro_RO/Address.phpnuW+APKqZzz[Faker/Provider/hy_AM/Color.phpnuW+APKqZu<<J]Faker/Provider/hy_AM/Person.phpnuW+APKqZ66!%Faker/Provider/hy_AM/Internet.phpnuW+APKqZzLL$Faker/Provider/hy_AM/PhoneNumber.phpnuW+APKqZV# LFaker/Provider/hy_AM/Company.phpnuW+APKqZ(HH Faker/Provider/hy_AM/Address.phpnuW+APKqZp  Faker/Provider/en_NG/Person.phpnuW+APKqZΦϔ!Faker/Provider/en_NG/Internet.phpnuW+APKqZ_ $Faker/Provider/en_NG/PhoneNumber.phpnuW+APKqZoZkk Faker/Provider/en_NG/Address.phpnuW+APKqZ} ؈Faker/Provider/Medical.phpnuW+APKqZtD Faker/Provider/it_IT/Payment.phpnuW+APKqZ7Faker/Provider/it_IT/Person.phpnuW+APKqZ ooFaker/Provider/it_IT/Text.phpnuW+APKqZas''!Faker/Provider/it_IT/Internet.phpnuW+APKqZ>==$/Faker/Provider/it_IT/PhoneNumber.phpnuW+APKqZ%O\ Faker/Provider/it_IT/Company.phpnuW+APKqZS Faker/Provider/it_IT/Address.phpnuW+APKqZT4LFaker/Provider/Color.phpnuW+APKqZWH!!Faker/Provider/zh_TW/DateTime.phpnuW+APKqZa wFaker/Provider/zh_TW/Payment.phpnuW+APKqZimuuFaker/Provider/zh_TW/Color.phpnuW+APKqZ,: : sFaker/Provider/zh_TW/Person.phpnuW+APKqZ% Faker/Provider/zh_TW/Text.phpnuW+APKqZzQ!Faker/Provider/zh_TW/Internet.phpnuW+APKqZ{ݫ}}$Faker/Provider/zh_TW/PhoneNumber.phpnuW+APKqZT!&& Faker/Provider/zh_TW/Company.phpnuW+APKqZgSK&M&M "Faker/Provider/zh_TW/Address.phpnuW+APKqZ#G J DpFaker/Provider/ro_MD/Payment.phpnuW+APKqZa|-->sFaker/Provider/ro_MD/Person.phpnuW+APKqZ^!>Faker/Provider/ro_MD/Text.phpnuW+APKqZT$5Faker/Provider/ro_MD/PhoneNumber.phpnuW+APKqZS<< Faker/Provider/ro_MD/Address.phpnuW+APKqZs$O -Faker/Provider/de_CH/Payment.phpnuW+APKqZ)'Faker/Provider/de_CH/Person.phpnuW+APKqZOrtFaker/Provider/de_CH/Text.phpnuW+APKqZ}}!Faker/Provider/de_CH/Internet.phpnuW+APKqZkSB$Faker/Provider/de_CH/PhoneNumber.phpnuW+APKqZ7"QKK Faker/Provider/de_CH/Company.phpnuW+APKqZ $)$) NFaker/Provider/de_CH/Address.phpnuW+APKqZwjɱFaker/Provider/bn_BD/Person.phpnuW+APKqZ9$Faker/Provider/bn_BD/PhoneNumber.phpnuW+APKqZsUU Faker/Provider/bn_BD/Company.phpnuW+APKqZb,,Faker/Provider/bn_BD/Utils.phpnuW+APKqZc;Faker/Provider/cs_CZ/Text.phpnuW+APKqZ8==!^&Faker/Provider/cs_CZ/Internet.phpnuW+APKqZmv$'Faker/Provider/cs_CZ/PhoneNumber.phpnuW+APKqZg0 F)Faker/Provider/cs_CZ/Company.phpnuW+APKqZr$$ 7Faker/Provider/cs_CZ/Address.phpnuW+APKqZS \Faker/Provider/Person.phpnuW+APKqZ^\\@iFaker/Provider/fr_CA/Color.phpnuW+APKqZiFaker/Provider/fr_CA/Person.phpnuW+APKqZID%6~Faker/Provider/fr_CA/Text.phpnuW+APKqZ`'`` ^Faker/Provider/fr_CA/Company.phpnuW+APKqZP _Faker/Provider/fr_CA/Address.phpnuW+APKqZXu**rFaker/Provider/es_AR/Person.phpnuW+APKqZNat$Faker/Provider/es_AR/PhoneNumber.phpnuW+APKqZ!`n áFaker/Provider/es_AR/Company.phpnuW+APKqZ>B Faker/Provider/es_AR/Address.phpnuW+APKqZm XFaker/Provider/sk_SK/Payment.phpnuW+APKqZn0--RFaker/Provider/sk_SK/Person.phpnuW+APKqZ[BB!iFaker/Provider/sk_SK/Internet.phpnuW+APKqZf##$Faker/Provider/sk_SK/PhoneNumber.phpnuW+APKqZZ>> sFaker/Provider/sk_SK/Company.phpnuW+APKqZ@" Faker/Provider/sk_SK/Address.phpnuW+APKqZw[ Faker/Provider/pt_PT/Payment.phpnuW+APKqZ Faker/Provider/pt_PT/Person.phpnuW+APKqZ;!qFaker/Provider/pt_PT/Internet.phpnuW+APKqZi«^^$Faker/Provider/pt_PT/PhoneNumber.phpnuW+APKqZxZ? Faker/Provider/pt_PT/Company.phpnuW+APKqZIe^}} Faker/Provider/pt_PT/Address.phpnuW+APKqZQ3 bFaker/Provider/lt_LT/Payment.phpnuW+APKqZ^Fnn\Faker/Provider/lt_LT/Person.phpnuW+APKqZ@<[!GFaker/Provider/lt_LT/Internet.phpnuW+APKqZ*,]VV$Faker/Provider/lt_LT/PhoneNumber.phpnuW+APKqZ-u WFaker/Provider/lt_LT/Company.phpnuW+APKqZ9 ܲ$$ ZFaker/Provider/lt_LT/Address.phpnuW+APKqZd`!\Faker/Provider/ka_GE/DateTime.phpnuW+APKqZ0ڋ AFaker/Provider/ka_GE/Payment.phpnuW+APKqZnaFFyFaker/Provider/ka_GE/Color.phpnuW+APKqZLNCp'p' Faker/Provider/ka_GE/Person.phpnuW+APKqZG_-Faker/Provider/ka_GE/Text.phpnuW+APKqZ9! Faker/Provider/ka_GE/Internet.phpnuW+APKqZdw  $ Faker/Provider/ka_GE/PhoneNumber.phpnuW+APKqZ[ % Faker/Provider/ka_GE/Company.phpnuW+APKqZjeI::  Faker/Provider/ka_GE/Address.phpnuW+APKqZj]Њ2 Faker/Provider/et_EE/Person.phpnuW+APKqZN Faker/Provider/Text.phpnuW+APKqZ!!i Faker/Provider/UserAgent.phpnuW+APKqZQ Ƌ Faker/Provider/nl_NL/Payment.phpnuW+APKqZ Faker/Provider/nl_NL/Color.phpnuW+APKqZw EwjwjƖ Faker/Provider/nl_NL/Person.phpnuW+APKqZ^Sd Faker/Provider/nl_NL/Text.phpnuW+APKqZ -  !Faker/Provider/nl_NL/Internet.phpnuW+APKqZ;ii$ Faker/Provider/nl_NL/PhoneNumber.phpnuW+APKqZ(}[}[ #Faker/Provider/nl_NL/Company.phpnuW+APKqZ|<< Faker/Provider/nl_NL/Address.phpnuW+APKqZ [5$Faker/Provider/en_SG/Person.phpnuW+APKqZS< $w-Faker/Provider/en_SG/PhoneNumber.phpnuW+APKqZ 8Faker/Provider/en_SG/Address.phpnuW+APKqZx GFaker/Provider/sr_RS/Payment.phpnuW+APKqZ`ȀJFaker/Provider/sr_RS/Person.phpnuW+APKqZ1 ,Faker/Provider/sr_RS/Address.phpnuW+APKqZ9,{DDKFaker/Provider/Internet.phpnuW+APKqZOkdkdFaker/Provider/File.phpnuW+APKqZᩞ @Faker/Provider/is_IS/Payment.phpnuW+APKqZK Y==:Faker/Provider/is_IS/Person.phpnuW+APKqZFxp!ƲFaker/Provider/is_IS/Internet.phpnuW+APKqZMqN<<$ƴFaker/Provider/is_IS/PhoneNumber.phpnuW+APKqZD^ i VFaker/Provider/is_IS/Company.phpnuW+APKqZDhO\!\! fFaker/Provider/is_IS/Address.phpnuW+APKqZxf Faker/Provider/at_AT/Payment.phpnuW+APKqZ_ KFaker/Provider/he_IL/Payment.phpnuW+APKqZӍ)*o*oEFaker/Provider/he_IL/Person.phpnuW+APKqZ?~$QFaker/Provider/he_IL/PhoneNumber.phpnuW+APKqZ\ܲqxx SFaker/Provider/he_IL/Company.phpnuW+APKqZyMxbb TFaker/Provider/he_IL/Address.phpnuW+APKqZG8G Faker/Provider/ne_NP/Payment.phpnuW+APKqZZ &Faker/Provider/ne_NP/Person.phpnuW+APKqZ/}!lFaker/Provider/ne_NP/Internet.phpnuW+APKqZpHgg$Faker/Provider/ne_NP/PhoneNumber.phpnuW+APKqZcL99 Faker/Provider/ne_NP/Address.phpnuW+APKqZٞ] * *6Faker/Provider/es_PE/Person.phpnuW+APKqZAA$(aFaker/Provider/es_PE/PhoneNumber.phpnuW+APKqZ6Eu!u! bFaker/Provider/es_PE/Company.phpnuW+APKqZuX^// Faker/Provider/es_PE/Address.phpnuW+APKqZTï Faker/Provider/el_GR/Payment.phpnuW+APKqZFaker/Provider/el_GR/Person.phpnuW+APKqZ\NySyS=Faker/Provider/el_GR/Text.phpnuW+APKqZ}n)n)$kFaker/Provider/el_GR/PhoneNumber.phpnuW+APKqZ3PY ŔFaker/Provider/el_GR/Company.phpnuW+APKqZޡGG ̝Faker/Provider/el_GR/Address.phpnuW+APKqZ#pFaker/Provider/Image.phpnuW+APKqZhZU!CFaker/Provider/en_HK/Internet.phpnuW+APKqZX 0  $Faker/Provider/en_HK/PhoneNumber.phpnuW+APKqZvÑ&& Faker/Provider/en_HK/Address.phpnuW+APKqZf=  R+Faker/Provider/nl_BE/Payment.phpnuW+APKqZK1Faker/Provider/nl_BE/Person.phpnuW+APKqZ'{5EWW2Faker/Provider/bg_BG/Person.phpnuW+APKqZ^Uك44!Sd3Faker/Provider/bg_BG/Internet.phpnuW+APKqZY $e3Faker/Provider/bg_BG/PhoneNumber.phpnuW+APKqZV$g3Faker/Provider/en_CA/PhoneNumber.phpnuW+APKqZ}g>> i3Faker/Provider/en_CA/Address.phpnuW+APKqZq 5q3Faker/Provider/hr_HR/Payment.phpnuW+APKqZ↚V V /t3Faker/Provider/hr_HR/Person.phpnuW+APKqZ!˩$3Faker/Provider/hr_HR/PhoneNumber.phpnuW+APKqZn~a ?3Faker/Provider/hr_HR/Company.phpnuW+APKqZ&h"h" Q3Faker/Provider/hr_HR/Address.phpnuW+APKqZʦ 3Faker/Provider/Company.phpnuW+APKqZo$l5l5ت3Faker/Provider/es_VE/Person.phpnuW+APKqZoUtt!3Faker/Provider/es_VE/Internet.phpnuW+APKqZ ƃ$X3Faker/Provider/es_VE/PhoneNumber.phpnuW+APKqZXÎ11 /3Faker/Provider/es_VE/Company.phpnuW+APKqZd d 3Faker/Provider/es_VE/Address.phpnuW+APKqZ@K 3Faker/Provider/hu_HU/Payment.phpnuW+APKqZ2AA3Faker/Provider/hu_HU/Person.phpnuW+APKqZQQa4Faker/Provider/hu_HU/Text.phpnuW+APKqZ  $xc9Faker/Provider/hu_HU/PhoneNumber.phpnuW+APKqZP   d9Faker/Provider/hu_HU/Company.phpnuW+APKqZڔ !! Gf9Faker/Provider/hu_HU/Address.phpnuW+APKqZ2J 9Faker/Provider/lv_LV/Payment.phpnuW+APKqZJ^?""9Faker/Provider/lv_LV/Color.phpnuW+APKqZ,Bv9Faker/Provider/lv_LV/Person.phpnuW+APKqZ%%!z:Faker/Provider/lv_LV/Internet.phpnuW+APKqZV''$t|:Faker/Provider/lv_LV/PhoneNumber.phpnuW+APKqZb~ }:Faker/Provider/lv_LV/Address.phpnuW+APKqZeV:Faker/Provider/ja_JP/Person.phpnuW+APKqZEE+:Faker/Provider/ja_JP/Text.phpnuW+APKqZ |Ty y !%<Faker/Provider/ja_JP/Internet.phpnuW+APKqZ>M$<Faker/Provider/ja_JP/PhoneNumber.phpnuW+APKqZΗ ll <Faker/Provider/ja_JP/Company.phpnuW+APKqZ^})!)! <Faker/Provider/ja_JP/Address.phpnuW+APKqZ_ױ &!=Faker/Provider/es_ES/Payment.phpnuW+APKqZ)e&=Faker/Provider/es_ES/Color.phpnuW+APKqZ]44O(=Faker/Provider/es_ES/Person.phpnuW+APKqZcC]=Faker/Provider/es_ES/Text.phpnuW+APKqZUpp!zAFaker/Provider/es_ES/Internet.phpnuW+APKqZ&$;AFaker/Provider/es_ES/PhoneNumber.phpnuW+APKqZa_S!S! BFaker/Provider/es_ES/Company.phpnuW+APKqZh C#BFaker/Provider/es_ES/Address.phpnuW+APKqZy ;BFaker/Provider/de_AT/Payment.phpnuW+APKqZgN,,ABFaker/Provider/de_AT/Person.phpnuW+APKqZY>PZZmBFaker/Provider/de_AT/Text.phpnuW+APKqZ(W!nBFaker/Provider/de_AT/Internet.phpnuW+APKqZ^$$oBFaker/Provider/de_AT/PhoneNumber.phpnuW+APKqZi999 qBFaker/Provider/de_AT/Company.phpnuW+APKqZCV=+=+ sBFaker/Provider/de_AT/Address.phpnuW+APKqZBb< BFaker/Provider/uk_UA/Payment.phpnuW+APKqZըddaBFaker/Provider/uk_UA/Color.phpnuW+APKqZGKKBFaker/Provider/uk_UA/Person.phpnuW+APKqZʴ_QQBFaker/Provider/uk_UA/Text.phpnuW+APKqZ;Z!KuHFaker/Provider/uk_UA/Internet.phpnuW+APKqZ''~GG$vHFaker/Provider/uk_UA/PhoneNumber.phpnuW+APKqZa M~HFaker/Provider/uk_UA/Company.phpnuW+APKqZX;P(P( HFaker/Provider/uk_UA/Address.phpnuW+APKqZQ'%NHFaker/Provider/sr_Latn_RS/Payment.phpnuW+APKqZV00$RHFaker/Provider/sr_Latn_RS/Person.phpnuW+APKqZ \3||%ևIFaker/Provider/sr_Latn_RS/Address.phpnuW+APKqZ!IFaker/Provider/en_NZ/Internet.phpnuW+APKqZ*6tt$IFaker/Provider/en_NZ/PhoneNumber.phpnuW+APKqZE IFaker/Provider/en_NZ/Address.phpnuW+APKqZ喥;; IFaker/Provider/pl_PL/Payment.phpnuW+APKqZ+pII%IFaker/Provider/pl_PL/LicensePlate.phpnuW+APKqZ7攱 JFaker/Provider/pl_PL/Color.phpnuW+APKqZ;!0A*A*JFaker/Provider/pl_PL/Person.phpnuW+APKqZn<@HJFaker/Provider/pl_PL/Text.phpnuW+APKqZDBB!NMFaker/Provider/pl_PL/Internet.phpnuW+APKqZvv$PMFaker/Provider/pl_PL/PhoneNumber.phpnuW+APKqZ{}r r LRMFaker/Provider/pl_PL/Company.phpnuW+APKqZmFDD \MFaker/Provider/pl_PL/Address.phpnuW+APKqZ)i 8MFaker/Provider/Address.phpnuW+APKqZ8}8} vMFaker/Provider/ru_RU/Payment.phpnuW+APKqZ K,NFaker/Provider/ru_RU/Color.phpnuW+APKqZy004NFaker/Provider/ru_RU/Person.phpnuW+APKqZ:{eNFaker/Provider/ru_RU/Text.phpnuW+APKqZ$OO!WTFaker/Provider/ru_RU/Internet.phpnuW+APKqZx$XTFaker/Provider/ru_RU/PhoneNumber.phpnuW+APKqZB\9\9 #ZTFaker/Provider/ru_RU/Company.phpnuW+APKqZt~*+*+ ϓTFaker/Provider/ru_RU/Address.phpnuW+APKqZ \3 ITFaker/Provider/da_DK/Payment.phpnuW+APKqZs??CTFaker/Provider/da_DK/Person.phpnuW+APKqZ5bb!;UFaker/Provider/da_DK/Internet.phpnuW+APKqZbTT$UFaker/Provider/da_DK/PhoneNumber.phpnuW+APKqZ~[KK UFaker/Provider/da_DK/Company.phpnuW+APKqZ2'';?;? 1UFaker/Provider/da_DK/Address.phpnuW+APKqZ MUFaker/Provider/ms_MY/Payment.phpnuW+APKqZӨEE&kUFaker/Provider/ms_MY/Miscellaneous.phpnuW+APKqZ<I}UFaker/Provider/ms_MY/Person.phpnuW+APKqZn$$$ΆVFaker/Provider/ms_MY/PhoneNumber.phpnuW+APKqZF77 FVFaker/Provider/ms_MY/Company.phpnuW+APKqZWFaker/Provider/fr_BE/Payment.phpnuW+APKqZf!\\nDWFaker/Provider/fr_BE/Color.phpnuW+APKqZ EWFaker/Provider/fr_BE/Person.phpnuW+APKqZ/m!nXWFaker/Provider/fr_BE/Internet.phpnuW+APKqZ ;$YWFaker/Provider/fr_BE/PhoneNumber.phpnuW+APKqZ@ qii [WFaker/Provider/fr_BE/Company.phpnuW+APKqZ|hh  Y]WFaker/Provider/fr_BE/Address.phpnuW+APKqZ]\DD iWFaker/Provider/ar_EG/Payment.phpnuW+APKqZCx\kWFaker/Provider/ar_EG/Color.phpnuW+APKqZx++arWFaker/Provider/ar_EG/Person.phpnuW+APKqZu52LLÝWFaker/Provider/ar_EG/Text.phpnuW+APKqZW!WFaker/Provider/ar_EG/Internet.phpnuW+APKqZ k3  WFaker/Provider/ar_EG/Company.phpnuW+APKqZ.b'' WFaker/Provider/ar_EG/Address.phpnuW+APKqZOР$XFaker/Provider/Uuid.phpnuW+APKqZjMY!c+XFaker/Provider/zh_CN/DateTime.phpnuW+APKqZ^ 0XFaker/Provider/zh_CN/Payment.phpnuW+APKqZXvv4XFaker/Provider/zh_CN/Color.phpnuW+APKqZLDXFaker/Provider/zh_CN/Person.phpnuW+APKqZy57!XXFaker/Provider/zh_CN/Internet.phpnuW+APKqZR5$[XFaker/Provider/zh_CN/PhoneNumber.phpnuW+APKqZ{%{% X_XFaker/Provider/zh_CN/Company.phpnuW+APKqZjR{ #XFaker/Provider/zh_CN/Address.phpnuW+APKqZ XFaker/Provider/de_DE/Payment.phpnuW+APKqZV*FFXFaker/Provider/de_DE/Person.phpnuW+APKqZ XFaker/Provider/de_DE/Text.phpnuW+APKqZ!!FZFaker/Provider/de_DE/Internet.phpnuW+APKqZ'Q$4ZFaker/Provider/de_DE/PhoneNumber.phpnuW+APKqZE*EE Z [Faker/Provider/de_DE/Company.phpnuW+APKqZVX+>+> [Faker/Provider/de_DE/Address.phpnuW+APKqZ9*..jQ[Faker/Provider/en_IN/Person.phpnuW+APKqZZJJ!r[Faker/Provider/en_IN/Internet.phpnuW+APKqZq$ [Faker/Provider/en_IN/PhoneNumber.phpnuW+APKqZi ۀ% % X[Faker/Provider/en_IN/Address.phpnuW+APKqZ)ͥ[Faker/Provider/fa_IR/Person.phpnuW+APKqZ x((7\Faker/Provider/fa_IR/Text.phpnuW+APKqZ !_^Faker/Provider/fa_IR/Internet.phpnuW+APKqZ# # $p^Faker/Provider/fa_IR/PhoneNumber.phpnuW+APKqZTS}n y^Faker/Provider/fa_IR/Company.phpnuW+APKqZ* u^Faker/Provider/fa_IR/Address.phpnuW+APKqZ?XX^Faker/Provider/Base.phpnuW+APKqZ#h_mm ^Faker/Provider/pt_BR/Payment.phpnuW+APKqZ|l$c^Faker/Provider/pt_BR/check_digit.phpnuW+APKqZ V_))y^Faker/Provider/pt_BR/Person.phpnuW+APKqZvP]j]j$_Faker/Provider/pt_BR/Text.phpnuW+APKqZIBB!aFaker/Provider/pt_BR/Internet.phpnuW+APKqZ-yD||$aFaker/Provider/pt_BR/PhoneNumber.phpnuW+APKqZP aFaker/Provider/pt_BR/Company.phpnuW+APKqZЍ[z aFaker/Provider/pt_BR/Address.phpnuW+APKqZ!}0aFaker/Extension/GeneratorAwareExtensionTrait.phpnuW+APKqZ~ess$RaFaker/Extension/VersionExtension.phpnuW+APKqZ,8LL$aFaker/Extension/BarcodeExtension.phpnuW+APKqZ($($%aFaker/Extension/DateTimeExtension.phpnuW+APKqZARJ 6aFaker/Extension/Helper.phpnuW+APKqZ$aFaker/Extension/CountryExtension.phpnuW+APKqZ#`%haFaker/Extension/ExtensionNotFound.phpnuW+APKqZ- oo#aFaker/Extension/NumberExtension.phpnuW+APKqZgRc"QbFaker/Extension/BloodExtension.phpnuW+APKqZ'1+bFaker/Extension/GeneratorAwareExtension.phpnuW+APKqZ|l&##!bFaker/Extension/FileExtension.phpnuW+APKqZk?j bFaker/Extension/Extension.phpnuW+APKqZLkmm" bFaker/Extension/ColorExtension.phpnuW+APKqZ$pbFaker/Extension/AddressExtension.phpnuW+APKqZ+-$bFaker/Extension/CompanyExtension.phpnuW+APKqZ8mKXbb#bFaker/Extension/PersonExtension.phpnuW+APKqZ Umm(IbFaker/Extension/PhoneNumberExtension.phpnuW+APKqZ{ɮTT!bFaker/Extension/UuidExtension.phpnuW+APKqZ $RRbFaker/ValidGenerator.phpnuW+APKqZ69M&bFaker/DefaultGenerator.phpnuW+APKqZ@ *bFaker/UniqueGenerator.phpnuW+APKqZƶg֒4bFaker/ChanceGenerator.phpnuW+APKqZ^99bFaker/Calculator/Inn.phpnuW+APKqZ ?bFaker/Calculator/Ean.phpnuW+APKqZl-CbFaker/Calculator/TCNo.phpnuW+APKqZ$t!HbFaker/Calculator/Iban.phpnuW+APKqZ  ~ObFaker/Calculator/Isbn.phpnuW+APKqZ󖤒UbFaker/Calculator/Luhn.phpnuW+APKqZ(T]bFaker/Guesser/Name.phpnuW+APKqZn rbFaker/Factory.phpnuW+APKqZ߭ ]]DzbFaker/Core/DateTime.phpnuW+APKqZebFaker/Core/Barcode.phpnuW+APKqZĚ'bFaker/Core/Coordinates.phpnuW+APKqZjccbFaker/Core/Number.phpnuW+APKqZF  8bFaker/Core/Color.phpnuW+APKqZt\\bFaker/Core/File.phpnuW+APKqZ8'&&vcFaker/Core/Blood.phpnuW+APKqZXJ  cFaker/Core/Version.phpnuW+APKqZA3x/"cFaker/Core/Uuid.phpnuW+APKqZ:j &L)cFaker/ORM/Mandango/EntityPopulator.phpnuW+APKqZO".WW(6cFaker/ORM/Mandango/ColumnTypeGuesser.phpnuW+APKqZ[ww 277$3eException/NoSuchElementException.phpnuW+APKcvZM??+eException/UnsupportedOperationException.phpnuW+APKcvZ:7XeQueueInterface.phpnuW+APKcvZKSw%eGenericArray.phpnuW+APKcvZ4Jy(y('eDoubleEndedQueueInterface.phpnuW+APKcvZ֕mm}PeSort.phpnuW+APKcvZ5MM "SeQueue.phpnuW+APKcvZ): : aeMap/NamedParameterMap.phpnuW+APKcvZ'a  +neMap/TypedMap.phpnuW+APKcvZE+ lyeMap/AbstractTypedMap.phpnuW+APKcvZ 9##seMap/TypedMapInterface.phpnuW+APKcvZh߃eMap/MapInterface.phpnuW+APKcvZ@i""eMap/AssociativeArrayMap.phpnuW+APKcvZb?ceMap/AbstractMap.phpnuW+APKcvZ}%%beArrayInterface.phpnuW+APKcvZS##ɰeCollectionInterface.phpnuW+APKcvZgWQ eTool/ValueExtractorTrait.phpnuW+APKcvZpeTool/ValueToStringTrait.phpnuW+APKcvZ̾f55eTool/TypeTrait.phpnuW+APKcvZOeAbstractArray.phpnuW+APKcvZoeAbstractSet.phpnuW+APKcvZ=fTaskQueueInterface.phpnuW+APKKZLtfCancellationException.phpnuW+APKKZd1*fRejectedPromise.phpnuW+APKKZdGfPromisorInterface.phpnuW+APKKZ' cfFulfilledPromise.phpnuW+APKKZ逿  ĸfPromiseInterface.phpnuW+APKKZR fCreate.phpnuW+APKKZYi$fEachPromise.phpnuW+APKKZWPAA ffCoroutine.phpnuW+APKKZk}fRejectionException.phpnuW+APKZ߾`fFpdfServiceProvider.phpnuW+APKZR11gFacades/Fpdf.phpnuW+APKZ8k NgFpdf/Fpdf.phpnuW+APKZq.>gFpdf/makefont/cp1254.mapnuW+APKZ /1gFpdf/makefont/cp1255.mapnuW+APKZRRCgFpdf/makefont/cp1257.mapnuW+APKZ|hFpdf/makefont/iso-8859-15.mapnuW+APKZlt hFpdf/makefont/cp1252.mapnuW+APKZlb'hFpdf/makefont/iso-8859-2.mapnuW+APKZZ]79hFpdf/makefont/koi8-r.mapnuW+APKZayQQLhFpdf/makefont/iso-8859-11.mapnuW+APKZ!/^hFpdf/makefont/cp1251.mapnuW+APKZcQqhFpdf/makefont/cp1250.mapnuW+APKZMFAhFpdf/makefont/koi8-u.mapnuW+APKZLehFpdf/makefont/cp874.mapnuW+APKZRShFpdf/makefont/iso-8859-9.mapnuW+APKZ=FFhFpdf/makefont/ttfparser.phpnuW+APKZiUooiFpdf/makefont/iso-8859-5.mapnuW+APKZ2giFpdf/makefont/iso-8859-4.mapnuW+APKZ+% %iFpdf/makefont/cp1253.mapnuW+APKZ;y*y*5iFpdf/makefont/makefont.phpnuW+APKZj`iFpdf/makefont/cp1258.mapnuW+APKZOUriFpdf/makefont/iso-8859-16.mapnuW+APKZ@eiFpdf/makefont/iso-8859-1.mapnuW+APKZ|a NN1iFpdf/makefont/iso-8859-7.mapnuW+APKZO;; ˨iFpdf/fpdf.cssnuW+APKZo@C CiFpdf/font/timesi.phpnuW+APKZ ?q IiFpdf/font/helveticai.phpnuW+APKZ| ^iFpdf/font/times.phpnuW+APKZDdiFpdf/font/courierb.phpnuW+APKZYۺiiFpdf/font/courier.phpnuW+APKZB hiFpdf/font/timesbi.phpnuW+APKZe viFpdf/font/helvetica.phpnuW+APKZ"? iFpdf/font/zapfdingbats.phpnuW+APKZձjFpdf/font/courieri.phpnuW+APKZf;jFpdf/font/symbol.phpnuW+APKZ  njFpdf/font/helveticab.phpnuW+APKZFK (jFpdf/font/helveticabi.phpnuW+APKZ:N6jFpdf/font/courierbi.phpnuW+APKZl 8jFpdf/font/timesb.phpnuW+APKZ҇*KKFjFpdf/license.txtnuW+APKZtDuu;Hjconfig/fpdf.phpnuW+APKuZX X KjReport/Xml/BuildInformation.phpnuW+APKuZ n&##VjReport/Xml/Facade.phpnuW+APKuZBkzjReport/Xml/Tests.phpnuW+APKuZ)ؓ{{jReport/Xml/Source.phpnuW+APKuZ=[[vjReport/Xml/Unit.phpnuW+APKuZ10ccjReport/Xml/Totals.phpnuW+APKuZjReport/Xml/Directory.phpnuW+APKuZoGkGGjReport/Xml/File.phpnuW+APKuZ?ں mjReport/Xml/Project.phpnuW+APKuZGgQQKjReport/Xml/Method.phpnuW+APKuZ<jReport/Xml/Node.phpnuW+APKuZ>>jReport/Xml/Coverage.phpnuW+APKuZ0 0 jReport/Xml/Report.phpnuW+APKuZ֠11jReport/Cobertura.phpnuW+APKuZ ((3 kReport/Html/Renderer.phpnuW+APKuZaA++2kReport/Html/Facade.phpnuW+APKuZZ6DkReport/Html/Renderer/Template/icons/file-directory.svgnuW+APKuZQUU001EkReport/Html/Renderer/Template/icons/file-code.svgnuW+APKuZ/yrr1iGkReport/Html/Renderer/Template/file_item.html.distnuW+APKuZm;;=&_KxStaticAnalysis/CachingFileAnalyser.phpnuW+APKuZ͘j]+]+0@^xStaticAnalysis/ExecutableLinesFindingVisitor.phpnuW+APKuZ W*W*)xStaticAnalysis/CodeUnitFindingVisitor.phpnuW+APKuZshh(xException/Xdebug3NotEnabledException.phpnuW+APKuZ"mxException/XmlException.phpnuW+APKuZjIJUU(SxException/Xdebug2NotEnabledException.phpnuW+APKuZww+xException/WriteOperationFailedException.phpnuW+APKuZc7ҾxException/StaticAnalysisCacheNotConfiguredException.phpnuW+APKuZV9&&1xException/UnintentionallyCoveredCodeException.phpnuW+APKuZ(E7&&4yxException/NoCodeCoverageDriverAvailableException.phpnuW+APKuZrD4xException/DeadCodeDetectionNotSupportedException.phpnuW+APKuZ2xException/PathExistsButIsNotDirectoryException.phpnuW+APKuZtst11- xException/ReportAlreadyFinalizedException.phpnuW+APKuZO}A8xException/BranchAndPathCoverageNotSupportedException.phpnuW+APKuZ[8PP'xException/PcovNotAvailableException.phpnuW+APKuZs$bxException/ParserException.phpnuW+APKuZ<OO)NxException/PhpdbgNotAvailableException.phpnuW+APKuZ&L!xException/ReflectionException.phpnuW+APKuZ;XXKxException/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.phpnuW+APKuZ$xException/TestIdMissingException.phpnuW+APKuZTT)xException/XdebugNotAvailableException.phpnuW+APKuZo )xException/WrongXdebugVersionException.phpnuW+APKuZ;s 1xException/DirectoryCouldNotBeCreatedException.phpnuW+APKuZ}$$ExProcessedCodeCoverageData.phpnuW+APKuZP Ȼi i = yDriver/PhpdbgDriver.phpnuW+APKuZYcFFyDriver/PcovDriver.phpnuW+APKuZ xyDriver/Xdebug2Driver.phpnuW+APKuZ2mVd d ,yDriver/Selector.phpnuW+APKuZ5> ,6yDriver/Xdebug3Driver.phpnuW+APKuZ#,CyDriver/Driver.phpnuW+APKuZ<.FF]TyCodeCoverage.phpnuW+APKuZBAyNode/CrapIndex.phpnuW+APKuZ d'd'yNode/Directory.phpnuW+APKuZ5?bUbU ZzUtil/Filesystem.phpnuW+APKuZ^zUtil/Percentage.phpnuW+APKuZqf-u!u!dzRawCodeCoverageData.phpnuW+APKuZVo4 4 [zFilter.phpnuW+APKZBjhh ɒzUploadedFileFactoryInterface.phpnuW+APKZDhEEzUriFactoryInterface.phpnuW+APKZyۜ zStreamFactoryInterface.phpnuW+APKZX""zResponseFactoryInterface.phpnuW+APKZBHA!OzServerRequestFactoryInterface.phpnuW+APKZrTX?zRequestFactoryInterface.phpnuW+APK%Zz0; ; }zLinesOfCode.phpnuW+APK%Zy<$zException/NegativeValueException.phpnuW+APK%Z &zException/IllogicalValuesException.phpnuW+APK%ZzLineCountingVisitor.phpnuW+APK%ZW zCounter.phpnuW+APKZPKzContent/Type/index.phpnuW+APKZ[8zException/Transport/mah.phpnuW+APK)Z?+V$ztype/CallableType.phpnuW+APK)Zj!11ztype/GenericObjectType.phpnuW+APK)ZVCee]ztype/IterableType.phpnuW+APK)ZL/ztype/MixedType.phpnuW+APK)Z3j cztype/UnionType.phpnuW+APK)Zs .{type/Type.phpnuW+APK)Z{type/VoidType.phpnuW+APK)Z "{type/IntersectionType.phpnuW+APK)Z?  P'{type/UnknownType.phpnuW+APK)Z')*{type/StaticType.phpnuW+APK)Zo|0{type/NullType.phpnuW+APK)ZV!pp3{type/FalseType.phpnuW+APK)Zkk7{type/TrueType.phpnuW+APK)Z R;{type/NeverType.phpnuW+APK)ZeTT^>{type/ObjectType.phpnuW+APK)ZCD{type/SimpleType.phpnuW+APK)Zyy ;M{TypeName.phpnuW+APK)ZOOT{ReflectionMapper.phpnuW+APK)Zg@ɼaa k{exception/Exception.phpnuW+APK)Z56wwl{exception/RuntimeException.phpnuW+APK)ZGv wn{Parameter.phpnuW+APK q{